Path: blob/main/contrib/llvm-project/llvm/lib/SandboxIR/Context.cpp
213766 views
//===- Context.cpp - The Context class of Sandbox IR ----------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/SandboxIR/Context.h"9#include "llvm/IR/InlineAsm.h"10#include "llvm/SandboxIR/Function.h"11#include "llvm/SandboxIR/Instruction.h"12#include "llvm/SandboxIR/Module.h"1314namespace llvm::sandboxir {1516std::unique_ptr<Value> Context::detachLLVMValue(llvm::Value *V) {17std::unique_ptr<Value> Erased;18auto It = LLVMValueToValueMap.find(V);19if (It != LLVMValueToValueMap.end()) {20auto *Val = It->second.release();21Erased = std::unique_ptr<Value>(Val);22LLVMValueToValueMap.erase(It);23}24return Erased;25}2627std::unique_ptr<Value> Context::detach(Value *V) {28assert(V->getSubclassID() != Value::ClassID::Constant &&29"Can't detach a constant!");30assert(V->getSubclassID() != Value::ClassID::User && "Can't detach a user!");31return detachLLVMValue(V->Val);32}3334Value *Context::registerValue(std::unique_ptr<Value> &&VPtr) {35assert(VPtr->getSubclassID() != Value::ClassID::User &&36"Can't register a user!");3738Value *V = VPtr.get();39[[maybe_unused]] auto Pair =40LLVMValueToValueMap.insert({VPtr->Val, std::move(VPtr)});41assert(Pair.second && "Already exists!");4243// Track creation of instructions.44// Please note that we don't allow the creation of detached instructions,45// meaning that the instructions need to be inserted into a block upon46// creation. This is why the tracker class combines creation and insertion.47if (auto *I = dyn_cast<Instruction>(V)) {48getTracker().emplaceIfTracking<CreateAndInsertInst>(I);49runCreateInstrCallbacks(I);50}5152return V;53}5455Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {56auto Pair = LLVMValueToValueMap.try_emplace(LLVMV);57auto It = Pair.first;58if (!Pair.second)59return It->second.get();6061// Instruction62if (auto *LLVMI = dyn_cast<llvm::Instruction>(LLVMV)) {63switch (LLVMI->getOpcode()) {64case llvm::Instruction::VAArg: {65auto *LLVMVAArg = cast<llvm::VAArgInst>(LLVMV);66It->second = std::unique_ptr<VAArgInst>(new VAArgInst(LLVMVAArg, *this));67return It->second.get();68}69case llvm::Instruction::Freeze: {70auto *LLVMFreeze = cast<llvm::FreezeInst>(LLVMV);71It->second =72std::unique_ptr<FreezeInst>(new FreezeInst(LLVMFreeze, *this));73return It->second.get();74}75case llvm::Instruction::Fence: {76auto *LLVMFence = cast<llvm::FenceInst>(LLVMV);77It->second = std::unique_ptr<FenceInst>(new FenceInst(LLVMFence, *this));78return It->second.get();79}80case llvm::Instruction::Select: {81auto *LLVMSel = cast<llvm::SelectInst>(LLVMV);82It->second = std::unique_ptr<SelectInst>(new SelectInst(LLVMSel, *this));83return It->second.get();84}85case llvm::Instruction::ExtractElement: {86auto *LLVMIns = cast<llvm::ExtractElementInst>(LLVMV);87It->second = std::unique_ptr<ExtractElementInst>(88new ExtractElementInst(LLVMIns, *this));89return It->second.get();90}91case llvm::Instruction::InsertElement: {92auto *LLVMIns = cast<llvm::InsertElementInst>(LLVMV);93It->second = std::unique_ptr<InsertElementInst>(94new InsertElementInst(LLVMIns, *this));95return It->second.get();96}97case llvm::Instruction::ShuffleVector: {98auto *LLVMIns = cast<llvm::ShuffleVectorInst>(LLVMV);99It->second = std::unique_ptr<ShuffleVectorInst>(100new ShuffleVectorInst(LLVMIns, *this));101return It->second.get();102}103case llvm::Instruction::ExtractValue: {104auto *LLVMIns = cast<llvm::ExtractValueInst>(LLVMV);105It->second = std::unique_ptr<ExtractValueInst>(106new ExtractValueInst(LLVMIns, *this));107return It->second.get();108}109case llvm::Instruction::InsertValue: {110auto *LLVMIns = cast<llvm::InsertValueInst>(LLVMV);111It->second =112std::unique_ptr<InsertValueInst>(new InsertValueInst(LLVMIns, *this));113return It->second.get();114}115case llvm::Instruction::Br: {116auto *LLVMBr = cast<llvm::BranchInst>(LLVMV);117It->second = std::unique_ptr<BranchInst>(new BranchInst(LLVMBr, *this));118return It->second.get();119}120case llvm::Instruction::Load: {121auto *LLVMLd = cast<llvm::LoadInst>(LLVMV);122It->second = std::unique_ptr<LoadInst>(new LoadInst(LLVMLd, *this));123return It->second.get();124}125case llvm::Instruction::Store: {126auto *LLVMSt = cast<llvm::StoreInst>(LLVMV);127It->second = std::unique_ptr<StoreInst>(new StoreInst(LLVMSt, *this));128return It->second.get();129}130case llvm::Instruction::Ret: {131auto *LLVMRet = cast<llvm::ReturnInst>(LLVMV);132It->second = std::unique_ptr<ReturnInst>(new ReturnInst(LLVMRet, *this));133return It->second.get();134}135case llvm::Instruction::Call: {136auto *LLVMCall = cast<llvm::CallInst>(LLVMV);137It->second = std::unique_ptr<CallInst>(new CallInst(LLVMCall, *this));138return It->second.get();139}140case llvm::Instruction::Invoke: {141auto *LLVMInvoke = cast<llvm::InvokeInst>(LLVMV);142It->second =143std::unique_ptr<InvokeInst>(new InvokeInst(LLVMInvoke, *this));144return It->second.get();145}146case llvm::Instruction::CallBr: {147auto *LLVMCallBr = cast<llvm::CallBrInst>(LLVMV);148It->second =149std::unique_ptr<CallBrInst>(new CallBrInst(LLVMCallBr, *this));150return It->second.get();151}152case llvm::Instruction::LandingPad: {153auto *LLVMLPad = cast<llvm::LandingPadInst>(LLVMV);154It->second =155std::unique_ptr<LandingPadInst>(new LandingPadInst(LLVMLPad, *this));156return It->second.get();157}158case llvm::Instruction::CatchPad: {159auto *LLVMCPI = cast<llvm::CatchPadInst>(LLVMV);160It->second =161std::unique_ptr<CatchPadInst>(new CatchPadInst(LLVMCPI, *this));162return It->second.get();163}164case llvm::Instruction::CleanupPad: {165auto *LLVMCPI = cast<llvm::CleanupPadInst>(LLVMV);166It->second =167std::unique_ptr<CleanupPadInst>(new CleanupPadInst(LLVMCPI, *this));168return It->second.get();169}170case llvm::Instruction::CatchRet: {171auto *LLVMCRI = cast<llvm::CatchReturnInst>(LLVMV);172It->second =173std::unique_ptr<CatchReturnInst>(new CatchReturnInst(LLVMCRI, *this));174return It->second.get();175}176case llvm::Instruction::CleanupRet: {177auto *LLVMCRI = cast<llvm::CleanupReturnInst>(LLVMV);178It->second = std::unique_ptr<CleanupReturnInst>(179new CleanupReturnInst(LLVMCRI, *this));180return It->second.get();181}182case llvm::Instruction::GetElementPtr: {183auto *LLVMGEP = cast<llvm::GetElementPtrInst>(LLVMV);184It->second = std::unique_ptr<GetElementPtrInst>(185new GetElementPtrInst(LLVMGEP, *this));186return It->second.get();187}188case llvm::Instruction::CatchSwitch: {189auto *LLVMCatchSwitchInst = cast<llvm::CatchSwitchInst>(LLVMV);190It->second = std::unique_ptr<CatchSwitchInst>(191new CatchSwitchInst(LLVMCatchSwitchInst, *this));192return It->second.get();193}194case llvm::Instruction::Resume: {195auto *LLVMResumeInst = cast<llvm::ResumeInst>(LLVMV);196It->second =197std::unique_ptr<ResumeInst>(new ResumeInst(LLVMResumeInst, *this));198return It->second.get();199}200case llvm::Instruction::Switch: {201auto *LLVMSwitchInst = cast<llvm::SwitchInst>(LLVMV);202It->second =203std::unique_ptr<SwitchInst>(new SwitchInst(LLVMSwitchInst, *this));204return It->second.get();205}206case llvm::Instruction::FNeg: {207auto *LLVMUnaryOperator = cast<llvm::UnaryOperator>(LLVMV);208It->second = std::unique_ptr<UnaryOperator>(209new UnaryOperator(LLVMUnaryOperator, *this));210return It->second.get();211}212case llvm::Instruction::Add:213case llvm::Instruction::FAdd:214case llvm::Instruction::Sub:215case llvm::Instruction::FSub:216case llvm::Instruction::Mul:217case llvm::Instruction::FMul:218case llvm::Instruction::UDiv:219case llvm::Instruction::SDiv:220case llvm::Instruction::FDiv:221case llvm::Instruction::URem:222case llvm::Instruction::SRem:223case llvm::Instruction::FRem:224case llvm::Instruction::Shl:225case llvm::Instruction::LShr:226case llvm::Instruction::AShr:227case llvm::Instruction::And:228case llvm::Instruction::Or:229case llvm::Instruction::Xor: {230auto *LLVMBinaryOperator = cast<llvm::BinaryOperator>(LLVMV);231It->second = std::unique_ptr<BinaryOperator>(232new BinaryOperator(LLVMBinaryOperator, *this));233return It->second.get();234}235case llvm::Instruction::AtomicRMW: {236auto *LLVMAtomicRMW = cast<llvm::AtomicRMWInst>(LLVMV);237It->second = std::unique_ptr<AtomicRMWInst>(238new AtomicRMWInst(LLVMAtomicRMW, *this));239return It->second.get();240}241case llvm::Instruction::AtomicCmpXchg: {242auto *LLVMAtomicCmpXchg = cast<llvm::AtomicCmpXchgInst>(LLVMV);243It->second = std::unique_ptr<AtomicCmpXchgInst>(244new AtomicCmpXchgInst(LLVMAtomicCmpXchg, *this));245return It->second.get();246}247case llvm::Instruction::Alloca: {248auto *LLVMAlloca = cast<llvm::AllocaInst>(LLVMV);249It->second =250std::unique_ptr<AllocaInst>(new AllocaInst(LLVMAlloca, *this));251return It->second.get();252}253case llvm::Instruction::ZExt:254case llvm::Instruction::SExt:255case llvm::Instruction::FPToUI:256case llvm::Instruction::FPToSI:257case llvm::Instruction::FPExt:258case llvm::Instruction::PtrToInt:259case llvm::Instruction::IntToPtr:260case llvm::Instruction::SIToFP:261case llvm::Instruction::UIToFP:262case llvm::Instruction::Trunc:263case llvm::Instruction::FPTrunc:264case llvm::Instruction::BitCast:265case llvm::Instruction::AddrSpaceCast: {266auto *LLVMCast = cast<llvm::CastInst>(LLVMV);267It->second = std::unique_ptr<CastInst>(new CastInst(LLVMCast, *this));268return It->second.get();269}270case llvm::Instruction::PHI: {271auto *LLVMPhi = cast<llvm::PHINode>(LLVMV);272It->second = std::unique_ptr<PHINode>(new PHINode(LLVMPhi, *this));273return It->second.get();274}275case llvm::Instruction::ICmp: {276auto *LLVMICmp = cast<llvm::ICmpInst>(LLVMV);277It->second = std::unique_ptr<ICmpInst>(new ICmpInst(LLVMICmp, *this));278return It->second.get();279}280case llvm::Instruction::FCmp: {281auto *LLVMFCmp = cast<llvm::FCmpInst>(LLVMV);282It->second = std::unique_ptr<FCmpInst>(new FCmpInst(LLVMFCmp, *this));283return It->second.get();284}285case llvm::Instruction::Unreachable: {286auto *LLVMUnreachable = cast<llvm::UnreachableInst>(LLVMV);287It->second = std::unique_ptr<UnreachableInst>(288new UnreachableInst(LLVMUnreachable, *this));289return It->second.get();290}291default:292break;293}294It->second = std::unique_ptr<OpaqueInst>(295new OpaqueInst(cast<llvm::Instruction>(LLVMV), *this));296return It->second.get();297}298// Constant299if (auto *LLVMC = dyn_cast<llvm::Constant>(LLVMV)) {300switch (LLVMC->getValueID()) {301case llvm::Value::ConstantIntVal:302It->second = std::unique_ptr<ConstantInt>(303new ConstantInt(cast<llvm::ConstantInt>(LLVMC), *this));304return It->second.get();305case llvm::Value::ConstantFPVal:306It->second = std::unique_ptr<ConstantFP>(307new ConstantFP(cast<llvm::ConstantFP>(LLVMC), *this));308return It->second.get();309case llvm::Value::BlockAddressVal:310It->second = std::unique_ptr<BlockAddress>(311new BlockAddress(cast<llvm::BlockAddress>(LLVMC), *this));312return It->second.get();313case llvm::Value::ConstantTokenNoneVal:314It->second = std::unique_ptr<ConstantTokenNone>(315new ConstantTokenNone(cast<llvm::ConstantTokenNone>(LLVMC), *this));316return It->second.get();317case llvm::Value::ConstantAggregateZeroVal: {318auto *CAZ = cast<llvm::ConstantAggregateZero>(LLVMC);319It->second = std::unique_ptr<ConstantAggregateZero>(320new ConstantAggregateZero(CAZ, *this));321auto *Ret = It->second.get();322// Must create sandboxir for elements.323auto EC = CAZ->getElementCount();324if (EC.isFixed()) {325for (auto ElmIdx : seq<unsigned>(0, EC.getFixedValue()))326getOrCreateValueInternal(CAZ->getElementValue(ElmIdx), CAZ);327}328return Ret;329}330case llvm::Value::ConstantPointerNullVal:331It->second = std::unique_ptr<ConstantPointerNull>(new ConstantPointerNull(332cast<llvm::ConstantPointerNull>(LLVMC), *this));333return It->second.get();334case llvm::Value::PoisonValueVal:335It->second = std::unique_ptr<PoisonValue>(336new PoisonValue(cast<llvm::PoisonValue>(LLVMC), *this));337return It->second.get();338case llvm::Value::UndefValueVal:339It->second = std::unique_ptr<UndefValue>(340new UndefValue(cast<llvm::UndefValue>(LLVMC), *this));341return It->second.get();342case llvm::Value::DSOLocalEquivalentVal: {343auto *DSOLE = cast<llvm::DSOLocalEquivalent>(LLVMC);344It->second = std::unique_ptr<DSOLocalEquivalent>(345new DSOLocalEquivalent(DSOLE, *this));346auto *Ret = It->second.get();347getOrCreateValueInternal(DSOLE->getGlobalValue(), DSOLE);348return Ret;349}350case llvm::Value::ConstantArrayVal:351It->second = std::unique_ptr<ConstantArray>(352new ConstantArray(cast<llvm::ConstantArray>(LLVMC), *this));353break;354case llvm::Value::ConstantStructVal:355It->second = std::unique_ptr<ConstantStruct>(356new ConstantStruct(cast<llvm::ConstantStruct>(LLVMC), *this));357break;358case llvm::Value::ConstantVectorVal:359It->second = std::unique_ptr<ConstantVector>(360new ConstantVector(cast<llvm::ConstantVector>(LLVMC), *this));361break;362case llvm::Value::ConstantDataArrayVal:363It->second = std::unique_ptr<ConstantDataArray>(364new ConstantDataArray(cast<llvm::ConstantDataArray>(LLVMC), *this));365break;366case llvm::Value::ConstantDataVectorVal:367It->second = std::unique_ptr<ConstantDataVector>(368new ConstantDataVector(cast<llvm::ConstantDataVector>(LLVMC), *this));369break;370case llvm::Value::FunctionVal:371It->second = std::unique_ptr<Function>(372new Function(cast<llvm::Function>(LLVMC), *this));373break;374case llvm::Value::GlobalIFuncVal:375It->second = std::unique_ptr<GlobalIFunc>(376new GlobalIFunc(cast<llvm::GlobalIFunc>(LLVMC), *this));377break;378case llvm::Value::GlobalVariableVal:379It->second = std::unique_ptr<GlobalVariable>(380new GlobalVariable(cast<llvm::GlobalVariable>(LLVMC), *this));381break;382case llvm::Value::GlobalAliasVal:383It->second = std::unique_ptr<GlobalAlias>(384new GlobalAlias(cast<llvm::GlobalAlias>(LLVMC), *this));385break;386case llvm::Value::NoCFIValueVal:387It->second = std::unique_ptr<NoCFIValue>(388new NoCFIValue(cast<llvm::NoCFIValue>(LLVMC), *this));389break;390case llvm::Value::ConstantPtrAuthVal:391It->second = std::unique_ptr<ConstantPtrAuth>(392new ConstantPtrAuth(cast<llvm::ConstantPtrAuth>(LLVMC), *this));393break;394case llvm::Value::ConstantExprVal:395It->second = std::unique_ptr<ConstantExpr>(396new ConstantExpr(cast<llvm::ConstantExpr>(LLVMC), *this));397break;398default:399It->second = std::unique_ptr<Constant>(new Constant(LLVMC, *this));400break;401}402auto *NewC = It->second.get();403for (llvm::Value *COp : LLVMC->operands())404getOrCreateValueInternal(COp, LLVMC);405return NewC;406}407// Argument408if (auto *LLVMArg = dyn_cast<llvm::Argument>(LLVMV)) {409It->second = std::unique_ptr<Argument>(new Argument(LLVMArg, *this));410return It->second.get();411}412// BasicBlock413if (auto *LLVMBB = dyn_cast<llvm::BasicBlock>(LLVMV)) {414assert(isa<llvm::BlockAddress>(U) &&415"This won't create a SBBB, don't call this function directly!");416if (auto *SBBB = getValue(LLVMBB))417return SBBB;418return nullptr;419}420// Metadata421if (auto *LLVMMD = dyn_cast<llvm::MetadataAsValue>(LLVMV)) {422It->second = std::unique_ptr<OpaqueValue>(new OpaqueValue(LLVMMD, *this));423return It->second.get();424}425// InlineAsm426if (auto *LLVMAsm = dyn_cast<llvm::InlineAsm>(LLVMV)) {427It->second = std::unique_ptr<OpaqueValue>(new OpaqueValue(LLVMAsm, *this));428return It->second.get();429}430llvm_unreachable("Unhandled LLVMV type!");431}432433Argument *Context::getOrCreateArgument(llvm::Argument *LLVMArg) {434auto Pair = LLVMValueToValueMap.try_emplace(LLVMArg);435auto It = Pair.first;436if (Pair.second) {437It->second = std::unique_ptr<Argument>(new Argument(LLVMArg, *this));438return cast<Argument>(It->second.get());439}440return cast<Argument>(It->second.get());441}442443Constant *Context::getOrCreateConstant(llvm::Constant *LLVMC) {444return cast<Constant>(getOrCreateValueInternal(LLVMC, 0));445}446447BasicBlock *Context::createBasicBlock(llvm::BasicBlock *LLVMBB) {448assert(getValue(LLVMBB) == nullptr && "Already exists!");449auto NewBBPtr = std::unique_ptr<BasicBlock>(new BasicBlock(LLVMBB, *this));450auto *BB = cast<BasicBlock>(registerValue(std::move(NewBBPtr)));451// Create SandboxIR for BB's body.452BB->buildBasicBlockFromLLVMIR(LLVMBB);453return BB;454}455456VAArgInst *Context::createVAArgInst(llvm::VAArgInst *SI) {457auto NewPtr = std::unique_ptr<VAArgInst>(new VAArgInst(SI, *this));458return cast<VAArgInst>(registerValue(std::move(NewPtr)));459}460461FreezeInst *Context::createFreezeInst(llvm::FreezeInst *SI) {462auto NewPtr = std::unique_ptr<FreezeInst>(new FreezeInst(SI, *this));463return cast<FreezeInst>(registerValue(std::move(NewPtr)));464}465466FenceInst *Context::createFenceInst(llvm::FenceInst *SI) {467auto NewPtr = std::unique_ptr<FenceInst>(new FenceInst(SI, *this));468return cast<FenceInst>(registerValue(std::move(NewPtr)));469}470471SelectInst *Context::createSelectInst(llvm::SelectInst *SI) {472auto NewPtr = std::unique_ptr<SelectInst>(new SelectInst(SI, *this));473return cast<SelectInst>(registerValue(std::move(NewPtr)));474}475476ExtractElementInst *477Context::createExtractElementInst(llvm::ExtractElementInst *EEI) {478auto NewPtr =479std::unique_ptr<ExtractElementInst>(new ExtractElementInst(EEI, *this));480return cast<ExtractElementInst>(registerValue(std::move(NewPtr)));481}482483InsertElementInst *484Context::createInsertElementInst(llvm::InsertElementInst *IEI) {485auto NewPtr =486std::unique_ptr<InsertElementInst>(new InsertElementInst(IEI, *this));487return cast<InsertElementInst>(registerValue(std::move(NewPtr)));488}489490ShuffleVectorInst *491Context::createShuffleVectorInst(llvm::ShuffleVectorInst *SVI) {492auto NewPtr =493std::unique_ptr<ShuffleVectorInst>(new ShuffleVectorInst(SVI, *this));494return cast<ShuffleVectorInst>(registerValue(std::move(NewPtr)));495}496497ExtractValueInst *Context::createExtractValueInst(llvm::ExtractValueInst *EVI) {498auto NewPtr =499std::unique_ptr<ExtractValueInst>(new ExtractValueInst(EVI, *this));500return cast<ExtractValueInst>(registerValue(std::move(NewPtr)));501}502503InsertValueInst *Context::createInsertValueInst(llvm::InsertValueInst *IVI) {504auto NewPtr =505std::unique_ptr<InsertValueInst>(new InsertValueInst(IVI, *this));506return cast<InsertValueInst>(registerValue(std::move(NewPtr)));507}508509BranchInst *Context::createBranchInst(llvm::BranchInst *BI) {510auto NewPtr = std::unique_ptr<BranchInst>(new BranchInst(BI, *this));511return cast<BranchInst>(registerValue(std::move(NewPtr)));512}513514LoadInst *Context::createLoadInst(llvm::LoadInst *LI) {515auto NewPtr = std::unique_ptr<LoadInst>(new LoadInst(LI, *this));516return cast<LoadInst>(registerValue(std::move(NewPtr)));517}518519StoreInst *Context::createStoreInst(llvm::StoreInst *SI) {520auto NewPtr = std::unique_ptr<StoreInst>(new StoreInst(SI, *this));521return cast<StoreInst>(registerValue(std::move(NewPtr)));522}523524ReturnInst *Context::createReturnInst(llvm::ReturnInst *I) {525auto NewPtr = std::unique_ptr<ReturnInst>(new ReturnInst(I, *this));526return cast<ReturnInst>(registerValue(std::move(NewPtr)));527}528529CallInst *Context::createCallInst(llvm::CallInst *I) {530auto NewPtr = std::unique_ptr<CallInst>(new CallInst(I, *this));531return cast<CallInst>(registerValue(std::move(NewPtr)));532}533534InvokeInst *Context::createInvokeInst(llvm::InvokeInst *I) {535auto NewPtr = std::unique_ptr<InvokeInst>(new InvokeInst(I, *this));536return cast<InvokeInst>(registerValue(std::move(NewPtr)));537}538539CallBrInst *Context::createCallBrInst(llvm::CallBrInst *I) {540auto NewPtr = std::unique_ptr<CallBrInst>(new CallBrInst(I, *this));541return cast<CallBrInst>(registerValue(std::move(NewPtr)));542}543544UnreachableInst *Context::createUnreachableInst(llvm::UnreachableInst *UI) {545auto NewPtr =546std::unique_ptr<UnreachableInst>(new UnreachableInst(UI, *this));547return cast<UnreachableInst>(registerValue(std::move(NewPtr)));548}549LandingPadInst *Context::createLandingPadInst(llvm::LandingPadInst *I) {550auto NewPtr = std::unique_ptr<LandingPadInst>(new LandingPadInst(I, *this));551return cast<LandingPadInst>(registerValue(std::move(NewPtr)));552}553CatchPadInst *Context::createCatchPadInst(llvm::CatchPadInst *I) {554auto NewPtr = std::unique_ptr<CatchPadInst>(new CatchPadInst(I, *this));555return cast<CatchPadInst>(registerValue(std::move(NewPtr)));556}557CleanupPadInst *Context::createCleanupPadInst(llvm::CleanupPadInst *I) {558auto NewPtr = std::unique_ptr<CleanupPadInst>(new CleanupPadInst(I, *this));559return cast<CleanupPadInst>(registerValue(std::move(NewPtr)));560}561CatchReturnInst *Context::createCatchReturnInst(llvm::CatchReturnInst *I) {562auto NewPtr = std::unique_ptr<CatchReturnInst>(new CatchReturnInst(I, *this));563return cast<CatchReturnInst>(registerValue(std::move(NewPtr)));564}565CleanupReturnInst *566Context::createCleanupReturnInst(llvm::CleanupReturnInst *I) {567auto NewPtr =568std::unique_ptr<CleanupReturnInst>(new CleanupReturnInst(I, *this));569return cast<CleanupReturnInst>(registerValue(std::move(NewPtr)));570}571GetElementPtrInst *572Context::createGetElementPtrInst(llvm::GetElementPtrInst *I) {573auto NewPtr =574std::unique_ptr<GetElementPtrInst>(new GetElementPtrInst(I, *this));575return cast<GetElementPtrInst>(registerValue(std::move(NewPtr)));576}577CatchSwitchInst *Context::createCatchSwitchInst(llvm::CatchSwitchInst *I) {578auto NewPtr = std::unique_ptr<CatchSwitchInst>(new CatchSwitchInst(I, *this));579return cast<CatchSwitchInst>(registerValue(std::move(NewPtr)));580}581ResumeInst *Context::createResumeInst(llvm::ResumeInst *I) {582auto NewPtr = std::unique_ptr<ResumeInst>(new ResumeInst(I, *this));583return cast<ResumeInst>(registerValue(std::move(NewPtr)));584}585SwitchInst *Context::createSwitchInst(llvm::SwitchInst *I) {586auto NewPtr = std::unique_ptr<SwitchInst>(new SwitchInst(I, *this));587return cast<SwitchInst>(registerValue(std::move(NewPtr)));588}589UnaryOperator *Context::createUnaryOperator(llvm::UnaryOperator *I) {590auto NewPtr = std::unique_ptr<UnaryOperator>(new UnaryOperator(I, *this));591return cast<UnaryOperator>(registerValue(std::move(NewPtr)));592}593BinaryOperator *Context::createBinaryOperator(llvm::BinaryOperator *I) {594auto NewPtr = std::unique_ptr<BinaryOperator>(new BinaryOperator(I, *this));595return cast<BinaryOperator>(registerValue(std::move(NewPtr)));596}597AtomicRMWInst *Context::createAtomicRMWInst(llvm::AtomicRMWInst *I) {598auto NewPtr = std::unique_ptr<AtomicRMWInst>(new AtomicRMWInst(I, *this));599return cast<AtomicRMWInst>(registerValue(std::move(NewPtr)));600}601AtomicCmpXchgInst *602Context::createAtomicCmpXchgInst(llvm::AtomicCmpXchgInst *I) {603auto NewPtr =604std::unique_ptr<AtomicCmpXchgInst>(new AtomicCmpXchgInst(I, *this));605return cast<AtomicCmpXchgInst>(registerValue(std::move(NewPtr)));606}607AllocaInst *Context::createAllocaInst(llvm::AllocaInst *I) {608auto NewPtr = std::unique_ptr<AllocaInst>(new AllocaInst(I, *this));609return cast<AllocaInst>(registerValue(std::move(NewPtr)));610}611CastInst *Context::createCastInst(llvm::CastInst *I) {612auto NewPtr = std::unique_ptr<CastInst>(new CastInst(I, *this));613return cast<CastInst>(registerValue(std::move(NewPtr)));614}615PHINode *Context::createPHINode(llvm::PHINode *I) {616auto NewPtr = std::unique_ptr<PHINode>(new PHINode(I, *this));617return cast<PHINode>(registerValue(std::move(NewPtr)));618}619ICmpInst *Context::createICmpInst(llvm::ICmpInst *I) {620auto NewPtr = std::unique_ptr<ICmpInst>(new ICmpInst(I, *this));621return cast<ICmpInst>(registerValue(std::move(NewPtr)));622}623FCmpInst *Context::createFCmpInst(llvm::FCmpInst *I) {624auto NewPtr = std::unique_ptr<FCmpInst>(new FCmpInst(I, *this));625return cast<FCmpInst>(registerValue(std::move(NewPtr)));626}627Value *Context::getValue(llvm::Value *V) const {628auto It = LLVMValueToValueMap.find(V);629if (It != LLVMValueToValueMap.end())630return It->second.get();631return nullptr;632}633634Context::Context(LLVMContext &LLVMCtx)635: LLVMCtx(LLVMCtx), IRTracker(*this),636LLVMIRBuilder(LLVMCtx, ConstantFolder()) {}637638Context::~Context() {}639640void Context::clear() {641// TODO: Ideally we should clear only function-scope objects, and keep global642// objects, like Constants to avoid recreating them.643LLVMValueToValueMap.clear();644}645646Module *Context::getModule(llvm::Module *LLVMM) const {647auto It = LLVMModuleToModuleMap.find(LLVMM);648if (It != LLVMModuleToModuleMap.end())649return It->second.get();650return nullptr;651}652653Module *Context::getOrCreateModule(llvm::Module *LLVMM) {654auto Pair = LLVMModuleToModuleMap.try_emplace(LLVMM);655auto It = Pair.first;656if (!Pair.second)657return It->second.get();658It->second = std::unique_ptr<Module>(new Module(*LLVMM, *this));659return It->second.get();660}661662Function *Context::createFunction(llvm::Function *F) {663// Create the module if needed before we create the new sandboxir::Function.664// Note: this won't fully populate the module. The only globals that will be665// available will be the ones being used within the function.666getOrCreateModule(F->getParent());667668// There may be a function declaration already defined. Regardless destroy it.669if (Function *ExistingF = cast_or_null<Function>(getValue(F)))670detach(ExistingF);671672auto NewFPtr = std::unique_ptr<Function>(new Function(F, *this));673auto *SBF = cast<Function>(registerValue(std::move(NewFPtr)));674// Create arguments.675for (auto &Arg : F->args())676getOrCreateArgument(&Arg);677// Create BBs.678for (auto &BB : *F)679createBasicBlock(&BB);680return SBF;681}682683Module *Context::createModule(llvm::Module *LLVMM) {684auto *M = getOrCreateModule(LLVMM);685// Create the functions.686for (auto &LLVMF : *LLVMM)687createFunction(&LLVMF);688// Create globals.689for (auto &Global : LLVMM->globals())690getOrCreateValue(&Global);691// Create aliases.692for (auto &Alias : LLVMM->aliases())693getOrCreateValue(&Alias);694// Create ifuncs.695for (auto &IFunc : LLVMM->ifuncs())696getOrCreateValue(&IFunc);697698return M;699}700701void Context::runEraseInstrCallbacks(Instruction *I) {702for (const auto &CBEntry : EraseInstrCallbacks)703CBEntry.second(I);704}705706void Context::runCreateInstrCallbacks(Instruction *I) {707for (auto &CBEntry : CreateInstrCallbacks)708CBEntry.second(I);709}710711void Context::runMoveInstrCallbacks(Instruction *I, const BBIterator &WhereIt) {712for (auto &CBEntry : MoveInstrCallbacks)713CBEntry.second(I, WhereIt);714}715716void Context::runSetUseCallbacks(const Use &U, Value *NewSrc) {717for (auto &CBEntry : SetUseCallbacks)718CBEntry.second(U, NewSrc);719}720721// An arbitrary limit, to check for accidental misuse. We expect a small number722// of callbacks to be registered at a time, but we can increase this number if723// we discover we needed more.724[[maybe_unused]] static constexpr int MaxRegisteredCallbacks = 16;725726Context::CallbackID Context::registerEraseInstrCallback(EraseInstrCallback CB) {727assert(EraseInstrCallbacks.size() <= MaxRegisteredCallbacks &&728"EraseInstrCallbacks size limit exceeded");729CallbackID ID{NextCallbackID++};730EraseInstrCallbacks[ID] = CB;731return ID;732}733void Context::unregisterEraseInstrCallback(CallbackID ID) {734[[maybe_unused]] bool Erased = EraseInstrCallbacks.erase(ID);735assert(Erased &&736"Callback ID not found in EraseInstrCallbacks during deregistration");737}738739Context::CallbackID740Context::registerCreateInstrCallback(CreateInstrCallback CB) {741assert(CreateInstrCallbacks.size() <= MaxRegisteredCallbacks &&742"CreateInstrCallbacks size limit exceeded");743CallbackID ID{NextCallbackID++};744CreateInstrCallbacks[ID] = CB;745return ID;746}747void Context::unregisterCreateInstrCallback(CallbackID ID) {748[[maybe_unused]] bool Erased = CreateInstrCallbacks.erase(ID);749assert(Erased &&750"Callback ID not found in CreateInstrCallbacks during deregistration");751}752753Context::CallbackID Context::registerMoveInstrCallback(MoveInstrCallback CB) {754assert(MoveInstrCallbacks.size() <= MaxRegisteredCallbacks &&755"MoveInstrCallbacks size limit exceeded");756CallbackID ID{NextCallbackID++};757MoveInstrCallbacks[ID] = CB;758return ID;759}760void Context::unregisterMoveInstrCallback(CallbackID ID) {761[[maybe_unused]] bool Erased = MoveInstrCallbacks.erase(ID);762assert(Erased &&763"Callback ID not found in MoveInstrCallbacks during deregistration");764}765766Context::CallbackID Context::registerSetUseCallback(SetUseCallback CB) {767assert(SetUseCallbacks.size() <= MaxRegisteredCallbacks &&768"SetUseCallbacks size limit exceeded");769CallbackID ID{NextCallbackID++};770SetUseCallbacks[ID] = CB;771return ID;772}773void Context::unregisterSetUseCallback(CallbackID ID) {774[[maybe_unused]] bool Erased = SetUseCallbacks.erase(ID);775assert(Erased &&776"Callback ID not found in SetUseCallbacks during deregistration");777}778779} // namespace llvm::sandboxir780781782