
This patch implements a callback mechanism similar to the existing ones, but for getting notified whenever a Use edge gets updated. This is going to be used in a follow up patch by the Dependency Graph.
122 lines
4.0 KiB
C++
122 lines
4.0 KiB
C++
//===- User.cpp - The User class of Sandbox IR ----------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/SandboxIR/User.h"
|
|
#include "llvm/SandboxIR/Context.h"
|
|
|
|
namespace llvm::sandboxir {
|
|
|
|
Use OperandUseIterator::operator*() const { return Use; }
|
|
|
|
OperandUseIterator &OperandUseIterator::operator++() {
|
|
assert(Use.LLVMUse != nullptr && "Already at end!");
|
|
User *User = Use.getUser();
|
|
Use = User->getOperandUseInternal(Use.getOperandNo() + 1, /*Verify=*/false);
|
|
return *this;
|
|
}
|
|
|
|
UserUseIterator &UserUseIterator::operator++() {
|
|
// Get the corresponding llvm::Use, get the next in the list, and update the
|
|
// sandboxir::Use.
|
|
llvm::Use *&LLVMUse = Use.LLVMUse;
|
|
assert(LLVMUse != nullptr && "Already at end!");
|
|
LLVMUse = LLVMUse->getNext();
|
|
if (LLVMUse == nullptr) {
|
|
Use.Usr = nullptr;
|
|
return *this;
|
|
}
|
|
auto *Ctx = Use.Ctx;
|
|
auto *LLVMUser = LLVMUse->getUser();
|
|
Use.Usr = cast_or_null<sandboxir::User>(Ctx->getValue(LLVMUser));
|
|
return *this;
|
|
}
|
|
|
|
OperandUseIterator OperandUseIterator::operator+(unsigned Num) const {
|
|
sandboxir::Use U = Use.getUser()->getOperandUseInternal(
|
|
Use.getOperandNo() + Num, /*Verify=*/true);
|
|
return OperandUseIterator(U);
|
|
}
|
|
|
|
OperandUseIterator OperandUseIterator::operator-(unsigned Num) const {
|
|
assert(Use.getOperandNo() >= Num && "Out of bounds!");
|
|
sandboxir::Use U = Use.getUser()->getOperandUseInternal(
|
|
Use.getOperandNo() - Num, /*Verify=*/true);
|
|
return OperandUseIterator(U);
|
|
}
|
|
|
|
int OperandUseIterator::operator-(const OperandUseIterator &Other) const {
|
|
int ThisOpNo = Use.getOperandNo();
|
|
int OtherOpNo = Other.Use.getOperandNo();
|
|
return ThisOpNo - OtherOpNo;
|
|
}
|
|
|
|
Use User::getOperandUseDefault(unsigned OpIdx, bool Verify) const {
|
|
assert((!Verify || OpIdx < getNumOperands()) && "Out of bounds!");
|
|
assert(isa<llvm::User>(Val) && "Non-users have no operands!");
|
|
llvm::Use *LLVMUse;
|
|
if (OpIdx != getNumOperands())
|
|
LLVMUse = &cast<llvm::User>(Val)->getOperandUse(OpIdx);
|
|
else
|
|
LLVMUse = cast<llvm::User>(Val)->op_end();
|
|
return Use(LLVMUse, const_cast<User *>(this), Ctx);
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
void User::verifyUserOfLLVMUse(const llvm::Use &Use) const {
|
|
assert(Ctx.getValue(Use.getUser()) == this &&
|
|
"Use not found in this SBUser's operands!");
|
|
}
|
|
#endif
|
|
|
|
bool User::classof(const Value *From) {
|
|
switch (From->getSubclassID()) {
|
|
#define DEF_VALUE(ID, CLASS)
|
|
#define DEF_USER(ID, CLASS) \
|
|
case ClassID::ID: \
|
|
return true;
|
|
#define DEF_INSTR(ID, OPC, CLASS) \
|
|
case ClassID::ID: \
|
|
return true;
|
|
#include "llvm/SandboxIR/Values.def"
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void User::setOperand(unsigned OperandIdx, Value *Operand) {
|
|
assert(isa<llvm::User>(Val) && "No operands!");
|
|
const auto &U = getOperandUse(OperandIdx);
|
|
Ctx.getTracker().emplaceIfTracking<UseSet>(U);
|
|
Ctx.runSetUseCallbacks(U, Operand);
|
|
// We are delegating to llvm::User::setOperand().
|
|
cast<llvm::User>(Val)->setOperand(OperandIdx, Operand->Val);
|
|
}
|
|
|
|
bool User::replaceUsesOfWith(Value *FromV, Value *ToV) {
|
|
auto &Tracker = Ctx.getTracker();
|
|
for (auto OpIdx : seq<unsigned>(0, getNumOperands())) {
|
|
auto Use = getOperandUse(OpIdx);
|
|
if (Use.get() == FromV) {
|
|
Ctx.runSetUseCallbacks(Use, ToV);
|
|
if (Tracker.isTracking())
|
|
Tracker.emplaceIfTracking<UseSet>(Use);
|
|
}
|
|
}
|
|
// We are delegating RUOW to LLVM IR's RUOW.
|
|
return cast<llvm::User>(Val)->replaceUsesOfWith(FromV->Val, ToV->Val);
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
void User::dumpCommonHeader(raw_ostream &OS) const {
|
|
Value::dumpCommonHeader(OS);
|
|
// TODO: This is incomplete
|
|
}
|
|
#endif // NDEBUG
|
|
|
|
} // namespace llvm::sandboxir
|