Joos1W Compiler Framework
All Classes Functions Typedefs Pages
IRBuilder.h
1 #pragma once
2 
3 #include "tir/BasicBlock.h"
4 #include "tir/Constant.h"
5 #include "tir/Context.h"
6 #include "tir/Instructions.h"
7 
8 namespace tir {
9 
10 class IRBuilder {
11 public:
12  IRBuilder(Context& ctx) : ctx_{ctx}, insertPoint_{} {}
13 
14  /**
15  * @brief Set the insertion point to the given basic block. This will insert
16  * new instructions after the given instruction iterator.
17  *
18  * @param it The iterator to set the insertion point to
19  */
20  void setInsertPoint(BasicBlock::iterator it) { insertPoint_ = it; }
21 
22  /**
23  * @brief Set the insertion point to the given instruction. This will insert
24  * new instructions after the given instruction.
25  *
26  * @param instr The instruction to set the insertion point to
27  */
28  void setInsertPoint(Instruction* instr) { setInsertPoint(instr->iter()); }
29 
30  /**
31  * @brief Set the insertion point to the beginning of the given basic block.
32  *
33  * @param bb The basic block to set the insertion point to
34  */
35  void setInsertPoint(BasicBlock* bb) {
36  insertPoint_ = bb->begin();
37  }
38 
39  BasicBlock* currentBlock() {
40  return insertPoint_.getBB();
41  }
42 
43 public:
44  /**
45  * @brief Create a new basic block within the given function. This does
46  * not change the insertion point, unlike the other create functions.
47  *
48  * @param parent The parent function of the basic block
49  * @return BasicBlock* The new (empty) basic block
50  */
51  BasicBlock* createBasicBlock(Function* parent) {
52  return BasicBlock::Create(ctx_, parent);
53  }
54 
55  /**
56  * @brief Create a binary instruction with the given operation and
57  * left-hand and right-hand operands (as values).
58  *
59  * @param op The binary operation to perform
60  * @param lhs The LHS value
61  * @param rhs The RHS value
62  * @return BinaryInst* A pointer to the instruction
63  */
65  return insert(BinaryInst::Create(ctx_, op, lhs, rhs));
66  }
67 
68  /**
69  * @brief Create a call instruction with the given callee and arguments.
70  *
71  * @param callee The function to call
72  * @param args The arguments to pass to the function
73  * @return CallInst* A pointer to the instruction
74  */
75  Instruction* createCallInstr(Value* callee, utils::range_ref<Value*> args) {
76  return insert(CallInst::Create(ctx_, callee, args));
77  }
78 
79  /**
80  * @brief Create a load instruction with the given type and pointer.
81  * The type is the type of the value to load and will dictate the size of
82  * the load operation. The ptr is the pointer to load from.
83  *
84  * @param type The type of the value to load
85  * @param ptr The pointer to load from
86  * @return LoadInst* A pointer to the instruction
87  */
89  return insert(LoadInst::Create(ctx_, type, ptr));
90  }
91 
92  /**
93  * @brief Create a store instruction with the given value and pointer.
94  * The value is the value to store and the ptr is the pointer to store to.
95  *
96  * @param val The value to store
97  * @param ptr The pointer to store to
98  * @return StoreInst* A pointer to the instruction
99  */
101  return insert(StoreInst::Create(ctx_, val, ptr));
102  }
103 
104  /**
105  * @brief Create a return instruction with the given value.
106  *
107  * @param val The value to return
108  * @return ReturnInst* A pointer to the instruction
109  */
111  return insert(ReturnInst::Create(ctx_, val));
112  }
113 
114  /**
115  * @brief Create a return instruction with no value (void).
116  *
117  * @return ReturnInst* A pointer to the instruction
118  */
120  return insert(ReturnInst::Create(ctx_, nullptr));
121  }
122 
123  /**
124  * @brief Creates an unconditional branch instruction to the given target
125  * basic block.
126  *
127  * @param target The target basic block
128  * @return BranchInst* A pointer to the instruction
129  */
130  Instruction* createBranchInstr(BasicBlock* target) {
131  return createBranchInstr(Constant::CreateBool(ctx_, true), target, target);
132  }
133 
134  /**
135  * @brief Create a conditional branch instruction with the given condition
136  * and true and false target basic blocks.
137  *
138  * @param cond The condition to branch on
139  * @param true_target The target basic block if the condition is true
140  * @param false_target The target basic block if the condition is false
141  * @return BranchInst* A pointer to the instruction
142  */
143  Instruction* createBranchInstr(Value* cond, BasicBlock* true_target,
144  BasicBlock* false_target) {
145  return insert(BranchInst::Create(ctx_, cond, true_target, false_target));
146  }
147 
148  /**
149  * @brief Create a comparison instruction with the given predicate and
150  * left-hand and right-hand operands.
151  *
152  * @param pred The comparison predicate
153  * @param lhs The LHS value
154  * @param rhs The RHS value
155  * @return CmpInst* A pointer to the instruction
156  */
157  Instruction* createCmpInstr(CmpInst::Predicate pred, Value* lhs, Value* rhs) {
158  return insert(CmpInst::Create(ctx_, pred, lhs, rhs));
159  }
160 
161  /**
162  * @brief Create the generic trunc/zext/sext instruction with the given
163  * operation, value, and destination type.
164  *
165  * @param op The cast operation to perform
166  * @param val The value to cast
167  * @param destTy The destination type
168  * @return Instruction* The created instruction
169  */
170  Instruction* createICastInstr(ICastInst::CastOp op, Value* val, Type* destTy) {
171  return insert(ICastInst::Create(ctx_, op, val, destTy));
172  }
173 
174  Instruction* createGEPInstr(Value* ptr, StructType* t, utils::range_ref<Value*> indices) {
175  return insert(GetElementPtrInst::Create(ctx_, ptr, t, indices));
176  }
177 
178 private:
179  Instruction* insert(Instruction* instr) {
180  assert(insertPoint_.getBB() && "No insertion point set");
181  if(insertPoint_.isAfterLast()) {
182  insertPoint_.getBB()->appendAfterEnd(instr);
183  } else if(insertPoint_.isBeforeFirst()) {
184  insertPoint_.getBB()->insertBeforeBegin(instr);
185  } else {
186  instr->insertAfter(*insertPoint_);
187  }
188  insertPoint_ = instr->iter();
189  return instr;
190  }
191 
192 private:
193  tir::Context& ctx_;
194  BasicBlock::iterator insertPoint_;
195 };
196 
197 } // namespace tir