Path: blob/main/contrib/llvm-project/llvm/lib/SandboxIR/Instruction.cpp
213766 views
//===- Instruction.cpp - The Instructions 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/Instruction.h"9#include "llvm/SandboxIR/Function.h"1011namespace llvm::sandboxir {1213const char *Instruction::getOpcodeName(Opcode Opc) {14switch (Opc) {15#define OP(OPC) \16case Opcode::OPC: \17return #OPC;18#define OPCODES(...) __VA_ARGS__19#define DEF_INSTR(ID, OPC, CLASS) OPC20#include "llvm/SandboxIR/Values.def"21}22llvm_unreachable("Unknown Opcode");23}2425llvm::Instruction *Instruction::getTopmostLLVMInstruction() const {26Instruction *Prev = getPrevNode();27if (Prev == nullptr) {28// If at top of the BB, return the first BB instruction.29return &*cast<llvm::BasicBlock>(getParent()->Val)->begin();30}31// Else get the Previous sandbox IR instruction's bottom IR instruction and32// return its successor.33llvm::Instruction *PrevBotI = cast<llvm::Instruction>(Prev->Val);34return PrevBotI->getNextNode();35}3637BBIterator Instruction::getIterator() const {38auto *I = cast<llvm::Instruction>(Val);39return BasicBlock::iterator(I->getParent(), I->getIterator(), &Ctx);40}4142Instruction *Instruction::getNextNode() const {43assert(getParent() != nullptr && "Detached!");44assert(getIterator() != getParent()->end() && "Already at end!");45// `Val` is the bottom-most LLVM IR instruction. Get the next in the chain,46// and get the corresponding sandboxir Instruction that maps to it. This works47// even for SandboxIR Instructions that map to more than one LLVM Instruction.48auto *LLVMI = cast<llvm::Instruction>(Val);49assert(LLVMI->getParent() != nullptr && "LLVM IR instr is detached!");50auto *NextLLVMI = LLVMI->getNextNode();51auto *NextI = cast_or_null<Instruction>(Ctx.getValue(NextLLVMI));52if (NextI == nullptr)53return nullptr;54return NextI;55}5657Instruction *Instruction::getPrevNode() const {58assert(getParent() != nullptr && "Detached!");59auto It = getIterator();60if (It != getParent()->begin())61return std::prev(getIterator()).get();62return nullptr;63}6465void Instruction::removeFromParent() {66Ctx.getTracker().emplaceIfTracking<RemoveFromParent>(this);6768// Detach all the LLVM IR instructions from their parent BB.69for (llvm::Instruction *I : getLLVMInstrs())70I->removeFromParent();71}7273void Instruction::eraseFromParent() {74assert(users().empty() && "Still connected to users, can't erase!");7576Ctx.runEraseInstrCallbacks(this);77std::unique_ptr<Value> Detached = Ctx.detach(this);78auto LLVMInstrs = getLLVMInstrs();7980auto &Tracker = Ctx.getTracker();81if (Tracker.isTracking()) {82Tracker.track(std::make_unique<EraseFromParent>(std::move(Detached)));83// We don't actually delete the IR instruction, because then it would be84// impossible to bring it back from the dead at the same memory location.85// Instead we remove it from its BB and track its current location.86for (llvm::Instruction *I : LLVMInstrs)87I->removeFromParent();88// TODO: Multi-instructions need special treatment because some of the89// references are internal to the instruction.90for (llvm::Instruction *I : LLVMInstrs)91I->dropAllReferences();92} else {93// Erase in reverse to avoid erasing nstructions with attached uses.94for (llvm::Instruction *I : reverse(LLVMInstrs))95I->eraseFromParent();96}97}9899void Instruction::moveBefore(BasicBlock &BB, const BBIterator &WhereIt) {100if (std::next(getIterator()) == WhereIt)101// Destination is same as origin, nothing to do.102return;103104Ctx.runMoveInstrCallbacks(this, WhereIt);105Ctx.getTracker().emplaceIfTracking<MoveInstr>(this);106107auto *LLVMBB = cast<llvm::BasicBlock>(BB.Val);108llvm::BasicBlock::iterator It;109if (WhereIt == BB.end()) {110It = LLVMBB->end();111} else {112Instruction *WhereI = &*WhereIt;113It = WhereI->getTopmostLLVMInstruction()->getIterator();114}115// TODO: Move this to the verifier of sandboxir::Instruction.116assert(is_sorted(getLLVMInstrs(),117[](auto *I1, auto *I2) { return I1->comesBefore(I2); }) &&118"Expected program order!");119// Do the actual move in LLVM IR.120for (auto *I : getLLVMInstrs())121I->moveBefore(*LLVMBB, It);122}123124void Instruction::insertBefore(Instruction *BeforeI) {125llvm::Instruction *BeforeTopI = BeforeI->getTopmostLLVMInstruction();126127Ctx.getTracker().emplaceIfTracking<InsertIntoBB>(this);128129// Insert the LLVM IR Instructions in program order.130for (llvm::Instruction *I : getLLVMInstrs())131I->insertBefore(BeforeTopI->getIterator());132}133134void Instruction::insertAfter(Instruction *AfterI) {135insertInto(AfterI->getParent(), std::next(AfterI->getIterator()));136}137138void Instruction::insertInto(BasicBlock *BB, const BBIterator &WhereIt) {139llvm::BasicBlock *LLVMBB = cast<llvm::BasicBlock>(BB->Val);140llvm::Instruction *LLVMBeforeI;141llvm::BasicBlock::iterator LLVMBeforeIt;142Instruction *BeforeI;143if (WhereIt != BB->end()) {144BeforeI = &*WhereIt;145LLVMBeforeI = BeforeI->getTopmostLLVMInstruction();146LLVMBeforeIt = LLVMBeforeI->getIterator();147} else {148BeforeI = nullptr;149LLVMBeforeI = nullptr;150LLVMBeforeIt = LLVMBB->end();151}152153Ctx.getTracker().emplaceIfTracking<InsertIntoBB>(this);154155// Insert the LLVM IR Instructions in program order.156for (llvm::Instruction *I : getLLVMInstrs())157I->insertInto(LLVMBB, LLVMBeforeIt);158}159160BasicBlock *Instruction::getParent() const {161// Get the LLVM IR Instruction that this maps to, get its parent, and get the162// corresponding sandboxir::BasicBlock by looking it up in sandboxir::Context.163auto *BB = cast<llvm::Instruction>(Val)->getParent();164if (BB == nullptr)165return nullptr;166return cast<BasicBlock>(Ctx.getValue(BB));167}168169bool Instruction::classof(const sandboxir::Value *From) {170switch (From->getSubclassID()) {171#define DEF_INSTR(ID, OPC, CLASS) \172case ClassID::ID: \173return true;174#include "llvm/SandboxIR/Values.def"175default:176return false;177}178}179180void Instruction::setHasNoUnsignedWrap(bool B) {181Ctx.getTracker()182.emplaceIfTracking<GenericSetter<&Instruction::hasNoUnsignedWrap,183&Instruction::setHasNoUnsignedWrap>>(184this);185cast<llvm::Instruction>(Val)->setHasNoUnsignedWrap(B);186}187188void Instruction::setHasNoSignedWrap(bool B) {189Ctx.getTracker()190.emplaceIfTracking<GenericSetter<&Instruction::hasNoSignedWrap,191&Instruction::setHasNoSignedWrap>>(this);192cast<llvm::Instruction>(Val)->setHasNoSignedWrap(B);193}194195void Instruction::setFast(bool B) {196Ctx.getTracker()197.emplaceIfTracking<198GenericSetter<&Instruction::isFast, &Instruction::setFast>>(this);199cast<llvm::Instruction>(Val)->setFast(B);200}201202void Instruction::setIsExact(bool B) {203Ctx.getTracker()204.emplaceIfTracking<205GenericSetter<&Instruction::isExact, &Instruction::setIsExact>>(this);206cast<llvm::Instruction>(Val)->setIsExact(B);207}208209void Instruction::setHasAllowReassoc(bool B) {210Ctx.getTracker()211.emplaceIfTracking<GenericSetter<&Instruction::hasAllowReassoc,212&Instruction::setHasAllowReassoc>>(this);213cast<llvm::Instruction>(Val)->setHasAllowReassoc(B);214}215216void Instruction::setHasNoNaNs(bool B) {217Ctx.getTracker()218.emplaceIfTracking<219GenericSetter<&Instruction::hasNoNaNs, &Instruction::setHasNoNaNs>>(220this);221cast<llvm::Instruction>(Val)->setHasNoNaNs(B);222}223224void Instruction::setHasNoInfs(bool B) {225Ctx.getTracker()226.emplaceIfTracking<227GenericSetter<&Instruction::hasNoInfs, &Instruction::setHasNoInfs>>(228this);229cast<llvm::Instruction>(Val)->setHasNoInfs(B);230}231232void Instruction::setHasNoSignedZeros(bool B) {233Ctx.getTracker()234.emplaceIfTracking<GenericSetter<&Instruction::hasNoSignedZeros,235&Instruction::setHasNoSignedZeros>>(236this);237cast<llvm::Instruction>(Val)->setHasNoSignedZeros(B);238}239240void Instruction::setHasAllowReciprocal(bool B) {241Ctx.getTracker()242.emplaceIfTracking<GenericSetter<&Instruction::hasAllowReciprocal,243&Instruction::setHasAllowReciprocal>>(244this);245cast<llvm::Instruction>(Val)->setHasAllowReciprocal(B);246}247248void Instruction::setHasAllowContract(bool B) {249Ctx.getTracker()250.emplaceIfTracking<GenericSetter<&Instruction::hasAllowContract,251&Instruction::setHasAllowContract>>(252this);253cast<llvm::Instruction>(Val)->setHasAllowContract(B);254}255256void Instruction::setFastMathFlags(FastMathFlags FMF) {257Ctx.getTracker()258.emplaceIfTracking<GenericSetter<&Instruction::getFastMathFlags,259&Instruction::copyFastMathFlags>>(this);260cast<llvm::Instruction>(Val)->setFastMathFlags(FMF);261}262263void Instruction::copyFastMathFlags(FastMathFlags FMF) {264Ctx.getTracker()265.emplaceIfTracking<GenericSetter<&Instruction::getFastMathFlags,266&Instruction::copyFastMathFlags>>(this);267cast<llvm::Instruction>(Val)->copyFastMathFlags(FMF);268}269270Type *Instruction::getAccessType() const {271return Ctx.getType(cast<llvm::Instruction>(Val)->getAccessType());272}273274void Instruction::setHasApproxFunc(bool B) {275Ctx.getTracker()276.emplaceIfTracking<GenericSetter<&Instruction::hasApproxFunc,277&Instruction::setHasApproxFunc>>(this);278cast<llvm::Instruction>(Val)->setHasApproxFunc(B);279}280281#ifndef NDEBUG282void Instruction::dumpOS(raw_ostream &OS) const {283OS << "Unimplemented! Please override dump().";284}285#endif // NDEBUG286287VAArgInst *VAArgInst::create(Value *List, Type *Ty, InsertPosition Pos,288Context &Ctx, const Twine &Name) {289auto &Builder = setInsertPos(Pos);290auto *LLVMI =291cast<llvm::VAArgInst>(Builder.CreateVAArg(List->Val, Ty->LLVMTy, Name));292return Ctx.createVAArgInst(LLVMI);293}294295Value *VAArgInst::getPointerOperand() {296return Ctx.getValue(cast<llvm::VAArgInst>(Val)->getPointerOperand());297}298299FreezeInst *FreezeInst::create(Value *V, InsertPosition Pos, Context &Ctx,300const Twine &Name) {301auto &Builder = setInsertPos(Pos);302auto *LLVMI = cast<llvm::FreezeInst>(Builder.CreateFreeze(V->Val, Name));303return Ctx.createFreezeInst(LLVMI);304}305306FenceInst *FenceInst::create(AtomicOrdering Ordering, InsertPosition Pos,307Context &Ctx, SyncScope::ID SSID) {308auto &Builder = Instruction::setInsertPos(Pos);309llvm::FenceInst *LLVMI = Builder.CreateFence(Ordering, SSID);310return Ctx.createFenceInst(LLVMI);311}312313void FenceInst::setOrdering(AtomicOrdering Ordering) {314Ctx.getTracker()315.emplaceIfTracking<316GenericSetter<&FenceInst::getOrdering, &FenceInst::setOrdering>>(317this);318cast<llvm::FenceInst>(Val)->setOrdering(Ordering);319}320321void FenceInst::setSyncScopeID(SyncScope::ID SSID) {322Ctx.getTracker()323.emplaceIfTracking<GenericSetter<&FenceInst::getSyncScopeID,324&FenceInst::setSyncScopeID>>(this);325cast<llvm::FenceInst>(Val)->setSyncScopeID(SSID);326}327328Value *SelectInst::create(Value *Cond, Value *True, Value *False,329InsertPosition Pos, Context &Ctx, const Twine &Name) {330auto &Builder = Instruction::setInsertPos(Pos);331llvm::Value *NewV =332Builder.CreateSelect(Cond->Val, True->Val, False->Val, Name);333if (auto *NewSI = dyn_cast<llvm::SelectInst>(NewV))334return Ctx.createSelectInst(NewSI);335assert(isa<llvm::Constant>(NewV) && "Expected constant");336return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));337}338339void SelectInst::swapValues() {340Ctx.getTracker().emplaceIfTracking<UseSwap>(getOperandUse(1),341getOperandUse(2));342cast<llvm::SelectInst>(Val)->swapValues();343}344345bool SelectInst::classof(const Value *From) {346return From->getSubclassID() == ClassID::Select;347}348349BranchInst *BranchInst::create(BasicBlock *IfTrue, InsertPosition Pos,350Context &Ctx) {351auto &Builder = setInsertPos(Pos);352llvm::BranchInst *NewBr =353Builder.CreateBr(cast<llvm::BasicBlock>(IfTrue->Val));354return Ctx.createBranchInst(NewBr);355}356357BranchInst *BranchInst::create(BasicBlock *IfTrue, BasicBlock *IfFalse,358Value *Cond, InsertPosition Pos, Context &Ctx) {359auto &Builder = setInsertPos(Pos);360llvm::BranchInst *NewBr =361Builder.CreateCondBr(Cond->Val, cast<llvm::BasicBlock>(IfTrue->Val),362cast<llvm::BasicBlock>(IfFalse->Val));363return Ctx.createBranchInst(NewBr);364}365366bool BranchInst::classof(const Value *From) {367return From->getSubclassID() == ClassID::Br;368}369370Value *BranchInst::getCondition() const {371assert(isConditional() && "Cannot get condition of an uncond branch!");372return Ctx.getValue(cast<llvm::BranchInst>(Val)->getCondition());373}374375BasicBlock *BranchInst::getSuccessor(unsigned SuccIdx) const {376assert(SuccIdx < getNumSuccessors() &&377"Successor # out of range for Branch!");378return cast_or_null<BasicBlock>(379Ctx.getValue(cast<llvm::BranchInst>(Val)->getSuccessor(SuccIdx)));380}381382void BranchInst::setSuccessor(unsigned Idx, BasicBlock *NewSucc) {383assert((Idx == 0 || Idx == 1) && "Out of bounds!");384setOperand(2u - Idx, NewSucc);385}386387BasicBlock *BranchInst::LLVMBBToSBBB::operator()(llvm::BasicBlock *BB) const {388return cast<BasicBlock>(Ctx.getValue(BB));389}390const BasicBlock *391BranchInst::ConstLLVMBBToSBBB::operator()(const llvm::BasicBlock *BB) const {392return cast<BasicBlock>(Ctx.getValue(BB));393}394395void LoadInst::setVolatile(bool V) {396Ctx.getTracker()397.emplaceIfTracking<398GenericSetter<&LoadInst::isVolatile, &LoadInst::setVolatile>>(this);399cast<llvm::LoadInst>(Val)->setVolatile(V);400}401402LoadInst *LoadInst::create(Type *Ty, Value *Ptr, MaybeAlign Align,403InsertPosition Pos, bool IsVolatile, Context &Ctx,404const Twine &Name) {405auto &Builder = setInsertPos(Pos);406auto *NewLI =407Builder.CreateAlignedLoad(Ty->LLVMTy, Ptr->Val, Align, IsVolatile, Name);408auto *NewSBI = Ctx.createLoadInst(NewLI);409return NewSBI;410}411412bool LoadInst::classof(const Value *From) {413return From->getSubclassID() == ClassID::Load;414}415416Value *LoadInst::getPointerOperand() const {417return Ctx.getValue(cast<llvm::LoadInst>(Val)->getPointerOperand());418}419420void StoreInst::setVolatile(bool V) {421Ctx.getTracker()422.emplaceIfTracking<423GenericSetter<&StoreInst::isVolatile, &StoreInst::setVolatile>>(this);424cast<llvm::StoreInst>(Val)->setVolatile(V);425}426427StoreInst *StoreInst::create(Value *V, Value *Ptr, MaybeAlign Align,428InsertPosition Pos, bool IsVolatile,429Context &Ctx) {430auto &Builder = setInsertPos(Pos);431auto *NewSI = Builder.CreateAlignedStore(V->Val, Ptr->Val, Align, IsVolatile);432auto *NewSBI = Ctx.createStoreInst(NewSI);433return NewSBI;434}435436bool StoreInst::classof(const Value *From) {437return From->getSubclassID() == ClassID::Store;438}439440Value *StoreInst::getValueOperand() const {441return Ctx.getValue(cast<llvm::StoreInst>(Val)->getValueOperand());442}443444Value *StoreInst::getPointerOperand() const {445return Ctx.getValue(cast<llvm::StoreInst>(Val)->getPointerOperand());446}447448UnreachableInst *UnreachableInst::create(InsertPosition Pos, Context &Ctx) {449auto &Builder = setInsertPos(Pos);450llvm::UnreachableInst *NewUI = Builder.CreateUnreachable();451return Ctx.createUnreachableInst(NewUI);452}453454bool UnreachableInst::classof(const Value *From) {455return From->getSubclassID() == ClassID::Unreachable;456}457458ReturnInst *ReturnInst::createCommon(Value *RetVal, IRBuilder<> &Builder,459Context &Ctx) {460llvm::ReturnInst *NewRI;461if (RetVal != nullptr)462NewRI = Builder.CreateRet(RetVal->Val);463else464NewRI = Builder.CreateRetVoid();465return Ctx.createReturnInst(NewRI);466}467468ReturnInst *ReturnInst::create(Value *RetVal, InsertPosition Pos,469Context &Ctx) {470auto &Builder = setInsertPos(Pos);471return createCommon(RetVal, Builder, Ctx);472}473474Value *ReturnInst::getReturnValue() const {475auto *LLVMRetVal = cast<llvm::ReturnInst>(Val)->getReturnValue();476return LLVMRetVal != nullptr ? Ctx.getValue(LLVMRetVal) : nullptr;477}478479FunctionType *CallBase::getFunctionType() const {480return cast<FunctionType>(481Ctx.getType(cast<llvm::CallBase>(Val)->getFunctionType()));482}483484Value *CallBase::getCalledOperand() const {485return Ctx.getValue(cast<llvm::CallBase>(Val)->getCalledOperand());486}487488Use CallBase::getCalledOperandUse() const {489llvm::Use *LLVMUse = &cast<llvm::CallBase>(Val)->getCalledOperandUse();490return Use(LLVMUse, cast<User>(Ctx.getValue(LLVMUse->getUser())), Ctx);491}492493Function *CallBase::getCalledFunction() const {494return cast_or_null<Function>(495Ctx.getValue(cast<llvm::CallBase>(Val)->getCalledFunction()));496}497Function *CallBase::getCaller() {498return cast<Function>(Ctx.getValue(cast<llvm::CallBase>(Val)->getCaller()));499}500501void CallBase::setCalledFunction(Function *F) {502// F's function type is private, so we rely on `setCalledFunction()` to update503// it. But even though we are calling `setCalledFunction()` we also need to504// track this change at the SandboxIR level, which is why we call505// `setCalledOperand()` here.506// Note: This may break if `setCalledFunction()` early returns if `F`507// is already set, but we do have a unit test for it.508setCalledOperand(F);509cast<llvm::CallBase>(Val)->setCalledFunction(510cast<llvm::FunctionType>(F->getFunctionType()->LLVMTy),511cast<llvm::Function>(F->Val));512}513514CallInst *CallInst::create(FunctionType *FTy, Value *Func,515ArrayRef<Value *> Args, InsertPosition Pos,516Context &Ctx, const Twine &NameStr) {517auto &Builder = setInsertPos(Pos);518SmallVector<llvm::Value *> LLVMArgs;519LLVMArgs.reserve(Args.size());520for (Value *Arg : Args)521LLVMArgs.push_back(Arg->Val);522llvm::CallInst *NewCI = Builder.CreateCall(523cast<llvm::FunctionType>(FTy->LLVMTy), Func->Val, LLVMArgs, NameStr);524return Ctx.createCallInst(NewCI);525}526527InvokeInst *InvokeInst::create(FunctionType *FTy, Value *Func,528BasicBlock *IfNormal, BasicBlock *IfException,529ArrayRef<Value *> Args, InsertPosition Pos,530Context &Ctx, const Twine &NameStr) {531auto &Builder = setInsertPos(Pos);532SmallVector<llvm::Value *> LLVMArgs;533LLVMArgs.reserve(Args.size());534for (Value *Arg : Args)535LLVMArgs.push_back(Arg->Val);536llvm::InvokeInst *Invoke = Builder.CreateInvoke(537cast<llvm::FunctionType>(FTy->LLVMTy), Func->Val,538cast<llvm::BasicBlock>(IfNormal->Val),539cast<llvm::BasicBlock>(IfException->Val), LLVMArgs, NameStr);540return Ctx.createInvokeInst(Invoke);541}542543BasicBlock *InvokeInst::getNormalDest() const {544return cast<BasicBlock>(545Ctx.getValue(cast<llvm::InvokeInst>(Val)->getNormalDest()));546}547BasicBlock *InvokeInst::getUnwindDest() const {548return cast<BasicBlock>(549Ctx.getValue(cast<llvm::InvokeInst>(Val)->getUnwindDest()));550}551void InvokeInst::setNormalDest(BasicBlock *BB) {552setOperand(1, BB);553assert(getNormalDest() == BB && "LLVM IR uses a different operan index!");554}555void InvokeInst::setUnwindDest(BasicBlock *BB) {556setOperand(2, BB);557assert(getUnwindDest() == BB && "LLVM IR uses a different operan index!");558}559LandingPadInst *InvokeInst::getLandingPadInst() const {560return cast<LandingPadInst>(561Ctx.getValue(cast<llvm::InvokeInst>(Val)->getLandingPadInst()));562;563}564BasicBlock *InvokeInst::getSuccessor(unsigned SuccIdx) const {565return cast<BasicBlock>(566Ctx.getValue(cast<llvm::InvokeInst>(Val)->getSuccessor(SuccIdx)));567}568569CallBrInst *CallBrInst::create(FunctionType *FTy, Value *Func,570BasicBlock *DefaultDest,571ArrayRef<BasicBlock *> IndirectDests,572ArrayRef<Value *> Args, InsertPosition Pos,573Context &Ctx, const Twine &NameStr) {574auto &Builder = setInsertPos(Pos);575SmallVector<llvm::BasicBlock *> LLVMIndirectDests;576LLVMIndirectDests.reserve(IndirectDests.size());577for (BasicBlock *IndDest : IndirectDests)578LLVMIndirectDests.push_back(cast<llvm::BasicBlock>(IndDest->Val));579580SmallVector<llvm::Value *> LLVMArgs;581LLVMArgs.reserve(Args.size());582for (Value *Arg : Args)583LLVMArgs.push_back(Arg->Val);584585llvm::CallBrInst *CallBr =586Builder.CreateCallBr(cast<llvm::FunctionType>(FTy->LLVMTy), Func->Val,587cast<llvm::BasicBlock>(DefaultDest->Val),588LLVMIndirectDests, LLVMArgs, NameStr);589return Ctx.createCallBrInst(CallBr);590}591592Value *CallBrInst::getIndirectDestLabel(unsigned Idx) const {593return Ctx.getValue(cast<llvm::CallBrInst>(Val)->getIndirectDestLabel(Idx));594}595Value *CallBrInst::getIndirectDestLabelUse(unsigned Idx) const {596return Ctx.getValue(597cast<llvm::CallBrInst>(Val)->getIndirectDestLabelUse(Idx));598}599BasicBlock *CallBrInst::getDefaultDest() const {600return cast<BasicBlock>(601Ctx.getValue(cast<llvm::CallBrInst>(Val)->getDefaultDest()));602}603BasicBlock *CallBrInst::getIndirectDest(unsigned Idx) const {604return cast<BasicBlock>(605Ctx.getValue(cast<llvm::CallBrInst>(Val)->getIndirectDest(Idx)));606}607llvm::SmallVector<BasicBlock *, 16> CallBrInst::getIndirectDests() const {608SmallVector<BasicBlock *, 16> BBs;609for (llvm::BasicBlock *LLVMBB :610cast<llvm::CallBrInst>(Val)->getIndirectDests())611BBs.push_back(cast<BasicBlock>(Ctx.getValue(LLVMBB)));612return BBs;613}614void CallBrInst::setDefaultDest(BasicBlock *BB) {615Ctx.getTracker()616.emplaceIfTracking<GenericSetter<&CallBrInst::getDefaultDest,617&CallBrInst::setDefaultDest>>(this);618cast<llvm::CallBrInst>(Val)->setDefaultDest(cast<llvm::BasicBlock>(BB->Val));619}620void CallBrInst::setIndirectDest(unsigned Idx, BasicBlock *BB) {621Ctx.getTracker()622.emplaceIfTracking<GenericSetterWithIdx<&CallBrInst::getIndirectDest,623&CallBrInst::setIndirectDest>>(624this, Idx);625cast<llvm::CallBrInst>(Val)->setIndirectDest(Idx,626cast<llvm::BasicBlock>(BB->Val));627}628BasicBlock *CallBrInst::getSuccessor(unsigned Idx) const {629return cast<BasicBlock>(630Ctx.getValue(cast<llvm::CallBrInst>(Val)->getSuccessor(Idx)));631}632633LandingPadInst *LandingPadInst::create(Type *RetTy, unsigned NumReservedClauses,634InsertPosition Pos, Context &Ctx,635const Twine &Name) {636auto &Builder = setInsertPos(Pos);637llvm::LandingPadInst *LLVMI =638Builder.CreateLandingPad(RetTy->LLVMTy, NumReservedClauses, Name);639return Ctx.createLandingPadInst(LLVMI);640}641642void LandingPadInst::setCleanup(bool V) {643Ctx.getTracker()644.emplaceIfTracking<GenericSetter<&LandingPadInst::isCleanup,645&LandingPadInst::setCleanup>>(this);646cast<llvm::LandingPadInst>(Val)->setCleanup(V);647}648649Constant *LandingPadInst::getClause(unsigned Idx) const {650return cast<Constant>(651Ctx.getValue(cast<llvm::LandingPadInst>(Val)->getClause(Idx)));652}653654Value *FuncletPadInst::getParentPad() const {655return Ctx.getValue(cast<llvm::FuncletPadInst>(Val)->getParentPad());656}657658void FuncletPadInst::setParentPad(Value *ParentPad) {659Ctx.getTracker()660.emplaceIfTracking<GenericSetter<&FuncletPadInst::getParentPad,661&FuncletPadInst::setParentPad>>(this);662cast<llvm::FuncletPadInst>(Val)->setParentPad(ParentPad->Val);663}664665Value *FuncletPadInst::getArgOperand(unsigned Idx) const {666return Ctx.getValue(cast<llvm::FuncletPadInst>(Val)->getArgOperand(Idx));667}668669void FuncletPadInst::setArgOperand(unsigned Idx, Value *V) {670Ctx.getTracker()671.emplaceIfTracking<GenericSetterWithIdx<&FuncletPadInst::getArgOperand,672&FuncletPadInst::setArgOperand>>(673this, Idx);674cast<llvm::FuncletPadInst>(Val)->setArgOperand(Idx, V->Val);675}676677CatchSwitchInst *CatchPadInst::getCatchSwitch() const {678return cast<CatchSwitchInst>(679Ctx.getValue(cast<llvm::CatchPadInst>(Val)->getCatchSwitch()));680}681682CatchPadInst *CatchPadInst::create(Value *ParentPad, ArrayRef<Value *> Args,683InsertPosition Pos, Context &Ctx,684const Twine &Name) {685auto &Builder = setInsertPos(Pos);686SmallVector<llvm::Value *> LLVMArgs;687LLVMArgs.reserve(Args.size());688for (auto *Arg : Args)689LLVMArgs.push_back(Arg->Val);690llvm::CatchPadInst *LLVMI =691Builder.CreateCatchPad(ParentPad->Val, LLVMArgs, Name);692return Ctx.createCatchPadInst(LLVMI);693}694695CleanupPadInst *CleanupPadInst::create(Value *ParentPad, ArrayRef<Value *> Args,696InsertPosition Pos, Context &Ctx,697const Twine &Name) {698auto &Builder = setInsertPos(Pos);699SmallVector<llvm::Value *> LLVMArgs;700LLVMArgs.reserve(Args.size());701for (auto *Arg : Args)702LLVMArgs.push_back(Arg->Val);703llvm::CleanupPadInst *LLVMI =704Builder.CreateCleanupPad(ParentPad->Val, LLVMArgs, Name);705return Ctx.createCleanupPadInst(LLVMI);706}707708CatchReturnInst *CatchReturnInst::create(CatchPadInst *CatchPad, BasicBlock *BB,709InsertPosition Pos, Context &Ctx) {710auto &Builder = setInsertPos(Pos);711llvm::CatchReturnInst *LLVMI = Builder.CreateCatchRet(712cast<llvm::CatchPadInst>(CatchPad->Val), cast<llvm::BasicBlock>(BB->Val));713return Ctx.createCatchReturnInst(LLVMI);714}715716CatchPadInst *CatchReturnInst::getCatchPad() const {717return cast<CatchPadInst>(718Ctx.getValue(cast<llvm::CatchReturnInst>(Val)->getCatchPad()));719}720721void CatchReturnInst::setCatchPad(CatchPadInst *CatchPad) {722Ctx.getTracker()723.emplaceIfTracking<GenericSetter<&CatchReturnInst::getCatchPad,724&CatchReturnInst::setCatchPad>>(this);725cast<llvm::CatchReturnInst>(Val)->setCatchPad(726cast<llvm::CatchPadInst>(CatchPad->Val));727}728729BasicBlock *CatchReturnInst::getSuccessor() const {730return cast<BasicBlock>(731Ctx.getValue(cast<llvm::CatchReturnInst>(Val)->getSuccessor()));732}733734void CatchReturnInst::setSuccessor(BasicBlock *NewSucc) {735Ctx.getTracker()736.emplaceIfTracking<GenericSetter<&CatchReturnInst::getSuccessor,737&CatchReturnInst::setSuccessor>>(this);738cast<llvm::CatchReturnInst>(Val)->setSuccessor(739cast<llvm::BasicBlock>(NewSucc->Val));740}741742Value *CatchReturnInst::getCatchSwitchParentPad() const {743return Ctx.getValue(744cast<llvm::CatchReturnInst>(Val)->getCatchSwitchParentPad());745}746747CleanupReturnInst *CleanupReturnInst::create(CleanupPadInst *CleanupPad,748BasicBlock *UnwindBB,749InsertPosition Pos, Context &Ctx) {750auto &Builder = setInsertPos(Pos);751auto *LLVMUnwindBB =752UnwindBB != nullptr ? cast<llvm::BasicBlock>(UnwindBB->Val) : nullptr;753llvm::CleanupReturnInst *LLVMI = Builder.CreateCleanupRet(754cast<llvm::CleanupPadInst>(CleanupPad->Val), LLVMUnwindBB);755return Ctx.createCleanupReturnInst(LLVMI);756}757758CleanupPadInst *CleanupReturnInst::getCleanupPad() const {759return cast<CleanupPadInst>(760Ctx.getValue(cast<llvm::CleanupReturnInst>(Val)->getCleanupPad()));761}762763void CleanupReturnInst::setCleanupPad(CleanupPadInst *CleanupPad) {764Ctx.getTracker()765.emplaceIfTracking<GenericSetter<&CleanupReturnInst::getCleanupPad,766&CleanupReturnInst::setCleanupPad>>(767this);768cast<llvm::CleanupReturnInst>(Val)->setCleanupPad(769cast<llvm::CleanupPadInst>(CleanupPad->Val));770}771772BasicBlock *CleanupReturnInst::getUnwindDest() const {773return cast_or_null<BasicBlock>(774Ctx.getValue(cast<llvm::CleanupReturnInst>(Val)->getUnwindDest()));775}776777void CleanupReturnInst::setUnwindDest(BasicBlock *NewDest) {778Ctx.getTracker()779.emplaceIfTracking<GenericSetter<&CleanupReturnInst::getUnwindDest,780&CleanupReturnInst::setUnwindDest>>(781this);782cast<llvm::CleanupReturnInst>(Val)->setUnwindDest(783cast<llvm::BasicBlock>(NewDest->Val));784}785786Value *GetElementPtrInst::create(Type *Ty, Value *Ptr,787ArrayRef<Value *> IdxList, InsertPosition Pos,788Context &Ctx, const Twine &NameStr) {789auto &Builder = setInsertPos(Pos);790SmallVector<llvm::Value *> LLVMIdxList;791LLVMIdxList.reserve(IdxList.size());792for (Value *Idx : IdxList)793LLVMIdxList.push_back(Idx->Val);794llvm::Value *NewV =795Builder.CreateGEP(Ty->LLVMTy, Ptr->Val, LLVMIdxList, NameStr);796if (auto *NewGEP = dyn_cast<llvm::GetElementPtrInst>(NewV))797return Ctx.createGetElementPtrInst(NewGEP);798assert(isa<llvm::Constant>(NewV) && "Expected constant");799return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));800}801802Type *GetElementPtrInst::getSourceElementType() const {803return Ctx.getType(804cast<llvm::GetElementPtrInst>(Val)->getSourceElementType());805}806807Type *GetElementPtrInst::getResultElementType() const {808return Ctx.getType(809cast<llvm::GetElementPtrInst>(Val)->getResultElementType());810}811812Value *GetElementPtrInst::getPointerOperand() const {813return Ctx.getValue(cast<llvm::GetElementPtrInst>(Val)->getPointerOperand());814}815816Type *GetElementPtrInst::getPointerOperandType() const {817return Ctx.getType(818cast<llvm::GetElementPtrInst>(Val)->getPointerOperandType());819}820821BasicBlock *PHINode::LLVMBBToBB::operator()(llvm::BasicBlock *LLVMBB) const {822return cast<BasicBlock>(Ctx.getValue(LLVMBB));823}824825PHINode *PHINode::create(Type *Ty, unsigned NumReservedValues,826InsertPosition Pos, Context &Ctx, const Twine &Name) {827auto &Builder = setInsertPos(Pos);828llvm::PHINode *NewPHI =829Builder.CreatePHI(Ty->LLVMTy, NumReservedValues, Name);830return Ctx.createPHINode(NewPHI);831}832833bool PHINode::classof(const Value *From) {834return From->getSubclassID() == ClassID::PHI;835}836837Value *PHINode::getIncomingValue(unsigned Idx) const {838return Ctx.getValue(cast<llvm::PHINode>(Val)->getIncomingValue(Idx));839}840void PHINode::setIncomingValue(unsigned Idx, Value *V) {841Ctx.getTracker()842.emplaceIfTracking<GenericSetterWithIdx<&PHINode::getIncomingValue,843&PHINode::setIncomingValue>>(this,844Idx);845cast<llvm::PHINode>(Val)->setIncomingValue(Idx, V->Val);846}847BasicBlock *PHINode::getIncomingBlock(unsigned Idx) const {848return cast<BasicBlock>(849Ctx.getValue(cast<llvm::PHINode>(Val)->getIncomingBlock(Idx)));850}851BasicBlock *PHINode::getIncomingBlock(const Use &U) const {852llvm::Use *LLVMUse = U.LLVMUse;853llvm::BasicBlock *BB = cast<llvm::PHINode>(Val)->getIncomingBlock(*LLVMUse);854return cast<BasicBlock>(Ctx.getValue(BB));855}856void PHINode::setIncomingBlock(unsigned Idx, BasicBlock *BB) {857// Helper to disambiguate PHINode::getIncomingBlock(unsigned).858constexpr BasicBlock *(PHINode::*GetIncomingBlockFn)(unsigned) const =859&PHINode::getIncomingBlock;860Ctx.getTracker()861.emplaceIfTracking<862GenericSetterWithIdx<GetIncomingBlockFn, &PHINode::setIncomingBlock>>(863this, Idx);864cast<llvm::PHINode>(Val)->setIncomingBlock(Idx,865cast<llvm::BasicBlock>(BB->Val));866}867void PHINode::addIncoming(Value *V, BasicBlock *BB) {868auto &Tracker = Ctx.getTracker();869Tracker.emplaceIfTracking<PHIAddIncoming>(this);870871cast<llvm::PHINode>(Val)->addIncoming(V->Val,872cast<llvm::BasicBlock>(BB->Val));873}874Value *PHINode::removeIncomingValue(unsigned Idx) {875auto &Tracker = Ctx.getTracker();876Tracker.emplaceIfTracking<PHIRemoveIncoming>(this, Idx);877llvm::Value *LLVMV =878cast<llvm::PHINode>(Val)->removeIncomingValue(Idx,879/*DeletePHIIfEmpty=*/false);880return Ctx.getValue(LLVMV);881}882Value *PHINode::removeIncomingValue(BasicBlock *BB) {883auto &Tracker = Ctx.getTracker();884Tracker.emplaceIfTracking<PHIRemoveIncoming>(this, getBasicBlockIndex(BB));885886auto *LLVMBB = cast<llvm::BasicBlock>(BB->Val);887llvm::Value *LLVMV =888cast<llvm::PHINode>(Val)->removeIncomingValue(LLVMBB,889/*DeletePHIIfEmpty=*/false);890return Ctx.getValue(LLVMV);891}892int PHINode::getBasicBlockIndex(const BasicBlock *BB) const {893auto *LLVMBB = cast<llvm::BasicBlock>(BB->Val);894return cast<llvm::PHINode>(Val)->getBasicBlockIndex(LLVMBB);895}896Value *PHINode::getIncomingValueForBlock(const BasicBlock *BB) const {897auto *LLVMBB = cast<llvm::BasicBlock>(BB->Val);898llvm::Value *LLVMV =899cast<llvm::PHINode>(Val)->getIncomingValueForBlock(LLVMBB);900return Ctx.getValue(LLVMV);901}902Value *PHINode::hasConstantValue() const {903llvm::Value *LLVMV = cast<llvm::PHINode>(Val)->hasConstantValue();904return LLVMV != nullptr ? Ctx.getValue(LLVMV) : nullptr;905}906void PHINode::replaceIncomingBlockWith(const BasicBlock *Old, BasicBlock *New) {907assert(New && Old && "Sandbox IR PHI node got a null basic block!");908for (unsigned Idx = 0, NumOps = cast<llvm::PHINode>(Val)->getNumOperands();909Idx != NumOps; ++Idx)910if (getIncomingBlock(Idx) == Old)911setIncomingBlock(Idx, New);912}913void PHINode::removeIncomingValueIf(function_ref<bool(unsigned)> Predicate) {914// Avoid duplicate tracking by going through this->removeIncomingValue here at915// the expense of some performance. Copy PHI::removeIncomingValueIf more916// directly if performance becomes an issue.917918// Removing the element at index X, moves the element previously at X + 1919// to X. Working from the end avoids complications from that.920unsigned Idx = getNumIncomingValues();921while (Idx > 0) {922if (Predicate(Idx - 1))923removeIncomingValue(Idx - 1);924--Idx;925}926}927928Value *CmpInst::create(Predicate P, Value *S1, Value *S2, InsertPosition Pos,929Context &Ctx, const Twine &Name) {930auto &Builder = setInsertPos(Pos);931auto *LLVMV = Builder.CreateCmp(P, S1->Val, S2->Val, Name);932// It may have been folded into a constant.933if (auto *LLVMC = dyn_cast<llvm::Constant>(LLVMV))934return Ctx.getOrCreateConstant(LLVMC);935if (isa<llvm::ICmpInst>(LLVMV))936return Ctx.createICmpInst(cast<llvm::ICmpInst>(LLVMV));937return Ctx.createFCmpInst(cast<llvm::FCmpInst>(LLVMV));938}939940Value *CmpInst::createWithCopiedFlags(Predicate P, Value *S1, Value *S2,941const Instruction *F, InsertPosition Pos,942Context &Ctx, const Twine &Name) {943Value *V = create(P, S1, S2, Pos, Ctx, Name);944if (auto *C = dyn_cast<Constant>(V))945return C;946cast<llvm::CmpInst>(V->Val)->copyIRFlags(F->Val);947return V;948}949950Type *CmpInst::makeCmpResultType(Type *OpndType) {951if (auto *VT = dyn_cast<VectorType>(OpndType)) {952// TODO: Cleanup when we have more complete support for953// sandboxir::VectorType954return OpndType->getContext().getType(llvm::VectorType::get(955llvm::Type::getInt1Ty(OpndType->getContext().LLVMCtx),956cast<llvm::VectorType>(VT->LLVMTy)->getElementCount()));957}958return Type::getInt1Ty(OpndType->getContext());959}960961void CmpInst::setPredicate(Predicate P) {962Ctx.getTracker()963.emplaceIfTracking<964GenericSetter<&CmpInst::getPredicate, &CmpInst::setPredicate>>(this);965cast<llvm::CmpInst>(Val)->setPredicate(P);966}967968void CmpInst::swapOperands() {969if (ICmpInst *IC = dyn_cast<ICmpInst>(this))970IC->swapOperands();971else972cast<FCmpInst>(this)->swapOperands();973}974975void ICmpInst::swapOperands() {976Ctx.getTracker().emplaceIfTracking<CmpSwapOperands>(this);977cast<llvm::ICmpInst>(Val)->swapOperands();978}979980void FCmpInst::swapOperands() {981Ctx.getTracker().emplaceIfTracking<CmpSwapOperands>(this);982cast<llvm::FCmpInst>(Val)->swapOperands();983}984985#ifndef NDEBUG986void CmpInst::dumpOS(raw_ostream &OS) const {987dumpCommonPrefix(OS);988dumpCommonSuffix(OS);989}990991void CmpInst::dump() const {992dumpOS(dbgs());993dbgs() << "\n";994}995#endif // NDEBUG996997static llvm::Instruction::CastOps getLLVMCastOp(Instruction::Opcode Opc) {998switch (Opc) {999case Instruction::Opcode::ZExt:1000return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::ZExt);1001case Instruction::Opcode::SExt:1002return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::SExt);1003case Instruction::Opcode::FPToUI:1004return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPToUI);1005case Instruction::Opcode::FPToSI:1006return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPToSI);1007case Instruction::Opcode::FPExt:1008return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPExt);1009case Instruction::Opcode::PtrToInt:1010return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::PtrToInt);1011case Instruction::Opcode::IntToPtr:1012return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::IntToPtr);1013case Instruction::Opcode::SIToFP:1014return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::SIToFP);1015case Instruction::Opcode::UIToFP:1016return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::UIToFP);1017case Instruction::Opcode::Trunc:1018return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::Trunc);1019case Instruction::Opcode::FPTrunc:1020return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPTrunc);1021case Instruction::Opcode::BitCast:1022return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::BitCast);1023case Instruction::Opcode::AddrSpaceCast:1024return static_cast<llvm::Instruction::CastOps>(1025llvm::Instruction::AddrSpaceCast);1026default:1027llvm_unreachable("Opcode not suitable for CastInst!");1028}1029}10301031/// \Returns the LLVM opcode that corresponds to \p Opc.1032static llvm::Instruction::UnaryOps getLLVMUnaryOp(Instruction::Opcode Opc) {1033switch (Opc) {1034case Instruction::Opcode::FNeg:1035return static_cast<llvm::Instruction::UnaryOps>(llvm::Instruction::FNeg);1036default:1037llvm_unreachable("Not a unary op!");1038}1039}10401041CatchSwitchInst *CatchSwitchInst::create(Value *ParentPad, BasicBlock *UnwindBB,1042unsigned NumHandlers,1043InsertPosition Pos, Context &Ctx,1044const Twine &Name) {1045auto &Builder = setInsertPos(Pos);1046llvm::CatchSwitchInst *LLVMCSI = Builder.CreateCatchSwitch(1047ParentPad->Val, cast<llvm::BasicBlock>(UnwindBB->Val), NumHandlers, Name);1048return Ctx.createCatchSwitchInst(LLVMCSI);1049}10501051Value *CatchSwitchInst::getParentPad() const {1052return Ctx.getValue(cast<llvm::CatchSwitchInst>(Val)->getParentPad());1053}10541055void CatchSwitchInst::setParentPad(Value *ParentPad) {1056Ctx.getTracker()1057.emplaceIfTracking<GenericSetter<&CatchSwitchInst::getParentPad,1058&CatchSwitchInst::setParentPad>>(this);1059cast<llvm::CatchSwitchInst>(Val)->setParentPad(ParentPad->Val);1060}10611062BasicBlock *CatchSwitchInst::getUnwindDest() const {1063return cast_or_null<BasicBlock>(1064Ctx.getValue(cast<llvm::CatchSwitchInst>(Val)->getUnwindDest()));1065}10661067void CatchSwitchInst::setUnwindDest(BasicBlock *UnwindDest) {1068Ctx.getTracker()1069.emplaceIfTracking<GenericSetter<&CatchSwitchInst::getUnwindDest,1070&CatchSwitchInst::setUnwindDest>>(this);1071cast<llvm::CatchSwitchInst>(Val)->setUnwindDest(1072cast<llvm::BasicBlock>(UnwindDest->Val));1073}10741075void CatchSwitchInst::addHandler(BasicBlock *Dest) {1076Ctx.getTracker().emplaceIfTracking<CatchSwitchAddHandler>(this);1077cast<llvm::CatchSwitchInst>(Val)->addHandler(1078cast<llvm::BasicBlock>(Dest->Val));1079}10801081ResumeInst *ResumeInst::create(Value *Exn, InsertPosition Pos, Context &Ctx) {1082auto &Builder = setInsertPos(Pos);1083auto *LLVMI = cast<llvm::ResumeInst>(Builder.CreateResume(Exn->Val));1084return Ctx.createResumeInst(LLVMI);1085}10861087Value *ResumeInst::getValue() const {1088return Ctx.getValue(cast<llvm::ResumeInst>(Val)->getValue());1089}10901091SwitchInst *SwitchInst::create(Value *V, BasicBlock *Dest, unsigned NumCases,1092InsertPosition Pos, Context &Ctx,1093const Twine &Name) {1094auto &Builder = setInsertPos(Pos);1095llvm::SwitchInst *LLVMSwitch =1096Builder.CreateSwitch(V->Val, cast<llvm::BasicBlock>(Dest->Val), NumCases);1097return Ctx.createSwitchInst(LLVMSwitch);1098}10991100Value *SwitchInst::getCondition() const {1101return Ctx.getValue(cast<llvm::SwitchInst>(Val)->getCondition());1102}11031104void SwitchInst::setCondition(Value *V) {1105Ctx.getTracker()1106.emplaceIfTracking<1107GenericSetter<&SwitchInst::getCondition, &SwitchInst::setCondition>>(1108this);1109cast<llvm::SwitchInst>(Val)->setCondition(V->Val);1110}11111112BasicBlock *SwitchInst::getDefaultDest() const {1113return cast<BasicBlock>(1114Ctx.getValue(cast<llvm::SwitchInst>(Val)->getDefaultDest()));1115}11161117void SwitchInst::setDefaultDest(BasicBlock *DefaultCase) {1118Ctx.getTracker()1119.emplaceIfTracking<GenericSetter<&SwitchInst::getDefaultDest,1120&SwitchInst::setDefaultDest>>(this);1121cast<llvm::SwitchInst>(Val)->setDefaultDest(1122cast<llvm::BasicBlock>(DefaultCase->Val));1123}1124ConstantInt *SwitchInst::findCaseDest(BasicBlock *BB) {1125auto *LLVMC = cast<llvm::SwitchInst>(Val)->findCaseDest(1126cast<llvm::BasicBlock>(BB->Val));1127return LLVMC != nullptr ? cast<ConstantInt>(Ctx.getValue(LLVMC)) : nullptr;1128}11291130void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) {1131Ctx.getTracker().emplaceIfTracking<SwitchAddCase>(this, OnVal);1132// TODO: Track this!1133cast<llvm::SwitchInst>(Val)->addCase(cast<llvm::ConstantInt>(OnVal->Val),1134cast<llvm::BasicBlock>(Dest->Val));1135}11361137SwitchInst::CaseIt SwitchInst::removeCase(CaseIt It) {1138Ctx.getTracker().emplaceIfTracking<SwitchRemoveCase>(this);11391140auto *LLVMSwitch = cast<llvm::SwitchInst>(Val);1141unsigned CaseNum = It - case_begin();1142llvm::SwitchInst::CaseIt LLVMIt(LLVMSwitch, CaseNum);1143auto LLVMCaseIt = LLVMSwitch->removeCase(LLVMIt);1144unsigned Num = LLVMCaseIt - LLVMSwitch->case_begin();1145return CaseIt(this, Num);1146}11471148BasicBlock *SwitchInst::getSuccessor(unsigned Idx) const {1149return cast<BasicBlock>(1150Ctx.getValue(cast<llvm::SwitchInst>(Val)->getSuccessor(Idx)));1151}11521153void SwitchInst::setSuccessor(unsigned Idx, BasicBlock *NewSucc) {1154Ctx.getTracker()1155.emplaceIfTracking<GenericSetterWithIdx<&SwitchInst::getSuccessor,1156&SwitchInst::setSuccessor>>(this,1157Idx);1158cast<llvm::SwitchInst>(Val)->setSuccessor(1159Idx, cast<llvm::BasicBlock>(NewSucc->Val));1160}11611162Value *UnaryOperator::create(Instruction::Opcode Op, Value *OpV,1163InsertPosition Pos, Context &Ctx,1164const Twine &Name) {1165auto &Builder = setInsertPos(Pos);1166auto *NewLLVMV = Builder.CreateUnOp(getLLVMUnaryOp(Op), OpV->Val, Name);1167if (auto *NewUnOpV = dyn_cast<llvm::UnaryOperator>(NewLLVMV)) {1168return Ctx.createUnaryOperator(NewUnOpV);1169}1170assert(isa<llvm::Constant>(NewLLVMV) && "Expected constant");1171return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewLLVMV));1172}11731174Value *UnaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *OpV,1175Value *CopyFrom, InsertPosition Pos,1176Context &Ctx, const Twine &Name) {1177auto *NewV = create(Op, OpV, Pos, Ctx, Name);1178if (auto *UnI = dyn_cast<llvm::UnaryOperator>(NewV->Val))1179UnI->copyIRFlags(CopyFrom->Val);1180return NewV;1181}11821183/// \Returns the LLVM opcode that corresponds to \p Opc.1184static llvm::Instruction::BinaryOps getLLVMBinaryOp(Instruction::Opcode Opc) {1185switch (Opc) {1186case Instruction::Opcode::Add:1187return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Add);1188case Instruction::Opcode::FAdd:1189return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FAdd);1190case Instruction::Opcode::Sub:1191return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Sub);1192case Instruction::Opcode::FSub:1193return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FSub);1194case Instruction::Opcode::Mul:1195return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Mul);1196case Instruction::Opcode::FMul:1197return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FMul);1198case Instruction::Opcode::UDiv:1199return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::UDiv);1200case Instruction::Opcode::SDiv:1201return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::SDiv);1202case Instruction::Opcode::FDiv:1203return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FDiv);1204case Instruction::Opcode::URem:1205return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::URem);1206case Instruction::Opcode::SRem:1207return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::SRem);1208case Instruction::Opcode::FRem:1209return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FRem);1210case Instruction::Opcode::Shl:1211return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Shl);1212case Instruction::Opcode::LShr:1213return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::LShr);1214case Instruction::Opcode::AShr:1215return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::AShr);1216case Instruction::Opcode::And:1217return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::And);1218case Instruction::Opcode::Or:1219return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Or);1220case Instruction::Opcode::Xor:1221return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Xor);1222default:1223llvm_unreachable("Not a binary op!");1224}1225}1226Value *BinaryOperator::create(Instruction::Opcode Op, Value *LHS, Value *RHS,1227InsertPosition Pos, Context &Ctx,1228const Twine &Name) {1229auto &Builder = setInsertPos(Pos);1230llvm::Value *NewV =1231Builder.CreateBinOp(getLLVMBinaryOp(Op), LHS->Val, RHS->Val, Name);1232if (auto *NewBinOp = dyn_cast<llvm::BinaryOperator>(NewV))1233return Ctx.createBinaryOperator(NewBinOp);1234assert(isa<llvm::Constant>(NewV) && "Expected constant");1235return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));1236}12371238Value *BinaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *LHS,1239Value *RHS, Value *CopyFrom,1240InsertPosition Pos, Context &Ctx,1241const Twine &Name) {12421243Value *NewV = create(Op, LHS, RHS, Pos, Ctx, Name);1244if (auto *NewBO = dyn_cast<BinaryOperator>(NewV))1245cast<llvm::BinaryOperator>(NewBO->Val)->copyIRFlags(CopyFrom->Val);1246return NewV;1247}12481249void PossiblyDisjointInst::setIsDisjoint(bool B) {1250Ctx.getTracker()1251.emplaceIfTracking<GenericSetter<&PossiblyDisjointInst::isDisjoint,1252&PossiblyDisjointInst::setIsDisjoint>>(1253this);1254cast<llvm::PossiblyDisjointInst>(Val)->setIsDisjoint(B);1255}12561257void AtomicRMWInst::setAlignment(Align Align) {1258Ctx.getTracker()1259.emplaceIfTracking<GenericSetter<&AtomicRMWInst::getAlign,1260&AtomicRMWInst::setAlignment>>(this);1261cast<llvm::AtomicRMWInst>(Val)->setAlignment(Align);1262}12631264void AtomicRMWInst::setVolatile(bool V) {1265Ctx.getTracker()1266.emplaceIfTracking<GenericSetter<&AtomicRMWInst::isVolatile,1267&AtomicRMWInst::setVolatile>>(this);1268cast<llvm::AtomicRMWInst>(Val)->setVolatile(V);1269}12701271void AtomicRMWInst::setOrdering(AtomicOrdering Ordering) {1272Ctx.getTracker()1273.emplaceIfTracking<GenericSetter<&AtomicRMWInst::getOrdering,1274&AtomicRMWInst::setOrdering>>(this);1275cast<llvm::AtomicRMWInst>(Val)->setOrdering(Ordering);1276}12771278void AtomicRMWInst::setSyncScopeID(SyncScope::ID SSID) {1279Ctx.getTracker()1280.emplaceIfTracking<GenericSetter<&AtomicRMWInst::getSyncScopeID,1281&AtomicRMWInst::setSyncScopeID>>(this);1282cast<llvm::AtomicRMWInst>(Val)->setSyncScopeID(SSID);1283}12841285Value *AtomicRMWInst::getPointerOperand() {1286return Ctx.getValue(cast<llvm::AtomicRMWInst>(Val)->getPointerOperand());1287}12881289Value *AtomicRMWInst::getValOperand() {1290return Ctx.getValue(cast<llvm::AtomicRMWInst>(Val)->getValOperand());1291}12921293AtomicRMWInst *AtomicRMWInst::create(BinOp Op, Value *Ptr, Value *Val,1294MaybeAlign Align, AtomicOrdering Ordering,1295InsertPosition Pos, Context &Ctx,1296SyncScope::ID SSID, const Twine &Name) {1297auto &Builder = setInsertPos(Pos);1298auto *LLVMAtomicRMW =1299Builder.CreateAtomicRMW(Op, Ptr->Val, Val->Val, Align, Ordering, SSID);1300LLVMAtomicRMW->setName(Name);1301return Ctx.createAtomicRMWInst(LLVMAtomicRMW);1302}13031304void AtomicCmpXchgInst::setSyncScopeID(SyncScope::ID SSID) {1305Ctx.getTracker()1306.emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getSyncScopeID,1307&AtomicCmpXchgInst::setSyncScopeID>>(1308this);1309cast<llvm::AtomicCmpXchgInst>(Val)->setSyncScopeID(SSID);1310}13111312Value *AtomicCmpXchgInst::getPointerOperand() {1313return Ctx.getValue(cast<llvm::AtomicCmpXchgInst>(Val)->getPointerOperand());1314}13151316Value *AtomicCmpXchgInst::getCompareOperand() {1317return Ctx.getValue(cast<llvm::AtomicCmpXchgInst>(Val)->getCompareOperand());1318}13191320Value *AtomicCmpXchgInst::getNewValOperand() {1321return Ctx.getValue(cast<llvm::AtomicCmpXchgInst>(Val)->getNewValOperand());1322}13231324AtomicCmpXchgInst *1325AtomicCmpXchgInst::create(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align,1326AtomicOrdering SuccessOrdering,1327AtomicOrdering FailureOrdering, InsertPosition Pos,1328Context &Ctx, SyncScope::ID SSID, const Twine &Name) {1329auto &Builder = setInsertPos(Pos);1330auto *LLVMAtomicCmpXchg =1331Builder.CreateAtomicCmpXchg(Ptr->Val, Cmp->Val, New->Val, Align,1332SuccessOrdering, FailureOrdering, SSID);1333LLVMAtomicCmpXchg->setName(Name);1334return Ctx.createAtomicCmpXchgInst(LLVMAtomicCmpXchg);1335}13361337void AtomicCmpXchgInst::setAlignment(Align Align) {1338Ctx.getTracker()1339.emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getAlign,1340&AtomicCmpXchgInst::setAlignment>>(this);1341cast<llvm::AtomicCmpXchgInst>(Val)->setAlignment(Align);1342}13431344void AtomicCmpXchgInst::setVolatile(bool V) {1345Ctx.getTracker()1346.emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::isVolatile,1347&AtomicCmpXchgInst::setVolatile>>(this);1348cast<llvm::AtomicCmpXchgInst>(Val)->setVolatile(V);1349}13501351void AtomicCmpXchgInst::setWeak(bool IsWeak) {1352Ctx.getTracker()1353.emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::isWeak,1354&AtomicCmpXchgInst::setWeak>>(this);1355cast<llvm::AtomicCmpXchgInst>(Val)->setWeak(IsWeak);1356}13571358void AtomicCmpXchgInst::setSuccessOrdering(AtomicOrdering Ordering) {1359Ctx.getTracker()1360.emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getSuccessOrdering,1361&AtomicCmpXchgInst::setSuccessOrdering>>(1362this);1363cast<llvm::AtomicCmpXchgInst>(Val)->setSuccessOrdering(Ordering);1364}13651366void AtomicCmpXchgInst::setFailureOrdering(AtomicOrdering Ordering) {1367Ctx.getTracker()1368.emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getFailureOrdering,1369&AtomicCmpXchgInst::setFailureOrdering>>(1370this);1371cast<llvm::AtomicCmpXchgInst>(Val)->setFailureOrdering(Ordering);1372}13731374AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace, InsertPosition Pos,1375Context &Ctx, Value *ArraySize,1376const Twine &Name) {1377auto &Builder = setInsertPos(Pos);1378auto *NewAlloca =1379Builder.CreateAlloca(Ty->LLVMTy, AddrSpace, ArraySize->Val, Name);1380return Ctx.createAllocaInst(NewAlloca);1381}13821383Type *AllocaInst::getAllocatedType() const {1384return Ctx.getType(cast<llvm::AllocaInst>(Val)->getAllocatedType());1385}13861387void AllocaInst::setAllocatedType(Type *Ty) {1388Ctx.getTracker()1389.emplaceIfTracking<GenericSetter<&AllocaInst::getAllocatedType,1390&AllocaInst::setAllocatedType>>(this);1391cast<llvm::AllocaInst>(Val)->setAllocatedType(Ty->LLVMTy);1392}13931394void AllocaInst::setAlignment(Align Align) {1395Ctx.getTracker()1396.emplaceIfTracking<1397GenericSetter<&AllocaInst::getAlign, &AllocaInst::setAlignment>>(1398this);1399cast<llvm::AllocaInst>(Val)->setAlignment(Align);1400}14011402void AllocaInst::setUsedWithInAlloca(bool V) {1403Ctx.getTracker()1404.emplaceIfTracking<GenericSetter<&AllocaInst::isUsedWithInAlloca,1405&AllocaInst::setUsedWithInAlloca>>(this);1406cast<llvm::AllocaInst>(Val)->setUsedWithInAlloca(V);1407}14081409Value *AllocaInst::getArraySize() {1410return Ctx.getValue(cast<llvm::AllocaInst>(Val)->getArraySize());1411}14121413PointerType *AllocaInst::getType() const {1414return cast<PointerType>(Ctx.getType(cast<llvm::AllocaInst>(Val)->getType()));1415}14161417Value *CastInst::create(Type *DestTy, Opcode Op, Value *Operand,1418InsertPosition Pos, Context &Ctx, const Twine &Name) {1419assert(getLLVMCastOp(Op) && "Opcode not suitable for CastInst!");1420auto &Builder = setInsertPos(Pos);1421auto *NewV =1422Builder.CreateCast(getLLVMCastOp(Op), Operand->Val, DestTy->LLVMTy, Name);1423if (auto *NewCI = dyn_cast<llvm::CastInst>(NewV))1424return Ctx.createCastInst(NewCI);1425assert(isa<llvm::Constant>(NewV) && "Expected constant");1426return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));1427}14281429bool CastInst::classof(const Value *From) {1430return From->getSubclassID() == ClassID::Cast;1431}14321433Type *CastInst::getSrcTy() const {1434return Ctx.getType(cast<llvm::CastInst>(Val)->getSrcTy());1435}14361437Type *CastInst::getDestTy() const {1438return Ctx.getType(cast<llvm::CastInst>(Val)->getDestTy());1439}14401441void PossiblyNonNegInst::setNonNeg(bool B) {1442Ctx.getTracker()1443.emplaceIfTracking<GenericSetter<&PossiblyNonNegInst::hasNonNeg,1444&PossiblyNonNegInst::setNonNeg>>(this);1445cast<llvm::PossiblyNonNegInst>(Val)->setNonNeg(B);1446}14471448Value *InsertElementInst::create(Value *Vec, Value *NewElt, Value *Idx,1449InsertPosition Pos, Context &Ctx,1450const Twine &Name) {1451auto &Builder = Instruction::setInsertPos(Pos);1452llvm::Value *NewV =1453Builder.CreateInsertElement(Vec->Val, NewElt->Val, Idx->Val, Name);1454if (auto *NewInsert = dyn_cast<llvm::InsertElementInst>(NewV))1455return Ctx.createInsertElementInst(NewInsert);1456assert(isa<llvm::Constant>(NewV) && "Expected constant");1457return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));1458}14591460Value *ExtractElementInst::create(Value *Vec, Value *Idx, InsertPosition Pos,1461Context &Ctx, const Twine &Name) {1462auto &Builder = setInsertPos(Pos);1463llvm::Value *NewV = Builder.CreateExtractElement(Vec->Val, Idx->Val, Name);1464if (auto *NewExtract = dyn_cast<llvm::ExtractElementInst>(NewV))1465return Ctx.createExtractElementInst(NewExtract);1466assert(isa<llvm::Constant>(NewV) && "Expected constant");1467return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));1468}14691470Value *ShuffleVectorInst::create(Value *V1, Value *V2, Value *Mask,1471InsertPosition Pos, Context &Ctx,1472const Twine &Name) {1473auto &Builder = setInsertPos(Pos);1474llvm::Value *NewV =1475Builder.CreateShuffleVector(V1->Val, V2->Val, Mask->Val, Name);1476if (auto *NewShuffle = dyn_cast<llvm::ShuffleVectorInst>(NewV))1477return Ctx.createShuffleVectorInst(NewShuffle);1478assert(isa<llvm::Constant>(NewV) && "Expected constant");1479return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));1480}14811482Value *ShuffleVectorInst::create(Value *V1, Value *V2, ArrayRef<int> Mask,1483InsertPosition Pos, Context &Ctx,1484const Twine &Name) {1485auto &Builder = setInsertPos(Pos);1486llvm::Value *NewV = Builder.CreateShuffleVector(V1->Val, V2->Val, Mask, Name);1487if (auto *NewShuffle = dyn_cast<llvm::ShuffleVectorInst>(NewV))1488return Ctx.createShuffleVectorInst(NewShuffle);1489assert(isa<llvm::Constant>(NewV) && "Expected constant");1490return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));1491}14921493void ShuffleVectorInst::setShuffleMask(ArrayRef<int> Mask) {1494Ctx.getTracker().emplaceIfTracking<ShuffleVectorSetMask>(this);1495cast<llvm::ShuffleVectorInst>(Val)->setShuffleMask(Mask);1496}14971498VectorType *ShuffleVectorInst::getType() const {1499return cast<VectorType>(1500Ctx.getType(cast<llvm::ShuffleVectorInst>(Val)->getType()));1501}15021503void ShuffleVectorInst::commute() {1504Ctx.getTracker().emplaceIfTracking<ShuffleVectorSetMask>(this);1505Ctx.getTracker().emplaceIfTracking<UseSwap>(getOperandUse(0),1506getOperandUse(1));1507cast<llvm::ShuffleVectorInst>(Val)->commute();1508}15091510Constant *ShuffleVectorInst::getShuffleMaskForBitcode() const {1511return Ctx.getOrCreateConstant(1512cast<llvm::ShuffleVectorInst>(Val)->getShuffleMaskForBitcode());1513}15141515Constant *ShuffleVectorInst::convertShuffleMaskForBitcode(ArrayRef<int> Mask,1516Type *ResultTy) {1517return ResultTy->getContext().getOrCreateConstant(1518llvm::ShuffleVectorInst::convertShuffleMaskForBitcode(Mask,1519ResultTy->LLVMTy));1520}15211522VectorType *ExtractElementInst::getVectorOperandType() const {1523return cast<VectorType>(Ctx.getType(getVectorOperand()->getType()->LLVMTy));1524}15251526Value *ExtractValueInst::create(Value *Agg, ArrayRef<unsigned> Idxs,1527InsertPosition Pos, Context &Ctx,1528const Twine &Name) {1529auto &Builder = setInsertPos(Pos);1530llvm::Value *NewV = Builder.CreateExtractValue(Agg->Val, Idxs, Name);1531if (auto *NewExtractValueInst = dyn_cast<llvm::ExtractValueInst>(NewV))1532return Ctx.createExtractValueInst(NewExtractValueInst);1533assert(isa<llvm::Constant>(NewV) && "Expected constant");1534return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));1535}15361537Type *ExtractValueInst::getIndexedType(Type *Agg, ArrayRef<unsigned> Idxs) {1538auto *LLVMTy = llvm::ExtractValueInst::getIndexedType(Agg->LLVMTy, Idxs);1539return Agg->getContext().getType(LLVMTy);1540}15411542Value *InsertValueInst::create(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,1543InsertPosition Pos, Context &Ctx,1544const Twine &Name) {1545auto &Builder = setInsertPos(Pos);1546llvm::Value *NewV = Builder.CreateInsertValue(Agg->Val, Val->Val, Idxs, Name);1547if (auto *NewInsertValueInst = dyn_cast<llvm::InsertValueInst>(NewV))1548return Ctx.createInsertValueInst(NewInsertValueInst);1549assert(isa<llvm::Constant>(NewV) && "Expected constant");1550return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));1551}15521553ConstantTokenNone *ConstantTokenNone::get(Context &Ctx) {1554auto *LLVMC = llvm::ConstantTokenNone::get(Ctx.LLVMCtx);1555return cast<ConstantTokenNone>(Ctx.getOrCreateConstant(LLVMC));1556}15571558} // namespace llvm::sandboxir155915601561