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*>(); }