1//===- Value.cpp - The Value class of Sandbox IR --------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/SandboxIR/Value.h"
10#include "llvm/SandboxIR/Context.h"
11#include "llvm/SandboxIR/User.h"
12#include <sstream>
13
14namespace llvm::sandboxir {
15
16Value::Value(ClassID SubclassID, llvm::Value *Val, Context &Ctx)
17 : SubclassID(SubclassID), Val(Val), Ctx(Ctx) {
18#ifndef NDEBUG
19 UID = Ctx.getNumValues();
20#endif
21}
22
23Value::use_iterator Value::use_begin() {
24 llvm::Use *LLVMUse = nullptr;
25 if (Val->use_begin() != Val->use_end())
26 LLVMUse = &*Val->use_begin();
27 User *User = LLVMUse != nullptr ? cast_or_null<sandboxir::User>(Val: Ctx.getValue(
28 V: Val->use_begin()->getUser()))
29 : nullptr;
30 return use_iterator(Use(LLVMUse, User, Ctx));
31}
32
33Value::user_iterator Value::user_begin() {
34 auto UseBegin = Val->use_begin();
35 auto UseEnd = Val->use_end();
36 bool AtEnd = UseBegin == UseEnd;
37 llvm::Use *LLVMUse = AtEnd ? nullptr : &*UseBegin;
38 User *User =
39 AtEnd ? nullptr
40 : cast_or_null<sandboxir::User>(Val: Ctx.getValue(V: &*LLVMUse->getUser()));
41 return user_iterator(Use(LLVMUse, User, Ctx), UseToUser());
42}
43
44unsigned Value::getNumUses() const { return range_size(Range: Val->users()); }
45
46Type *Value::getType() const { return Ctx.getType(LLVMTy: Val->getType()); }
47
48void Value::replaceUsesWithIf(
49 Value *OtherV, llvm::function_ref<bool(const Use &)> ShouldReplace) {
50 assert(getType() == OtherV->getType() && "Can't replace with different type");
51 llvm::Value *OtherVal = OtherV->Val;
52 // We are delegating RUWIf to LLVM IR's RUWIf.
53 Val->replaceUsesWithIf(
54 New: OtherVal, ShouldReplace: [&ShouldReplace, this, OtherV](llvm::Use &LLVMUse) -> bool {
55 User *DstU = cast_or_null<User>(Val: Ctx.getValue(V: LLVMUse.getUser()));
56 if (DstU == nullptr)
57 return false;
58 Use UseToReplace(&LLVMUse, DstU, Ctx);
59 if (!ShouldReplace(UseToReplace))
60 return false;
61 Ctx.getTracker().emplaceIfTracking<UseSet>(Args: UseToReplace);
62 Ctx.runSetUseCallbacks(U: UseToReplace, NewSrc: OtherV);
63 return true;
64 });
65}
66
67void Value::replaceAllUsesWith(Value *Other) {
68 assert(getType() == Other->getType() &&
69 "Replacing with Value of different type!");
70 auto &Tracker = Ctx.getTracker();
71 for (auto Use : uses()) {
72 Ctx.runSetUseCallbacks(U: Use, NewSrc: Other);
73 if (Tracker.isTracking())
74 Tracker.track(Change: std::make_unique<UseSet>(args&: Use));
75 }
76 // We are delegating RAUW to LLVM IR's RAUW.
77 Val->replaceAllUsesWith(V: Other->Val);
78}
79
80#ifndef NDEBUG
81std::string Value::getUid() const {
82 std::stringstream SS;
83 SS << "SB" << UID << ".";
84 return SS.str();
85}
86
87void Value::dumpCommonHeader(raw_ostream &OS) const {
88 OS << getUid() << " " << getSubclassIDStr(SubclassID) << " ";
89}
90
91void Value::dumpCommonFooter(raw_ostream &OS) const {
92 OS.indent(2) << "Val: ";
93 if (Val)
94 OS << *Val;
95 else
96 OS << "NULL";
97 OS << "\n";
98}
99
100void Value::dumpCommonPrefix(raw_ostream &OS) const {
101 if (Val)
102 OS << *Val;
103 else
104 OS << "NULL ";
105}
106
107void Value::dumpCommonSuffix(raw_ostream &OS) const {
108 OS << " ; " << getUid() << " (" << getSubclassIDStr(SubclassID) << ")";
109}
110
111void Value::printAsOperandCommon(raw_ostream &OS) const {
112 if (Val)
113 Val->printAsOperand(OS);
114 else
115 OS << "NULL ";
116}
117
118void Value::dump() const {
119 dumpOS(dbgs());
120 dbgs() << "\n";
121}
122#endif // NDEBUG
123
124} // namespace llvm::sandboxir
125