5 #include "tir/BasicBlock.h" 
    6 #include "tir/Context.h" 
    9 #include "utils/EnumMacros.h" 
   10 #include "utils/Utils.h" 
   27    friend class BasicBlock;
 
   30 #define BINOP_KINDS(F) 
   46 #define PREDICATE_KINDS(F) 
   56 #undef PREDICATE_KINDS 
   70    using DataType = std::variant<BinOp, Predicate, CastOp, 
Type*, StructType*>;
 
   72    constexpr T 
const& get() 
const {
 
   73       return std::get<T>(data_);
 
   80    Instruction(
Context& ctx, tir::
Type* resultTy, DataType data)
 
   81          : 
User{ctx, resultTy},
 
   91    virtual bool isTerminator() 
const { 
return false; }
 
   94       assert(!isDestroyed() && 
"Instruction is already destroyed");
 
  101       parent_ = inst->parent_;
 
  103       if(!prev_ && parent_) {
 
  104          parent_->first_ = 
this;
 
  109       assert(!isDestroyed() && 
"Instruction is already destroyed");
 
  116       parent_ = inst->parent_;
 
  118       if(!next_ && parent_) {
 
  119          parent_->last_ = 
this;
 
  123    auto* parent() 
const { 
return parent_; }
 
  130       return BasicBlock::iterator{
 
  131             next_ ? next_ : 
this, 
this->parent_, !next_, 
false};
 
  135       return BasicBlock::iterator{
 
  136             prev_ ? prev_ : 
this, 
this->parent_, 
false, !prev_};
 
  139    auto iter() { 
return BasicBlock::iterator{
this, 
this->parent_, 
false, 
false}; }
 
  146       assert(!isDestroyed() && 
"Instruction is already destroyed");
 
  148          prev_->next_ = next_;
 
  151          next_->prev_ = prev_;
 
  154          if(parent_->first_ == 
this) {
 
  155             parent_->first_ = next_;
 
  157          if(parent_->last_ == 
this) {
 
  158             parent_->last_ = prev_;
 
  162       next_ = prev_ = 
nullptr;
 
  166    void setParent(BasicBlock* parent) { parent_ = parent; }
 
  172    const DataType data_;
 
  187    BranchInst(
Context& ctx, 
Value* cond, BasicBlock* trueBB, BasicBlock* falseBB);
 
  190    static BranchInst* Create(
Context& ctx, 
Value* cond, BasicBlock* trueBB,
 
  191                              BasicBlock* falseBB) {
 
  193             ctx.alloc().allocate_bytes(
sizeof(BranchInst), 
alignof(BranchInst));
 
  194       return new(buf) BranchInst{ctx, cond, trueBB, falseBB};
 
  198    bool isTerminator() 
const override { 
return true; }
 
  199    BasicBlock* getSuccessor(
unsigned idx) 
const;
 
  200    std::ostream& print(std::ostream& os) 
const override;
 
  201    void replaceSuccessor(
unsigned idx, BasicBlock* newBB) {
 
  202       assert(idx < 2 && 
"Index out of bounds");
 
  203       replaceChild(idx+1, newBB);
 
  218             ctx.alloc().allocate_bytes(
sizeof(ReturnInst), 
alignof(ReturnInst));
 
  219       return new(buf) ReturnInst{ctx, ret};
 
  223    bool isReturnVoid() 
const { 
return numChildren() == 0; }
 
  224    bool isTerminator() 
const override { 
return true; }
 
  225    std::ostream& print(std::ostream& os) 
const override;
 
  241       auto buf = ctx.alloc().allocate_bytes(
sizeof(StoreInst), 
alignof(StoreInst));
 
  242       return new(buf) StoreInst{ctx, val, ptr};
 
  246    std::ostream& print(std::ostream& os) 
const override;
 
  260       auto buf = ctx.alloc().allocate_bytes(
sizeof(LoadInst), 
alignof(LoadInst));
 
  261       return new(buf) LoadInst{ctx, type, ptr};
 
  265    std::ostream& print(std::ostream& os) 
const override;
 
  283       auto buf = ctx.alloc().allocate_bytes(
sizeof(CallInst), 
alignof(CallInst));
 
  284       return new(buf) CallInst{ctx, callee, args};
 
  288    std::ostream& print(std::ostream& os) 
const override;
 
  289    bool isTerminator() 
const override;
 
  290    Function* getCallee() 
const;
 
  309             ctx.alloc().allocate_bytes(
sizeof(BinaryInst), 
alignof(BinaryInst));
 
  310       return new(buf) BinaryInst{ctx, binop, lhs, rhs};
 
  314    std::ostream& print(std::ostream& os) 
const override;
 
  315    BinOp binop() 
const { 
return get<BinOp>(); }
 
  328       auto buf = ctx.alloc().allocate_bytes(
sizeof(CmpInst), 
alignof(CmpInst));
 
  329       return new(buf) CmpInst{ctx, pred, lhs, rhs};
 
  333    std::ostream& print(std::ostream& os) 
const override;
 
  334    Predicate predicate() 
const { 
return get<Predicate>(); }
 
  346    static ICastInst* Create(
Context& ctx, CastOp op, 
Value* val, 
Type* destTy) {
 
  347       auto buf = ctx.alloc().allocate_bytes(
sizeof(ICastInst), 
alignof(ICastInst));
 
  348       return new(buf) ICastInst{ctx, op, val, destTy};
 
  352    std::ostream& print(std::ostream& os) 
const override;
 
  353    CastOp castop() 
const { 
return get<CastOp>(); }
 
  369    static AllocaInst* Create(
Context& ctx, 
Type* type) {
 
  371             ctx.alloc().allocate_bytes(
sizeof(AllocaInst), 
alignof(AllocaInst));
 
  372       return new(buf) AllocaInst{ctx, type};
 
  376    std::ostream& print(std::ostream& os) 
const override;
 
  385    GetElementPtrInst(
Context& ctx, 
Value* ptr, StructType* structTy,
 
  389    static GetElementPtrInst* Create(
Context& ctx, 
Value* ptr, StructType* structTy,
 
  391       auto buf = ctx.alloc().allocate_bytes(
sizeof(GetElementPtrInst),
 
  392                                             alignof(GetElementPtrInst));
 
  393       return new(buf) GetElementPtrInst{ctx, ptr, structTy, indices};
 
  397    std::ostream& print(std::ostream& os) 
const override;
 
  399       auto structTy = get<StructType*>();
 
  400       return structTy->getIndexedType(indices);
 
  402    auto getStructType() 
const { 
return get<StructType*>(); }