| 1 | //===- User.cpp - The User 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/User.h" |
| 10 | #include "llvm/SandboxIR/Context.h" |
| 11 | |
| 12 | namespace llvm::sandboxir { |
| 13 | |
| 14 | Use OperandUseIterator::operator*() const { return Use; } |
| 15 | |
| 16 | OperandUseIterator &OperandUseIterator::operator++() { |
| 17 | assert(Use.LLVMUse != nullptr && "Already at end!" ); |
| 18 | User *User = Use.getUser(); |
| 19 | Use = User->getOperandUseInternal(OpIdx: Use.getOperandNo() + 1, /*Verify=*/false); |
| 20 | return *this; |
| 21 | } |
| 22 | |
| 23 | UserUseIterator &UserUseIterator::operator++() { |
| 24 | // Get the corresponding llvm::Use, get the next in the list, and update the |
| 25 | // sandboxir::Use. |
| 26 | llvm::Use *&LLVMUse = Use.LLVMUse; |
| 27 | assert(LLVMUse != nullptr && "Already at end!" ); |
| 28 | LLVMUse = LLVMUse->getNext(); |
| 29 | if (LLVMUse == nullptr) { |
| 30 | Use.Usr = nullptr; |
| 31 | return *this; |
| 32 | } |
| 33 | auto *Ctx = Use.Ctx; |
| 34 | auto *LLVMUser = LLVMUse->getUser(); |
| 35 | Use.Usr = cast_or_null<sandboxir::User>(Val: Ctx->getValue(V: LLVMUser)); |
| 36 | return *this; |
| 37 | } |
| 38 | |
| 39 | OperandUseIterator OperandUseIterator::operator+(unsigned Num) const { |
| 40 | sandboxir::Use U = Use.getUser()->getOperandUseInternal( |
| 41 | OpIdx: Use.getOperandNo() + Num, /*Verify=*/true); |
| 42 | return OperandUseIterator(U); |
| 43 | } |
| 44 | |
| 45 | OperandUseIterator OperandUseIterator::operator-(unsigned Num) const { |
| 46 | assert(Use.getOperandNo() >= Num && "Out of bounds!" ); |
| 47 | sandboxir::Use U = Use.getUser()->getOperandUseInternal( |
| 48 | OpIdx: Use.getOperandNo() - Num, /*Verify=*/true); |
| 49 | return OperandUseIterator(U); |
| 50 | } |
| 51 | |
| 52 | int OperandUseIterator::operator-(const OperandUseIterator &Other) const { |
| 53 | int ThisOpNo = Use.getOperandNo(); |
| 54 | int OtherOpNo = Other.Use.getOperandNo(); |
| 55 | return ThisOpNo - OtherOpNo; |
| 56 | } |
| 57 | |
| 58 | Use User::getOperandUseDefault(unsigned OpIdx, bool Verify) const { |
| 59 | assert((!Verify || OpIdx < getNumOperands()) && "Out of bounds!" ); |
| 60 | assert(isa<llvm::User>(Val) && "Non-users have no operands!" ); |
| 61 | llvm::Use *LLVMUse; |
| 62 | if (OpIdx != getNumOperands()) |
| 63 | LLVMUse = &cast<llvm::User>(Val)->getOperandUse(i: OpIdx); |
| 64 | else |
| 65 | LLVMUse = cast<llvm::User>(Val)->op_end(); |
| 66 | return Use(LLVMUse, const_cast<User *>(this), Ctx); |
| 67 | } |
| 68 | |
| 69 | #ifndef NDEBUG |
| 70 | void User::verifyUserOfLLVMUse(const llvm::Use &Use) const { |
| 71 | assert(Ctx.getValue(Use.getUser()) == this && |
| 72 | "Use not found in this SBUser's operands!" ); |
| 73 | } |
| 74 | #endif |
| 75 | |
| 76 | bool User::classof(const Value *From) { |
| 77 | switch (From->getSubclassID()) { |
| 78 | #define DEF_VALUE(ID, CLASS) |
| 79 | #define DEF_USER(ID, CLASS) \ |
| 80 | case ClassID::ID: \ |
| 81 | return true; |
| 82 | #define DEF_INSTR(ID, OPC, CLASS) \ |
| 83 | case ClassID::ID: \ |
| 84 | return true; |
| 85 | #include "llvm/SandboxIR/Values.def" |
| 86 | default: |
| 87 | return false; |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | void User::setOperand(unsigned OperandIdx, Value *Operand) { |
| 92 | assert(isa<llvm::User>(Val) && "No operands!" ); |
| 93 | const auto &U = getOperandUse(OpIdx: OperandIdx); |
| 94 | Ctx.getTracker().emplaceIfTracking<UseSet>(Args: U); |
| 95 | Ctx.runSetUseCallbacks(U, NewSrc: Operand); |
| 96 | // We are delegating to llvm::User::setOperand(). |
| 97 | cast<llvm::User>(Val)->setOperand(i: OperandIdx, Val: Operand->Val); |
| 98 | } |
| 99 | |
| 100 | bool User::replaceUsesOfWith(Value *FromV, Value *ToV) { |
| 101 | auto &Tracker = Ctx.getTracker(); |
| 102 | for (auto OpIdx : seq<unsigned>(Begin: 0, End: getNumOperands())) { |
| 103 | auto Use = getOperandUse(OpIdx); |
| 104 | if (Use.get() == FromV) { |
| 105 | Ctx.runSetUseCallbacks(U: Use, NewSrc: ToV); |
| 106 | if (Tracker.isTracking()) |
| 107 | Tracker.emplaceIfTracking<UseSet>(Args: Use); |
| 108 | } |
| 109 | } |
| 110 | // We are delegating RUOW to LLVM IR's RUOW. |
| 111 | return cast<llvm::User>(Val)->replaceUsesOfWith(From: FromV->Val, To: ToV->Val); |
| 112 | } |
| 113 | |
| 114 | #ifndef NDEBUG |
| 115 | void User::dumpCommonHeader(raw_ostream &OS) const { |
| 116 | Value::dumpCommonHeader(OS); |
| 117 | // TODO: This is incomplete |
| 118 | } |
| 119 | #endif // NDEBUG |
| 120 | |
| 121 | } // namespace llvm::sandboxir |
| 122 | |