brintos

brintos / llvm-project-archived public Read only

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