Files
clang-p2996/llvm/lib/SandboxIR/Context.cpp
vporpo c0c42c8b32 [SandboxIR][NFC] Change order of ifs in Context::getOrCreateValueInternal() (#127891)
Move the most common if statement to the top and the least common ones
to the bottom. This should save CPU cycles during compilation.

This patch also prefixes the llvm variables with the LLVM prefix to make
the naming convention in this function more uniform. For example `C` to
`LLVMC`.
2025-02-19 13:08:43 -08:00

773 lines
29 KiB
C++

//===- Context.cpp - The Context 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/Context.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/SandboxIR/Function.h"
#include "llvm/SandboxIR/Instruction.h"
#include "llvm/SandboxIR/Module.h"
namespace llvm::sandboxir {
std::unique_ptr<Value> Context::detachLLVMValue(llvm::Value *V) {
std::unique_ptr<Value> Erased;
auto It = LLVMValueToValueMap.find(V);
if (It != LLVMValueToValueMap.end()) {
auto *Val = It->second.release();
Erased = std::unique_ptr<Value>(Val);
LLVMValueToValueMap.erase(It);
}
return Erased;
}
std::unique_ptr<Value> Context::detach(Value *V) {
assert(V->getSubclassID() != Value::ClassID::Constant &&
"Can't detach a constant!");
assert(V->getSubclassID() != Value::ClassID::User && "Can't detach a user!");
return detachLLVMValue(V->Val);
}
Value *Context::registerValue(std::unique_ptr<Value> &&VPtr) {
assert(VPtr->getSubclassID() != Value::ClassID::User &&
"Can't register a user!");
Value *V = VPtr.get();
[[maybe_unused]] auto Pair =
LLVMValueToValueMap.insert({VPtr->Val, std::move(VPtr)});
assert(Pair.second && "Already exists!");
// Track creation of instructions.
// Please note that we don't allow the creation of detached instructions,
// meaning that the instructions need to be inserted into a block upon
// creation. This is why the tracker class combines creation and insertion.
if (auto *I = dyn_cast<Instruction>(V)) {
getTracker().emplaceIfTracking<CreateAndInsertInst>(I);
runCreateInstrCallbacks(I);
}
return V;
}
Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
auto Pair = LLVMValueToValueMap.insert({LLVMV, nullptr});
auto It = Pair.first;
if (!Pair.second)
return It->second.get();
// Instruction
if (auto *LLVMI = dyn_cast<llvm::Instruction>(LLVMV)) {
switch (LLVMI->getOpcode()) {
case llvm::Instruction::VAArg: {
auto *LLVMVAArg = cast<llvm::VAArgInst>(LLVMV);
It->second = std::unique_ptr<VAArgInst>(new VAArgInst(LLVMVAArg, *this));
return It->second.get();
}
case llvm::Instruction::Freeze: {
auto *LLVMFreeze = cast<llvm::FreezeInst>(LLVMV);
It->second =
std::unique_ptr<FreezeInst>(new FreezeInst(LLVMFreeze, *this));
return It->second.get();
}
case llvm::Instruction::Fence: {
auto *LLVMFence = cast<llvm::FenceInst>(LLVMV);
It->second = std::unique_ptr<FenceInst>(new FenceInst(LLVMFence, *this));
return It->second.get();
}
case llvm::Instruction::Select: {
auto *LLVMSel = cast<llvm::SelectInst>(LLVMV);
It->second = std::unique_ptr<SelectInst>(new SelectInst(LLVMSel, *this));
return It->second.get();
}
case llvm::Instruction::ExtractElement: {
auto *LLVMIns = cast<llvm::ExtractElementInst>(LLVMV);
It->second = std::unique_ptr<ExtractElementInst>(
new ExtractElementInst(LLVMIns, *this));
return It->second.get();
}
case llvm::Instruction::InsertElement: {
auto *LLVMIns = cast<llvm::InsertElementInst>(LLVMV);
It->second = std::unique_ptr<InsertElementInst>(
new InsertElementInst(LLVMIns, *this));
return It->second.get();
}
case llvm::Instruction::ShuffleVector: {
auto *LLVMIns = cast<llvm::ShuffleVectorInst>(LLVMV);
It->second = std::unique_ptr<ShuffleVectorInst>(
new ShuffleVectorInst(LLVMIns, *this));
return It->second.get();
}
case llvm::Instruction::ExtractValue: {
auto *LLVMIns = cast<llvm::ExtractValueInst>(LLVMV);
It->second = std::unique_ptr<ExtractValueInst>(
new ExtractValueInst(LLVMIns, *this));
return It->second.get();
}
case llvm::Instruction::InsertValue: {
auto *LLVMIns = cast<llvm::InsertValueInst>(LLVMV);
It->second =
std::unique_ptr<InsertValueInst>(new InsertValueInst(LLVMIns, *this));
return It->second.get();
}
case llvm::Instruction::Br: {
auto *LLVMBr = cast<llvm::BranchInst>(LLVMV);
It->second = std::unique_ptr<BranchInst>(new BranchInst(LLVMBr, *this));
return It->second.get();
}
case llvm::Instruction::Load: {
auto *LLVMLd = cast<llvm::LoadInst>(LLVMV);
It->second = std::unique_ptr<LoadInst>(new LoadInst(LLVMLd, *this));
return It->second.get();
}
case llvm::Instruction::Store: {
auto *LLVMSt = cast<llvm::StoreInst>(LLVMV);
It->second = std::unique_ptr<StoreInst>(new StoreInst(LLVMSt, *this));
return It->second.get();
}
case llvm::Instruction::Ret: {
auto *LLVMRet = cast<llvm::ReturnInst>(LLVMV);
It->second = std::unique_ptr<ReturnInst>(new ReturnInst(LLVMRet, *this));
return It->second.get();
}
case llvm::Instruction::Call: {
auto *LLVMCall = cast<llvm::CallInst>(LLVMV);
It->second = std::unique_ptr<CallInst>(new CallInst(LLVMCall, *this));
return It->second.get();
}
case llvm::Instruction::Invoke: {
auto *LLVMInvoke = cast<llvm::InvokeInst>(LLVMV);
It->second =
std::unique_ptr<InvokeInst>(new InvokeInst(LLVMInvoke, *this));
return It->second.get();
}
case llvm::Instruction::CallBr: {
auto *LLVMCallBr = cast<llvm::CallBrInst>(LLVMV);
It->second =
std::unique_ptr<CallBrInst>(new CallBrInst(LLVMCallBr, *this));
return It->second.get();
}
case llvm::Instruction::LandingPad: {
auto *LLVMLPad = cast<llvm::LandingPadInst>(LLVMV);
It->second =
std::unique_ptr<LandingPadInst>(new LandingPadInst(LLVMLPad, *this));
return It->second.get();
}
case llvm::Instruction::CatchPad: {
auto *LLVMCPI = cast<llvm::CatchPadInst>(LLVMV);
It->second =
std::unique_ptr<CatchPadInst>(new CatchPadInst(LLVMCPI, *this));
return It->second.get();
}
case llvm::Instruction::CleanupPad: {
auto *LLVMCPI = cast<llvm::CleanupPadInst>(LLVMV);
It->second =
std::unique_ptr<CleanupPadInst>(new CleanupPadInst(LLVMCPI, *this));
return It->second.get();
}
case llvm::Instruction::CatchRet: {
auto *LLVMCRI = cast<llvm::CatchReturnInst>(LLVMV);
It->second =
std::unique_ptr<CatchReturnInst>(new CatchReturnInst(LLVMCRI, *this));
return It->second.get();
}
case llvm::Instruction::CleanupRet: {
auto *LLVMCRI = cast<llvm::CleanupReturnInst>(LLVMV);
It->second = std::unique_ptr<CleanupReturnInst>(
new CleanupReturnInst(LLVMCRI, *this));
return It->second.get();
}
case llvm::Instruction::GetElementPtr: {
auto *LLVMGEP = cast<llvm::GetElementPtrInst>(LLVMV);
It->second = std::unique_ptr<GetElementPtrInst>(
new GetElementPtrInst(LLVMGEP, *this));
return It->second.get();
}
case llvm::Instruction::CatchSwitch: {
auto *LLVMCatchSwitchInst = cast<llvm::CatchSwitchInst>(LLVMV);
It->second = std::unique_ptr<CatchSwitchInst>(
new CatchSwitchInst(LLVMCatchSwitchInst, *this));
return It->second.get();
}
case llvm::Instruction::Resume: {
auto *LLVMResumeInst = cast<llvm::ResumeInst>(LLVMV);
It->second =
std::unique_ptr<ResumeInst>(new ResumeInst(LLVMResumeInst, *this));
return It->second.get();
}
case llvm::Instruction::Switch: {
auto *LLVMSwitchInst = cast<llvm::SwitchInst>(LLVMV);
It->second =
std::unique_ptr<SwitchInst>(new SwitchInst(LLVMSwitchInst, *this));
return It->second.get();
}
case llvm::Instruction::FNeg: {
auto *LLVMUnaryOperator = cast<llvm::UnaryOperator>(LLVMV);
It->second = std::unique_ptr<UnaryOperator>(
new UnaryOperator(LLVMUnaryOperator, *this));
return It->second.get();
}
case llvm::Instruction::Add:
case llvm::Instruction::FAdd:
case llvm::Instruction::Sub:
case llvm::Instruction::FSub:
case llvm::Instruction::Mul:
case llvm::Instruction::FMul:
case llvm::Instruction::UDiv:
case llvm::Instruction::SDiv:
case llvm::Instruction::FDiv:
case llvm::Instruction::URem:
case llvm::Instruction::SRem:
case llvm::Instruction::FRem:
case llvm::Instruction::Shl:
case llvm::Instruction::LShr:
case llvm::Instruction::AShr:
case llvm::Instruction::And:
case llvm::Instruction::Or:
case llvm::Instruction::Xor: {
auto *LLVMBinaryOperator = cast<llvm::BinaryOperator>(LLVMV);
It->second = std::unique_ptr<BinaryOperator>(
new BinaryOperator(LLVMBinaryOperator, *this));
return It->second.get();
}
case llvm::Instruction::AtomicRMW: {
auto *LLVMAtomicRMW = cast<llvm::AtomicRMWInst>(LLVMV);
It->second = std::unique_ptr<AtomicRMWInst>(
new AtomicRMWInst(LLVMAtomicRMW, *this));
return It->second.get();
}
case llvm::Instruction::AtomicCmpXchg: {
auto *LLVMAtomicCmpXchg = cast<llvm::AtomicCmpXchgInst>(LLVMV);
It->second = std::unique_ptr<AtomicCmpXchgInst>(
new AtomicCmpXchgInst(LLVMAtomicCmpXchg, *this));
return It->second.get();
}
case llvm::Instruction::Alloca: {
auto *LLVMAlloca = cast<llvm::AllocaInst>(LLVMV);
It->second =
std::unique_ptr<AllocaInst>(new AllocaInst(LLVMAlloca, *this));
return It->second.get();
}
case llvm::Instruction::ZExt:
case llvm::Instruction::SExt:
case llvm::Instruction::FPToUI:
case llvm::Instruction::FPToSI:
case llvm::Instruction::FPExt:
case llvm::Instruction::PtrToInt:
case llvm::Instruction::IntToPtr:
case llvm::Instruction::SIToFP:
case llvm::Instruction::UIToFP:
case llvm::Instruction::Trunc:
case llvm::Instruction::FPTrunc:
case llvm::Instruction::BitCast:
case llvm::Instruction::AddrSpaceCast: {
auto *LLVMCast = cast<llvm::CastInst>(LLVMV);
It->second = std::unique_ptr<CastInst>(new CastInst(LLVMCast, *this));
return It->second.get();
}
case llvm::Instruction::PHI: {
auto *LLVMPhi = cast<llvm::PHINode>(LLVMV);
It->second = std::unique_ptr<PHINode>(new PHINode(LLVMPhi, *this));
return It->second.get();
}
case llvm::Instruction::ICmp: {
auto *LLVMICmp = cast<llvm::ICmpInst>(LLVMV);
It->second = std::unique_ptr<ICmpInst>(new ICmpInst(LLVMICmp, *this));
return It->second.get();
}
case llvm::Instruction::FCmp: {
auto *LLVMFCmp = cast<llvm::FCmpInst>(LLVMV);
It->second = std::unique_ptr<FCmpInst>(new FCmpInst(LLVMFCmp, *this));
return It->second.get();
}
case llvm::Instruction::Unreachable: {
auto *LLVMUnreachable = cast<llvm::UnreachableInst>(LLVMV);
It->second = std::unique_ptr<UnreachableInst>(
new UnreachableInst(LLVMUnreachable, *this));
return It->second.get();
}
default:
break;
}
It->second = std::unique_ptr<OpaqueInst>(
new OpaqueInst(cast<llvm::Instruction>(LLVMV), *this));
return It->second.get();
}
// Constant
if (auto *LLVMC = dyn_cast<llvm::Constant>(LLVMV)) {
switch (LLVMC->getValueID()) {
case llvm::Value::ConstantIntVal:
It->second = std::unique_ptr<ConstantInt>(
new ConstantInt(cast<llvm::ConstantInt>(LLVMC), *this));
return It->second.get();
case llvm::Value::ConstantFPVal:
It->second = std::unique_ptr<ConstantFP>(
new ConstantFP(cast<llvm::ConstantFP>(LLVMC), *this));
return It->second.get();
case llvm::Value::BlockAddressVal:
It->second = std::unique_ptr<BlockAddress>(
new BlockAddress(cast<llvm::BlockAddress>(LLVMC), *this));
return It->second.get();
case llvm::Value::ConstantTokenNoneVal:
It->second = std::unique_ptr<ConstantTokenNone>(
new ConstantTokenNone(cast<llvm::ConstantTokenNone>(LLVMC), *this));
return It->second.get();
case llvm::Value::ConstantAggregateZeroVal: {
auto *CAZ = cast<llvm::ConstantAggregateZero>(LLVMC);
It->second = std::unique_ptr<ConstantAggregateZero>(
new ConstantAggregateZero(CAZ, *this));
auto *Ret = It->second.get();
// Must create sandboxir for elements.
auto EC = CAZ->getElementCount();
if (EC.isFixed()) {
for (auto ElmIdx : seq<unsigned>(0, EC.getFixedValue()))
getOrCreateValueInternal(CAZ->getElementValue(ElmIdx), CAZ);
}
return Ret;
}
case llvm::Value::ConstantPointerNullVal:
It->second = std::unique_ptr<ConstantPointerNull>(new ConstantPointerNull(
cast<llvm::ConstantPointerNull>(LLVMC), *this));
return It->second.get();
case llvm::Value::PoisonValueVal:
It->second = std::unique_ptr<PoisonValue>(
new PoisonValue(cast<llvm::PoisonValue>(LLVMC), *this));
return It->second.get();
case llvm::Value::UndefValueVal:
It->second = std::unique_ptr<UndefValue>(
new UndefValue(cast<llvm::UndefValue>(LLVMC), *this));
return It->second.get();
case llvm::Value::DSOLocalEquivalentVal: {
auto *DSOLE = cast<llvm::DSOLocalEquivalent>(LLVMC);
It->second = std::unique_ptr<DSOLocalEquivalent>(
new DSOLocalEquivalent(DSOLE, *this));
auto *Ret = It->second.get();
getOrCreateValueInternal(DSOLE->getGlobalValue(), DSOLE);
return Ret;
}
case llvm::Value::ConstantArrayVal:
It->second = std::unique_ptr<ConstantArray>(
new ConstantArray(cast<llvm::ConstantArray>(LLVMC), *this));
break;
case llvm::Value::ConstantStructVal:
It->second = std::unique_ptr<ConstantStruct>(
new ConstantStruct(cast<llvm::ConstantStruct>(LLVMC), *this));
break;
case llvm::Value::ConstantVectorVal:
It->second = std::unique_ptr<ConstantVector>(
new ConstantVector(cast<llvm::ConstantVector>(LLVMC), *this));
break;
case llvm::Value::FunctionVal:
It->second = std::unique_ptr<Function>(
new Function(cast<llvm::Function>(LLVMC), *this));
break;
case llvm::Value::GlobalIFuncVal:
It->second = std::unique_ptr<GlobalIFunc>(
new GlobalIFunc(cast<llvm::GlobalIFunc>(LLVMC), *this));
break;
case llvm::Value::GlobalVariableVal:
It->second = std::unique_ptr<GlobalVariable>(
new GlobalVariable(cast<llvm::GlobalVariable>(LLVMC), *this));
break;
case llvm::Value::GlobalAliasVal:
It->second = std::unique_ptr<GlobalAlias>(
new GlobalAlias(cast<llvm::GlobalAlias>(LLVMC), *this));
break;
case llvm::Value::NoCFIValueVal:
It->second = std::unique_ptr<NoCFIValue>(
new NoCFIValue(cast<llvm::NoCFIValue>(LLVMC), *this));
break;
case llvm::Value::ConstantPtrAuthVal:
It->second = std::unique_ptr<ConstantPtrAuth>(
new ConstantPtrAuth(cast<llvm::ConstantPtrAuth>(LLVMC), *this));
break;
case llvm::Value::ConstantExprVal:
It->second = std::unique_ptr<ConstantExpr>(
new ConstantExpr(cast<llvm::ConstantExpr>(LLVMC), *this));
break;
default:
It->second = std::unique_ptr<Constant>(new Constant(LLVMC, *this));
break;
}
auto *NewC = It->second.get();
for (llvm::Value *COp : LLVMC->operands())
getOrCreateValueInternal(COp, LLVMC);
return NewC;
}
// Argument
if (auto *LLVMArg = dyn_cast<llvm::Argument>(LLVMV)) {
It->second = std::unique_ptr<Argument>(new Argument(LLVMArg, *this));
return It->second.get();
}
// BasicBlock
if (auto *LLVMBB = dyn_cast<llvm::BasicBlock>(LLVMV)) {
assert(isa<llvm::BlockAddress>(U) &&
"This won't create a SBBB, don't call this function directly!");
if (auto *SBBB = getValue(LLVMBB))
return SBBB;
return nullptr;
}
// Metadata
if (auto *LLVMMD = dyn_cast<llvm::MetadataAsValue>(LLVMV)) {
It->second = std::unique_ptr<OpaqueValue>(new OpaqueValue(LLVMMD, *this));
return It->second.get();
}
// InlineAsm
if (auto *LLVMAsm = dyn_cast<llvm::InlineAsm>(LLVMV)) {
It->second = std::unique_ptr<OpaqueValue>(new OpaqueValue(LLVMAsm, *this));
return It->second.get();
}
llvm_unreachable("Unhandled LLVMV type!");
}
Argument *Context::getOrCreateArgument(llvm::Argument *LLVMArg) {
auto Pair = LLVMValueToValueMap.insert({LLVMArg, nullptr});
auto It = Pair.first;
if (Pair.second) {
It->second = std::unique_ptr<Argument>(new Argument(LLVMArg, *this));
return cast<Argument>(It->second.get());
}
return cast<Argument>(It->second.get());
}
Constant *Context::getOrCreateConstant(llvm::Constant *LLVMC) {
return cast<Constant>(getOrCreateValueInternal(LLVMC, 0));
}
BasicBlock *Context::createBasicBlock(llvm::BasicBlock *LLVMBB) {
assert(getValue(LLVMBB) == nullptr && "Already exists!");
auto NewBBPtr = std::unique_ptr<BasicBlock>(new BasicBlock(LLVMBB, *this));
auto *BB = cast<BasicBlock>(registerValue(std::move(NewBBPtr)));
// Create SandboxIR for BB's body.
BB->buildBasicBlockFromLLVMIR(LLVMBB);
return BB;
}
VAArgInst *Context::createVAArgInst(llvm::VAArgInst *SI) {
auto NewPtr = std::unique_ptr<VAArgInst>(new VAArgInst(SI, *this));
return cast<VAArgInst>(registerValue(std::move(NewPtr)));
}
FreezeInst *Context::createFreezeInst(llvm::FreezeInst *SI) {
auto NewPtr = std::unique_ptr<FreezeInst>(new FreezeInst(SI, *this));
return cast<FreezeInst>(registerValue(std::move(NewPtr)));
}
FenceInst *Context::createFenceInst(llvm::FenceInst *SI) {
auto NewPtr = std::unique_ptr<FenceInst>(new FenceInst(SI, *this));
return cast<FenceInst>(registerValue(std::move(NewPtr)));
}
SelectInst *Context::createSelectInst(llvm::SelectInst *SI) {
auto NewPtr = std::unique_ptr<SelectInst>(new SelectInst(SI, *this));
return cast<SelectInst>(registerValue(std::move(NewPtr)));
}
ExtractElementInst *
Context::createExtractElementInst(llvm::ExtractElementInst *EEI) {
auto NewPtr =
std::unique_ptr<ExtractElementInst>(new ExtractElementInst(EEI, *this));
return cast<ExtractElementInst>(registerValue(std::move(NewPtr)));
}
InsertElementInst *
Context::createInsertElementInst(llvm::InsertElementInst *IEI) {
auto NewPtr =
std::unique_ptr<InsertElementInst>(new InsertElementInst(IEI, *this));
return cast<InsertElementInst>(registerValue(std::move(NewPtr)));
}
ShuffleVectorInst *
Context::createShuffleVectorInst(llvm::ShuffleVectorInst *SVI) {
auto NewPtr =
std::unique_ptr<ShuffleVectorInst>(new ShuffleVectorInst(SVI, *this));
return cast<ShuffleVectorInst>(registerValue(std::move(NewPtr)));
}
ExtractValueInst *Context::createExtractValueInst(llvm::ExtractValueInst *EVI) {
auto NewPtr =
std::unique_ptr<ExtractValueInst>(new ExtractValueInst(EVI, *this));
return cast<ExtractValueInst>(registerValue(std::move(NewPtr)));
}
InsertValueInst *Context::createInsertValueInst(llvm::InsertValueInst *IVI) {
auto NewPtr =
std::unique_ptr<InsertValueInst>(new InsertValueInst(IVI, *this));
return cast<InsertValueInst>(registerValue(std::move(NewPtr)));
}
BranchInst *Context::createBranchInst(llvm::BranchInst *BI) {
auto NewPtr = std::unique_ptr<BranchInst>(new BranchInst(BI, *this));
return cast<BranchInst>(registerValue(std::move(NewPtr)));
}
LoadInst *Context::createLoadInst(llvm::LoadInst *LI) {
auto NewPtr = std::unique_ptr<LoadInst>(new LoadInst(LI, *this));
return cast<LoadInst>(registerValue(std::move(NewPtr)));
}
StoreInst *Context::createStoreInst(llvm::StoreInst *SI) {
auto NewPtr = std::unique_ptr<StoreInst>(new StoreInst(SI, *this));
return cast<StoreInst>(registerValue(std::move(NewPtr)));
}
ReturnInst *Context::createReturnInst(llvm::ReturnInst *I) {
auto NewPtr = std::unique_ptr<ReturnInst>(new ReturnInst(I, *this));
return cast<ReturnInst>(registerValue(std::move(NewPtr)));
}
CallInst *Context::createCallInst(llvm::CallInst *I) {
auto NewPtr = std::unique_ptr<CallInst>(new CallInst(I, *this));
return cast<CallInst>(registerValue(std::move(NewPtr)));
}
InvokeInst *Context::createInvokeInst(llvm::InvokeInst *I) {
auto NewPtr = std::unique_ptr<InvokeInst>(new InvokeInst(I, *this));
return cast<InvokeInst>(registerValue(std::move(NewPtr)));
}
CallBrInst *Context::createCallBrInst(llvm::CallBrInst *I) {
auto NewPtr = std::unique_ptr<CallBrInst>(new CallBrInst(I, *this));
return cast<CallBrInst>(registerValue(std::move(NewPtr)));
}
UnreachableInst *Context::createUnreachableInst(llvm::UnreachableInst *UI) {
auto NewPtr =
std::unique_ptr<UnreachableInst>(new UnreachableInst(UI, *this));
return cast<UnreachableInst>(registerValue(std::move(NewPtr)));
}
LandingPadInst *Context::createLandingPadInst(llvm::LandingPadInst *I) {
auto NewPtr = std::unique_ptr<LandingPadInst>(new LandingPadInst(I, *this));
return cast<LandingPadInst>(registerValue(std::move(NewPtr)));
}
CatchPadInst *Context::createCatchPadInst(llvm::CatchPadInst *I) {
auto NewPtr = std::unique_ptr<CatchPadInst>(new CatchPadInst(I, *this));
return cast<CatchPadInst>(registerValue(std::move(NewPtr)));
}
CleanupPadInst *Context::createCleanupPadInst(llvm::CleanupPadInst *I) {
auto NewPtr = std::unique_ptr<CleanupPadInst>(new CleanupPadInst(I, *this));
return cast<CleanupPadInst>(registerValue(std::move(NewPtr)));
}
CatchReturnInst *Context::createCatchReturnInst(llvm::CatchReturnInst *I) {
auto NewPtr = std::unique_ptr<CatchReturnInst>(new CatchReturnInst(I, *this));
return cast<CatchReturnInst>(registerValue(std::move(NewPtr)));
}
CleanupReturnInst *
Context::createCleanupReturnInst(llvm::CleanupReturnInst *I) {
auto NewPtr =
std::unique_ptr<CleanupReturnInst>(new CleanupReturnInst(I, *this));
return cast<CleanupReturnInst>(registerValue(std::move(NewPtr)));
}
GetElementPtrInst *
Context::createGetElementPtrInst(llvm::GetElementPtrInst *I) {
auto NewPtr =
std::unique_ptr<GetElementPtrInst>(new GetElementPtrInst(I, *this));
return cast<GetElementPtrInst>(registerValue(std::move(NewPtr)));
}
CatchSwitchInst *Context::createCatchSwitchInst(llvm::CatchSwitchInst *I) {
auto NewPtr = std::unique_ptr<CatchSwitchInst>(new CatchSwitchInst(I, *this));
return cast<CatchSwitchInst>(registerValue(std::move(NewPtr)));
}
ResumeInst *Context::createResumeInst(llvm::ResumeInst *I) {
auto NewPtr = std::unique_ptr<ResumeInst>(new ResumeInst(I, *this));
return cast<ResumeInst>(registerValue(std::move(NewPtr)));
}
SwitchInst *Context::createSwitchInst(llvm::SwitchInst *I) {
auto NewPtr = std::unique_ptr<SwitchInst>(new SwitchInst(I, *this));
return cast<SwitchInst>(registerValue(std::move(NewPtr)));
}
UnaryOperator *Context::createUnaryOperator(llvm::UnaryOperator *I) {
auto NewPtr = std::unique_ptr<UnaryOperator>(new UnaryOperator(I, *this));
return cast<UnaryOperator>(registerValue(std::move(NewPtr)));
}
BinaryOperator *Context::createBinaryOperator(llvm::BinaryOperator *I) {
auto NewPtr = std::unique_ptr<BinaryOperator>(new BinaryOperator(I, *this));
return cast<BinaryOperator>(registerValue(std::move(NewPtr)));
}
AtomicRMWInst *Context::createAtomicRMWInst(llvm::AtomicRMWInst *I) {
auto NewPtr = std::unique_ptr<AtomicRMWInst>(new AtomicRMWInst(I, *this));
return cast<AtomicRMWInst>(registerValue(std::move(NewPtr)));
}
AtomicCmpXchgInst *
Context::createAtomicCmpXchgInst(llvm::AtomicCmpXchgInst *I) {
auto NewPtr =
std::unique_ptr<AtomicCmpXchgInst>(new AtomicCmpXchgInst(I, *this));
return cast<AtomicCmpXchgInst>(registerValue(std::move(NewPtr)));
}
AllocaInst *Context::createAllocaInst(llvm::AllocaInst *I) {
auto NewPtr = std::unique_ptr<AllocaInst>(new AllocaInst(I, *this));
return cast<AllocaInst>(registerValue(std::move(NewPtr)));
}
CastInst *Context::createCastInst(llvm::CastInst *I) {
auto NewPtr = std::unique_ptr<CastInst>(new CastInst(I, *this));
return cast<CastInst>(registerValue(std::move(NewPtr)));
}
PHINode *Context::createPHINode(llvm::PHINode *I) {
auto NewPtr = std::unique_ptr<PHINode>(new PHINode(I, *this));
return cast<PHINode>(registerValue(std::move(NewPtr)));
}
ICmpInst *Context::createICmpInst(llvm::ICmpInst *I) {
auto NewPtr = std::unique_ptr<ICmpInst>(new ICmpInst(I, *this));
return cast<ICmpInst>(registerValue(std::move(NewPtr)));
}
FCmpInst *Context::createFCmpInst(llvm::FCmpInst *I) {
auto NewPtr = std::unique_ptr<FCmpInst>(new FCmpInst(I, *this));
return cast<FCmpInst>(registerValue(std::move(NewPtr)));
}
Value *Context::getValue(llvm::Value *V) const {
auto It = LLVMValueToValueMap.find(V);
if (It != LLVMValueToValueMap.end())
return It->second.get();
return nullptr;
}
Context::Context(LLVMContext &LLVMCtx)
: LLVMCtx(LLVMCtx), IRTracker(*this),
LLVMIRBuilder(LLVMCtx, ConstantFolder()) {}
Context::~Context() {}
void Context::clear() {
// TODO: Ideally we should clear only function-scope objects, and keep global
// objects, like Constants to avoid recreating them.
LLVMValueToValueMap.clear();
}
Module *Context::getModule(llvm::Module *LLVMM) const {
auto It = LLVMModuleToModuleMap.find(LLVMM);
if (It != LLVMModuleToModuleMap.end())
return It->second.get();
return nullptr;
}
Module *Context::getOrCreateModule(llvm::Module *LLVMM) {
auto Pair = LLVMModuleToModuleMap.insert({LLVMM, nullptr});
auto It = Pair.first;
if (!Pair.second)
return It->second.get();
It->second = std::unique_ptr<Module>(new Module(*LLVMM, *this));
return It->second.get();
}
Function *Context::createFunction(llvm::Function *F) {
// Create the module if needed before we create the new sandboxir::Function.
// Note: this won't fully populate the module. The only globals that will be
// available will be the ones being used within the function.
getOrCreateModule(F->getParent());
// There may be a function declaration already defined. Regardless destroy it.
if (Function *ExistingF = cast_or_null<Function>(getValue(F)))
detach(ExistingF);
auto NewFPtr = std::unique_ptr<Function>(new Function(F, *this));
auto *SBF = cast<Function>(registerValue(std::move(NewFPtr)));
// Create arguments.
for (auto &Arg : F->args())
getOrCreateArgument(&Arg);
// Create BBs.
for (auto &BB : *F)
createBasicBlock(&BB);
return SBF;
}
Module *Context::createModule(llvm::Module *LLVMM) {
auto *M = getOrCreateModule(LLVMM);
// Create the functions.
for (auto &LLVMF : *LLVMM)
createFunction(&LLVMF);
// Create globals.
for (auto &Global : LLVMM->globals())
getOrCreateValue(&Global);
// Create aliases.
for (auto &Alias : LLVMM->aliases())
getOrCreateValue(&Alias);
// Create ifuncs.
for (auto &IFunc : LLVMM->ifuncs())
getOrCreateValue(&IFunc);
return M;
}
void Context::runEraseInstrCallbacks(Instruction *I) {
for (const auto &CBEntry : EraseInstrCallbacks)
CBEntry.second(I);
}
void Context::runCreateInstrCallbacks(Instruction *I) {
for (auto &CBEntry : CreateInstrCallbacks)
CBEntry.second(I);
}
void Context::runMoveInstrCallbacks(Instruction *I, const BBIterator &WhereIt) {
for (auto &CBEntry : MoveInstrCallbacks)
CBEntry.second(I, WhereIt);
}
void Context::runSetUseCallbacks(const Use &U, Value *NewSrc) {
for (auto &CBEntry : SetUseCallbacks)
CBEntry.second(U, NewSrc);
}
// An arbitrary limit, to check for accidental misuse. We expect a small number
// of callbacks to be registered at a time, but we can increase this number if
// we discover we needed more.
[[maybe_unused]] static constexpr int MaxRegisteredCallbacks = 16;
Context::CallbackID Context::registerEraseInstrCallback(EraseInstrCallback CB) {
assert(EraseInstrCallbacks.size() <= MaxRegisteredCallbacks &&
"EraseInstrCallbacks size limit exceeded");
CallbackID ID{NextCallbackID++};
EraseInstrCallbacks[ID] = CB;
return ID;
}
void Context::unregisterEraseInstrCallback(CallbackID ID) {
[[maybe_unused]] bool Erased = EraseInstrCallbacks.erase(ID);
assert(Erased &&
"Callback ID not found in EraseInstrCallbacks during deregistration");
}
Context::CallbackID
Context::registerCreateInstrCallback(CreateInstrCallback CB) {
assert(CreateInstrCallbacks.size() <= MaxRegisteredCallbacks &&
"CreateInstrCallbacks size limit exceeded");
CallbackID ID{NextCallbackID++};
CreateInstrCallbacks[ID] = CB;
return ID;
}
void Context::unregisterCreateInstrCallback(CallbackID ID) {
[[maybe_unused]] bool Erased = CreateInstrCallbacks.erase(ID);
assert(Erased &&
"Callback ID not found in CreateInstrCallbacks during deregistration");
}
Context::CallbackID Context::registerMoveInstrCallback(MoveInstrCallback CB) {
assert(MoveInstrCallbacks.size() <= MaxRegisteredCallbacks &&
"MoveInstrCallbacks size limit exceeded");
CallbackID ID{NextCallbackID++};
MoveInstrCallbacks[ID] = CB;
return ID;
}
void Context::unregisterMoveInstrCallback(CallbackID ID) {
[[maybe_unused]] bool Erased = MoveInstrCallbacks.erase(ID);
assert(Erased &&
"Callback ID not found in MoveInstrCallbacks during deregistration");
}
Context::CallbackID Context::registerSetUseCallback(SetUseCallback CB) {
assert(SetUseCallbacks.size() <= MaxRegisteredCallbacks &&
"SetUseCallbacks size limit exceeded");
CallbackID ID{NextCallbackID++};
SetUseCallbacks[ID] = CB;
return ID;
}
void Context::unregisterSetUseCallback(CallbackID ID) {
[[maybe_unused]] bool Erased = SetUseCallbacks.erase(ID);
assert(Erased &&
"Callback ID not found in SetUseCallbacks during deregistration");
}
} // namespace llvm::sandboxir