1 //===- SandboxIR.h ----------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Sandbox IR is a lightweight overlay transactional IR on top of LLVM IR. 10 // Features: 11 // - You can save/rollback the state of the IR at any time. 12 // - Any changes made to Sandbox IR will automatically update the underlying 13 // LLVM IR so both IRs are always in sync. 14 // - Feels like LLVM IR, similar API. 15 // 16 // SandboxIR forms a class hierarchy that resembles that of LLVM IR 17 // but is in the `sandboxir` namespace: 18 // 19 // namespace sandboxir { 20 // 21 // +- Argument +- BinaryOperator 22 // | | 23 // Value -+- BasicBlock +- BranchInst 24 // | | 25 // +- Function +- Constant +- CastInst 26 // | | | 27 // +- User ------+- Instruction -+- CallInst 28 // | 29 // +- CmpInst 30 // | 31 // +- ExtractElementInst 32 // | 33 // +- GetElementPtrInst 34 // | 35 // +- InsertElementInst 36 // | 37 // +- LoadInst 38 // | 39 // +- OpaqueInst 40 // | 41 // +- PHINode 42 // | 43 // +- ReturnInst 44 // | 45 // +- SelectInst 46 // | 47 // +- ShuffleVectorInst 48 // | 49 // +- StoreInst 50 // | 51 // +- UnaryOperator 52 // 53 // Use 54 // 55 // } // namespace sandboxir 56 // 57 58 #ifndef LLVM_SANDBOXIR_SANDBOXIR_H 59 #define LLVM_SANDBOXIR_SANDBOXIR_H 60 61 #include "llvm/IR/Function.h" 62 #include "llvm/IR/IRBuilder.h" 63 #include "llvm/IR/User.h" 64 #include "llvm/IR/Value.h" 65 #include "llvm/SandboxIR/Tracker.h" 66 #include "llvm/SandboxIR/Use.h" 67 #include "llvm/Support/raw_ostream.h" 68 #include <iterator> 69 70 namespace llvm { 71 72 namespace sandboxir { 73 74 class BasicBlock; 75 class Context; 76 class Function; 77 class Instruction; 78 class SelectInst; 79 class LoadInst; 80 class ReturnInst; 81 class StoreInst; 82 class User; 83 class Value; 84 85 /// Iterator for the `Use` edges of a User's operands. 86 /// \Returns the operand `Use` when dereferenced. 87 class OperandUseIterator { 88 sandboxir::Use Use; 89 /// Don't let the user create a non-empty OperandUseIterator. OperandUseIterator(const class Use & Use)90 OperandUseIterator(const class Use &Use) : Use(Use) {} 91 friend class User; // For constructor 92 #define DEF_INSTR(ID, OPC, CLASS) friend class CLASS; // For constructor 93 #include "llvm/SandboxIR/SandboxIRValues.def" 94 95 public: 96 using difference_type = std::ptrdiff_t; 97 using value_type = sandboxir::Use; 98 using pointer = value_type *; 99 using reference = value_type &; 100 using iterator_category = std::input_iterator_tag; 101 102 OperandUseIterator() = default; 103 value_type operator*() const; 104 OperandUseIterator &operator++(); 105 bool operator==(const OperandUseIterator &Other) const { 106 return Use == Other.Use; 107 } 108 bool operator!=(const OperandUseIterator &Other) const { 109 return !(*this == Other); 110 } 111 }; 112 113 /// Iterator for the `Use` edges of a Value's users. 114 /// \Returns a `Use` when dereferenced. 115 class UserUseIterator { 116 sandboxir::Use Use; 117 /// Don't let the user create a non-empty UserUseIterator. UserUseIterator(const class Use & Use)118 UserUseIterator(const class Use &Use) : Use(Use) {} 119 friend class Value; // For constructor 120 121 public: 122 using difference_type = std::ptrdiff_t; 123 using value_type = sandboxir::Use; 124 using pointer = value_type *; 125 using reference = value_type &; 126 using iterator_category = std::input_iterator_tag; 127 128 UserUseIterator() = default; 129 value_type operator*() const { return Use; } 130 UserUseIterator &operator++(); 131 bool operator==(const UserUseIterator &Other) const { 132 return Use == Other.Use; 133 } 134 bool operator!=(const UserUseIterator &Other) const { 135 return !(*this == Other); 136 } 137 }; 138 139 /// A SandboxIR Value has users. This is the base class. 140 class Value { 141 public: 142 enum class ClassID : unsigned { 143 #define DEF_VALUE(ID, CLASS) ID, 144 #define DEF_USER(ID, CLASS) ID, 145 #define DEF_INSTR(ID, OPC, CLASS) ID, 146 #include "llvm/SandboxIR/SandboxIRValues.def" 147 }; 148 149 protected: getSubclassIDStr(ClassID ID)150 static const char *getSubclassIDStr(ClassID ID) { 151 switch (ID) { 152 #define DEF_VALUE(ID, CLASS) \ 153 case ClassID::ID: \ 154 return #ID; 155 #define DEF_USER(ID, CLASS) \ 156 case ClassID::ID: \ 157 return #ID; 158 #define DEF_INSTR(ID, OPC, CLASS) \ 159 case ClassID::ID: \ 160 return #ID; 161 #include "llvm/SandboxIR/SandboxIRValues.def" 162 } 163 llvm_unreachable("Unimplemented ID"); 164 } 165 166 /// For isa/dyn_cast. 167 ClassID SubclassID; 168 #ifndef NDEBUG 169 /// A unique ID used for forming the name (used for debugging). 170 unsigned UID; 171 #endif 172 /// The LLVM Value that corresponds to this SandboxIR Value. 173 /// NOTE: Some sandboxir Instructions, like Packs, may include more than one 174 /// value and in these cases `Val` points to the last instruction in program 175 /// order. 176 llvm::Value *Val = nullptr; 177 178 friend class Context; // For getting `Val`. 179 friend class User; // For getting `Val`. 180 friend class Use; // For getting `Val`. 181 friend class SelectInst; // For getting `Val`. 182 friend class LoadInst; // For getting `Val`. 183 friend class StoreInst; // For getting `Val`. 184 friend class ReturnInst; // For getting `Val`. 185 186 /// All values point to the context. 187 Context &Ctx; 188 // This is used by eraseFromParent(). clearValue()189 void clearValue() { Val = nullptr; } 190 template <typename ItTy, typename SBTy> friend class LLVMOpUserItToSBTy; 191 192 Value(ClassID SubclassID, llvm::Value *Val, Context &Ctx); 193 194 public: 195 virtual ~Value() = default; getSubclassID()196 ClassID getSubclassID() const { return SubclassID; } 197 198 using use_iterator = UserUseIterator; 199 using const_use_iterator = UserUseIterator; 200 201 use_iterator use_begin(); use_begin()202 const_use_iterator use_begin() const { 203 return const_cast<Value *>(this)->use_begin(); 204 } use_end()205 use_iterator use_end() { return use_iterator(Use(nullptr, nullptr, Ctx)); } use_end()206 const_use_iterator use_end() const { 207 return const_cast<Value *>(this)->use_end(); 208 } 209 uses()210 iterator_range<use_iterator> uses() { 211 return make_range<use_iterator>(use_begin(), use_end()); 212 } uses()213 iterator_range<const_use_iterator> uses() const { 214 return make_range<const_use_iterator>(use_begin(), use_end()); 215 } 216 217 /// Helper for mapped_iterator. 218 struct UseToUser { operatorUseToUser219 User *operator()(const Use &Use) const { return &*Use.getUser(); } 220 }; 221 222 using user_iterator = mapped_iterator<sandboxir::UserUseIterator, UseToUser>; 223 using const_user_iterator = user_iterator; 224 225 user_iterator user_begin(); user_end()226 user_iterator user_end() { 227 return user_iterator(Use(nullptr, nullptr, Ctx), UseToUser()); 228 } user_begin()229 const_user_iterator user_begin() const { 230 return const_cast<Value *>(this)->user_begin(); 231 } user_end()232 const_user_iterator user_end() const { 233 return const_cast<Value *>(this)->user_end(); 234 } 235 users()236 iterator_range<user_iterator> users() { 237 return make_range<user_iterator>(user_begin(), user_end()); 238 } users()239 iterator_range<const_user_iterator> users() const { 240 return make_range<const_user_iterator>(user_begin(), user_end()); 241 } 242 /// \Returns the number of user edges (not necessarily to unique users). 243 /// WARNING: This is a linear-time operation. 244 unsigned getNumUses() const; 245 /// Return true if this value has N uses or more. 246 /// This is logically equivalent to getNumUses() >= N. 247 /// WARNING: This can be expensive, as it is linear to the number of users. hasNUsesOrMore(unsigned Num)248 bool hasNUsesOrMore(unsigned Num) const { 249 unsigned Cnt = 0; 250 for (auto It = use_begin(), ItE = use_end(); It != ItE; ++It) { 251 if (++Cnt >= Num) 252 return true; 253 } 254 return false; 255 } 256 /// Return true if this Value has exactly N uses. hasNUses(unsigned Num)257 bool hasNUses(unsigned Num) const { 258 unsigned Cnt = 0; 259 for (auto It = use_begin(), ItE = use_end(); It != ItE; ++It) { 260 if (++Cnt > Num) 261 return false; 262 } 263 return Cnt == Num; 264 } 265 getType()266 Type *getType() const { return Val->getType(); } 267 getContext()268 Context &getContext() const { return Ctx; } 269 270 void replaceUsesWithIf(Value *OtherV, 271 llvm::function_ref<bool(const Use &)> ShouldReplace); 272 void replaceAllUsesWith(Value *Other); 273 274 /// \Returns the LLVM IR name of the bottom-most LLVM value. getName()275 StringRef getName() const { return Val->getName(); } 276 277 #ifndef NDEBUG 278 /// Should crash if there is something wrong with the instruction. 279 virtual void verify() const = 0; 280 /// Returns the unique id in the form 'SB<number>.' like 'SB1.' 281 std::string getUid() const; 282 virtual void dumpCommonHeader(raw_ostream &OS) const; 283 void dumpCommonFooter(raw_ostream &OS) const; 284 void dumpCommonPrefix(raw_ostream &OS) const; 285 void dumpCommonSuffix(raw_ostream &OS) const; 286 void printAsOperandCommon(raw_ostream &OS) const; 287 friend raw_ostream &operator<<(raw_ostream &OS, const sandboxir::Value &V) { 288 V.dump(OS); 289 return OS; 290 } 291 virtual void dump(raw_ostream &OS) const = 0; 292 LLVM_DUMP_METHOD virtual void dump() const = 0; 293 #endif 294 }; 295 296 /// Argument of a sandboxir::Function. 297 class Argument : public sandboxir::Value { Argument(llvm::Argument * Arg,sandboxir::Context & Ctx)298 Argument(llvm::Argument *Arg, sandboxir::Context &Ctx) 299 : sandboxir::Value(ClassID::Argument, Arg, Ctx) {} 300 friend class Context; // For constructor. 301 302 public: classof(const sandboxir::Value * From)303 static bool classof(const sandboxir::Value *From) { 304 return From->getSubclassID() == ClassID::Argument; 305 } 306 #ifndef NDEBUG verify()307 void verify() const final { 308 assert(isa<llvm::Argument>(Val) && "Expected Argument!"); 309 } 310 friend raw_ostream &operator<<(raw_ostream &OS, 311 const sandboxir::Argument &TArg) { 312 TArg.dump(OS); 313 return OS; 314 } 315 void printAsOperand(raw_ostream &OS) const; 316 void dump(raw_ostream &OS) const final; 317 LLVM_DUMP_METHOD void dump() const final; 318 #endif 319 }; 320 321 /// A sandboxir::User has operands. 322 class User : public Value { 323 protected: User(ClassID ID,llvm::Value * V,Context & Ctx)324 User(ClassID ID, llvm::Value *V, Context &Ctx) : Value(ID, V, Ctx) {} 325 326 /// \Returns the Use edge that corresponds to \p OpIdx. 327 /// Note: This is the default implementation that works for instructions that 328 /// match the underlying LLVM instruction. All others should use a different 329 /// implementation. 330 Use getOperandUseDefault(unsigned OpIdx, bool Verify) const; 331 /// \Returns the Use for the \p OpIdx'th operand. This is virtual to allow 332 /// instructions to deviate from the LLVM IR operands, which is a requirement 333 /// for sandboxir Instructions that consist of more than one LLVM Instruction. 334 virtual Use getOperandUseInternal(unsigned OpIdx, bool Verify) const = 0; 335 friend class OperandUseIterator; // for getOperandUseInternal() 336 337 /// The default implementation works only for single-LLVMIR-instruction 338 /// Users and only if they match exactly the LLVM instruction. getUseOperandNoDefault(const Use & Use)339 unsigned getUseOperandNoDefault(const Use &Use) const { 340 return Use.LLVMUse->getOperandNo(); 341 } 342 /// \Returns the operand index of \p Use. 343 virtual unsigned getUseOperandNo(const Use &Use) const = 0; 344 friend unsigned Use::getOperandNo() const; // For getUseOperandNo() 345 346 #ifndef NDEBUG 347 void verifyUserOfLLVMUse(const llvm::Use &Use) const; 348 #endif // NDEBUG 349 350 public: 351 /// For isa/dyn_cast. 352 static bool classof(const Value *From); 353 using op_iterator = OperandUseIterator; 354 using const_op_iterator = OperandUseIterator; 355 using op_range = iterator_range<op_iterator>; 356 using const_op_range = iterator_range<const_op_iterator>; 357 op_begin()358 virtual op_iterator op_begin() { 359 assert(isa<llvm::User>(Val) && "Expect User value!"); 360 return op_iterator(getOperandUseInternal(0, /*Verify=*/false)); 361 } op_end()362 virtual op_iterator op_end() { 363 assert(isa<llvm::User>(Val) && "Expect User value!"); 364 return op_iterator( 365 getOperandUseInternal(getNumOperands(), /*Verify=*/false)); 366 } op_begin()367 virtual const_op_iterator op_begin() const { 368 return const_cast<User *>(this)->op_begin(); 369 } op_end()370 virtual const_op_iterator op_end() const { 371 return const_cast<User *>(this)->op_end(); 372 } 373 operands()374 op_range operands() { return make_range<op_iterator>(op_begin(), op_end()); } operands()375 const_op_range operands() const { 376 return make_range<const_op_iterator>(op_begin(), op_end()); 377 } getOperand(unsigned OpIdx)378 Value *getOperand(unsigned OpIdx) const { return getOperandUse(OpIdx).get(); } 379 /// \Returns the operand edge for \p OpIdx. NOTE: This should also work for 380 /// OpIdx == getNumOperands(), which is used for op_end(). getOperandUse(unsigned OpIdx)381 Use getOperandUse(unsigned OpIdx) const { 382 return getOperandUseInternal(OpIdx, /*Verify=*/true); 383 } getNumOperands()384 virtual unsigned getNumOperands() const { 385 return isa<llvm::User>(Val) ? cast<llvm::User>(Val)->getNumOperands() : 0; 386 } 387 388 virtual void setOperand(unsigned OperandIdx, Value *Operand); 389 /// Replaces any operands that match \p FromV with \p ToV. Returns whether any 390 /// operands were replaced. 391 bool replaceUsesOfWith(Value *FromV, Value *ToV); 392 393 #ifndef NDEBUG verify()394 void verify() const override { 395 assert(isa<llvm::User>(Val) && "Expected User!"); 396 } 397 void dumpCommonHeader(raw_ostream &OS) const final; dump(raw_ostream & OS)398 void dump(raw_ostream &OS) const override { 399 // TODO: Remove this tmp implementation once we get the Instruction classes. 400 } dump()401 LLVM_DUMP_METHOD void dump() const override { 402 // TODO: Remove this tmp implementation once we get the Instruction classes. 403 } 404 #endif 405 }; 406 407 class Constant : public sandboxir::User { Constant(llvm::Constant * C,sandboxir::Context & SBCtx)408 Constant(llvm::Constant *C, sandboxir::Context &SBCtx) 409 : sandboxir::User(ClassID::Constant, C, SBCtx) {} 410 friend class Context; // For constructor. getOperandUseInternal(unsigned OpIdx,bool Verify)411 Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final { 412 return getOperandUseDefault(OpIdx, Verify); 413 } 414 415 public: 416 static Constant *createInt(Type *Ty, uint64_t V, Context &Ctx, 417 bool IsSigned = false); 418 /// For isa/dyn_cast. classof(const sandboxir::Value * From)419 static bool classof(const sandboxir::Value *From) { 420 return From->getSubclassID() == ClassID::Constant || 421 From->getSubclassID() == ClassID::Function; 422 } getParent()423 sandboxir::Context &getParent() const { return getContext(); } getUseOperandNo(const Use & Use)424 unsigned getUseOperandNo(const Use &Use) const final { 425 return getUseOperandNoDefault(Use); 426 } 427 #ifndef NDEBUG verify()428 void verify() const final { 429 assert(isa<llvm::Constant>(Val) && "Expected Constant!"); 430 } 431 friend raw_ostream &operator<<(raw_ostream &OS, 432 const sandboxir::Constant &SBC) { 433 SBC.dump(OS); 434 return OS; 435 } 436 void dump(raw_ostream &OS) const override; 437 LLVM_DUMP_METHOD void dump() const override; 438 #endif 439 }; 440 441 /// Iterator for `Instruction`s in a `BasicBlock. 442 /// \Returns an sandboxir::Instruction & when derereferenced. 443 class BBIterator { 444 public: 445 using difference_type = std::ptrdiff_t; 446 using value_type = Instruction; 447 using pointer = value_type *; 448 using reference = value_type &; 449 using iterator_category = std::bidirectional_iterator_tag; 450 451 private: 452 llvm::BasicBlock *BB; 453 llvm::BasicBlock::iterator It; 454 Context *Ctx; 455 pointer getInstr(llvm::BasicBlock::iterator It) const; 456 457 public: BBIterator()458 BBIterator() : BB(nullptr), Ctx(nullptr) {} BBIterator(llvm::BasicBlock * BB,llvm::BasicBlock::iterator It,Context * Ctx)459 BBIterator(llvm::BasicBlock *BB, llvm::BasicBlock::iterator It, Context *Ctx) 460 : BB(BB), It(It), Ctx(Ctx) {} 461 reference operator*() const { return *getInstr(It); } 462 BBIterator &operator++(); 463 BBIterator operator++(int) { 464 auto Copy = *this; 465 ++*this; 466 return Copy; 467 } 468 BBIterator &operator--(); 469 BBIterator operator--(int) { 470 auto Copy = *this; 471 --*this; 472 return Copy; 473 } 474 bool operator==(const BBIterator &Other) const { 475 assert(Ctx == Other.Ctx && "BBIterators in different context!"); 476 return It == Other.It; 477 } 478 bool operator!=(const BBIterator &Other) const { return !(*this == Other); } 479 /// \Returns the SBInstruction that corresponds to this iterator, or null if 480 /// the instruction is not found in the IR-to-SandboxIR tables. get()481 pointer get() const { return getInstr(It); } 482 }; 483 484 /// A sandboxir::User with operands, opcode and linked with previous/next 485 /// instructions in an instruction list. 486 class Instruction : public sandboxir::User { 487 public: 488 enum class Opcode { 489 #define DEF_VALUE(ID, CLASS) 490 #define DEF_USER(ID, CLASS) 491 #define OP(OPC) OPC, 492 #define DEF_INSTR(ID, OPC, CLASS) OPC 493 #include "llvm/SandboxIR/SandboxIRValues.def" 494 }; 495 496 protected: Instruction(ClassID ID,Opcode Opc,llvm::Instruction * I,sandboxir::Context & SBCtx)497 Instruction(ClassID ID, Opcode Opc, llvm::Instruction *I, 498 sandboxir::Context &SBCtx) 499 : sandboxir::User(ID, I, SBCtx), Opc(Opc) {} 500 501 Opcode Opc; 502 503 /// A SandboxIR Instruction may map to multiple LLVM IR Instruction. This 504 /// returns its topmost LLVM IR instruction. 505 llvm::Instruction *getTopmostLLVMInstruction() const; 506 friend class SelectInst; // For getTopmostLLVMInstruction(). 507 friend class LoadInst; // For getTopmostLLVMInstruction(). 508 friend class StoreInst; // For getTopmostLLVMInstruction(). 509 friend class ReturnInst; // For getTopmostLLVMInstruction(). 510 511 /// \Returns the LLVM IR Instructions that this SandboxIR maps to in program 512 /// order. 513 virtual SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const = 0; 514 friend class EraseFromParent; // For getLLVMInstrs(). 515 516 public: 517 static const char *getOpcodeName(Opcode Opc); 518 #ifndef NDEBUG 519 friend raw_ostream &operator<<(raw_ostream &OS, Opcode Opc) { 520 OS << getOpcodeName(Opc); 521 return OS; 522 } 523 #endif 524 /// This is used by BasicBlock::iterator. 525 virtual unsigned getNumOfIRInstrs() const = 0; 526 /// \Returns a BasicBlock::iterator for this Instruction. 527 BBIterator getIterator() const; 528 /// \Returns the next sandboxir::Instruction in the block, or nullptr if at 529 /// the end of the block. 530 Instruction *getNextNode() const; 531 /// \Returns the previous sandboxir::Instruction in the block, or nullptr if 532 /// at the beginning of the block. 533 Instruction *getPrevNode() const; 534 /// \Returns this Instruction's opcode. Note that SandboxIR has its own opcode 535 /// state to allow for new SandboxIR-specific instructions. getOpcode()536 Opcode getOpcode() const { return Opc; } 537 /// Detach this from its parent BasicBlock without deleting it. 538 void removeFromParent(); 539 /// Detach this Value from its parent and delete it. 540 void eraseFromParent(); 541 /// Insert this detached instruction before \p BeforeI. 542 void insertBefore(Instruction *BeforeI); 543 /// Insert this detached instruction after \p AfterI. 544 void insertAfter(Instruction *AfterI); 545 /// Insert this detached instruction into \p BB at \p WhereIt. 546 void insertInto(BasicBlock *BB, const BBIterator &WhereIt); 547 /// Move this instruction to \p WhereIt. 548 void moveBefore(BasicBlock &BB, const BBIterator &WhereIt); 549 /// Move this instruction before \p Before. moveBefore(Instruction * Before)550 void moveBefore(Instruction *Before) { 551 moveBefore(*Before->getParent(), Before->getIterator()); 552 } 553 /// Move this instruction after \p After. moveAfter(Instruction * After)554 void moveAfter(Instruction *After) { 555 moveBefore(*After->getParent(), std::next(After->getIterator())); 556 } 557 /// \Returns the BasicBlock containing this Instruction, or null if it is 558 /// detached. 559 BasicBlock *getParent() const; 560 /// For isa/dyn_cast. 561 static bool classof(const sandboxir::Value *From); 562 563 #ifndef NDEBUG 564 friend raw_ostream &operator<<(raw_ostream &OS, 565 const sandboxir::Instruction &SBI) { 566 SBI.dump(OS); 567 return OS; 568 } 569 void dump(raw_ostream &OS) const override; 570 LLVM_DUMP_METHOD void dump() const override; 571 #endif 572 }; 573 574 class SelectInst : public Instruction { 575 /// Use Context::createSelectInst(). Don't call the 576 /// constructor directly. SelectInst(llvm::SelectInst * CI,Context & Ctx)577 SelectInst(llvm::SelectInst *CI, Context &Ctx) 578 : Instruction(ClassID::Select, Opcode::Select, CI, Ctx) {} 579 friend Context; // for SelectInst() getOperandUseInternal(unsigned OpIdx,bool Verify)580 Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final { 581 return getOperandUseDefault(OpIdx, Verify); 582 } getLLVMInstrs()583 SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final { 584 return {cast<llvm::Instruction>(Val)}; 585 } 586 static Value *createCommon(Value *Cond, Value *True, Value *False, 587 const Twine &Name, IRBuilder<> &Builder, 588 Context &Ctx); 589 590 public: getUseOperandNo(const Use & Use)591 unsigned getUseOperandNo(const Use &Use) const final { 592 return getUseOperandNoDefault(Use); 593 } getNumOfIRInstrs()594 unsigned getNumOfIRInstrs() const final { return 1u; } 595 static Value *create(Value *Cond, Value *True, Value *False, 596 Instruction *InsertBefore, Context &Ctx, 597 const Twine &Name = ""); 598 static Value *create(Value *Cond, Value *True, Value *False, 599 BasicBlock *InsertAtEnd, Context &Ctx, 600 const Twine &Name = ""); getCondition()601 Value *getCondition() { return getOperand(0); } getTrueValue()602 Value *getTrueValue() { return getOperand(1); } getFalseValue()603 Value *getFalseValue() { return getOperand(2); } 604 setCondition(Value * New)605 void setCondition(Value *New) { setOperand(0, New); } setTrueValue(Value * New)606 void setTrueValue(Value *New) { setOperand(1, New); } setFalseValue(Value * New)607 void setFalseValue(Value *New) { setOperand(2, New); } swapValues()608 void swapValues() { cast<llvm::SelectInst>(Val)->swapValues(); } 609 /// For isa/dyn_cast. 610 static bool classof(const Value *From); 611 #ifndef NDEBUG verify()612 void verify() const final { 613 assert(isa<llvm::SelectInst>(Val) && "Expected SelectInst!"); 614 } 615 void dump(raw_ostream &OS) const override; 616 LLVM_DUMP_METHOD void dump() const override; 617 #endif 618 }; 619 620 class LoadInst final : public Instruction { 621 /// Use LoadInst::create() instead of calling the constructor. LoadInst(llvm::LoadInst * LI,Context & Ctx)622 LoadInst(llvm::LoadInst *LI, Context &Ctx) 623 : Instruction(ClassID::Load, Opcode::Load, LI, Ctx) {} 624 friend Context; // for LoadInst() getOperandUseInternal(unsigned OpIdx,bool Verify)625 Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final { 626 return getOperandUseDefault(OpIdx, Verify); 627 } getLLVMInstrs()628 SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final { 629 return {cast<llvm::Instruction>(Val)}; 630 } 631 632 public: getUseOperandNo(const Use & Use)633 unsigned getUseOperandNo(const Use &Use) const final { 634 return getUseOperandNoDefault(Use); 635 } 636 getNumOfIRInstrs()637 unsigned getNumOfIRInstrs() const final { return 1u; } 638 static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align, 639 Instruction *InsertBefore, Context &Ctx, 640 const Twine &Name = ""); 641 static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align, 642 BasicBlock *InsertAtEnd, Context &Ctx, 643 const Twine &Name = ""); 644 /// For isa/dyn_cast. 645 static bool classof(const Value *From); 646 Value *getPointerOperand() const; getAlign()647 Align getAlign() const { return cast<llvm::LoadInst>(Val)->getAlign(); } isUnordered()648 bool isUnordered() const { return cast<llvm::LoadInst>(Val)->isUnordered(); } isSimple()649 bool isSimple() const { return cast<llvm::LoadInst>(Val)->isSimple(); } 650 #ifndef NDEBUG verify()651 void verify() const final { 652 assert(isa<llvm::LoadInst>(Val) && "Expected LoadInst!"); 653 } 654 void dump(raw_ostream &OS) const override; 655 LLVM_DUMP_METHOD void dump() const override; 656 #endif 657 }; 658 659 class StoreInst final : public Instruction { 660 /// Use StoreInst::create(). StoreInst(llvm::StoreInst * SI,Context & Ctx)661 StoreInst(llvm::StoreInst *SI, Context &Ctx) 662 : Instruction(ClassID::Store, Opcode::Store, SI, Ctx) {} 663 friend Context; // for StoreInst() getOperandUseInternal(unsigned OpIdx,bool Verify)664 Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final { 665 return getOperandUseDefault(OpIdx, Verify); 666 } getLLVMInstrs()667 SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final { 668 return {cast<llvm::Instruction>(Val)}; 669 } 670 671 public: getUseOperandNo(const Use & Use)672 unsigned getUseOperandNo(const Use &Use) const final { 673 return getUseOperandNoDefault(Use); 674 } getNumOfIRInstrs()675 unsigned getNumOfIRInstrs() const final { return 1u; } 676 static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align, 677 Instruction *InsertBefore, Context &Ctx); 678 static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align, 679 BasicBlock *InsertAtEnd, Context &Ctx); 680 /// For isa/dyn_cast. 681 static bool classof(const Value *From); 682 Value *getValueOperand() const; 683 Value *getPointerOperand() const; getAlign()684 Align getAlign() const { return cast<llvm::StoreInst>(Val)->getAlign(); } isSimple()685 bool isSimple() const { return cast<llvm::StoreInst>(Val)->isSimple(); } isUnordered()686 bool isUnordered() const { return cast<llvm::StoreInst>(Val)->isUnordered(); } 687 #ifndef NDEBUG verify()688 void verify() const final { 689 assert(isa<llvm::StoreInst>(Val) && "Expected StoreInst!"); 690 } 691 void dump(raw_ostream &OS) const override; 692 LLVM_DUMP_METHOD void dump() const override; 693 #endif 694 }; 695 696 class ReturnInst final : public Instruction { 697 /// Use ReturnInst::create() instead of calling the constructor. ReturnInst(llvm::Instruction * I,Context & Ctx)698 ReturnInst(llvm::Instruction *I, Context &Ctx) 699 : Instruction(ClassID::Ret, Opcode::Ret, I, Ctx) {} ReturnInst(ClassID SubclassID,llvm::Instruction * I,Context & Ctx)700 ReturnInst(ClassID SubclassID, llvm::Instruction *I, Context &Ctx) 701 : Instruction(SubclassID, Opcode::Ret, I, Ctx) {} 702 friend class Context; // For accessing the constructor in create*() getOperandUseInternal(unsigned OpIdx,bool Verify)703 Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final { 704 return getOperandUseDefault(OpIdx, Verify); 705 } getLLVMInstrs()706 SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final { 707 return {cast<llvm::Instruction>(Val)}; 708 } 709 static ReturnInst *createCommon(Value *RetVal, IRBuilder<> &Builder, 710 Context &Ctx); 711 712 public: 713 static ReturnInst *create(Value *RetVal, Instruction *InsertBefore, 714 Context &Ctx); 715 static ReturnInst *create(Value *RetVal, BasicBlock *InsertAtEnd, 716 Context &Ctx); classof(const Value * From)717 static bool classof(const Value *From) { 718 return From->getSubclassID() == ClassID::Ret; 719 } getUseOperandNo(const Use & Use)720 unsigned getUseOperandNo(const Use &Use) const final { 721 return getUseOperandNoDefault(Use); 722 } getNumOfIRInstrs()723 unsigned getNumOfIRInstrs() const final { return 1u; } 724 /// \Returns null if there is no return value. 725 Value *getReturnValue() const; 726 #ifndef NDEBUG verify()727 void verify() const final {} 728 void dump(raw_ostream &OS) const override; 729 LLVM_DUMP_METHOD void dump() const override; 730 #endif 731 }; 732 733 /// An LLLVM Instruction that has no SandboxIR equivalent class gets mapped to 734 /// an OpaqueInstr. 735 class OpaqueInst : public sandboxir::Instruction { OpaqueInst(llvm::Instruction * I,sandboxir::Context & Ctx)736 OpaqueInst(llvm::Instruction *I, sandboxir::Context &Ctx) 737 : sandboxir::Instruction(ClassID::Opaque, Opcode::Opaque, I, Ctx) {} OpaqueInst(ClassID SubclassID,llvm::Instruction * I,sandboxir::Context & Ctx)738 OpaqueInst(ClassID SubclassID, llvm::Instruction *I, sandboxir::Context &Ctx) 739 : sandboxir::Instruction(SubclassID, Opcode::Opaque, I, Ctx) {} 740 friend class Context; // For constructor. getOperandUseInternal(unsigned OpIdx,bool Verify)741 Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final { 742 return getOperandUseDefault(OpIdx, Verify); 743 } getLLVMInstrs()744 SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final { 745 return {cast<llvm::Instruction>(Val)}; 746 } 747 748 public: classof(const sandboxir::Value * From)749 static bool classof(const sandboxir::Value *From) { 750 return From->getSubclassID() == ClassID::Opaque; 751 } getUseOperandNo(const Use & Use)752 unsigned getUseOperandNo(const Use &Use) const final { 753 return getUseOperandNoDefault(Use); 754 } getNumOfIRInstrs()755 unsigned getNumOfIRInstrs() const final { return 1u; } 756 #ifndef NDEBUG verify()757 void verify() const final { 758 // Nothing to do 759 } 760 friend raw_ostream &operator<<(raw_ostream &OS, 761 const sandboxir::OpaqueInst &OI) { 762 OI.dump(OS); 763 return OS; 764 } 765 void dump(raw_ostream &OS) const override; 766 LLVM_DUMP_METHOD void dump() const override; 767 #endif 768 }; 769 770 /// Contains a list of sandboxir::Instruction's. 771 class BasicBlock : public Value { 772 /// Builds a graph that contains all values in \p BB in their original form 773 /// i.e., no vectorization is taking place here. 774 void buildBasicBlockFromLLVMIR(llvm::BasicBlock *LLVMBB); 775 friend class Context; // For `buildBasicBlockFromIR` 776 friend class Instruction; // For LLVM Val. 777 BasicBlock(llvm::BasicBlock * BB,Context & SBCtx)778 BasicBlock(llvm::BasicBlock *BB, Context &SBCtx) 779 : Value(ClassID::Block, BB, SBCtx) { 780 buildBasicBlockFromLLVMIR(BB); 781 } 782 783 public: 784 ~BasicBlock() = default; 785 /// For isa/dyn_cast. classof(const Value * From)786 static bool classof(const Value *From) { 787 return From->getSubclassID() == Value::ClassID::Block; 788 } 789 Function *getParent() const; 790 using iterator = BBIterator; 791 iterator begin() const; end()792 iterator end() const { 793 auto *BB = cast<llvm::BasicBlock>(Val); 794 return iterator(BB, BB->end(), &Ctx); 795 } rbegin()796 std::reverse_iterator<iterator> rbegin() const { 797 return std::make_reverse_iterator(end()); 798 } rend()799 std::reverse_iterator<iterator> rend() const { 800 return std::make_reverse_iterator(begin()); 801 } getContext()802 Context &getContext() const { return Ctx; } 803 Instruction *getTerminator() const; empty()804 bool empty() const { return begin() == end(); } 805 Instruction &front() const; 806 Instruction &back() const; 807 808 #ifndef NDEBUG verify()809 void verify() const final { 810 assert(isa<llvm::BasicBlock>(Val) && "Expected BasicBlock!"); 811 } 812 friend raw_ostream &operator<<(raw_ostream &OS, const BasicBlock &SBBB) { 813 SBBB.dump(OS); 814 return OS; 815 } 816 void dump(raw_ostream &OS) const final; 817 LLVM_DUMP_METHOD void dump() const final; 818 #endif 819 }; 820 821 class Context { 822 protected: 823 LLVMContext &LLVMCtx; 824 Tracker IRTracker; 825 826 /// Maps LLVM Value to the corresponding sandboxir::Value. Owns all 827 /// SandboxIR objects. 828 DenseMap<llvm::Value *, std::unique_ptr<sandboxir::Value>> 829 LLVMValueToValueMap; 830 831 /// Remove \p V from the maps and returns the unique_ptr. 832 std::unique_ptr<Value> detachLLVMValue(llvm::Value *V); 833 /// Remove \p SBV from all SandboxIR maps and stop owning it. This effectively 834 /// detaches \p V from the underlying IR. 835 std::unique_ptr<Value> detach(Value *V); 836 friend void Instruction::eraseFromParent(); // For detach(). 837 /// Take ownership of VPtr and store it in `LLVMValueToValueMap`. 838 Value *registerValue(std::unique_ptr<Value> &&VPtr); 839 friend class EraseFromParent; // For registerValue(). 840 /// This is the actual function that creates sandboxir values for \p V, 841 /// and among others handles all instruction types. 842 Value *getOrCreateValueInternal(llvm::Value *V, llvm::User *U = nullptr); 843 /// Get or create a sandboxir::Argument for an existing LLVM IR \p LLVMArg. getOrCreateArgument(llvm::Argument * LLVMArg)844 Argument *getOrCreateArgument(llvm::Argument *LLVMArg) { 845 auto Pair = LLVMValueToValueMap.insert({LLVMArg, nullptr}); 846 auto It = Pair.first; 847 if (Pair.second) { 848 It->second = std::unique_ptr<Argument>(new Argument(LLVMArg, *this)); 849 return cast<Argument>(It->second.get()); 850 } 851 return cast<Argument>(It->second.get()); 852 } 853 /// Get or create a sandboxir::Value for an existing LLVM IR \p LLVMV. getOrCreateValue(llvm::Value * LLVMV)854 Value *getOrCreateValue(llvm::Value *LLVMV) { 855 return getOrCreateValueInternal(LLVMV, 0); 856 } 857 /// Get or create a sandboxir::Constant from an existing LLVM IR \p LLVMC. getOrCreateConstant(llvm::Constant * LLVMC)858 Constant *getOrCreateConstant(llvm::Constant *LLVMC) { 859 return cast<Constant>(getOrCreateValueInternal(LLVMC, 0)); 860 } 861 friend class Constant; // For getOrCreateConstant(). 862 /// Create a sandboxir::BasicBlock for an existing LLVM IR \p BB. This will 863 /// also create all contents of the block. 864 BasicBlock *createBasicBlock(llvm::BasicBlock *BB); 865 866 friend class BasicBlock; // For getOrCreateValue(). 867 868 IRBuilder<ConstantFolder> LLVMIRBuilder; getLLVMIRBuilder()869 auto &getLLVMIRBuilder() { return LLVMIRBuilder; } 870 871 SelectInst *createSelectInst(llvm::SelectInst *SI); 872 friend SelectInst; // For createSelectInst() 873 LoadInst *createLoadInst(llvm::LoadInst *LI); 874 friend LoadInst; // For createLoadInst() 875 StoreInst *createStoreInst(llvm::StoreInst *SI); 876 friend StoreInst; // For createStoreInst() 877 ReturnInst *createReturnInst(llvm::ReturnInst *I); 878 friend ReturnInst; // For createReturnInst() 879 880 public: Context(LLVMContext & LLVMCtx)881 Context(LLVMContext &LLVMCtx) 882 : LLVMCtx(LLVMCtx), IRTracker(*this), 883 LLVMIRBuilder(LLVMCtx, ConstantFolder()) {} 884 getTracker()885 Tracker &getTracker() { return IRTracker; } 886 /// Convenience function for `getTracker().save()` save()887 void save() { IRTracker.save(); } 888 /// Convenience function for `getTracker().revert()` revert()889 void revert() { IRTracker.revert(); } 890 /// Convenience function for `getTracker().accept()` accept()891 void accept() { IRTracker.accept(); } 892 893 sandboxir::Value *getValue(llvm::Value *V) const; getValue(const llvm::Value * V)894 const sandboxir::Value *getValue(const llvm::Value *V) const { 895 return getValue(const_cast<llvm::Value *>(V)); 896 } 897 /// Create a sandboxir::Function for an existing LLVM IR \p F, including all 898 /// blocks and instructions. 899 /// This is the main API function for creating Sandbox IR. 900 Function *createFunction(llvm::Function *F); 901 902 /// \Returns the number of values registered with Context. getNumValues()903 size_t getNumValues() const { return LLVMValueToValueMap.size(); } 904 }; 905 906 class Function : public sandboxir::Value { 907 /// Helper for mapped_iterator. 908 struct LLVMBBToBB { 909 Context &Ctx; LLVMBBToBBLLVMBBToBB910 LLVMBBToBB(Context &Ctx) : Ctx(Ctx) {} operatorLLVMBBToBB911 BasicBlock &operator()(llvm::BasicBlock &LLVMBB) const { 912 return *cast<BasicBlock>(Ctx.getValue(&LLVMBB)); 913 } 914 }; 915 /// Use Context::createFunction() instead. Function(llvm::Function * F,sandboxir::Context & Ctx)916 Function(llvm::Function *F, sandboxir::Context &Ctx) 917 : sandboxir::Value(ClassID::Function, F, Ctx) {} 918 friend class Context; // For constructor. 919 920 public: 921 /// For isa/dyn_cast. classof(const sandboxir::Value * From)922 static bool classof(const sandboxir::Value *From) { 923 return From->getSubclassID() == ClassID::Function; 924 } 925 getArg(unsigned Idx)926 Argument *getArg(unsigned Idx) const { 927 llvm::Argument *Arg = cast<llvm::Function>(Val)->getArg(Idx); 928 return cast<Argument>(Ctx.getValue(Arg)); 929 } 930 arg_size()931 size_t arg_size() const { return cast<llvm::Function>(Val)->arg_size(); } arg_empty()932 bool arg_empty() const { return cast<llvm::Function>(Val)->arg_empty(); } 933 934 using iterator = mapped_iterator<llvm::Function::iterator, LLVMBBToBB>; begin()935 iterator begin() const { 936 LLVMBBToBB BBGetter(Ctx); 937 return iterator(cast<llvm::Function>(Val)->begin(), BBGetter); 938 } end()939 iterator end() const { 940 LLVMBBToBB BBGetter(Ctx); 941 return iterator(cast<llvm::Function>(Val)->end(), BBGetter); 942 } 943 944 #ifndef NDEBUG verify()945 void verify() const final { 946 assert(isa<llvm::Function>(Val) && "Expected Function!"); 947 } 948 void dumpNameAndArgs(raw_ostream &OS) const; 949 void dump(raw_ostream &OS) const final; 950 LLVM_DUMP_METHOD void dump() const final; 951 #endif 952 }; 953 954 } // namespace sandboxir 955 } // namespace llvm 956 957 #endif // LLVM_SANDBOXIR_SANDBOXIR_H 958