1*0fca6ea1SDimitry Andric //===- SandboxIR.cpp - A transactional overlay IR on top of LLVM IR -------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric 9*0fca6ea1SDimitry Andric #include "llvm/SandboxIR/SandboxIR.h" 10*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 11*0fca6ea1SDimitry Andric #include "llvm/IR/Constants.h" 12*0fca6ea1SDimitry Andric #include "llvm/Support/Debug.h" 13*0fca6ea1SDimitry Andric #include <sstream> 14*0fca6ea1SDimitry Andric 15*0fca6ea1SDimitry Andric using namespace llvm::sandboxir; 16*0fca6ea1SDimitry Andric 17*0fca6ea1SDimitry Andric Value *Use::get() const { return Ctx->getValue(LLVMUse->get()); } 18*0fca6ea1SDimitry Andric 19*0fca6ea1SDimitry Andric void Use::set(Value *V) { LLVMUse->set(V->Val); } 20*0fca6ea1SDimitry Andric 21*0fca6ea1SDimitry Andric unsigned Use::getOperandNo() const { return Usr->getUseOperandNo(*this); } 22*0fca6ea1SDimitry Andric 23*0fca6ea1SDimitry Andric #ifndef NDEBUG 24*0fca6ea1SDimitry Andric void Use::dump(raw_ostream &OS) const { 25*0fca6ea1SDimitry Andric Value *Def = nullptr; 26*0fca6ea1SDimitry Andric if (LLVMUse == nullptr) 27*0fca6ea1SDimitry Andric OS << "<null> LLVM Use! "; 28*0fca6ea1SDimitry Andric else 29*0fca6ea1SDimitry Andric Def = Ctx->getValue(LLVMUse->get()); 30*0fca6ea1SDimitry Andric OS << "Def: "; 31*0fca6ea1SDimitry Andric if (Def == nullptr) 32*0fca6ea1SDimitry Andric OS << "NULL"; 33*0fca6ea1SDimitry Andric else 34*0fca6ea1SDimitry Andric OS << *Def; 35*0fca6ea1SDimitry Andric OS << "\n"; 36*0fca6ea1SDimitry Andric 37*0fca6ea1SDimitry Andric OS << "User: "; 38*0fca6ea1SDimitry Andric if (Usr == nullptr) 39*0fca6ea1SDimitry Andric OS << "NULL"; 40*0fca6ea1SDimitry Andric else 41*0fca6ea1SDimitry Andric OS << *Usr; 42*0fca6ea1SDimitry Andric OS << "\n"; 43*0fca6ea1SDimitry Andric 44*0fca6ea1SDimitry Andric OS << "OperandNo: "; 45*0fca6ea1SDimitry Andric if (Usr == nullptr) 46*0fca6ea1SDimitry Andric OS << "N/A"; 47*0fca6ea1SDimitry Andric else 48*0fca6ea1SDimitry Andric OS << getOperandNo(); 49*0fca6ea1SDimitry Andric OS << "\n"; 50*0fca6ea1SDimitry Andric } 51*0fca6ea1SDimitry Andric 52*0fca6ea1SDimitry Andric void Use::dump() const { dump(dbgs()); } 53*0fca6ea1SDimitry Andric #endif // NDEBUG 54*0fca6ea1SDimitry Andric 55*0fca6ea1SDimitry Andric Use OperandUseIterator::operator*() const { return Use; } 56*0fca6ea1SDimitry Andric 57*0fca6ea1SDimitry Andric OperandUseIterator &OperandUseIterator::operator++() { 58*0fca6ea1SDimitry Andric assert(Use.LLVMUse != nullptr && "Already at end!"); 59*0fca6ea1SDimitry Andric User *User = Use.getUser(); 60*0fca6ea1SDimitry Andric Use = User->getOperandUseInternal(Use.getOperandNo() + 1, /*Verify=*/false); 61*0fca6ea1SDimitry Andric return *this; 62*0fca6ea1SDimitry Andric } 63*0fca6ea1SDimitry Andric 64*0fca6ea1SDimitry Andric UserUseIterator &UserUseIterator::operator++() { 65*0fca6ea1SDimitry Andric // Get the corresponding llvm::Use, get the next in the list, and update the 66*0fca6ea1SDimitry Andric // sandboxir::Use. 67*0fca6ea1SDimitry Andric llvm::Use *&LLVMUse = Use.LLVMUse; 68*0fca6ea1SDimitry Andric assert(LLVMUse != nullptr && "Already at end!"); 69*0fca6ea1SDimitry Andric LLVMUse = LLVMUse->getNext(); 70*0fca6ea1SDimitry Andric if (LLVMUse == nullptr) { 71*0fca6ea1SDimitry Andric Use.Usr = nullptr; 72*0fca6ea1SDimitry Andric return *this; 73*0fca6ea1SDimitry Andric } 74*0fca6ea1SDimitry Andric auto *Ctx = Use.Ctx; 75*0fca6ea1SDimitry Andric auto *LLVMUser = LLVMUse->getUser(); 76*0fca6ea1SDimitry Andric Use.Usr = cast_or_null<sandboxir::User>(Ctx->getValue(LLVMUser)); 77*0fca6ea1SDimitry Andric return *this; 78*0fca6ea1SDimitry Andric } 79*0fca6ea1SDimitry Andric 80*0fca6ea1SDimitry Andric Value::Value(ClassID SubclassID, llvm::Value *Val, Context &Ctx) 81*0fca6ea1SDimitry Andric : SubclassID(SubclassID), Val(Val), Ctx(Ctx) { 82*0fca6ea1SDimitry Andric #ifndef NDEBUG 83*0fca6ea1SDimitry Andric UID = Ctx.getNumValues(); 84*0fca6ea1SDimitry Andric #endif 85*0fca6ea1SDimitry Andric } 86*0fca6ea1SDimitry Andric 87*0fca6ea1SDimitry Andric Value::use_iterator Value::use_begin() { 88*0fca6ea1SDimitry Andric llvm::Use *LLVMUse = nullptr; 89*0fca6ea1SDimitry Andric if (Val->use_begin() != Val->use_end()) 90*0fca6ea1SDimitry Andric LLVMUse = &*Val->use_begin(); 91*0fca6ea1SDimitry Andric User *User = LLVMUse != nullptr ? cast_or_null<sandboxir::User>(Ctx.getValue( 92*0fca6ea1SDimitry Andric Val->use_begin()->getUser())) 93*0fca6ea1SDimitry Andric : nullptr; 94*0fca6ea1SDimitry Andric return use_iterator(Use(LLVMUse, User, Ctx)); 95*0fca6ea1SDimitry Andric } 96*0fca6ea1SDimitry Andric 97*0fca6ea1SDimitry Andric Value::user_iterator Value::user_begin() { 98*0fca6ea1SDimitry Andric auto UseBegin = Val->use_begin(); 99*0fca6ea1SDimitry Andric auto UseEnd = Val->use_end(); 100*0fca6ea1SDimitry Andric bool AtEnd = UseBegin == UseEnd; 101*0fca6ea1SDimitry Andric llvm::Use *LLVMUse = AtEnd ? nullptr : &*UseBegin; 102*0fca6ea1SDimitry Andric User *User = 103*0fca6ea1SDimitry Andric AtEnd ? nullptr 104*0fca6ea1SDimitry Andric : cast_or_null<sandboxir::User>(Ctx.getValue(&*LLVMUse->getUser())); 105*0fca6ea1SDimitry Andric return user_iterator(Use(LLVMUse, User, Ctx), UseToUser()); 106*0fca6ea1SDimitry Andric } 107*0fca6ea1SDimitry Andric 108*0fca6ea1SDimitry Andric unsigned Value::getNumUses() const { return range_size(Val->users()); } 109*0fca6ea1SDimitry Andric 110*0fca6ea1SDimitry Andric void Value::replaceUsesWithIf( 111*0fca6ea1SDimitry Andric Value *OtherV, llvm::function_ref<bool(const Use &)> ShouldReplace) { 112*0fca6ea1SDimitry Andric assert(getType() == OtherV->getType() && "Can't replace with different type"); 113*0fca6ea1SDimitry Andric llvm::Value *OtherVal = OtherV->Val; 114*0fca6ea1SDimitry Andric // We are delegating RUWIf to LLVM IR's RUWIf. 115*0fca6ea1SDimitry Andric Val->replaceUsesWithIf( 116*0fca6ea1SDimitry Andric OtherVal, [&ShouldReplace, this](llvm::Use &LLVMUse) -> bool { 117*0fca6ea1SDimitry Andric User *DstU = cast_or_null<User>(Ctx.getValue(LLVMUse.getUser())); 118*0fca6ea1SDimitry Andric if (DstU == nullptr) 119*0fca6ea1SDimitry Andric return false; 120*0fca6ea1SDimitry Andric Use UseToReplace(&LLVMUse, DstU, Ctx); 121*0fca6ea1SDimitry Andric if (!ShouldReplace(UseToReplace)) 122*0fca6ea1SDimitry Andric return false; 123*0fca6ea1SDimitry Andric auto &Tracker = Ctx.getTracker(); 124*0fca6ea1SDimitry Andric if (Tracker.isTracking()) 125*0fca6ea1SDimitry Andric Tracker.track(std::make_unique<UseSet>(UseToReplace, Tracker)); 126*0fca6ea1SDimitry Andric return true; 127*0fca6ea1SDimitry Andric }); 128*0fca6ea1SDimitry Andric } 129*0fca6ea1SDimitry Andric 130*0fca6ea1SDimitry Andric void Value::replaceAllUsesWith(Value *Other) { 131*0fca6ea1SDimitry Andric assert(getType() == Other->getType() && 132*0fca6ea1SDimitry Andric "Replacing with Value of different type!"); 133*0fca6ea1SDimitry Andric auto &Tracker = Ctx.getTracker(); 134*0fca6ea1SDimitry Andric if (Tracker.isTracking()) { 135*0fca6ea1SDimitry Andric for (auto Use : uses()) 136*0fca6ea1SDimitry Andric Tracker.track(std::make_unique<UseSet>(Use, Tracker)); 137*0fca6ea1SDimitry Andric } 138*0fca6ea1SDimitry Andric // We are delegating RAUW to LLVM IR's RAUW. 139*0fca6ea1SDimitry Andric Val->replaceAllUsesWith(Other->Val); 140*0fca6ea1SDimitry Andric } 141*0fca6ea1SDimitry Andric 142*0fca6ea1SDimitry Andric #ifndef NDEBUG 143*0fca6ea1SDimitry Andric std::string Value::getUid() const { 144*0fca6ea1SDimitry Andric std::stringstream SS; 145*0fca6ea1SDimitry Andric SS << "SB" << UID << "."; 146*0fca6ea1SDimitry Andric return SS.str(); 147*0fca6ea1SDimitry Andric } 148*0fca6ea1SDimitry Andric 149*0fca6ea1SDimitry Andric void Value::dumpCommonHeader(raw_ostream &OS) const { 150*0fca6ea1SDimitry Andric OS << getUid() << " " << getSubclassIDStr(SubclassID) << " "; 151*0fca6ea1SDimitry Andric } 152*0fca6ea1SDimitry Andric 153*0fca6ea1SDimitry Andric void Value::dumpCommonFooter(raw_ostream &OS) const { 154*0fca6ea1SDimitry Andric OS.indent(2) << "Val: "; 155*0fca6ea1SDimitry Andric if (Val) 156*0fca6ea1SDimitry Andric OS << *Val; 157*0fca6ea1SDimitry Andric else 158*0fca6ea1SDimitry Andric OS << "NULL"; 159*0fca6ea1SDimitry Andric OS << "\n"; 160*0fca6ea1SDimitry Andric } 161*0fca6ea1SDimitry Andric 162*0fca6ea1SDimitry Andric void Value::dumpCommonPrefix(raw_ostream &OS) const { 163*0fca6ea1SDimitry Andric if (Val) 164*0fca6ea1SDimitry Andric OS << *Val; 165*0fca6ea1SDimitry Andric else 166*0fca6ea1SDimitry Andric OS << "NULL "; 167*0fca6ea1SDimitry Andric } 168*0fca6ea1SDimitry Andric 169*0fca6ea1SDimitry Andric void Value::dumpCommonSuffix(raw_ostream &OS) const { 170*0fca6ea1SDimitry Andric OS << " ; " << getUid() << " (" << getSubclassIDStr(SubclassID) << ")"; 171*0fca6ea1SDimitry Andric } 172*0fca6ea1SDimitry Andric 173*0fca6ea1SDimitry Andric void Value::printAsOperandCommon(raw_ostream &OS) const { 174*0fca6ea1SDimitry Andric if (Val) 175*0fca6ea1SDimitry Andric Val->printAsOperand(OS); 176*0fca6ea1SDimitry Andric else 177*0fca6ea1SDimitry Andric OS << "NULL "; 178*0fca6ea1SDimitry Andric } 179*0fca6ea1SDimitry Andric 180*0fca6ea1SDimitry Andric void Argument::printAsOperand(raw_ostream &OS) const { 181*0fca6ea1SDimitry Andric printAsOperandCommon(OS); 182*0fca6ea1SDimitry Andric } 183*0fca6ea1SDimitry Andric void Argument::dump(raw_ostream &OS) const { 184*0fca6ea1SDimitry Andric dumpCommonPrefix(OS); 185*0fca6ea1SDimitry Andric dumpCommonSuffix(OS); 186*0fca6ea1SDimitry Andric } 187*0fca6ea1SDimitry Andric void Argument::dump() const { 188*0fca6ea1SDimitry Andric dump(dbgs()); 189*0fca6ea1SDimitry Andric dbgs() << "\n"; 190*0fca6ea1SDimitry Andric } 191*0fca6ea1SDimitry Andric #endif // NDEBUG 192*0fca6ea1SDimitry Andric 193*0fca6ea1SDimitry Andric Use User::getOperandUseDefault(unsigned OpIdx, bool Verify) const { 194*0fca6ea1SDimitry Andric assert((!Verify || OpIdx < getNumOperands()) && "Out of bounds!"); 195*0fca6ea1SDimitry Andric assert(isa<llvm::User>(Val) && "Non-users have no operands!"); 196*0fca6ea1SDimitry Andric llvm::Use *LLVMUse; 197*0fca6ea1SDimitry Andric if (OpIdx != getNumOperands()) 198*0fca6ea1SDimitry Andric LLVMUse = &cast<llvm::User>(Val)->getOperandUse(OpIdx); 199*0fca6ea1SDimitry Andric else 200*0fca6ea1SDimitry Andric LLVMUse = cast<llvm::User>(Val)->op_end(); 201*0fca6ea1SDimitry Andric return Use(LLVMUse, const_cast<User *>(this), Ctx); 202*0fca6ea1SDimitry Andric } 203*0fca6ea1SDimitry Andric 204*0fca6ea1SDimitry Andric #ifndef NDEBUG 205*0fca6ea1SDimitry Andric void User::verifyUserOfLLVMUse(const llvm::Use &Use) const { 206*0fca6ea1SDimitry Andric assert(Ctx.getValue(Use.getUser()) == this && 207*0fca6ea1SDimitry Andric "Use not found in this SBUser's operands!"); 208*0fca6ea1SDimitry Andric } 209*0fca6ea1SDimitry Andric #endif 210*0fca6ea1SDimitry Andric 211*0fca6ea1SDimitry Andric bool User::classof(const Value *From) { 212*0fca6ea1SDimitry Andric switch (From->getSubclassID()) { 213*0fca6ea1SDimitry Andric #define DEF_VALUE(ID, CLASS) 214*0fca6ea1SDimitry Andric #define DEF_USER(ID, CLASS) \ 215*0fca6ea1SDimitry Andric case ClassID::ID: \ 216*0fca6ea1SDimitry Andric return true; 217*0fca6ea1SDimitry Andric #define DEF_INSTR(ID, OPC, CLASS) \ 218*0fca6ea1SDimitry Andric case ClassID::ID: \ 219*0fca6ea1SDimitry Andric return true; 220*0fca6ea1SDimitry Andric #include "llvm/SandboxIR/SandboxIRValues.def" 221*0fca6ea1SDimitry Andric default: 222*0fca6ea1SDimitry Andric return false; 223*0fca6ea1SDimitry Andric } 224*0fca6ea1SDimitry Andric } 225*0fca6ea1SDimitry Andric 226*0fca6ea1SDimitry Andric void User::setOperand(unsigned OperandIdx, Value *Operand) { 227*0fca6ea1SDimitry Andric assert(isa<llvm::User>(Val) && "No operands!"); 228*0fca6ea1SDimitry Andric auto &Tracker = Ctx.getTracker(); 229*0fca6ea1SDimitry Andric if (Tracker.isTracking()) 230*0fca6ea1SDimitry Andric Tracker.track(std::make_unique<UseSet>(getOperandUse(OperandIdx), Tracker)); 231*0fca6ea1SDimitry Andric // We are delegating to llvm::User::setOperand(). 232*0fca6ea1SDimitry Andric cast<llvm::User>(Val)->setOperand(OperandIdx, Operand->Val); 233*0fca6ea1SDimitry Andric } 234*0fca6ea1SDimitry Andric 235*0fca6ea1SDimitry Andric bool User::replaceUsesOfWith(Value *FromV, Value *ToV) { 236*0fca6ea1SDimitry Andric auto &Tracker = Ctx.getTracker(); 237*0fca6ea1SDimitry Andric if (Tracker.isTracking()) { 238*0fca6ea1SDimitry Andric for (auto OpIdx : seq<unsigned>(0, getNumOperands())) { 239*0fca6ea1SDimitry Andric auto Use = getOperandUse(OpIdx); 240*0fca6ea1SDimitry Andric if (Use.get() == FromV) 241*0fca6ea1SDimitry Andric Tracker.track(std::make_unique<UseSet>(Use, Tracker)); 242*0fca6ea1SDimitry Andric } 243*0fca6ea1SDimitry Andric } 244*0fca6ea1SDimitry Andric // We are delegating RUOW to LLVM IR's RUOW. 245*0fca6ea1SDimitry Andric return cast<llvm::User>(Val)->replaceUsesOfWith(FromV->Val, ToV->Val); 246*0fca6ea1SDimitry Andric } 247*0fca6ea1SDimitry Andric 248*0fca6ea1SDimitry Andric #ifndef NDEBUG 249*0fca6ea1SDimitry Andric void User::dumpCommonHeader(raw_ostream &OS) const { 250*0fca6ea1SDimitry Andric Value::dumpCommonHeader(OS); 251*0fca6ea1SDimitry Andric // TODO: This is incomplete 252*0fca6ea1SDimitry Andric } 253*0fca6ea1SDimitry Andric #endif // NDEBUG 254*0fca6ea1SDimitry Andric 255*0fca6ea1SDimitry Andric BBIterator &BBIterator::operator++() { 256*0fca6ea1SDimitry Andric auto ItE = BB->end(); 257*0fca6ea1SDimitry Andric assert(It != ItE && "Already at end!"); 258*0fca6ea1SDimitry Andric ++It; 259*0fca6ea1SDimitry Andric if (It == ItE) 260*0fca6ea1SDimitry Andric return *this; 261*0fca6ea1SDimitry Andric Instruction &NextI = *cast<sandboxir::Instruction>(Ctx->getValue(&*It)); 262*0fca6ea1SDimitry Andric unsigned Num = NextI.getNumOfIRInstrs(); 263*0fca6ea1SDimitry Andric assert(Num > 0 && "Bad getNumOfIRInstrs()"); 264*0fca6ea1SDimitry Andric It = std::next(It, Num - 1); 265*0fca6ea1SDimitry Andric return *this; 266*0fca6ea1SDimitry Andric } 267*0fca6ea1SDimitry Andric 268*0fca6ea1SDimitry Andric BBIterator &BBIterator::operator--() { 269*0fca6ea1SDimitry Andric assert(It != BB->begin() && "Already at begin!"); 270*0fca6ea1SDimitry Andric if (It == BB->end()) { 271*0fca6ea1SDimitry Andric --It; 272*0fca6ea1SDimitry Andric return *this; 273*0fca6ea1SDimitry Andric } 274*0fca6ea1SDimitry Andric Instruction &CurrI = **this; 275*0fca6ea1SDimitry Andric unsigned Num = CurrI.getNumOfIRInstrs(); 276*0fca6ea1SDimitry Andric assert(Num > 0 && "Bad getNumOfIRInstrs()"); 277*0fca6ea1SDimitry Andric assert(std::prev(It, Num - 1) != BB->begin() && "Already at begin!"); 278*0fca6ea1SDimitry Andric It = std::prev(It, Num); 279*0fca6ea1SDimitry Andric return *this; 280*0fca6ea1SDimitry Andric } 281*0fca6ea1SDimitry Andric 282*0fca6ea1SDimitry Andric const char *Instruction::getOpcodeName(Opcode Opc) { 283*0fca6ea1SDimitry Andric switch (Opc) { 284*0fca6ea1SDimitry Andric #define DEF_VALUE(ID, CLASS) 285*0fca6ea1SDimitry Andric #define DEF_USER(ID, CLASS) 286*0fca6ea1SDimitry Andric #define OP(OPC) \ 287*0fca6ea1SDimitry Andric case Opcode::OPC: \ 288*0fca6ea1SDimitry Andric return #OPC; 289*0fca6ea1SDimitry Andric #define DEF_INSTR(ID, OPC, CLASS) OPC 290*0fca6ea1SDimitry Andric #include "llvm/SandboxIR/SandboxIRValues.def" 291*0fca6ea1SDimitry Andric } 292*0fca6ea1SDimitry Andric llvm_unreachable("Unknown Opcode"); 293*0fca6ea1SDimitry Andric } 294*0fca6ea1SDimitry Andric 295*0fca6ea1SDimitry Andric llvm::Instruction *Instruction::getTopmostLLVMInstruction() const { 296*0fca6ea1SDimitry Andric Instruction *Prev = getPrevNode(); 297*0fca6ea1SDimitry Andric if (Prev == nullptr) { 298*0fca6ea1SDimitry Andric // If at top of the BB, return the first BB instruction. 299*0fca6ea1SDimitry Andric return &*cast<llvm::BasicBlock>(getParent()->Val)->begin(); 300*0fca6ea1SDimitry Andric } 301*0fca6ea1SDimitry Andric // Else get the Previous sandbox IR instruction's bottom IR instruction and 302*0fca6ea1SDimitry Andric // return its successor. 303*0fca6ea1SDimitry Andric llvm::Instruction *PrevBotI = cast<llvm::Instruction>(Prev->Val); 304*0fca6ea1SDimitry Andric return PrevBotI->getNextNode(); 305*0fca6ea1SDimitry Andric } 306*0fca6ea1SDimitry Andric 307*0fca6ea1SDimitry Andric BBIterator Instruction::getIterator() const { 308*0fca6ea1SDimitry Andric auto *I = cast<llvm::Instruction>(Val); 309*0fca6ea1SDimitry Andric return BasicBlock::iterator(I->getParent(), I->getIterator(), &Ctx); 310*0fca6ea1SDimitry Andric } 311*0fca6ea1SDimitry Andric 312*0fca6ea1SDimitry Andric Instruction *Instruction::getNextNode() const { 313*0fca6ea1SDimitry Andric assert(getParent() != nullptr && "Detached!"); 314*0fca6ea1SDimitry Andric assert(getIterator() != getParent()->end() && "Already at end!"); 315*0fca6ea1SDimitry Andric // `Val` is the bottom-most LLVM IR instruction. Get the next in the chain, 316*0fca6ea1SDimitry Andric // and get the corresponding sandboxir Instruction that maps to it. This works 317*0fca6ea1SDimitry Andric // even for SandboxIR Instructions that map to more than one LLVM Instruction. 318*0fca6ea1SDimitry Andric auto *LLVMI = cast<llvm::Instruction>(Val); 319*0fca6ea1SDimitry Andric assert(LLVMI->getParent() != nullptr && "LLVM IR instr is detached!"); 320*0fca6ea1SDimitry Andric auto *NextLLVMI = LLVMI->getNextNode(); 321*0fca6ea1SDimitry Andric auto *NextI = cast_or_null<Instruction>(Ctx.getValue(NextLLVMI)); 322*0fca6ea1SDimitry Andric if (NextI == nullptr) 323*0fca6ea1SDimitry Andric return nullptr; 324*0fca6ea1SDimitry Andric return NextI; 325*0fca6ea1SDimitry Andric } 326*0fca6ea1SDimitry Andric 327*0fca6ea1SDimitry Andric Instruction *Instruction::getPrevNode() const { 328*0fca6ea1SDimitry Andric assert(getParent() != nullptr && "Detached!"); 329*0fca6ea1SDimitry Andric auto It = getIterator(); 330*0fca6ea1SDimitry Andric if (It != getParent()->begin()) 331*0fca6ea1SDimitry Andric return std::prev(getIterator()).get(); 332*0fca6ea1SDimitry Andric return nullptr; 333*0fca6ea1SDimitry Andric } 334*0fca6ea1SDimitry Andric 335*0fca6ea1SDimitry Andric void Instruction::removeFromParent() { 336*0fca6ea1SDimitry Andric auto &Tracker = Ctx.getTracker(); 337*0fca6ea1SDimitry Andric if (Tracker.isTracking()) 338*0fca6ea1SDimitry Andric Tracker.track(std::make_unique<RemoveFromParent>(this, Tracker)); 339*0fca6ea1SDimitry Andric 340*0fca6ea1SDimitry Andric // Detach all the LLVM IR instructions from their parent BB. 341*0fca6ea1SDimitry Andric for (llvm::Instruction *I : getLLVMInstrs()) 342*0fca6ea1SDimitry Andric I->removeFromParent(); 343*0fca6ea1SDimitry Andric } 344*0fca6ea1SDimitry Andric 345*0fca6ea1SDimitry Andric void Instruction::eraseFromParent() { 346*0fca6ea1SDimitry Andric assert(users().empty() && "Still connected to users, can't erase!"); 347*0fca6ea1SDimitry Andric std::unique_ptr<Value> Detached = Ctx.detach(this); 348*0fca6ea1SDimitry Andric auto LLVMInstrs = getLLVMInstrs(); 349*0fca6ea1SDimitry Andric 350*0fca6ea1SDimitry Andric auto &Tracker = Ctx.getTracker(); 351*0fca6ea1SDimitry Andric if (Tracker.isTracking()) { 352*0fca6ea1SDimitry Andric Tracker.track( 353*0fca6ea1SDimitry Andric std::make_unique<EraseFromParent>(std::move(Detached), Tracker)); 354*0fca6ea1SDimitry Andric // We don't actually delete the IR instruction, because then it would be 355*0fca6ea1SDimitry Andric // impossible to bring it back from the dead at the same memory location. 356*0fca6ea1SDimitry Andric // Instead we remove it from its BB and track its current location. 357*0fca6ea1SDimitry Andric for (llvm::Instruction *I : LLVMInstrs) 358*0fca6ea1SDimitry Andric I->removeFromParent(); 359*0fca6ea1SDimitry Andric // TODO: Multi-instructions need special treatment because some of the 360*0fca6ea1SDimitry Andric // references are internal to the instruction. 361*0fca6ea1SDimitry Andric for (llvm::Instruction *I : LLVMInstrs) 362*0fca6ea1SDimitry Andric I->dropAllReferences(); 363*0fca6ea1SDimitry Andric } else { 364*0fca6ea1SDimitry Andric // Erase in reverse to avoid erasing nstructions with attached uses. 365*0fca6ea1SDimitry Andric for (llvm::Instruction *I : reverse(LLVMInstrs)) 366*0fca6ea1SDimitry Andric I->eraseFromParent(); 367*0fca6ea1SDimitry Andric } 368*0fca6ea1SDimitry Andric } 369*0fca6ea1SDimitry Andric 370*0fca6ea1SDimitry Andric void Instruction::moveBefore(BasicBlock &BB, const BBIterator &WhereIt) { 371*0fca6ea1SDimitry Andric if (std::next(getIterator()) == WhereIt) 372*0fca6ea1SDimitry Andric // Destination is same as origin, nothing to do. 373*0fca6ea1SDimitry Andric return; 374*0fca6ea1SDimitry Andric 375*0fca6ea1SDimitry Andric auto &Tracker = Ctx.getTracker(); 376*0fca6ea1SDimitry Andric if (Tracker.isTracking()) 377*0fca6ea1SDimitry Andric Tracker.track(std::make_unique<MoveInstr>(this, Tracker)); 378*0fca6ea1SDimitry Andric 379*0fca6ea1SDimitry Andric auto *LLVMBB = cast<llvm::BasicBlock>(BB.Val); 380*0fca6ea1SDimitry Andric llvm::BasicBlock::iterator It; 381*0fca6ea1SDimitry Andric if (WhereIt == BB.end()) { 382*0fca6ea1SDimitry Andric It = LLVMBB->end(); 383*0fca6ea1SDimitry Andric } else { 384*0fca6ea1SDimitry Andric Instruction *WhereI = &*WhereIt; 385*0fca6ea1SDimitry Andric It = WhereI->getTopmostLLVMInstruction()->getIterator(); 386*0fca6ea1SDimitry Andric } 387*0fca6ea1SDimitry Andric // TODO: Move this to the verifier of sandboxir::Instruction. 388*0fca6ea1SDimitry Andric assert(is_sorted(getLLVMInstrs(), 389*0fca6ea1SDimitry Andric [](auto *I1, auto *I2) { return I1->comesBefore(I2); }) && 390*0fca6ea1SDimitry Andric "Expected program order!"); 391*0fca6ea1SDimitry Andric // Do the actual move in LLVM IR. 392*0fca6ea1SDimitry Andric for (auto *I : getLLVMInstrs()) 393*0fca6ea1SDimitry Andric I->moveBefore(*LLVMBB, It); 394*0fca6ea1SDimitry Andric } 395*0fca6ea1SDimitry Andric 396*0fca6ea1SDimitry Andric void Instruction::insertBefore(Instruction *BeforeI) { 397*0fca6ea1SDimitry Andric llvm::Instruction *BeforeTopI = BeforeI->getTopmostLLVMInstruction(); 398*0fca6ea1SDimitry Andric // TODO: Move this to the verifier of sandboxir::Instruction. 399*0fca6ea1SDimitry Andric assert(is_sorted(getLLVMInstrs(), 400*0fca6ea1SDimitry Andric [](auto *I1, auto *I2) { return I1->comesBefore(I2); }) && 401*0fca6ea1SDimitry Andric "Expected program order!"); 402*0fca6ea1SDimitry Andric // Insert the LLVM IR Instructions in program order. 403*0fca6ea1SDimitry Andric for (llvm::Instruction *I : getLLVMInstrs()) 404*0fca6ea1SDimitry Andric I->insertBefore(BeforeTopI); 405*0fca6ea1SDimitry Andric } 406*0fca6ea1SDimitry Andric 407*0fca6ea1SDimitry Andric void Instruction::insertAfter(Instruction *AfterI) { 408*0fca6ea1SDimitry Andric insertInto(AfterI->getParent(), std::next(AfterI->getIterator())); 409*0fca6ea1SDimitry Andric } 410*0fca6ea1SDimitry Andric 411*0fca6ea1SDimitry Andric void Instruction::insertInto(BasicBlock *BB, const BBIterator &WhereIt) { 412*0fca6ea1SDimitry Andric llvm::BasicBlock *LLVMBB = cast<llvm::BasicBlock>(BB->Val); 413*0fca6ea1SDimitry Andric llvm::Instruction *LLVMBeforeI; 414*0fca6ea1SDimitry Andric llvm::BasicBlock::iterator LLVMBeforeIt; 415*0fca6ea1SDimitry Andric if (WhereIt != BB->end()) { 416*0fca6ea1SDimitry Andric Instruction *BeforeI = &*WhereIt; 417*0fca6ea1SDimitry Andric LLVMBeforeI = BeforeI->getTopmostLLVMInstruction(); 418*0fca6ea1SDimitry Andric LLVMBeforeIt = LLVMBeforeI->getIterator(); 419*0fca6ea1SDimitry Andric } else { 420*0fca6ea1SDimitry Andric LLVMBeforeI = nullptr; 421*0fca6ea1SDimitry Andric LLVMBeforeIt = LLVMBB->end(); 422*0fca6ea1SDimitry Andric } 423*0fca6ea1SDimitry Andric // Insert the LLVM IR Instructions in program order. 424*0fca6ea1SDimitry Andric for (llvm::Instruction *I : getLLVMInstrs()) 425*0fca6ea1SDimitry Andric I->insertInto(LLVMBB, LLVMBeforeIt); 426*0fca6ea1SDimitry Andric } 427*0fca6ea1SDimitry Andric 428*0fca6ea1SDimitry Andric BasicBlock *Instruction::getParent() const { 429*0fca6ea1SDimitry Andric // Get the LLVM IR Instruction that this maps to, get its parent, and get the 430*0fca6ea1SDimitry Andric // corresponding sandboxir::BasicBlock by looking it up in sandboxir::Context. 431*0fca6ea1SDimitry Andric auto *BB = cast<llvm::Instruction>(Val)->getParent(); 432*0fca6ea1SDimitry Andric if (BB == nullptr) 433*0fca6ea1SDimitry Andric return nullptr; 434*0fca6ea1SDimitry Andric return cast<BasicBlock>(Ctx.getValue(BB)); 435*0fca6ea1SDimitry Andric } 436*0fca6ea1SDimitry Andric 437*0fca6ea1SDimitry Andric bool Instruction::classof(const sandboxir::Value *From) { 438*0fca6ea1SDimitry Andric switch (From->getSubclassID()) { 439*0fca6ea1SDimitry Andric #define DEF_INSTR(ID, OPC, CLASS) \ 440*0fca6ea1SDimitry Andric case ClassID::ID: \ 441*0fca6ea1SDimitry Andric return true; 442*0fca6ea1SDimitry Andric #include "llvm/SandboxIR/SandboxIRValues.def" 443*0fca6ea1SDimitry Andric default: 444*0fca6ea1SDimitry Andric return false; 445*0fca6ea1SDimitry Andric } 446*0fca6ea1SDimitry Andric } 447*0fca6ea1SDimitry Andric 448*0fca6ea1SDimitry Andric #ifndef NDEBUG 449*0fca6ea1SDimitry Andric void Instruction::dump(raw_ostream &OS) const { 450*0fca6ea1SDimitry Andric OS << "Unimplemented! Please override dump()."; 451*0fca6ea1SDimitry Andric } 452*0fca6ea1SDimitry Andric void Instruction::dump() const { 453*0fca6ea1SDimitry Andric dump(dbgs()); 454*0fca6ea1SDimitry Andric dbgs() << "\n"; 455*0fca6ea1SDimitry Andric } 456*0fca6ea1SDimitry Andric #endif // NDEBUG 457*0fca6ea1SDimitry Andric 458*0fca6ea1SDimitry Andric Value *SelectInst::createCommon(Value *Cond, Value *True, Value *False, 459*0fca6ea1SDimitry Andric const Twine &Name, IRBuilder<> &Builder, 460*0fca6ea1SDimitry Andric Context &Ctx) { 461*0fca6ea1SDimitry Andric llvm::Value *NewV = 462*0fca6ea1SDimitry Andric Builder.CreateSelect(Cond->Val, True->Val, False->Val, Name); 463*0fca6ea1SDimitry Andric if (auto *NewSI = dyn_cast<llvm::SelectInst>(NewV)) 464*0fca6ea1SDimitry Andric return Ctx.createSelectInst(NewSI); 465*0fca6ea1SDimitry Andric assert(isa<llvm::Constant>(NewV) && "Expected constant"); 466*0fca6ea1SDimitry Andric return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV)); 467*0fca6ea1SDimitry Andric } 468*0fca6ea1SDimitry Andric 469*0fca6ea1SDimitry Andric Value *SelectInst::create(Value *Cond, Value *True, Value *False, 470*0fca6ea1SDimitry Andric Instruction *InsertBefore, Context &Ctx, 471*0fca6ea1SDimitry Andric const Twine &Name) { 472*0fca6ea1SDimitry Andric llvm::Instruction *BeforeIR = InsertBefore->getTopmostLLVMInstruction(); 473*0fca6ea1SDimitry Andric auto &Builder = Ctx.getLLVMIRBuilder(); 474*0fca6ea1SDimitry Andric Builder.SetInsertPoint(BeforeIR); 475*0fca6ea1SDimitry Andric return createCommon(Cond, True, False, Name, Builder, Ctx); 476*0fca6ea1SDimitry Andric } 477*0fca6ea1SDimitry Andric 478*0fca6ea1SDimitry Andric Value *SelectInst::create(Value *Cond, Value *True, Value *False, 479*0fca6ea1SDimitry Andric BasicBlock *InsertAtEnd, Context &Ctx, 480*0fca6ea1SDimitry Andric const Twine &Name) { 481*0fca6ea1SDimitry Andric auto *IRInsertAtEnd = cast<llvm::BasicBlock>(InsertAtEnd->Val); 482*0fca6ea1SDimitry Andric auto &Builder = Ctx.getLLVMIRBuilder(); 483*0fca6ea1SDimitry Andric Builder.SetInsertPoint(IRInsertAtEnd); 484*0fca6ea1SDimitry Andric return createCommon(Cond, True, False, Name, Builder, Ctx); 485*0fca6ea1SDimitry Andric } 486*0fca6ea1SDimitry Andric 487*0fca6ea1SDimitry Andric bool SelectInst::classof(const Value *From) { 488*0fca6ea1SDimitry Andric return From->getSubclassID() == ClassID::Select; 489*0fca6ea1SDimitry Andric } 490*0fca6ea1SDimitry Andric 491*0fca6ea1SDimitry Andric #ifndef NDEBUG 492*0fca6ea1SDimitry Andric void SelectInst::dump(raw_ostream &OS) const { 493*0fca6ea1SDimitry Andric dumpCommonPrefix(OS); 494*0fca6ea1SDimitry Andric dumpCommonSuffix(OS); 495*0fca6ea1SDimitry Andric } 496*0fca6ea1SDimitry Andric 497*0fca6ea1SDimitry Andric void SelectInst::dump() const { 498*0fca6ea1SDimitry Andric dump(dbgs()); 499*0fca6ea1SDimitry Andric dbgs() << "\n"; 500*0fca6ea1SDimitry Andric } 501*0fca6ea1SDimitry Andric #endif // NDEBUG 502*0fca6ea1SDimitry Andric 503*0fca6ea1SDimitry Andric LoadInst *LoadInst::create(Type *Ty, Value *Ptr, MaybeAlign Align, 504*0fca6ea1SDimitry Andric Instruction *InsertBefore, Context &Ctx, 505*0fca6ea1SDimitry Andric const Twine &Name) { 506*0fca6ea1SDimitry Andric llvm::Instruction *BeforeIR = InsertBefore->getTopmostLLVMInstruction(); 507*0fca6ea1SDimitry Andric auto &Builder = Ctx.getLLVMIRBuilder(); 508*0fca6ea1SDimitry Andric Builder.SetInsertPoint(BeforeIR); 509*0fca6ea1SDimitry Andric auto *NewLI = Builder.CreateAlignedLoad(Ty, Ptr->Val, Align, 510*0fca6ea1SDimitry Andric /*isVolatile=*/false, Name); 511*0fca6ea1SDimitry Andric auto *NewSBI = Ctx.createLoadInst(NewLI); 512*0fca6ea1SDimitry Andric return NewSBI; 513*0fca6ea1SDimitry Andric } 514*0fca6ea1SDimitry Andric 515*0fca6ea1SDimitry Andric LoadInst *LoadInst::create(Type *Ty, Value *Ptr, MaybeAlign Align, 516*0fca6ea1SDimitry Andric BasicBlock *InsertAtEnd, Context &Ctx, 517*0fca6ea1SDimitry Andric const Twine &Name) { 518*0fca6ea1SDimitry Andric auto &Builder = Ctx.getLLVMIRBuilder(); 519*0fca6ea1SDimitry Andric Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val)); 520*0fca6ea1SDimitry Andric auto *NewLI = Builder.CreateAlignedLoad(Ty, Ptr->Val, Align, 521*0fca6ea1SDimitry Andric /*isVolatile=*/false, Name); 522*0fca6ea1SDimitry Andric auto *NewSBI = Ctx.createLoadInst(NewLI); 523*0fca6ea1SDimitry Andric return NewSBI; 524*0fca6ea1SDimitry Andric } 525*0fca6ea1SDimitry Andric 526*0fca6ea1SDimitry Andric bool LoadInst::classof(const Value *From) { 527*0fca6ea1SDimitry Andric return From->getSubclassID() == ClassID::Load; 528*0fca6ea1SDimitry Andric } 529*0fca6ea1SDimitry Andric 530*0fca6ea1SDimitry Andric Value *LoadInst::getPointerOperand() const { 531*0fca6ea1SDimitry Andric return Ctx.getValue(cast<llvm::LoadInst>(Val)->getPointerOperand()); 532*0fca6ea1SDimitry Andric } 533*0fca6ea1SDimitry Andric 534*0fca6ea1SDimitry Andric #ifndef NDEBUG 535*0fca6ea1SDimitry Andric void LoadInst::dump(raw_ostream &OS) const { 536*0fca6ea1SDimitry Andric dumpCommonPrefix(OS); 537*0fca6ea1SDimitry Andric dumpCommonSuffix(OS); 538*0fca6ea1SDimitry Andric } 539*0fca6ea1SDimitry Andric 540*0fca6ea1SDimitry Andric void LoadInst::dump() const { 541*0fca6ea1SDimitry Andric dump(dbgs()); 542*0fca6ea1SDimitry Andric dbgs() << "\n"; 543*0fca6ea1SDimitry Andric } 544*0fca6ea1SDimitry Andric #endif // NDEBUG 545*0fca6ea1SDimitry Andric StoreInst *StoreInst::create(Value *V, Value *Ptr, MaybeAlign Align, 546*0fca6ea1SDimitry Andric Instruction *InsertBefore, Context &Ctx) { 547*0fca6ea1SDimitry Andric llvm::Instruction *BeforeIR = InsertBefore->getTopmostLLVMInstruction(); 548*0fca6ea1SDimitry Andric auto &Builder = Ctx.getLLVMIRBuilder(); 549*0fca6ea1SDimitry Andric Builder.SetInsertPoint(BeforeIR); 550*0fca6ea1SDimitry Andric auto *NewSI = 551*0fca6ea1SDimitry Andric Builder.CreateAlignedStore(V->Val, Ptr->Val, Align, /*isVolatile=*/false); 552*0fca6ea1SDimitry Andric auto *NewSBI = Ctx.createStoreInst(NewSI); 553*0fca6ea1SDimitry Andric return NewSBI; 554*0fca6ea1SDimitry Andric } 555*0fca6ea1SDimitry Andric StoreInst *StoreInst::create(Value *V, Value *Ptr, MaybeAlign Align, 556*0fca6ea1SDimitry Andric BasicBlock *InsertAtEnd, Context &Ctx) { 557*0fca6ea1SDimitry Andric auto *InsertAtEndIR = cast<llvm::BasicBlock>(InsertAtEnd->Val); 558*0fca6ea1SDimitry Andric auto &Builder = Ctx.getLLVMIRBuilder(); 559*0fca6ea1SDimitry Andric Builder.SetInsertPoint(InsertAtEndIR); 560*0fca6ea1SDimitry Andric auto *NewSI = 561*0fca6ea1SDimitry Andric Builder.CreateAlignedStore(V->Val, Ptr->Val, Align, /*isVolatile=*/false); 562*0fca6ea1SDimitry Andric auto *NewSBI = Ctx.createStoreInst(NewSI); 563*0fca6ea1SDimitry Andric return NewSBI; 564*0fca6ea1SDimitry Andric } 565*0fca6ea1SDimitry Andric 566*0fca6ea1SDimitry Andric bool StoreInst::classof(const Value *From) { 567*0fca6ea1SDimitry Andric return From->getSubclassID() == ClassID::Store; 568*0fca6ea1SDimitry Andric } 569*0fca6ea1SDimitry Andric 570*0fca6ea1SDimitry Andric Value *StoreInst::getValueOperand() const { 571*0fca6ea1SDimitry Andric return Ctx.getValue(cast<llvm::StoreInst>(Val)->getValueOperand()); 572*0fca6ea1SDimitry Andric } 573*0fca6ea1SDimitry Andric 574*0fca6ea1SDimitry Andric Value *StoreInst::getPointerOperand() const { 575*0fca6ea1SDimitry Andric return Ctx.getValue(cast<llvm::StoreInst>(Val)->getPointerOperand()); 576*0fca6ea1SDimitry Andric } 577*0fca6ea1SDimitry Andric 578*0fca6ea1SDimitry Andric #ifndef NDEBUG 579*0fca6ea1SDimitry Andric void StoreInst::dump(raw_ostream &OS) const { 580*0fca6ea1SDimitry Andric dumpCommonPrefix(OS); 581*0fca6ea1SDimitry Andric dumpCommonSuffix(OS); 582*0fca6ea1SDimitry Andric } 583*0fca6ea1SDimitry Andric 584*0fca6ea1SDimitry Andric void StoreInst::dump() const { 585*0fca6ea1SDimitry Andric dump(dbgs()); 586*0fca6ea1SDimitry Andric dbgs() << "\n"; 587*0fca6ea1SDimitry Andric } 588*0fca6ea1SDimitry Andric #endif // NDEBUG 589*0fca6ea1SDimitry Andric 590*0fca6ea1SDimitry Andric ReturnInst *ReturnInst::createCommon(Value *RetVal, IRBuilder<> &Builder, 591*0fca6ea1SDimitry Andric Context &Ctx) { 592*0fca6ea1SDimitry Andric llvm::ReturnInst *NewRI; 593*0fca6ea1SDimitry Andric if (RetVal != nullptr) 594*0fca6ea1SDimitry Andric NewRI = Builder.CreateRet(RetVal->Val); 595*0fca6ea1SDimitry Andric else 596*0fca6ea1SDimitry Andric NewRI = Builder.CreateRetVoid(); 597*0fca6ea1SDimitry Andric return Ctx.createReturnInst(NewRI); 598*0fca6ea1SDimitry Andric } 599*0fca6ea1SDimitry Andric 600*0fca6ea1SDimitry Andric ReturnInst *ReturnInst::create(Value *RetVal, Instruction *InsertBefore, 601*0fca6ea1SDimitry Andric Context &Ctx) { 602*0fca6ea1SDimitry Andric llvm::Instruction *BeforeIR = InsertBefore->getTopmostLLVMInstruction(); 603*0fca6ea1SDimitry Andric auto &Builder = Ctx.getLLVMIRBuilder(); 604*0fca6ea1SDimitry Andric Builder.SetInsertPoint(BeforeIR); 605*0fca6ea1SDimitry Andric return createCommon(RetVal, Builder, Ctx); 606*0fca6ea1SDimitry Andric } 607*0fca6ea1SDimitry Andric 608*0fca6ea1SDimitry Andric ReturnInst *ReturnInst::create(Value *RetVal, BasicBlock *InsertAtEnd, 609*0fca6ea1SDimitry Andric Context &Ctx) { 610*0fca6ea1SDimitry Andric auto &Builder = Ctx.getLLVMIRBuilder(); 611*0fca6ea1SDimitry Andric Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val)); 612*0fca6ea1SDimitry Andric return createCommon(RetVal, Builder, Ctx); 613*0fca6ea1SDimitry Andric } 614*0fca6ea1SDimitry Andric 615*0fca6ea1SDimitry Andric Value *ReturnInst::getReturnValue() const { 616*0fca6ea1SDimitry Andric auto *LLVMRetVal = cast<llvm::ReturnInst>(Val)->getReturnValue(); 617*0fca6ea1SDimitry Andric return LLVMRetVal != nullptr ? Ctx.getValue(LLVMRetVal) : nullptr; 618*0fca6ea1SDimitry Andric } 619*0fca6ea1SDimitry Andric 620*0fca6ea1SDimitry Andric #ifndef NDEBUG 621*0fca6ea1SDimitry Andric void ReturnInst::dump(raw_ostream &OS) const { 622*0fca6ea1SDimitry Andric dumpCommonPrefix(OS); 623*0fca6ea1SDimitry Andric dumpCommonSuffix(OS); 624*0fca6ea1SDimitry Andric } 625*0fca6ea1SDimitry Andric 626*0fca6ea1SDimitry Andric void ReturnInst::dump() const { 627*0fca6ea1SDimitry Andric dump(dbgs()); 628*0fca6ea1SDimitry Andric dbgs() << "\n"; 629*0fca6ea1SDimitry Andric } 630*0fca6ea1SDimitry Andric 631*0fca6ea1SDimitry Andric void OpaqueInst::dump(raw_ostream &OS) const { 632*0fca6ea1SDimitry Andric dumpCommonPrefix(OS); 633*0fca6ea1SDimitry Andric dumpCommonSuffix(OS); 634*0fca6ea1SDimitry Andric } 635*0fca6ea1SDimitry Andric 636*0fca6ea1SDimitry Andric void OpaqueInst::dump() const { 637*0fca6ea1SDimitry Andric dump(dbgs()); 638*0fca6ea1SDimitry Andric dbgs() << "\n"; 639*0fca6ea1SDimitry Andric } 640*0fca6ea1SDimitry Andric #endif // NDEBUG 641*0fca6ea1SDimitry Andric 642*0fca6ea1SDimitry Andric Constant *Constant::createInt(Type *Ty, uint64_t V, Context &Ctx, 643*0fca6ea1SDimitry Andric bool IsSigned) { 644*0fca6ea1SDimitry Andric llvm::Constant *LLVMC = llvm::ConstantInt::get(Ty, V, IsSigned); 645*0fca6ea1SDimitry Andric return Ctx.getOrCreateConstant(LLVMC); 646*0fca6ea1SDimitry Andric } 647*0fca6ea1SDimitry Andric 648*0fca6ea1SDimitry Andric #ifndef NDEBUG 649*0fca6ea1SDimitry Andric void Constant::dump(raw_ostream &OS) const { 650*0fca6ea1SDimitry Andric dumpCommonPrefix(OS); 651*0fca6ea1SDimitry Andric dumpCommonSuffix(OS); 652*0fca6ea1SDimitry Andric } 653*0fca6ea1SDimitry Andric 654*0fca6ea1SDimitry Andric void Constant::dump() const { 655*0fca6ea1SDimitry Andric dump(dbgs()); 656*0fca6ea1SDimitry Andric dbgs() << "\n"; 657*0fca6ea1SDimitry Andric } 658*0fca6ea1SDimitry Andric 659*0fca6ea1SDimitry Andric void Function::dumpNameAndArgs(raw_ostream &OS) const { 660*0fca6ea1SDimitry Andric auto *F = cast<llvm::Function>(Val); 661*0fca6ea1SDimitry Andric OS << *F->getReturnType() << " @" << F->getName() << "("; 662*0fca6ea1SDimitry Andric interleave( 663*0fca6ea1SDimitry Andric F->args(), 664*0fca6ea1SDimitry Andric [this, &OS](const llvm::Argument &LLVMArg) { 665*0fca6ea1SDimitry Andric auto *SBArg = cast_or_null<Argument>(Ctx.getValue(&LLVMArg)); 666*0fca6ea1SDimitry Andric if (SBArg == nullptr) 667*0fca6ea1SDimitry Andric OS << "NULL"; 668*0fca6ea1SDimitry Andric else 669*0fca6ea1SDimitry Andric SBArg->printAsOperand(OS); 670*0fca6ea1SDimitry Andric }, 671*0fca6ea1SDimitry Andric [&] { OS << ", "; }); 672*0fca6ea1SDimitry Andric OS << ")"; 673*0fca6ea1SDimitry Andric } 674*0fca6ea1SDimitry Andric void Function::dump(raw_ostream &OS) const { 675*0fca6ea1SDimitry Andric dumpNameAndArgs(OS); 676*0fca6ea1SDimitry Andric OS << " {\n"; 677*0fca6ea1SDimitry Andric auto *LLVMF = cast<llvm::Function>(Val); 678*0fca6ea1SDimitry Andric interleave( 679*0fca6ea1SDimitry Andric *LLVMF, 680*0fca6ea1SDimitry Andric [this, &OS](const llvm::BasicBlock &LLVMBB) { 681*0fca6ea1SDimitry Andric auto *BB = cast_or_null<BasicBlock>(Ctx.getValue(&LLVMBB)); 682*0fca6ea1SDimitry Andric if (BB == nullptr) 683*0fca6ea1SDimitry Andric OS << "NULL"; 684*0fca6ea1SDimitry Andric else 685*0fca6ea1SDimitry Andric OS << *BB; 686*0fca6ea1SDimitry Andric }, 687*0fca6ea1SDimitry Andric [&OS] { OS << "\n"; }); 688*0fca6ea1SDimitry Andric OS << "}\n"; 689*0fca6ea1SDimitry Andric } 690*0fca6ea1SDimitry Andric void Function::dump() const { 691*0fca6ea1SDimitry Andric dump(dbgs()); 692*0fca6ea1SDimitry Andric dbgs() << "\n"; 693*0fca6ea1SDimitry Andric } 694*0fca6ea1SDimitry Andric #endif // NDEBUG 695*0fca6ea1SDimitry Andric 696*0fca6ea1SDimitry Andric BasicBlock::iterator::pointer 697*0fca6ea1SDimitry Andric BasicBlock::iterator::getInstr(llvm::BasicBlock::iterator It) const { 698*0fca6ea1SDimitry Andric return cast_or_null<Instruction>(Ctx->getValue(&*It)); 699*0fca6ea1SDimitry Andric } 700*0fca6ea1SDimitry Andric 701*0fca6ea1SDimitry Andric std::unique_ptr<Value> Context::detachLLVMValue(llvm::Value *V) { 702*0fca6ea1SDimitry Andric std::unique_ptr<Value> Erased; 703*0fca6ea1SDimitry Andric auto It = LLVMValueToValueMap.find(V); 704*0fca6ea1SDimitry Andric if (It != LLVMValueToValueMap.end()) { 705*0fca6ea1SDimitry Andric auto *Val = It->second.release(); 706*0fca6ea1SDimitry Andric Erased = std::unique_ptr<Value>(Val); 707*0fca6ea1SDimitry Andric LLVMValueToValueMap.erase(It); 708*0fca6ea1SDimitry Andric } 709*0fca6ea1SDimitry Andric return Erased; 710*0fca6ea1SDimitry Andric } 711*0fca6ea1SDimitry Andric 712*0fca6ea1SDimitry Andric std::unique_ptr<Value> Context::detach(Value *V) { 713*0fca6ea1SDimitry Andric assert(V->getSubclassID() != Value::ClassID::Constant && 714*0fca6ea1SDimitry Andric "Can't detach a constant!"); 715*0fca6ea1SDimitry Andric assert(V->getSubclassID() != Value::ClassID::User && "Can't detach a user!"); 716*0fca6ea1SDimitry Andric return detachLLVMValue(V->Val); 717*0fca6ea1SDimitry Andric } 718*0fca6ea1SDimitry Andric 719*0fca6ea1SDimitry Andric Value *Context::registerValue(std::unique_ptr<Value> &&VPtr) { 720*0fca6ea1SDimitry Andric assert(VPtr->getSubclassID() != Value::ClassID::User && 721*0fca6ea1SDimitry Andric "Can't register a user!"); 722*0fca6ea1SDimitry Andric Value *V = VPtr.get(); 723*0fca6ea1SDimitry Andric [[maybe_unused]] auto Pair = 724*0fca6ea1SDimitry Andric LLVMValueToValueMap.insert({VPtr->Val, std::move(VPtr)}); 725*0fca6ea1SDimitry Andric assert(Pair.second && "Already exists!"); 726*0fca6ea1SDimitry Andric return V; 727*0fca6ea1SDimitry Andric } 728*0fca6ea1SDimitry Andric 729*0fca6ea1SDimitry Andric Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) { 730*0fca6ea1SDimitry Andric auto Pair = LLVMValueToValueMap.insert({LLVMV, nullptr}); 731*0fca6ea1SDimitry Andric auto It = Pair.first; 732*0fca6ea1SDimitry Andric if (!Pair.second) 733*0fca6ea1SDimitry Andric return It->second.get(); 734*0fca6ea1SDimitry Andric 735*0fca6ea1SDimitry Andric if (auto *C = dyn_cast<llvm::Constant>(LLVMV)) { 736*0fca6ea1SDimitry Andric It->second = std::unique_ptr<Constant>(new Constant(C, *this)); 737*0fca6ea1SDimitry Andric auto *NewC = It->second.get(); 738*0fca6ea1SDimitry Andric for (llvm::Value *COp : C->operands()) 739*0fca6ea1SDimitry Andric getOrCreateValueInternal(COp, C); 740*0fca6ea1SDimitry Andric return NewC; 741*0fca6ea1SDimitry Andric } 742*0fca6ea1SDimitry Andric if (auto *Arg = dyn_cast<llvm::Argument>(LLVMV)) { 743*0fca6ea1SDimitry Andric It->second = std::unique_ptr<Argument>(new Argument(Arg, *this)); 744*0fca6ea1SDimitry Andric return It->second.get(); 745*0fca6ea1SDimitry Andric } 746*0fca6ea1SDimitry Andric if (auto *BB = dyn_cast<llvm::BasicBlock>(LLVMV)) { 747*0fca6ea1SDimitry Andric assert(isa<BlockAddress>(U) && 748*0fca6ea1SDimitry Andric "This won't create a SBBB, don't call this function directly!"); 749*0fca6ea1SDimitry Andric if (auto *SBBB = getValue(BB)) 750*0fca6ea1SDimitry Andric return SBBB; 751*0fca6ea1SDimitry Andric return nullptr; 752*0fca6ea1SDimitry Andric } 753*0fca6ea1SDimitry Andric assert(isa<llvm::Instruction>(LLVMV) && "Expected Instruction"); 754*0fca6ea1SDimitry Andric 755*0fca6ea1SDimitry Andric switch (cast<llvm::Instruction>(LLVMV)->getOpcode()) { 756*0fca6ea1SDimitry Andric case llvm::Instruction::Select: { 757*0fca6ea1SDimitry Andric auto *LLVMSel = cast<llvm::SelectInst>(LLVMV); 758*0fca6ea1SDimitry Andric It->second = std::unique_ptr<SelectInst>(new SelectInst(LLVMSel, *this)); 759*0fca6ea1SDimitry Andric return It->second.get(); 760*0fca6ea1SDimitry Andric } 761*0fca6ea1SDimitry Andric case llvm::Instruction::Load: { 762*0fca6ea1SDimitry Andric auto *LLVMLd = cast<llvm::LoadInst>(LLVMV); 763*0fca6ea1SDimitry Andric It->second = std::unique_ptr<LoadInst>(new LoadInst(LLVMLd, *this)); 764*0fca6ea1SDimitry Andric return It->second.get(); 765*0fca6ea1SDimitry Andric } 766*0fca6ea1SDimitry Andric case llvm::Instruction::Store: { 767*0fca6ea1SDimitry Andric auto *LLVMSt = cast<llvm::StoreInst>(LLVMV); 768*0fca6ea1SDimitry Andric It->second = std::unique_ptr<StoreInst>(new StoreInst(LLVMSt, *this)); 769*0fca6ea1SDimitry Andric return It->second.get(); 770*0fca6ea1SDimitry Andric } 771*0fca6ea1SDimitry Andric case llvm::Instruction::Ret: { 772*0fca6ea1SDimitry Andric auto *LLVMRet = cast<llvm::ReturnInst>(LLVMV); 773*0fca6ea1SDimitry Andric It->second = std::unique_ptr<ReturnInst>(new ReturnInst(LLVMRet, *this)); 774*0fca6ea1SDimitry Andric return It->second.get(); 775*0fca6ea1SDimitry Andric } 776*0fca6ea1SDimitry Andric default: 777*0fca6ea1SDimitry Andric break; 778*0fca6ea1SDimitry Andric } 779*0fca6ea1SDimitry Andric 780*0fca6ea1SDimitry Andric It->second = std::unique_ptr<OpaqueInst>( 781*0fca6ea1SDimitry Andric new OpaqueInst(cast<llvm::Instruction>(LLVMV), *this)); 782*0fca6ea1SDimitry Andric return It->second.get(); 783*0fca6ea1SDimitry Andric } 784*0fca6ea1SDimitry Andric 785*0fca6ea1SDimitry Andric BasicBlock *Context::createBasicBlock(llvm::BasicBlock *LLVMBB) { 786*0fca6ea1SDimitry Andric assert(getValue(LLVMBB) == nullptr && "Already exists!"); 787*0fca6ea1SDimitry Andric auto NewBBPtr = std::unique_ptr<BasicBlock>(new BasicBlock(LLVMBB, *this)); 788*0fca6ea1SDimitry Andric auto *BB = cast<BasicBlock>(registerValue(std::move(NewBBPtr))); 789*0fca6ea1SDimitry Andric // Create SandboxIR for BB's body. 790*0fca6ea1SDimitry Andric BB->buildBasicBlockFromLLVMIR(LLVMBB); 791*0fca6ea1SDimitry Andric return BB; 792*0fca6ea1SDimitry Andric } 793*0fca6ea1SDimitry Andric 794*0fca6ea1SDimitry Andric SelectInst *Context::createSelectInst(llvm::SelectInst *SI) { 795*0fca6ea1SDimitry Andric auto NewPtr = std::unique_ptr<SelectInst>(new SelectInst(SI, *this)); 796*0fca6ea1SDimitry Andric return cast<SelectInst>(registerValue(std::move(NewPtr))); 797*0fca6ea1SDimitry Andric } 798*0fca6ea1SDimitry Andric 799*0fca6ea1SDimitry Andric LoadInst *Context::createLoadInst(llvm::LoadInst *LI) { 800*0fca6ea1SDimitry Andric auto NewPtr = std::unique_ptr<LoadInst>(new LoadInst(LI, *this)); 801*0fca6ea1SDimitry Andric return cast<LoadInst>(registerValue(std::move(NewPtr))); 802*0fca6ea1SDimitry Andric } 803*0fca6ea1SDimitry Andric 804*0fca6ea1SDimitry Andric StoreInst *Context::createStoreInst(llvm::StoreInst *SI) { 805*0fca6ea1SDimitry Andric auto NewPtr = std::unique_ptr<StoreInst>(new StoreInst(SI, *this)); 806*0fca6ea1SDimitry Andric return cast<StoreInst>(registerValue(std::move(NewPtr))); 807*0fca6ea1SDimitry Andric } 808*0fca6ea1SDimitry Andric 809*0fca6ea1SDimitry Andric ReturnInst *Context::createReturnInst(llvm::ReturnInst *I) { 810*0fca6ea1SDimitry Andric auto NewPtr = std::unique_ptr<ReturnInst>(new ReturnInst(I, *this)); 811*0fca6ea1SDimitry Andric return cast<ReturnInst>(registerValue(std::move(NewPtr))); 812*0fca6ea1SDimitry Andric } 813*0fca6ea1SDimitry Andric 814*0fca6ea1SDimitry Andric Value *Context::getValue(llvm::Value *V) const { 815*0fca6ea1SDimitry Andric auto It = LLVMValueToValueMap.find(V); 816*0fca6ea1SDimitry Andric if (It != LLVMValueToValueMap.end()) 817*0fca6ea1SDimitry Andric return It->second.get(); 818*0fca6ea1SDimitry Andric return nullptr; 819*0fca6ea1SDimitry Andric } 820*0fca6ea1SDimitry Andric 821*0fca6ea1SDimitry Andric Function *Context::createFunction(llvm::Function *F) { 822*0fca6ea1SDimitry Andric assert(getValue(F) == nullptr && "Already exists!"); 823*0fca6ea1SDimitry Andric auto NewFPtr = std::unique_ptr<Function>(new Function(F, *this)); 824*0fca6ea1SDimitry Andric // Create arguments. 825*0fca6ea1SDimitry Andric for (auto &Arg : F->args()) 826*0fca6ea1SDimitry Andric getOrCreateArgument(&Arg); 827*0fca6ea1SDimitry Andric // Create BBs. 828*0fca6ea1SDimitry Andric for (auto &BB : *F) 829*0fca6ea1SDimitry Andric createBasicBlock(&BB); 830*0fca6ea1SDimitry Andric auto *SBF = cast<Function>(registerValue(std::move(NewFPtr))); 831*0fca6ea1SDimitry Andric return SBF; 832*0fca6ea1SDimitry Andric } 833*0fca6ea1SDimitry Andric 834*0fca6ea1SDimitry Andric Function *BasicBlock::getParent() const { 835*0fca6ea1SDimitry Andric auto *BB = cast<llvm::BasicBlock>(Val); 836*0fca6ea1SDimitry Andric auto *F = BB->getParent(); 837*0fca6ea1SDimitry Andric if (F == nullptr) 838*0fca6ea1SDimitry Andric // Detached 839*0fca6ea1SDimitry Andric return nullptr; 840*0fca6ea1SDimitry Andric return cast_or_null<Function>(Ctx.getValue(F)); 841*0fca6ea1SDimitry Andric } 842*0fca6ea1SDimitry Andric 843*0fca6ea1SDimitry Andric void BasicBlock::buildBasicBlockFromLLVMIR(llvm::BasicBlock *LLVMBB) { 844*0fca6ea1SDimitry Andric for (llvm::Instruction &IRef : reverse(*LLVMBB)) { 845*0fca6ea1SDimitry Andric llvm::Instruction *I = &IRef; 846*0fca6ea1SDimitry Andric Ctx.getOrCreateValue(I); 847*0fca6ea1SDimitry Andric for (auto [OpIdx, Op] : enumerate(I->operands())) { 848*0fca6ea1SDimitry Andric // Skip instruction's label operands 849*0fca6ea1SDimitry Andric if (isa<llvm::BasicBlock>(Op)) 850*0fca6ea1SDimitry Andric continue; 851*0fca6ea1SDimitry Andric // Skip metadata 852*0fca6ea1SDimitry Andric if (isa<llvm::MetadataAsValue>(Op)) 853*0fca6ea1SDimitry Andric continue; 854*0fca6ea1SDimitry Andric // Skip asm 855*0fca6ea1SDimitry Andric if (isa<llvm::InlineAsm>(Op)) 856*0fca6ea1SDimitry Andric continue; 857*0fca6ea1SDimitry Andric Ctx.getOrCreateValue(Op); 858*0fca6ea1SDimitry Andric } 859*0fca6ea1SDimitry Andric } 860*0fca6ea1SDimitry Andric #if !defined(NDEBUG) && defined(SBVEC_EXPENSIVE_CHECKS) 861*0fca6ea1SDimitry Andric verify(); 862*0fca6ea1SDimitry Andric #endif 863*0fca6ea1SDimitry Andric } 864*0fca6ea1SDimitry Andric 865*0fca6ea1SDimitry Andric BasicBlock::iterator BasicBlock::begin() const { 866*0fca6ea1SDimitry Andric llvm::BasicBlock *BB = cast<llvm::BasicBlock>(Val); 867*0fca6ea1SDimitry Andric llvm::BasicBlock::iterator It = BB->begin(); 868*0fca6ea1SDimitry Andric if (!BB->empty()) { 869*0fca6ea1SDimitry Andric auto *V = Ctx.getValue(&*BB->begin()); 870*0fca6ea1SDimitry Andric assert(V != nullptr && "No SandboxIR for BB->begin()!"); 871*0fca6ea1SDimitry Andric auto *I = cast<Instruction>(V); 872*0fca6ea1SDimitry Andric unsigned Num = I->getNumOfIRInstrs(); 873*0fca6ea1SDimitry Andric assert(Num >= 1u && "Bad getNumOfIRInstrs()"); 874*0fca6ea1SDimitry Andric It = std::next(It, Num - 1); 875*0fca6ea1SDimitry Andric } 876*0fca6ea1SDimitry Andric return iterator(BB, It, &Ctx); 877*0fca6ea1SDimitry Andric } 878*0fca6ea1SDimitry Andric 879*0fca6ea1SDimitry Andric Instruction *BasicBlock::getTerminator() const { 880*0fca6ea1SDimitry Andric auto *TerminatorV = 881*0fca6ea1SDimitry Andric Ctx.getValue(cast<llvm::BasicBlock>(Val)->getTerminator()); 882*0fca6ea1SDimitry Andric return cast_or_null<Instruction>(TerminatorV); 883*0fca6ea1SDimitry Andric } 884*0fca6ea1SDimitry Andric 885*0fca6ea1SDimitry Andric Instruction &BasicBlock::front() const { 886*0fca6ea1SDimitry Andric auto *BB = cast<llvm::BasicBlock>(Val); 887*0fca6ea1SDimitry Andric assert(!BB->empty() && "Empty block!"); 888*0fca6ea1SDimitry Andric auto *SBI = cast<Instruction>(getContext().getValue(&*BB->begin())); 889*0fca6ea1SDimitry Andric assert(SBI != nullptr && "Expected Instr!"); 890*0fca6ea1SDimitry Andric return *SBI; 891*0fca6ea1SDimitry Andric } 892*0fca6ea1SDimitry Andric 893*0fca6ea1SDimitry Andric Instruction &BasicBlock::back() const { 894*0fca6ea1SDimitry Andric auto *BB = cast<llvm::BasicBlock>(Val); 895*0fca6ea1SDimitry Andric assert(!BB->empty() && "Empty block!"); 896*0fca6ea1SDimitry Andric auto *SBI = cast<Instruction>(getContext().getValue(&*BB->rbegin())); 897*0fca6ea1SDimitry Andric assert(SBI != nullptr && "Expected Instr!"); 898*0fca6ea1SDimitry Andric return *SBI; 899*0fca6ea1SDimitry Andric } 900*0fca6ea1SDimitry Andric 901*0fca6ea1SDimitry Andric #ifndef NDEBUG 902*0fca6ea1SDimitry Andric void BasicBlock::dump(raw_ostream &OS) const { 903*0fca6ea1SDimitry Andric llvm::BasicBlock *BB = cast<llvm::BasicBlock>(Val); 904*0fca6ea1SDimitry Andric const auto &Name = BB->getName(); 905*0fca6ea1SDimitry Andric OS << Name; 906*0fca6ea1SDimitry Andric if (!Name.empty()) 907*0fca6ea1SDimitry Andric OS << ":\n"; 908*0fca6ea1SDimitry Andric // If there are Instructions in the BB that are not mapped to SandboxIR, then 909*0fca6ea1SDimitry Andric // use a crash-proof dump. 910*0fca6ea1SDimitry Andric if (any_of(*BB, [this](llvm::Instruction &I) { 911*0fca6ea1SDimitry Andric return Ctx.getValue(&I) == nullptr; 912*0fca6ea1SDimitry Andric })) { 913*0fca6ea1SDimitry Andric OS << "<Crash-proof mode!>\n"; 914*0fca6ea1SDimitry Andric DenseSet<Instruction *> Visited; 915*0fca6ea1SDimitry Andric for (llvm::Instruction &IRef : *BB) { 916*0fca6ea1SDimitry Andric Value *SBV = Ctx.getValue(&IRef); 917*0fca6ea1SDimitry Andric if (SBV == nullptr) 918*0fca6ea1SDimitry Andric OS << IRef << " *** No SandboxIR ***\n"; 919*0fca6ea1SDimitry Andric else { 920*0fca6ea1SDimitry Andric auto *SBI = dyn_cast<Instruction>(SBV); 921*0fca6ea1SDimitry Andric if (SBI == nullptr) { 922*0fca6ea1SDimitry Andric OS << IRef << " *** Not a SBInstruction!!! ***\n"; 923*0fca6ea1SDimitry Andric } else { 924*0fca6ea1SDimitry Andric if (Visited.insert(SBI).second) 925*0fca6ea1SDimitry Andric OS << *SBI << "\n"; 926*0fca6ea1SDimitry Andric } 927*0fca6ea1SDimitry Andric } 928*0fca6ea1SDimitry Andric } 929*0fca6ea1SDimitry Andric } else { 930*0fca6ea1SDimitry Andric for (auto &SBI : *this) { 931*0fca6ea1SDimitry Andric SBI.dump(OS); 932*0fca6ea1SDimitry Andric OS << "\n"; 933*0fca6ea1SDimitry Andric } 934*0fca6ea1SDimitry Andric } 935*0fca6ea1SDimitry Andric } 936*0fca6ea1SDimitry Andric void BasicBlock::dump() const { 937*0fca6ea1SDimitry Andric dump(dbgs()); 938*0fca6ea1SDimitry Andric dbgs() << "\n"; 939*0fca6ea1SDimitry Andric } 940*0fca6ea1SDimitry Andric #endif // NDEBUG 941