
This introduces a new `ptrtoaddr` instruction which is similar to `ptrtoint` but has two differences: 1) Unlike `ptrtoint`, `ptrtoaddr` does not capture provenance 2) `ptrtoaddr` only extracts (and then extends/truncates) the low index-width bits of the pointer For most architectures, difference 2) does not matter since index (address) width and pointer representation width are the same, but this does make a difference for architectures that have pointers that aren't just plain integer addresses such as AMDGPU fat pointers or CHERI capabilities. This commit introduces textual and bitcode IR support as well as basic code generation, but optimization passes do not handle the new instruction yet so it may result in worse code than using ptrtoint. Follow-up changes will update capture tracking, etc. for the new instruction. RFC: https://discourse.llvm.org/t/clarifiying-the-semantics-of-ptrtoint/83987/54 Reviewed By: nikic Pull Request: https://github.com/llvm/llvm-project/pull/139357
1563 lines
59 KiB
C++
1563 lines
59 KiB
C++
//===- Instruction.cpp - The Instructions of Sandbox IR -------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/SandboxIR/Instruction.h"
|
|
#include "llvm/SandboxIR/Function.h"
|
|
|
|
namespace llvm::sandboxir {
|
|
|
|
const char *Instruction::getOpcodeName(Opcode Opc) {
|
|
switch (Opc) {
|
|
#define OP(OPC) \
|
|
case Opcode::OPC: \
|
|
return #OPC;
|
|
#define OPCODES(...) __VA_ARGS__
|
|
#define DEF_INSTR(ID, OPC, CLASS) OPC
|
|
#include "llvm/SandboxIR/Values.def"
|
|
}
|
|
llvm_unreachable("Unknown Opcode");
|
|
}
|
|
|
|
llvm::Instruction *Instruction::getTopmostLLVMInstruction() const {
|
|
Instruction *Prev = getPrevNode();
|
|
if (Prev == nullptr) {
|
|
// If at top of the BB, return the first BB instruction.
|
|
return &*cast<llvm::BasicBlock>(getParent()->Val)->begin();
|
|
}
|
|
// Else get the Previous sandbox IR instruction's bottom IR instruction and
|
|
// return its successor.
|
|
llvm::Instruction *PrevBotI = cast<llvm::Instruction>(Prev->Val);
|
|
return PrevBotI->getNextNode();
|
|
}
|
|
|
|
BBIterator Instruction::getIterator() const {
|
|
auto *I = cast<llvm::Instruction>(Val);
|
|
return BasicBlock::iterator(I->getParent(), I->getIterator(), &Ctx);
|
|
}
|
|
|
|
Instruction *Instruction::getNextNode() const {
|
|
assert(getParent() != nullptr && "Detached!");
|
|
assert(getIterator() != getParent()->end() && "Already at end!");
|
|
// `Val` is the bottom-most LLVM IR instruction. Get the next in the chain,
|
|
// and get the corresponding sandboxir Instruction that maps to it. This works
|
|
// even for SandboxIR Instructions that map to more than one LLVM Instruction.
|
|
auto *LLVMI = cast<llvm::Instruction>(Val);
|
|
assert(LLVMI->getParent() != nullptr && "LLVM IR instr is detached!");
|
|
auto *NextLLVMI = LLVMI->getNextNode();
|
|
auto *NextI = cast_or_null<Instruction>(Ctx.getValue(NextLLVMI));
|
|
if (NextI == nullptr)
|
|
return nullptr;
|
|
return NextI;
|
|
}
|
|
|
|
Instruction *Instruction::getPrevNode() const {
|
|
assert(getParent() != nullptr && "Detached!");
|
|
auto It = getIterator();
|
|
if (It != getParent()->begin())
|
|
return std::prev(getIterator()).get();
|
|
return nullptr;
|
|
}
|
|
|
|
void Instruction::removeFromParent() {
|
|
Ctx.getTracker().emplaceIfTracking<RemoveFromParent>(this);
|
|
|
|
// Detach all the LLVM IR instructions from their parent BB.
|
|
for (llvm::Instruction *I : getLLVMInstrs())
|
|
I->removeFromParent();
|
|
}
|
|
|
|
void Instruction::eraseFromParent() {
|
|
assert(users().empty() && "Still connected to users, can't erase!");
|
|
|
|
Ctx.runEraseInstrCallbacks(this);
|
|
std::unique_ptr<Value> Detached = Ctx.detach(this);
|
|
auto LLVMInstrs = getLLVMInstrs();
|
|
|
|
auto &Tracker = Ctx.getTracker();
|
|
if (Tracker.isTracking()) {
|
|
Tracker.track(std::make_unique<EraseFromParent>(std::move(Detached)));
|
|
// We don't actually delete the IR instruction, because then it would be
|
|
// impossible to bring it back from the dead at the same memory location.
|
|
// Instead we remove it from its BB and track its current location.
|
|
for (llvm::Instruction *I : LLVMInstrs)
|
|
I->removeFromParent();
|
|
// TODO: Multi-instructions need special treatment because some of the
|
|
// references are internal to the instruction.
|
|
for (llvm::Instruction *I : LLVMInstrs)
|
|
I->dropAllReferences();
|
|
} else {
|
|
// Erase in reverse to avoid erasing nstructions with attached uses.
|
|
for (llvm::Instruction *I : reverse(LLVMInstrs))
|
|
I->eraseFromParent();
|
|
}
|
|
}
|
|
|
|
void Instruction::moveBefore(BasicBlock &BB, const BBIterator &WhereIt) {
|
|
if (std::next(getIterator()) == WhereIt)
|
|
// Destination is same as origin, nothing to do.
|
|
return;
|
|
|
|
Ctx.runMoveInstrCallbacks(this, WhereIt);
|
|
Ctx.getTracker().emplaceIfTracking<MoveInstr>(this);
|
|
|
|
auto *LLVMBB = cast<llvm::BasicBlock>(BB.Val);
|
|
llvm::BasicBlock::iterator It;
|
|
if (WhereIt == BB.end()) {
|
|
It = LLVMBB->end();
|
|
} else {
|
|
Instruction *WhereI = &*WhereIt;
|
|
It = WhereI->getTopmostLLVMInstruction()->getIterator();
|
|
}
|
|
// TODO: Move this to the verifier of sandboxir::Instruction.
|
|
assert(is_sorted(getLLVMInstrs(),
|
|
[](auto *I1, auto *I2) { return I1->comesBefore(I2); }) &&
|
|
"Expected program order!");
|
|
// Do the actual move in LLVM IR.
|
|
for (auto *I : getLLVMInstrs())
|
|
I->moveBefore(*LLVMBB, It);
|
|
}
|
|
|
|
void Instruction::insertBefore(Instruction *BeforeI) {
|
|
llvm::Instruction *BeforeTopI = BeforeI->getTopmostLLVMInstruction();
|
|
|
|
Ctx.getTracker().emplaceIfTracking<InsertIntoBB>(this);
|
|
|
|
// Insert the LLVM IR Instructions in program order.
|
|
for (llvm::Instruction *I : getLLVMInstrs())
|
|
I->insertBefore(BeforeTopI->getIterator());
|
|
}
|
|
|
|
void Instruction::insertAfter(Instruction *AfterI) {
|
|
insertInto(AfterI->getParent(), std::next(AfterI->getIterator()));
|
|
}
|
|
|
|
void Instruction::insertInto(BasicBlock *BB, const BBIterator &WhereIt) {
|
|
llvm::BasicBlock *LLVMBB = cast<llvm::BasicBlock>(BB->Val);
|
|
llvm::Instruction *LLVMBeforeI;
|
|
llvm::BasicBlock::iterator LLVMBeforeIt;
|
|
Instruction *BeforeI;
|
|
if (WhereIt != BB->end()) {
|
|
BeforeI = &*WhereIt;
|
|
LLVMBeforeI = BeforeI->getTopmostLLVMInstruction();
|
|
LLVMBeforeIt = LLVMBeforeI->getIterator();
|
|
} else {
|
|
BeforeI = nullptr;
|
|
LLVMBeforeI = nullptr;
|
|
LLVMBeforeIt = LLVMBB->end();
|
|
}
|
|
|
|
Ctx.getTracker().emplaceIfTracking<InsertIntoBB>(this);
|
|
|
|
// Insert the LLVM IR Instructions in program order.
|
|
for (llvm::Instruction *I : getLLVMInstrs())
|
|
I->insertInto(LLVMBB, LLVMBeforeIt);
|
|
}
|
|
|
|
BasicBlock *Instruction::getParent() const {
|
|
// Get the LLVM IR Instruction that this maps to, get its parent, and get the
|
|
// corresponding sandboxir::BasicBlock by looking it up in sandboxir::Context.
|
|
auto *BB = cast<llvm::Instruction>(Val)->getParent();
|
|
if (BB == nullptr)
|
|
return nullptr;
|
|
return cast<BasicBlock>(Ctx.getValue(BB));
|
|
}
|
|
|
|
bool Instruction::classof(const sandboxir::Value *From) {
|
|
switch (From->getSubclassID()) {
|
|
#define DEF_INSTR(ID, OPC, CLASS) \
|
|
case ClassID::ID: \
|
|
return true;
|
|
#include "llvm/SandboxIR/Values.def"
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void Instruction::setHasNoUnsignedWrap(bool B) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&Instruction::hasNoUnsignedWrap,
|
|
&Instruction::setHasNoUnsignedWrap>>(
|
|
this);
|
|
cast<llvm::Instruction>(Val)->setHasNoUnsignedWrap(B);
|
|
}
|
|
|
|
void Instruction::setHasNoSignedWrap(bool B) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&Instruction::hasNoSignedWrap,
|
|
&Instruction::setHasNoSignedWrap>>(this);
|
|
cast<llvm::Instruction>(Val)->setHasNoSignedWrap(B);
|
|
}
|
|
|
|
void Instruction::setFast(bool B) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<
|
|
GenericSetter<&Instruction::isFast, &Instruction::setFast>>(this);
|
|
cast<llvm::Instruction>(Val)->setFast(B);
|
|
}
|
|
|
|
void Instruction::setIsExact(bool B) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<
|
|
GenericSetter<&Instruction::isExact, &Instruction::setIsExact>>(this);
|
|
cast<llvm::Instruction>(Val)->setIsExact(B);
|
|
}
|
|
|
|
void Instruction::setHasAllowReassoc(bool B) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&Instruction::hasAllowReassoc,
|
|
&Instruction::setHasAllowReassoc>>(this);
|
|
cast<llvm::Instruction>(Val)->setHasAllowReassoc(B);
|
|
}
|
|
|
|
void Instruction::setHasNoNaNs(bool B) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<
|
|
GenericSetter<&Instruction::hasNoNaNs, &Instruction::setHasNoNaNs>>(
|
|
this);
|
|
cast<llvm::Instruction>(Val)->setHasNoNaNs(B);
|
|
}
|
|
|
|
void Instruction::setHasNoInfs(bool B) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<
|
|
GenericSetter<&Instruction::hasNoInfs, &Instruction::setHasNoInfs>>(
|
|
this);
|
|
cast<llvm::Instruction>(Val)->setHasNoInfs(B);
|
|
}
|
|
|
|
void Instruction::setHasNoSignedZeros(bool B) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&Instruction::hasNoSignedZeros,
|
|
&Instruction::setHasNoSignedZeros>>(
|
|
this);
|
|
cast<llvm::Instruction>(Val)->setHasNoSignedZeros(B);
|
|
}
|
|
|
|
void Instruction::setHasAllowReciprocal(bool B) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&Instruction::hasAllowReciprocal,
|
|
&Instruction::setHasAllowReciprocal>>(
|
|
this);
|
|
cast<llvm::Instruction>(Val)->setHasAllowReciprocal(B);
|
|
}
|
|
|
|
void Instruction::setHasAllowContract(bool B) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&Instruction::hasAllowContract,
|
|
&Instruction::setHasAllowContract>>(
|
|
this);
|
|
cast<llvm::Instruction>(Val)->setHasAllowContract(B);
|
|
}
|
|
|
|
void Instruction::setFastMathFlags(FastMathFlags FMF) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&Instruction::getFastMathFlags,
|
|
&Instruction::copyFastMathFlags>>(this);
|
|
cast<llvm::Instruction>(Val)->setFastMathFlags(FMF);
|
|
}
|
|
|
|
void Instruction::copyFastMathFlags(FastMathFlags FMF) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&Instruction::getFastMathFlags,
|
|
&Instruction::copyFastMathFlags>>(this);
|
|
cast<llvm::Instruction>(Val)->copyFastMathFlags(FMF);
|
|
}
|
|
|
|
Type *Instruction::getAccessType() const {
|
|
return Ctx.getType(cast<llvm::Instruction>(Val)->getAccessType());
|
|
}
|
|
|
|
void Instruction::setHasApproxFunc(bool B) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&Instruction::hasApproxFunc,
|
|
&Instruction::setHasApproxFunc>>(this);
|
|
cast<llvm::Instruction>(Val)->setHasApproxFunc(B);
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
void Instruction::dumpOS(raw_ostream &OS) const {
|
|
OS << "Unimplemented! Please override dump().";
|
|
}
|
|
#endif // NDEBUG
|
|
|
|
VAArgInst *VAArgInst::create(Value *List, Type *Ty, InsertPosition Pos,
|
|
Context &Ctx, const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
auto *LLVMI =
|
|
cast<llvm::VAArgInst>(Builder.CreateVAArg(List->Val, Ty->LLVMTy, Name));
|
|
return Ctx.createVAArgInst(LLVMI);
|
|
}
|
|
|
|
Value *VAArgInst::getPointerOperand() {
|
|
return Ctx.getValue(cast<llvm::VAArgInst>(Val)->getPointerOperand());
|
|
}
|
|
|
|
FreezeInst *FreezeInst::create(Value *V, InsertPosition Pos, Context &Ctx,
|
|
const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
auto *LLVMI = cast<llvm::FreezeInst>(Builder.CreateFreeze(V->Val, Name));
|
|
return Ctx.createFreezeInst(LLVMI);
|
|
}
|
|
|
|
FenceInst *FenceInst::create(AtomicOrdering Ordering, InsertPosition Pos,
|
|
Context &Ctx, SyncScope::ID SSID) {
|
|
auto &Builder = Instruction::setInsertPos(Pos);
|
|
llvm::FenceInst *LLVMI = Builder.CreateFence(Ordering, SSID);
|
|
return Ctx.createFenceInst(LLVMI);
|
|
}
|
|
|
|
void FenceInst::setOrdering(AtomicOrdering Ordering) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<
|
|
GenericSetter<&FenceInst::getOrdering, &FenceInst::setOrdering>>(
|
|
this);
|
|
cast<llvm::FenceInst>(Val)->setOrdering(Ordering);
|
|
}
|
|
|
|
void FenceInst::setSyncScopeID(SyncScope::ID SSID) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&FenceInst::getSyncScopeID,
|
|
&FenceInst::setSyncScopeID>>(this);
|
|
cast<llvm::FenceInst>(Val)->setSyncScopeID(SSID);
|
|
}
|
|
|
|
Value *SelectInst::create(Value *Cond, Value *True, Value *False,
|
|
InsertPosition Pos, Context &Ctx, const Twine &Name) {
|
|
auto &Builder = Instruction::setInsertPos(Pos);
|
|
llvm::Value *NewV =
|
|
Builder.CreateSelect(Cond->Val, True->Val, False->Val, Name);
|
|
if (auto *NewSI = dyn_cast<llvm::SelectInst>(NewV))
|
|
return Ctx.createSelectInst(NewSI);
|
|
assert(isa<llvm::Constant>(NewV) && "Expected constant");
|
|
return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
|
|
}
|
|
|
|
void SelectInst::swapValues() {
|
|
Ctx.getTracker().emplaceIfTracking<UseSwap>(getOperandUse(1),
|
|
getOperandUse(2));
|
|
cast<llvm::SelectInst>(Val)->swapValues();
|
|
}
|
|
|
|
bool SelectInst::classof(const Value *From) {
|
|
return From->getSubclassID() == ClassID::Select;
|
|
}
|
|
|
|
BranchInst *BranchInst::create(BasicBlock *IfTrue, InsertPosition Pos,
|
|
Context &Ctx) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
llvm::BranchInst *NewBr =
|
|
Builder.CreateBr(cast<llvm::BasicBlock>(IfTrue->Val));
|
|
return Ctx.createBranchInst(NewBr);
|
|
}
|
|
|
|
BranchInst *BranchInst::create(BasicBlock *IfTrue, BasicBlock *IfFalse,
|
|
Value *Cond, InsertPosition Pos, Context &Ctx) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
llvm::BranchInst *NewBr =
|
|
Builder.CreateCondBr(Cond->Val, cast<llvm::BasicBlock>(IfTrue->Val),
|
|
cast<llvm::BasicBlock>(IfFalse->Val));
|
|
return Ctx.createBranchInst(NewBr);
|
|
}
|
|
|
|
bool BranchInst::classof(const Value *From) {
|
|
return From->getSubclassID() == ClassID::Br;
|
|
}
|
|
|
|
Value *BranchInst::getCondition() const {
|
|
assert(isConditional() && "Cannot get condition of an uncond branch!");
|
|
return Ctx.getValue(cast<llvm::BranchInst>(Val)->getCondition());
|
|
}
|
|
|
|
BasicBlock *BranchInst::getSuccessor(unsigned SuccIdx) const {
|
|
assert(SuccIdx < getNumSuccessors() &&
|
|
"Successor # out of range for Branch!");
|
|
return cast_or_null<BasicBlock>(
|
|
Ctx.getValue(cast<llvm::BranchInst>(Val)->getSuccessor(SuccIdx)));
|
|
}
|
|
|
|
void BranchInst::setSuccessor(unsigned Idx, BasicBlock *NewSucc) {
|
|
assert((Idx == 0 || Idx == 1) && "Out of bounds!");
|
|
setOperand(2u - Idx, NewSucc);
|
|
}
|
|
|
|
BasicBlock *BranchInst::LLVMBBToSBBB::operator()(llvm::BasicBlock *BB) const {
|
|
return cast<BasicBlock>(Ctx.getValue(BB));
|
|
}
|
|
const BasicBlock *
|
|
BranchInst::ConstLLVMBBToSBBB::operator()(const llvm::BasicBlock *BB) const {
|
|
return cast<BasicBlock>(Ctx.getValue(BB));
|
|
}
|
|
|
|
void LoadInst::setVolatile(bool V) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<
|
|
GenericSetter<&LoadInst::isVolatile, &LoadInst::setVolatile>>(this);
|
|
cast<llvm::LoadInst>(Val)->setVolatile(V);
|
|
}
|
|
|
|
LoadInst *LoadInst::create(Type *Ty, Value *Ptr, MaybeAlign Align,
|
|
InsertPosition Pos, bool IsVolatile, Context &Ctx,
|
|
const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
auto *NewLI =
|
|
Builder.CreateAlignedLoad(Ty->LLVMTy, Ptr->Val, Align, IsVolatile, Name);
|
|
auto *NewSBI = Ctx.createLoadInst(NewLI);
|
|
return NewSBI;
|
|
}
|
|
|
|
bool LoadInst::classof(const Value *From) {
|
|
return From->getSubclassID() == ClassID::Load;
|
|
}
|
|
|
|
Value *LoadInst::getPointerOperand() const {
|
|
return Ctx.getValue(cast<llvm::LoadInst>(Val)->getPointerOperand());
|
|
}
|
|
|
|
void StoreInst::setVolatile(bool V) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<
|
|
GenericSetter<&StoreInst::isVolatile, &StoreInst::setVolatile>>(this);
|
|
cast<llvm::StoreInst>(Val)->setVolatile(V);
|
|
}
|
|
|
|
StoreInst *StoreInst::create(Value *V, Value *Ptr, MaybeAlign Align,
|
|
InsertPosition Pos, bool IsVolatile,
|
|
Context &Ctx) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
auto *NewSI = Builder.CreateAlignedStore(V->Val, Ptr->Val, Align, IsVolatile);
|
|
auto *NewSBI = Ctx.createStoreInst(NewSI);
|
|
return NewSBI;
|
|
}
|
|
|
|
bool StoreInst::classof(const Value *From) {
|
|
return From->getSubclassID() == ClassID::Store;
|
|
}
|
|
|
|
Value *StoreInst::getValueOperand() const {
|
|
return Ctx.getValue(cast<llvm::StoreInst>(Val)->getValueOperand());
|
|
}
|
|
|
|
Value *StoreInst::getPointerOperand() const {
|
|
return Ctx.getValue(cast<llvm::StoreInst>(Val)->getPointerOperand());
|
|
}
|
|
|
|
UnreachableInst *UnreachableInst::create(InsertPosition Pos, Context &Ctx) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
llvm::UnreachableInst *NewUI = Builder.CreateUnreachable();
|
|
return Ctx.createUnreachableInst(NewUI);
|
|
}
|
|
|
|
bool UnreachableInst::classof(const Value *From) {
|
|
return From->getSubclassID() == ClassID::Unreachable;
|
|
}
|
|
|
|
ReturnInst *ReturnInst::createCommon(Value *RetVal, IRBuilder<> &Builder,
|
|
Context &Ctx) {
|
|
llvm::ReturnInst *NewRI;
|
|
if (RetVal != nullptr)
|
|
NewRI = Builder.CreateRet(RetVal->Val);
|
|
else
|
|
NewRI = Builder.CreateRetVoid();
|
|
return Ctx.createReturnInst(NewRI);
|
|
}
|
|
|
|
ReturnInst *ReturnInst::create(Value *RetVal, InsertPosition Pos,
|
|
Context &Ctx) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
return createCommon(RetVal, Builder, Ctx);
|
|
}
|
|
|
|
Value *ReturnInst::getReturnValue() const {
|
|
auto *LLVMRetVal = cast<llvm::ReturnInst>(Val)->getReturnValue();
|
|
return LLVMRetVal != nullptr ? Ctx.getValue(LLVMRetVal) : nullptr;
|
|
}
|
|
|
|
FunctionType *CallBase::getFunctionType() const {
|
|
return cast<FunctionType>(
|
|
Ctx.getType(cast<llvm::CallBase>(Val)->getFunctionType()));
|
|
}
|
|
|
|
Value *CallBase::getCalledOperand() const {
|
|
return Ctx.getValue(cast<llvm::CallBase>(Val)->getCalledOperand());
|
|
}
|
|
|
|
Use CallBase::getCalledOperandUse() const {
|
|
llvm::Use *LLVMUse = &cast<llvm::CallBase>(Val)->getCalledOperandUse();
|
|
return Use(LLVMUse, cast<User>(Ctx.getValue(LLVMUse->getUser())), Ctx);
|
|
}
|
|
|
|
Function *CallBase::getCalledFunction() const {
|
|
return cast_or_null<Function>(
|
|
Ctx.getValue(cast<llvm::CallBase>(Val)->getCalledFunction()));
|
|
}
|
|
Function *CallBase::getCaller() {
|
|
return cast<Function>(Ctx.getValue(cast<llvm::CallBase>(Val)->getCaller()));
|
|
}
|
|
|
|
void CallBase::setCalledFunction(Function *F) {
|
|
// F's function type is private, so we rely on `setCalledFunction()` to update
|
|
// it. But even though we are calling `setCalledFunction()` we also need to
|
|
// track this change at the SandboxIR level, which is why we call
|
|
// `setCalledOperand()` here.
|
|
// Note: This may break if `setCalledFunction()` early returns if `F`
|
|
// is already set, but we do have a unit test for it.
|
|
setCalledOperand(F);
|
|
cast<llvm::CallBase>(Val)->setCalledFunction(
|
|
cast<llvm::FunctionType>(F->getFunctionType()->LLVMTy),
|
|
cast<llvm::Function>(F->Val));
|
|
}
|
|
|
|
CallInst *CallInst::create(FunctionType *FTy, Value *Func,
|
|
ArrayRef<Value *> Args, InsertPosition Pos,
|
|
Context &Ctx, const Twine &NameStr) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
SmallVector<llvm::Value *> LLVMArgs;
|
|
LLVMArgs.reserve(Args.size());
|
|
for (Value *Arg : Args)
|
|
LLVMArgs.push_back(Arg->Val);
|
|
llvm::CallInst *NewCI = Builder.CreateCall(
|
|
cast<llvm::FunctionType>(FTy->LLVMTy), Func->Val, LLVMArgs, NameStr);
|
|
return Ctx.createCallInst(NewCI);
|
|
}
|
|
|
|
InvokeInst *InvokeInst::create(FunctionType *FTy, Value *Func,
|
|
BasicBlock *IfNormal, BasicBlock *IfException,
|
|
ArrayRef<Value *> Args, InsertPosition Pos,
|
|
Context &Ctx, const Twine &NameStr) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
SmallVector<llvm::Value *> LLVMArgs;
|
|
LLVMArgs.reserve(Args.size());
|
|
for (Value *Arg : Args)
|
|
LLVMArgs.push_back(Arg->Val);
|
|
llvm::InvokeInst *Invoke = Builder.CreateInvoke(
|
|
cast<llvm::FunctionType>(FTy->LLVMTy), Func->Val,
|
|
cast<llvm::BasicBlock>(IfNormal->Val),
|
|
cast<llvm::BasicBlock>(IfException->Val), LLVMArgs, NameStr);
|
|
return Ctx.createInvokeInst(Invoke);
|
|
}
|
|
|
|
BasicBlock *InvokeInst::getNormalDest() const {
|
|
return cast<BasicBlock>(
|
|
Ctx.getValue(cast<llvm::InvokeInst>(Val)->getNormalDest()));
|
|
}
|
|
BasicBlock *InvokeInst::getUnwindDest() const {
|
|
return cast<BasicBlock>(
|
|
Ctx.getValue(cast<llvm::InvokeInst>(Val)->getUnwindDest()));
|
|
}
|
|
void InvokeInst::setNormalDest(BasicBlock *BB) {
|
|
setOperand(1, BB);
|
|
assert(getNormalDest() == BB && "LLVM IR uses a different operan index!");
|
|
}
|
|
void InvokeInst::setUnwindDest(BasicBlock *BB) {
|
|
setOperand(2, BB);
|
|
assert(getUnwindDest() == BB && "LLVM IR uses a different operan index!");
|
|
}
|
|
LandingPadInst *InvokeInst::getLandingPadInst() const {
|
|
return cast<LandingPadInst>(
|
|
Ctx.getValue(cast<llvm::InvokeInst>(Val)->getLandingPadInst()));
|
|
;
|
|
}
|
|
BasicBlock *InvokeInst::getSuccessor(unsigned SuccIdx) const {
|
|
return cast<BasicBlock>(
|
|
Ctx.getValue(cast<llvm::InvokeInst>(Val)->getSuccessor(SuccIdx)));
|
|
}
|
|
|
|
CallBrInst *CallBrInst::create(FunctionType *FTy, Value *Func,
|
|
BasicBlock *DefaultDest,
|
|
ArrayRef<BasicBlock *> IndirectDests,
|
|
ArrayRef<Value *> Args, InsertPosition Pos,
|
|
Context &Ctx, const Twine &NameStr) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
SmallVector<llvm::BasicBlock *> LLVMIndirectDests;
|
|
LLVMIndirectDests.reserve(IndirectDests.size());
|
|
for (BasicBlock *IndDest : IndirectDests)
|
|
LLVMIndirectDests.push_back(cast<llvm::BasicBlock>(IndDest->Val));
|
|
|
|
SmallVector<llvm::Value *> LLVMArgs;
|
|
LLVMArgs.reserve(Args.size());
|
|
for (Value *Arg : Args)
|
|
LLVMArgs.push_back(Arg->Val);
|
|
|
|
llvm::CallBrInst *CallBr =
|
|
Builder.CreateCallBr(cast<llvm::FunctionType>(FTy->LLVMTy), Func->Val,
|
|
cast<llvm::BasicBlock>(DefaultDest->Val),
|
|
LLVMIndirectDests, LLVMArgs, NameStr);
|
|
return Ctx.createCallBrInst(CallBr);
|
|
}
|
|
|
|
Value *CallBrInst::getIndirectDestLabel(unsigned Idx) const {
|
|
return Ctx.getValue(cast<llvm::CallBrInst>(Val)->getIndirectDestLabel(Idx));
|
|
}
|
|
Value *CallBrInst::getIndirectDestLabelUse(unsigned Idx) const {
|
|
return Ctx.getValue(
|
|
cast<llvm::CallBrInst>(Val)->getIndirectDestLabelUse(Idx));
|
|
}
|
|
BasicBlock *CallBrInst::getDefaultDest() const {
|
|
return cast<BasicBlock>(
|
|
Ctx.getValue(cast<llvm::CallBrInst>(Val)->getDefaultDest()));
|
|
}
|
|
BasicBlock *CallBrInst::getIndirectDest(unsigned Idx) const {
|
|
return cast<BasicBlock>(
|
|
Ctx.getValue(cast<llvm::CallBrInst>(Val)->getIndirectDest(Idx)));
|
|
}
|
|
llvm::SmallVector<BasicBlock *, 16> CallBrInst::getIndirectDests() const {
|
|
SmallVector<BasicBlock *, 16> BBs;
|
|
for (llvm::BasicBlock *LLVMBB :
|
|
cast<llvm::CallBrInst>(Val)->getIndirectDests())
|
|
BBs.push_back(cast<BasicBlock>(Ctx.getValue(LLVMBB)));
|
|
return BBs;
|
|
}
|
|
void CallBrInst::setDefaultDest(BasicBlock *BB) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&CallBrInst::getDefaultDest,
|
|
&CallBrInst::setDefaultDest>>(this);
|
|
cast<llvm::CallBrInst>(Val)->setDefaultDest(cast<llvm::BasicBlock>(BB->Val));
|
|
}
|
|
void CallBrInst::setIndirectDest(unsigned Idx, BasicBlock *BB) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetterWithIdx<&CallBrInst::getIndirectDest,
|
|
&CallBrInst::setIndirectDest>>(
|
|
this, Idx);
|
|
cast<llvm::CallBrInst>(Val)->setIndirectDest(Idx,
|
|
cast<llvm::BasicBlock>(BB->Val));
|
|
}
|
|
BasicBlock *CallBrInst::getSuccessor(unsigned Idx) const {
|
|
return cast<BasicBlock>(
|
|
Ctx.getValue(cast<llvm::CallBrInst>(Val)->getSuccessor(Idx)));
|
|
}
|
|
|
|
LandingPadInst *LandingPadInst::create(Type *RetTy, unsigned NumReservedClauses,
|
|
InsertPosition Pos, Context &Ctx,
|
|
const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
llvm::LandingPadInst *LLVMI =
|
|
Builder.CreateLandingPad(RetTy->LLVMTy, NumReservedClauses, Name);
|
|
return Ctx.createLandingPadInst(LLVMI);
|
|
}
|
|
|
|
void LandingPadInst::setCleanup(bool V) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&LandingPadInst::isCleanup,
|
|
&LandingPadInst::setCleanup>>(this);
|
|
cast<llvm::LandingPadInst>(Val)->setCleanup(V);
|
|
}
|
|
|
|
Constant *LandingPadInst::getClause(unsigned Idx) const {
|
|
return cast<Constant>(
|
|
Ctx.getValue(cast<llvm::LandingPadInst>(Val)->getClause(Idx)));
|
|
}
|
|
|
|
Value *FuncletPadInst::getParentPad() const {
|
|
return Ctx.getValue(cast<llvm::FuncletPadInst>(Val)->getParentPad());
|
|
}
|
|
|
|
void FuncletPadInst::setParentPad(Value *ParentPad) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&FuncletPadInst::getParentPad,
|
|
&FuncletPadInst::setParentPad>>(this);
|
|
cast<llvm::FuncletPadInst>(Val)->setParentPad(ParentPad->Val);
|
|
}
|
|
|
|
Value *FuncletPadInst::getArgOperand(unsigned Idx) const {
|
|
return Ctx.getValue(cast<llvm::FuncletPadInst>(Val)->getArgOperand(Idx));
|
|
}
|
|
|
|
void FuncletPadInst::setArgOperand(unsigned Idx, Value *V) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetterWithIdx<&FuncletPadInst::getArgOperand,
|
|
&FuncletPadInst::setArgOperand>>(
|
|
this, Idx);
|
|
cast<llvm::FuncletPadInst>(Val)->setArgOperand(Idx, V->Val);
|
|
}
|
|
|
|
CatchSwitchInst *CatchPadInst::getCatchSwitch() const {
|
|
return cast<CatchSwitchInst>(
|
|
Ctx.getValue(cast<llvm::CatchPadInst>(Val)->getCatchSwitch()));
|
|
}
|
|
|
|
CatchPadInst *CatchPadInst::create(Value *ParentPad, ArrayRef<Value *> Args,
|
|
InsertPosition Pos, Context &Ctx,
|
|
const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
SmallVector<llvm::Value *> LLVMArgs;
|
|
LLVMArgs.reserve(Args.size());
|
|
for (auto *Arg : Args)
|
|
LLVMArgs.push_back(Arg->Val);
|
|
llvm::CatchPadInst *LLVMI =
|
|
Builder.CreateCatchPad(ParentPad->Val, LLVMArgs, Name);
|
|
return Ctx.createCatchPadInst(LLVMI);
|
|
}
|
|
|
|
CleanupPadInst *CleanupPadInst::create(Value *ParentPad, ArrayRef<Value *> Args,
|
|
InsertPosition Pos, Context &Ctx,
|
|
const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
SmallVector<llvm::Value *> LLVMArgs;
|
|
LLVMArgs.reserve(Args.size());
|
|
for (auto *Arg : Args)
|
|
LLVMArgs.push_back(Arg->Val);
|
|
llvm::CleanupPadInst *LLVMI =
|
|
Builder.CreateCleanupPad(ParentPad->Val, LLVMArgs, Name);
|
|
return Ctx.createCleanupPadInst(LLVMI);
|
|
}
|
|
|
|
CatchReturnInst *CatchReturnInst::create(CatchPadInst *CatchPad, BasicBlock *BB,
|
|
InsertPosition Pos, Context &Ctx) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
llvm::CatchReturnInst *LLVMI = Builder.CreateCatchRet(
|
|
cast<llvm::CatchPadInst>(CatchPad->Val), cast<llvm::BasicBlock>(BB->Val));
|
|
return Ctx.createCatchReturnInst(LLVMI);
|
|
}
|
|
|
|
CatchPadInst *CatchReturnInst::getCatchPad() const {
|
|
return cast<CatchPadInst>(
|
|
Ctx.getValue(cast<llvm::CatchReturnInst>(Val)->getCatchPad()));
|
|
}
|
|
|
|
void CatchReturnInst::setCatchPad(CatchPadInst *CatchPad) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&CatchReturnInst::getCatchPad,
|
|
&CatchReturnInst::setCatchPad>>(this);
|
|
cast<llvm::CatchReturnInst>(Val)->setCatchPad(
|
|
cast<llvm::CatchPadInst>(CatchPad->Val));
|
|
}
|
|
|
|
BasicBlock *CatchReturnInst::getSuccessor() const {
|
|
return cast<BasicBlock>(
|
|
Ctx.getValue(cast<llvm::CatchReturnInst>(Val)->getSuccessor()));
|
|
}
|
|
|
|
void CatchReturnInst::setSuccessor(BasicBlock *NewSucc) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&CatchReturnInst::getSuccessor,
|
|
&CatchReturnInst::setSuccessor>>(this);
|
|
cast<llvm::CatchReturnInst>(Val)->setSuccessor(
|
|
cast<llvm::BasicBlock>(NewSucc->Val));
|
|
}
|
|
|
|
Value *CatchReturnInst::getCatchSwitchParentPad() const {
|
|
return Ctx.getValue(
|
|
cast<llvm::CatchReturnInst>(Val)->getCatchSwitchParentPad());
|
|
}
|
|
|
|
CleanupReturnInst *CleanupReturnInst::create(CleanupPadInst *CleanupPad,
|
|
BasicBlock *UnwindBB,
|
|
InsertPosition Pos, Context &Ctx) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
auto *LLVMUnwindBB =
|
|
UnwindBB != nullptr ? cast<llvm::BasicBlock>(UnwindBB->Val) : nullptr;
|
|
llvm::CleanupReturnInst *LLVMI = Builder.CreateCleanupRet(
|
|
cast<llvm::CleanupPadInst>(CleanupPad->Val), LLVMUnwindBB);
|
|
return Ctx.createCleanupReturnInst(LLVMI);
|
|
}
|
|
|
|
CleanupPadInst *CleanupReturnInst::getCleanupPad() const {
|
|
return cast<CleanupPadInst>(
|
|
Ctx.getValue(cast<llvm::CleanupReturnInst>(Val)->getCleanupPad()));
|
|
}
|
|
|
|
void CleanupReturnInst::setCleanupPad(CleanupPadInst *CleanupPad) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&CleanupReturnInst::getCleanupPad,
|
|
&CleanupReturnInst::setCleanupPad>>(
|
|
this);
|
|
cast<llvm::CleanupReturnInst>(Val)->setCleanupPad(
|
|
cast<llvm::CleanupPadInst>(CleanupPad->Val));
|
|
}
|
|
|
|
BasicBlock *CleanupReturnInst::getUnwindDest() const {
|
|
return cast_or_null<BasicBlock>(
|
|
Ctx.getValue(cast<llvm::CleanupReturnInst>(Val)->getUnwindDest()));
|
|
}
|
|
|
|
void CleanupReturnInst::setUnwindDest(BasicBlock *NewDest) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&CleanupReturnInst::getUnwindDest,
|
|
&CleanupReturnInst::setUnwindDest>>(
|
|
this);
|
|
cast<llvm::CleanupReturnInst>(Val)->setUnwindDest(
|
|
cast<llvm::BasicBlock>(NewDest->Val));
|
|
}
|
|
|
|
Value *GetElementPtrInst::create(Type *Ty, Value *Ptr,
|
|
ArrayRef<Value *> IdxList, InsertPosition Pos,
|
|
Context &Ctx, const Twine &NameStr) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
SmallVector<llvm::Value *> LLVMIdxList;
|
|
LLVMIdxList.reserve(IdxList.size());
|
|
for (Value *Idx : IdxList)
|
|
LLVMIdxList.push_back(Idx->Val);
|
|
llvm::Value *NewV =
|
|
Builder.CreateGEP(Ty->LLVMTy, Ptr->Val, LLVMIdxList, NameStr);
|
|
if (auto *NewGEP = dyn_cast<llvm::GetElementPtrInst>(NewV))
|
|
return Ctx.createGetElementPtrInst(NewGEP);
|
|
assert(isa<llvm::Constant>(NewV) && "Expected constant");
|
|
return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
|
|
}
|
|
|
|
Type *GetElementPtrInst::getSourceElementType() const {
|
|
return Ctx.getType(
|
|
cast<llvm::GetElementPtrInst>(Val)->getSourceElementType());
|
|
}
|
|
|
|
Type *GetElementPtrInst::getResultElementType() const {
|
|
return Ctx.getType(
|
|
cast<llvm::GetElementPtrInst>(Val)->getResultElementType());
|
|
}
|
|
|
|
Value *GetElementPtrInst::getPointerOperand() const {
|
|
return Ctx.getValue(cast<llvm::GetElementPtrInst>(Val)->getPointerOperand());
|
|
}
|
|
|
|
Type *GetElementPtrInst::getPointerOperandType() const {
|
|
return Ctx.getType(
|
|
cast<llvm::GetElementPtrInst>(Val)->getPointerOperandType());
|
|
}
|
|
|
|
BasicBlock *PHINode::LLVMBBToBB::operator()(llvm::BasicBlock *LLVMBB) const {
|
|
return cast<BasicBlock>(Ctx.getValue(LLVMBB));
|
|
}
|
|
|
|
PHINode *PHINode::create(Type *Ty, unsigned NumReservedValues,
|
|
InsertPosition Pos, Context &Ctx, const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
llvm::PHINode *NewPHI =
|
|
Builder.CreatePHI(Ty->LLVMTy, NumReservedValues, Name);
|
|
return Ctx.createPHINode(NewPHI);
|
|
}
|
|
|
|
bool PHINode::classof(const Value *From) {
|
|
return From->getSubclassID() == ClassID::PHI;
|
|
}
|
|
|
|
Value *PHINode::getIncomingValue(unsigned Idx) const {
|
|
return Ctx.getValue(cast<llvm::PHINode>(Val)->getIncomingValue(Idx));
|
|
}
|
|
void PHINode::setIncomingValue(unsigned Idx, Value *V) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetterWithIdx<&PHINode::getIncomingValue,
|
|
&PHINode::setIncomingValue>>(this,
|
|
Idx);
|
|
cast<llvm::PHINode>(Val)->setIncomingValue(Idx, V->Val);
|
|
}
|
|
BasicBlock *PHINode::getIncomingBlock(unsigned Idx) const {
|
|
return cast<BasicBlock>(
|
|
Ctx.getValue(cast<llvm::PHINode>(Val)->getIncomingBlock(Idx)));
|
|
}
|
|
BasicBlock *PHINode::getIncomingBlock(const Use &U) const {
|
|
llvm::Use *LLVMUse = U.LLVMUse;
|
|
llvm::BasicBlock *BB = cast<llvm::PHINode>(Val)->getIncomingBlock(*LLVMUse);
|
|
return cast<BasicBlock>(Ctx.getValue(BB));
|
|
}
|
|
void PHINode::setIncomingBlock(unsigned Idx, BasicBlock *BB) {
|
|
// Helper to disambiguate PHINode::getIncomingBlock(unsigned).
|
|
constexpr BasicBlock *(PHINode::*GetIncomingBlockFn)(unsigned) const =
|
|
&PHINode::getIncomingBlock;
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<
|
|
GenericSetterWithIdx<GetIncomingBlockFn, &PHINode::setIncomingBlock>>(
|
|
this, Idx);
|
|
cast<llvm::PHINode>(Val)->setIncomingBlock(Idx,
|
|
cast<llvm::BasicBlock>(BB->Val));
|
|
}
|
|
void PHINode::addIncoming(Value *V, BasicBlock *BB) {
|
|
auto &Tracker = Ctx.getTracker();
|
|
Tracker.emplaceIfTracking<PHIAddIncoming>(this);
|
|
|
|
cast<llvm::PHINode>(Val)->addIncoming(V->Val,
|
|
cast<llvm::BasicBlock>(BB->Val));
|
|
}
|
|
Value *PHINode::removeIncomingValue(unsigned Idx) {
|
|
auto &Tracker = Ctx.getTracker();
|
|
Tracker.emplaceIfTracking<PHIRemoveIncoming>(this, Idx);
|
|
llvm::Value *LLVMV =
|
|
cast<llvm::PHINode>(Val)->removeIncomingValue(Idx,
|
|
/*DeletePHIIfEmpty=*/false);
|
|
return Ctx.getValue(LLVMV);
|
|
}
|
|
Value *PHINode::removeIncomingValue(BasicBlock *BB) {
|
|
auto &Tracker = Ctx.getTracker();
|
|
Tracker.emplaceIfTracking<PHIRemoveIncoming>(this, getBasicBlockIndex(BB));
|
|
|
|
auto *LLVMBB = cast<llvm::BasicBlock>(BB->Val);
|
|
llvm::Value *LLVMV =
|
|
cast<llvm::PHINode>(Val)->removeIncomingValue(LLVMBB,
|
|
/*DeletePHIIfEmpty=*/false);
|
|
return Ctx.getValue(LLVMV);
|
|
}
|
|
int PHINode::getBasicBlockIndex(const BasicBlock *BB) const {
|
|
auto *LLVMBB = cast<llvm::BasicBlock>(BB->Val);
|
|
return cast<llvm::PHINode>(Val)->getBasicBlockIndex(LLVMBB);
|
|
}
|
|
Value *PHINode::getIncomingValueForBlock(const BasicBlock *BB) const {
|
|
auto *LLVMBB = cast<llvm::BasicBlock>(BB->Val);
|
|
llvm::Value *LLVMV =
|
|
cast<llvm::PHINode>(Val)->getIncomingValueForBlock(LLVMBB);
|
|
return Ctx.getValue(LLVMV);
|
|
}
|
|
Value *PHINode::hasConstantValue() const {
|
|
llvm::Value *LLVMV = cast<llvm::PHINode>(Val)->hasConstantValue();
|
|
return LLVMV != nullptr ? Ctx.getValue(LLVMV) : nullptr;
|
|
}
|
|
void PHINode::replaceIncomingBlockWith(const BasicBlock *Old, BasicBlock *New) {
|
|
assert(New && Old && "Sandbox IR PHI node got a null basic block!");
|
|
for (unsigned Idx = 0, NumOps = cast<llvm::PHINode>(Val)->getNumOperands();
|
|
Idx != NumOps; ++Idx)
|
|
if (getIncomingBlock(Idx) == Old)
|
|
setIncomingBlock(Idx, New);
|
|
}
|
|
void PHINode::removeIncomingValueIf(function_ref<bool(unsigned)> Predicate) {
|
|
// Avoid duplicate tracking by going through this->removeIncomingValue here at
|
|
// the expense of some performance. Copy PHI::removeIncomingValueIf more
|
|
// directly if performance becomes an issue.
|
|
|
|
// Removing the element at index X, moves the element previously at X + 1
|
|
// to X. Working from the end avoids complications from that.
|
|
unsigned Idx = getNumIncomingValues();
|
|
while (Idx > 0) {
|
|
if (Predicate(Idx - 1))
|
|
removeIncomingValue(Idx - 1);
|
|
--Idx;
|
|
}
|
|
}
|
|
|
|
Value *CmpInst::create(Predicate P, Value *S1, Value *S2, InsertPosition Pos,
|
|
Context &Ctx, const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
auto *LLVMV = Builder.CreateCmp(P, S1->Val, S2->Val, Name);
|
|
// It may have been folded into a constant.
|
|
if (auto *LLVMC = dyn_cast<llvm::Constant>(LLVMV))
|
|
return Ctx.getOrCreateConstant(LLVMC);
|
|
if (isa<llvm::ICmpInst>(LLVMV))
|
|
return Ctx.createICmpInst(cast<llvm::ICmpInst>(LLVMV));
|
|
return Ctx.createFCmpInst(cast<llvm::FCmpInst>(LLVMV));
|
|
}
|
|
|
|
Value *CmpInst::createWithCopiedFlags(Predicate P, Value *S1, Value *S2,
|
|
const Instruction *F, InsertPosition Pos,
|
|
Context &Ctx, const Twine &Name) {
|
|
Value *V = create(P, S1, S2, Pos, Ctx, Name);
|
|
if (auto *C = dyn_cast<Constant>(V))
|
|
return C;
|
|
cast<llvm::CmpInst>(V->Val)->copyIRFlags(F->Val);
|
|
return V;
|
|
}
|
|
|
|
Type *CmpInst::makeCmpResultType(Type *OpndType) {
|
|
if (auto *VT = dyn_cast<VectorType>(OpndType)) {
|
|
// TODO: Cleanup when we have more complete support for
|
|
// sandboxir::VectorType
|
|
return OpndType->getContext().getType(llvm::VectorType::get(
|
|
llvm::Type::getInt1Ty(OpndType->getContext().LLVMCtx),
|
|
cast<llvm::VectorType>(VT->LLVMTy)->getElementCount()));
|
|
}
|
|
return Type::getInt1Ty(OpndType->getContext());
|
|
}
|
|
|
|
void CmpInst::setPredicate(Predicate P) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<
|
|
GenericSetter<&CmpInst::getPredicate, &CmpInst::setPredicate>>(this);
|
|
cast<llvm::CmpInst>(Val)->setPredicate(P);
|
|
}
|
|
|
|
void CmpInst::swapOperands() {
|
|
if (ICmpInst *IC = dyn_cast<ICmpInst>(this))
|
|
IC->swapOperands();
|
|
else
|
|
cast<FCmpInst>(this)->swapOperands();
|
|
}
|
|
|
|
void ICmpInst::swapOperands() {
|
|
Ctx.getTracker().emplaceIfTracking<CmpSwapOperands>(this);
|
|
cast<llvm::ICmpInst>(Val)->swapOperands();
|
|
}
|
|
|
|
void FCmpInst::swapOperands() {
|
|
Ctx.getTracker().emplaceIfTracking<CmpSwapOperands>(this);
|
|
cast<llvm::FCmpInst>(Val)->swapOperands();
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
void CmpInst::dumpOS(raw_ostream &OS) const {
|
|
dumpCommonPrefix(OS);
|
|
dumpCommonSuffix(OS);
|
|
}
|
|
|
|
void CmpInst::dump() const {
|
|
dumpOS(dbgs());
|
|
dbgs() << "\n";
|
|
}
|
|
#endif // NDEBUG
|
|
|
|
static llvm::Instruction::CastOps getLLVMCastOp(Instruction::Opcode Opc) {
|
|
switch (Opc) {
|
|
case Instruction::Opcode::ZExt:
|
|
return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::ZExt);
|
|
case Instruction::Opcode::SExt:
|
|
return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::SExt);
|
|
case Instruction::Opcode::FPToUI:
|
|
return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPToUI);
|
|
case Instruction::Opcode::FPToSI:
|
|
return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPToSI);
|
|
case Instruction::Opcode::FPExt:
|
|
return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPExt);
|
|
case Instruction::Opcode::PtrToAddr:
|
|
return static_cast<llvm::Instruction::CastOps>(
|
|
llvm::Instruction::PtrToAddr);
|
|
case Instruction::Opcode::PtrToInt:
|
|
return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::PtrToInt);
|
|
case Instruction::Opcode::IntToPtr:
|
|
return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::IntToPtr);
|
|
case Instruction::Opcode::SIToFP:
|
|
return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::SIToFP);
|
|
case Instruction::Opcode::UIToFP:
|
|
return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::UIToFP);
|
|
case Instruction::Opcode::Trunc:
|
|
return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::Trunc);
|
|
case Instruction::Opcode::FPTrunc:
|
|
return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPTrunc);
|
|
case Instruction::Opcode::BitCast:
|
|
return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::BitCast);
|
|
case Instruction::Opcode::AddrSpaceCast:
|
|
return static_cast<llvm::Instruction::CastOps>(
|
|
llvm::Instruction::AddrSpaceCast);
|
|
default:
|
|
llvm_unreachable("Opcode not suitable for CastInst!");
|
|
}
|
|
}
|
|
|
|
/// \Returns the LLVM opcode that corresponds to \p Opc.
|
|
static llvm::Instruction::UnaryOps getLLVMUnaryOp(Instruction::Opcode Opc) {
|
|
switch (Opc) {
|
|
case Instruction::Opcode::FNeg:
|
|
return static_cast<llvm::Instruction::UnaryOps>(llvm::Instruction::FNeg);
|
|
default:
|
|
llvm_unreachable("Not a unary op!");
|
|
}
|
|
}
|
|
|
|
CatchSwitchInst *CatchSwitchInst::create(Value *ParentPad, BasicBlock *UnwindBB,
|
|
unsigned NumHandlers,
|
|
InsertPosition Pos, Context &Ctx,
|
|
const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
llvm::CatchSwitchInst *LLVMCSI = Builder.CreateCatchSwitch(
|
|
ParentPad->Val, cast<llvm::BasicBlock>(UnwindBB->Val), NumHandlers, Name);
|
|
return Ctx.createCatchSwitchInst(LLVMCSI);
|
|
}
|
|
|
|
Value *CatchSwitchInst::getParentPad() const {
|
|
return Ctx.getValue(cast<llvm::CatchSwitchInst>(Val)->getParentPad());
|
|
}
|
|
|
|
void CatchSwitchInst::setParentPad(Value *ParentPad) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&CatchSwitchInst::getParentPad,
|
|
&CatchSwitchInst::setParentPad>>(this);
|
|
cast<llvm::CatchSwitchInst>(Val)->setParentPad(ParentPad->Val);
|
|
}
|
|
|
|
BasicBlock *CatchSwitchInst::getUnwindDest() const {
|
|
return cast_or_null<BasicBlock>(
|
|
Ctx.getValue(cast<llvm::CatchSwitchInst>(Val)->getUnwindDest()));
|
|
}
|
|
|
|
void CatchSwitchInst::setUnwindDest(BasicBlock *UnwindDest) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&CatchSwitchInst::getUnwindDest,
|
|
&CatchSwitchInst::setUnwindDest>>(this);
|
|
cast<llvm::CatchSwitchInst>(Val)->setUnwindDest(
|
|
cast<llvm::BasicBlock>(UnwindDest->Val));
|
|
}
|
|
|
|
void CatchSwitchInst::addHandler(BasicBlock *Dest) {
|
|
Ctx.getTracker().emplaceIfTracking<CatchSwitchAddHandler>(this);
|
|
cast<llvm::CatchSwitchInst>(Val)->addHandler(
|
|
cast<llvm::BasicBlock>(Dest->Val));
|
|
}
|
|
|
|
ResumeInst *ResumeInst::create(Value *Exn, InsertPosition Pos, Context &Ctx) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
auto *LLVMI = cast<llvm::ResumeInst>(Builder.CreateResume(Exn->Val));
|
|
return Ctx.createResumeInst(LLVMI);
|
|
}
|
|
|
|
Value *ResumeInst::getValue() const {
|
|
return Ctx.getValue(cast<llvm::ResumeInst>(Val)->getValue());
|
|
}
|
|
|
|
SwitchInst *SwitchInst::create(Value *V, BasicBlock *Dest, unsigned NumCases,
|
|
InsertPosition Pos, Context &Ctx,
|
|
const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
llvm::SwitchInst *LLVMSwitch =
|
|
Builder.CreateSwitch(V->Val, cast<llvm::BasicBlock>(Dest->Val), NumCases);
|
|
return Ctx.createSwitchInst(LLVMSwitch);
|
|
}
|
|
|
|
Value *SwitchInst::getCondition() const {
|
|
return Ctx.getValue(cast<llvm::SwitchInst>(Val)->getCondition());
|
|
}
|
|
|
|
void SwitchInst::setCondition(Value *V) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<
|
|
GenericSetter<&SwitchInst::getCondition, &SwitchInst::setCondition>>(
|
|
this);
|
|
cast<llvm::SwitchInst>(Val)->setCondition(V->Val);
|
|
}
|
|
|
|
BasicBlock *SwitchInst::getDefaultDest() const {
|
|
return cast<BasicBlock>(
|
|
Ctx.getValue(cast<llvm::SwitchInst>(Val)->getDefaultDest()));
|
|
}
|
|
|
|
void SwitchInst::setDefaultDest(BasicBlock *DefaultCase) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&SwitchInst::getDefaultDest,
|
|
&SwitchInst::setDefaultDest>>(this);
|
|
cast<llvm::SwitchInst>(Val)->setDefaultDest(
|
|
cast<llvm::BasicBlock>(DefaultCase->Val));
|
|
}
|
|
ConstantInt *SwitchInst::findCaseDest(BasicBlock *BB) {
|
|
auto *LLVMC = cast<llvm::SwitchInst>(Val)->findCaseDest(
|
|
cast<llvm::BasicBlock>(BB->Val));
|
|
return LLVMC != nullptr ? cast<ConstantInt>(Ctx.getValue(LLVMC)) : nullptr;
|
|
}
|
|
|
|
void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) {
|
|
Ctx.getTracker().emplaceIfTracking<SwitchAddCase>(this, OnVal);
|
|
// TODO: Track this!
|
|
cast<llvm::SwitchInst>(Val)->addCase(cast<llvm::ConstantInt>(OnVal->Val),
|
|
cast<llvm::BasicBlock>(Dest->Val));
|
|
}
|
|
|
|
SwitchInst::CaseIt SwitchInst::removeCase(CaseIt It) {
|
|
Ctx.getTracker().emplaceIfTracking<SwitchRemoveCase>(this);
|
|
|
|
auto *LLVMSwitch = cast<llvm::SwitchInst>(Val);
|
|
unsigned CaseNum = It - case_begin();
|
|
llvm::SwitchInst::CaseIt LLVMIt(LLVMSwitch, CaseNum);
|
|
auto LLVMCaseIt = LLVMSwitch->removeCase(LLVMIt);
|
|
unsigned Num = LLVMCaseIt - LLVMSwitch->case_begin();
|
|
return CaseIt(this, Num);
|
|
}
|
|
|
|
BasicBlock *SwitchInst::getSuccessor(unsigned Idx) const {
|
|
return cast<BasicBlock>(
|
|
Ctx.getValue(cast<llvm::SwitchInst>(Val)->getSuccessor(Idx)));
|
|
}
|
|
|
|
void SwitchInst::setSuccessor(unsigned Idx, BasicBlock *NewSucc) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetterWithIdx<&SwitchInst::getSuccessor,
|
|
&SwitchInst::setSuccessor>>(this,
|
|
Idx);
|
|
cast<llvm::SwitchInst>(Val)->setSuccessor(
|
|
Idx, cast<llvm::BasicBlock>(NewSucc->Val));
|
|
}
|
|
|
|
Value *UnaryOperator::create(Instruction::Opcode Op, Value *OpV,
|
|
InsertPosition Pos, Context &Ctx,
|
|
const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
auto *NewLLVMV = Builder.CreateUnOp(getLLVMUnaryOp(Op), OpV->Val, Name);
|
|
if (auto *NewUnOpV = dyn_cast<llvm::UnaryOperator>(NewLLVMV)) {
|
|
return Ctx.createUnaryOperator(NewUnOpV);
|
|
}
|
|
assert(isa<llvm::Constant>(NewLLVMV) && "Expected constant");
|
|
return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewLLVMV));
|
|
}
|
|
|
|
Value *UnaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *OpV,
|
|
Value *CopyFrom, InsertPosition Pos,
|
|
Context &Ctx, const Twine &Name) {
|
|
auto *NewV = create(Op, OpV, Pos, Ctx, Name);
|
|
if (auto *UnI = dyn_cast<llvm::UnaryOperator>(NewV->Val))
|
|
UnI->copyIRFlags(CopyFrom->Val);
|
|
return NewV;
|
|
}
|
|
|
|
/// \Returns the LLVM opcode that corresponds to \p Opc.
|
|
static llvm::Instruction::BinaryOps getLLVMBinaryOp(Instruction::Opcode Opc) {
|
|
switch (Opc) {
|
|
case Instruction::Opcode::Add:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Add);
|
|
case Instruction::Opcode::FAdd:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FAdd);
|
|
case Instruction::Opcode::Sub:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Sub);
|
|
case Instruction::Opcode::FSub:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FSub);
|
|
case Instruction::Opcode::Mul:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Mul);
|
|
case Instruction::Opcode::FMul:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FMul);
|
|
case Instruction::Opcode::UDiv:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::UDiv);
|
|
case Instruction::Opcode::SDiv:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::SDiv);
|
|
case Instruction::Opcode::FDiv:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FDiv);
|
|
case Instruction::Opcode::URem:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::URem);
|
|
case Instruction::Opcode::SRem:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::SRem);
|
|
case Instruction::Opcode::FRem:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FRem);
|
|
case Instruction::Opcode::Shl:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Shl);
|
|
case Instruction::Opcode::LShr:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::LShr);
|
|
case Instruction::Opcode::AShr:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::AShr);
|
|
case Instruction::Opcode::And:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::And);
|
|
case Instruction::Opcode::Or:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Or);
|
|
case Instruction::Opcode::Xor:
|
|
return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Xor);
|
|
default:
|
|
llvm_unreachable("Not a binary op!");
|
|
}
|
|
}
|
|
Value *BinaryOperator::create(Instruction::Opcode Op, Value *LHS, Value *RHS,
|
|
InsertPosition Pos, Context &Ctx,
|
|
const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
llvm::Value *NewV =
|
|
Builder.CreateBinOp(getLLVMBinaryOp(Op), LHS->Val, RHS->Val, Name);
|
|
if (auto *NewBinOp = dyn_cast<llvm::BinaryOperator>(NewV))
|
|
return Ctx.createBinaryOperator(NewBinOp);
|
|
assert(isa<llvm::Constant>(NewV) && "Expected constant");
|
|
return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
|
|
}
|
|
|
|
Value *BinaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *LHS,
|
|
Value *RHS, Value *CopyFrom,
|
|
InsertPosition Pos, Context &Ctx,
|
|
const Twine &Name) {
|
|
|
|
Value *NewV = create(Op, LHS, RHS, Pos, Ctx, Name);
|
|
if (auto *NewBO = dyn_cast<BinaryOperator>(NewV))
|
|
cast<llvm::BinaryOperator>(NewBO->Val)->copyIRFlags(CopyFrom->Val);
|
|
return NewV;
|
|
}
|
|
|
|
void PossiblyDisjointInst::setIsDisjoint(bool B) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&PossiblyDisjointInst::isDisjoint,
|
|
&PossiblyDisjointInst::setIsDisjoint>>(
|
|
this);
|
|
cast<llvm::PossiblyDisjointInst>(Val)->setIsDisjoint(B);
|
|
}
|
|
|
|
void AtomicRMWInst::setAlignment(Align Align) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&AtomicRMWInst::getAlign,
|
|
&AtomicRMWInst::setAlignment>>(this);
|
|
cast<llvm::AtomicRMWInst>(Val)->setAlignment(Align);
|
|
}
|
|
|
|
void AtomicRMWInst::setVolatile(bool V) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&AtomicRMWInst::isVolatile,
|
|
&AtomicRMWInst::setVolatile>>(this);
|
|
cast<llvm::AtomicRMWInst>(Val)->setVolatile(V);
|
|
}
|
|
|
|
void AtomicRMWInst::setOrdering(AtomicOrdering Ordering) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&AtomicRMWInst::getOrdering,
|
|
&AtomicRMWInst::setOrdering>>(this);
|
|
cast<llvm::AtomicRMWInst>(Val)->setOrdering(Ordering);
|
|
}
|
|
|
|
void AtomicRMWInst::setSyncScopeID(SyncScope::ID SSID) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&AtomicRMWInst::getSyncScopeID,
|
|
&AtomicRMWInst::setSyncScopeID>>(this);
|
|
cast<llvm::AtomicRMWInst>(Val)->setSyncScopeID(SSID);
|
|
}
|
|
|
|
Value *AtomicRMWInst::getPointerOperand() {
|
|
return Ctx.getValue(cast<llvm::AtomicRMWInst>(Val)->getPointerOperand());
|
|
}
|
|
|
|
Value *AtomicRMWInst::getValOperand() {
|
|
return Ctx.getValue(cast<llvm::AtomicRMWInst>(Val)->getValOperand());
|
|
}
|
|
|
|
AtomicRMWInst *AtomicRMWInst::create(BinOp Op, Value *Ptr, Value *Val,
|
|
MaybeAlign Align, AtomicOrdering Ordering,
|
|
InsertPosition Pos, Context &Ctx,
|
|
SyncScope::ID SSID, const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
auto *LLVMAtomicRMW =
|
|
Builder.CreateAtomicRMW(Op, Ptr->Val, Val->Val, Align, Ordering, SSID);
|
|
LLVMAtomicRMW->setName(Name);
|
|
return Ctx.createAtomicRMWInst(LLVMAtomicRMW);
|
|
}
|
|
|
|
void AtomicCmpXchgInst::setSyncScopeID(SyncScope::ID SSID) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getSyncScopeID,
|
|
&AtomicCmpXchgInst::setSyncScopeID>>(
|
|
this);
|
|
cast<llvm::AtomicCmpXchgInst>(Val)->setSyncScopeID(SSID);
|
|
}
|
|
|
|
Value *AtomicCmpXchgInst::getPointerOperand() {
|
|
return Ctx.getValue(cast<llvm::AtomicCmpXchgInst>(Val)->getPointerOperand());
|
|
}
|
|
|
|
Value *AtomicCmpXchgInst::getCompareOperand() {
|
|
return Ctx.getValue(cast<llvm::AtomicCmpXchgInst>(Val)->getCompareOperand());
|
|
}
|
|
|
|
Value *AtomicCmpXchgInst::getNewValOperand() {
|
|
return Ctx.getValue(cast<llvm::AtomicCmpXchgInst>(Val)->getNewValOperand());
|
|
}
|
|
|
|
AtomicCmpXchgInst *
|
|
AtomicCmpXchgInst::create(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align,
|
|
AtomicOrdering SuccessOrdering,
|
|
AtomicOrdering FailureOrdering, InsertPosition Pos,
|
|
Context &Ctx, SyncScope::ID SSID, const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
auto *LLVMAtomicCmpXchg =
|
|
Builder.CreateAtomicCmpXchg(Ptr->Val, Cmp->Val, New->Val, Align,
|
|
SuccessOrdering, FailureOrdering, SSID);
|
|
LLVMAtomicCmpXchg->setName(Name);
|
|
return Ctx.createAtomicCmpXchgInst(LLVMAtomicCmpXchg);
|
|
}
|
|
|
|
void AtomicCmpXchgInst::setAlignment(Align Align) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getAlign,
|
|
&AtomicCmpXchgInst::setAlignment>>(this);
|
|
cast<llvm::AtomicCmpXchgInst>(Val)->setAlignment(Align);
|
|
}
|
|
|
|
void AtomicCmpXchgInst::setVolatile(bool V) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::isVolatile,
|
|
&AtomicCmpXchgInst::setVolatile>>(this);
|
|
cast<llvm::AtomicCmpXchgInst>(Val)->setVolatile(V);
|
|
}
|
|
|
|
void AtomicCmpXchgInst::setWeak(bool IsWeak) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::isWeak,
|
|
&AtomicCmpXchgInst::setWeak>>(this);
|
|
cast<llvm::AtomicCmpXchgInst>(Val)->setWeak(IsWeak);
|
|
}
|
|
|
|
void AtomicCmpXchgInst::setSuccessOrdering(AtomicOrdering Ordering) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getSuccessOrdering,
|
|
&AtomicCmpXchgInst::setSuccessOrdering>>(
|
|
this);
|
|
cast<llvm::AtomicCmpXchgInst>(Val)->setSuccessOrdering(Ordering);
|
|
}
|
|
|
|
void AtomicCmpXchgInst::setFailureOrdering(AtomicOrdering Ordering) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getFailureOrdering,
|
|
&AtomicCmpXchgInst::setFailureOrdering>>(
|
|
this);
|
|
cast<llvm::AtomicCmpXchgInst>(Val)->setFailureOrdering(Ordering);
|
|
}
|
|
|
|
AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace, InsertPosition Pos,
|
|
Context &Ctx, Value *ArraySize,
|
|
const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
auto *NewAlloca =
|
|
Builder.CreateAlloca(Ty->LLVMTy, AddrSpace, ArraySize->Val, Name);
|
|
return Ctx.createAllocaInst(NewAlloca);
|
|
}
|
|
|
|
Type *AllocaInst::getAllocatedType() const {
|
|
return Ctx.getType(cast<llvm::AllocaInst>(Val)->getAllocatedType());
|
|
}
|
|
|
|
void AllocaInst::setAllocatedType(Type *Ty) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&AllocaInst::getAllocatedType,
|
|
&AllocaInst::setAllocatedType>>(this);
|
|
cast<llvm::AllocaInst>(Val)->setAllocatedType(Ty->LLVMTy);
|
|
}
|
|
|
|
void AllocaInst::setAlignment(Align Align) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<
|
|
GenericSetter<&AllocaInst::getAlign, &AllocaInst::setAlignment>>(
|
|
this);
|
|
cast<llvm::AllocaInst>(Val)->setAlignment(Align);
|
|
}
|
|
|
|
void AllocaInst::setUsedWithInAlloca(bool V) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&AllocaInst::isUsedWithInAlloca,
|
|
&AllocaInst::setUsedWithInAlloca>>(this);
|
|
cast<llvm::AllocaInst>(Val)->setUsedWithInAlloca(V);
|
|
}
|
|
|
|
Value *AllocaInst::getArraySize() {
|
|
return Ctx.getValue(cast<llvm::AllocaInst>(Val)->getArraySize());
|
|
}
|
|
|
|
PointerType *AllocaInst::getType() const {
|
|
return cast<PointerType>(Ctx.getType(cast<llvm::AllocaInst>(Val)->getType()));
|
|
}
|
|
|
|
Value *CastInst::create(Type *DestTy, Opcode Op, Value *Operand,
|
|
InsertPosition Pos, Context &Ctx, const Twine &Name) {
|
|
assert(getLLVMCastOp(Op) && "Opcode not suitable for CastInst!");
|
|
auto &Builder = setInsertPos(Pos);
|
|
auto *NewV =
|
|
Builder.CreateCast(getLLVMCastOp(Op), Operand->Val, DestTy->LLVMTy, Name);
|
|
if (auto *NewCI = dyn_cast<llvm::CastInst>(NewV))
|
|
return Ctx.createCastInst(NewCI);
|
|
assert(isa<llvm::Constant>(NewV) && "Expected constant");
|
|
return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
|
|
}
|
|
|
|
bool CastInst::classof(const Value *From) {
|
|
return From->getSubclassID() == ClassID::Cast;
|
|
}
|
|
|
|
Type *CastInst::getSrcTy() const {
|
|
return Ctx.getType(cast<llvm::CastInst>(Val)->getSrcTy());
|
|
}
|
|
|
|
Type *CastInst::getDestTy() const {
|
|
return Ctx.getType(cast<llvm::CastInst>(Val)->getDestTy());
|
|
}
|
|
|
|
void PossiblyNonNegInst::setNonNeg(bool B) {
|
|
Ctx.getTracker()
|
|
.emplaceIfTracking<GenericSetter<&PossiblyNonNegInst::hasNonNeg,
|
|
&PossiblyNonNegInst::setNonNeg>>(this);
|
|
cast<llvm::PossiblyNonNegInst>(Val)->setNonNeg(B);
|
|
}
|
|
|
|
Value *InsertElementInst::create(Value *Vec, Value *NewElt, Value *Idx,
|
|
InsertPosition Pos, Context &Ctx,
|
|
const Twine &Name) {
|
|
auto &Builder = Instruction::setInsertPos(Pos);
|
|
llvm::Value *NewV =
|
|
Builder.CreateInsertElement(Vec->Val, NewElt->Val, Idx->Val, Name);
|
|
if (auto *NewInsert = dyn_cast<llvm::InsertElementInst>(NewV))
|
|
return Ctx.createInsertElementInst(NewInsert);
|
|
assert(isa<llvm::Constant>(NewV) && "Expected constant");
|
|
return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
|
|
}
|
|
|
|
Value *ExtractElementInst::create(Value *Vec, Value *Idx, InsertPosition Pos,
|
|
Context &Ctx, const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
llvm::Value *NewV = Builder.CreateExtractElement(Vec->Val, Idx->Val, Name);
|
|
if (auto *NewExtract = dyn_cast<llvm::ExtractElementInst>(NewV))
|
|
return Ctx.createExtractElementInst(NewExtract);
|
|
assert(isa<llvm::Constant>(NewV) && "Expected constant");
|
|
return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
|
|
}
|
|
|
|
Value *ShuffleVectorInst::create(Value *V1, Value *V2, Value *Mask,
|
|
InsertPosition Pos, Context &Ctx,
|
|
const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
llvm::Value *NewV =
|
|
Builder.CreateShuffleVector(V1->Val, V2->Val, Mask->Val, Name);
|
|
if (auto *NewShuffle = dyn_cast<llvm::ShuffleVectorInst>(NewV))
|
|
return Ctx.createShuffleVectorInst(NewShuffle);
|
|
assert(isa<llvm::Constant>(NewV) && "Expected constant");
|
|
return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
|
|
}
|
|
|
|
Value *ShuffleVectorInst::create(Value *V1, Value *V2, ArrayRef<int> Mask,
|
|
InsertPosition Pos, Context &Ctx,
|
|
const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
llvm::Value *NewV = Builder.CreateShuffleVector(V1->Val, V2->Val, Mask, Name);
|
|
if (auto *NewShuffle = dyn_cast<llvm::ShuffleVectorInst>(NewV))
|
|
return Ctx.createShuffleVectorInst(NewShuffle);
|
|
assert(isa<llvm::Constant>(NewV) && "Expected constant");
|
|
return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
|
|
}
|
|
|
|
void ShuffleVectorInst::setShuffleMask(ArrayRef<int> Mask) {
|
|
Ctx.getTracker().emplaceIfTracking<ShuffleVectorSetMask>(this);
|
|
cast<llvm::ShuffleVectorInst>(Val)->setShuffleMask(Mask);
|
|
}
|
|
|
|
VectorType *ShuffleVectorInst::getType() const {
|
|
return cast<VectorType>(
|
|
Ctx.getType(cast<llvm::ShuffleVectorInst>(Val)->getType()));
|
|
}
|
|
|
|
void ShuffleVectorInst::commute() {
|
|
Ctx.getTracker().emplaceIfTracking<ShuffleVectorSetMask>(this);
|
|
Ctx.getTracker().emplaceIfTracking<UseSwap>(getOperandUse(0),
|
|
getOperandUse(1));
|
|
cast<llvm::ShuffleVectorInst>(Val)->commute();
|
|
}
|
|
|
|
Constant *ShuffleVectorInst::getShuffleMaskForBitcode() const {
|
|
return Ctx.getOrCreateConstant(
|
|
cast<llvm::ShuffleVectorInst>(Val)->getShuffleMaskForBitcode());
|
|
}
|
|
|
|
Constant *ShuffleVectorInst::convertShuffleMaskForBitcode(ArrayRef<int> Mask,
|
|
Type *ResultTy) {
|
|
return ResultTy->getContext().getOrCreateConstant(
|
|
llvm::ShuffleVectorInst::convertShuffleMaskForBitcode(Mask,
|
|
ResultTy->LLVMTy));
|
|
}
|
|
|
|
VectorType *ExtractElementInst::getVectorOperandType() const {
|
|
return cast<VectorType>(Ctx.getType(getVectorOperand()->getType()->LLVMTy));
|
|
}
|
|
|
|
Value *ExtractValueInst::create(Value *Agg, ArrayRef<unsigned> Idxs,
|
|
InsertPosition Pos, Context &Ctx,
|
|
const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
llvm::Value *NewV = Builder.CreateExtractValue(Agg->Val, Idxs, Name);
|
|
if (auto *NewExtractValueInst = dyn_cast<llvm::ExtractValueInst>(NewV))
|
|
return Ctx.createExtractValueInst(NewExtractValueInst);
|
|
assert(isa<llvm::Constant>(NewV) && "Expected constant");
|
|
return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
|
|
}
|
|
|
|
Type *ExtractValueInst::getIndexedType(Type *Agg, ArrayRef<unsigned> Idxs) {
|
|
auto *LLVMTy = llvm::ExtractValueInst::getIndexedType(Agg->LLVMTy, Idxs);
|
|
return Agg->getContext().getType(LLVMTy);
|
|
}
|
|
|
|
Value *InsertValueInst::create(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,
|
|
InsertPosition Pos, Context &Ctx,
|
|
const Twine &Name) {
|
|
auto &Builder = setInsertPos(Pos);
|
|
llvm::Value *NewV = Builder.CreateInsertValue(Agg->Val, Val->Val, Idxs, Name);
|
|
if (auto *NewInsertValueInst = dyn_cast<llvm::InsertValueInst>(NewV))
|
|
return Ctx.createInsertValueInst(NewInsertValueInst);
|
|
assert(isa<llvm::Constant>(NewV) && "Expected constant");
|
|
return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
|
|
}
|
|
|
|
ConstantTokenNone *ConstantTokenNone::get(Context &Ctx) {
|
|
auto *LLVMC = llvm::ConstantTokenNone::get(Ctx.LLVMCtx);
|
|
return cast<ConstantTokenNone>(Ctx.getOrCreateConstant(LLVMC));
|
|
}
|
|
|
|
} // namespace llvm::sandboxir
|