Joos1W Compiler Framework
All Classes Functions Typedefs Pages
Instructions.cc
1 #include "tir/Instructions.h"
2 
3 #include "tir/BasicBlock.h"
4 #include "tir/Constant.h"
5 #include "tir/TIR.h"
6 
7 namespace tir {
8 
9 static std::ostream& printNameOrConst(std::ostream& os, Value* val) {
10  if(auto* ci = dyn_cast<ConstantInt>(val)) {
11  os << *ci;
12  } else {
13  if(!val->type()->isLabelType()) os << *val->type() << " ";
14  val->printName(os);
15  }
16  return os;
17 }
18 
19 /* ===--------------------------------------------------------------------=== */
20 // BranchInst implementation
21 /* ===--------------------------------------------------------------------=== */
22 
23 BranchInst::BranchInst(Context& ctx, Value* cond, BasicBlock* trueBB,
24  BasicBlock* falseBB)
25  : Instruction{ctx, Type::getVoidTy(ctx)} {
26  addChild(cond);
27  addChild(trueBB);
28  addChild(falseBB);
29  static_assert(sizeof(BranchInst) == sizeof(Instruction));
30 }
31 
32 std::ostream& BranchInst::print(std::ostream& os) const {
33  os << "br ";
34  printNameOrConst(os, getChild(0)) << ", ";
35  printNameOrConst(os, getChild(1)) << ", ";
36  printNameOrConst(os, getChild(2));
37  return os;
38 }
39 
40 BasicBlock* BranchInst::getSuccessor(unsigned idx) const {
41  assert(idx < 2 && "BranchInst::getSuccessor index out of bounds");
42  return cast<BasicBlock>(getChild(idx + 1));
43 }
44 
45 /* ===--------------------------------------------------------------------=== */
46 // ReturnInst implementation
47 /* ===--------------------------------------------------------------------=== */
48 
49 ReturnInst::ReturnInst(Context& ctx, Value* ret)
50  : Instruction{ctx, ret ? ret->type() : Type::getVoidTy(ctx)} {
51  if(ret) addChild(ret);
52  static_assert(sizeof(ReturnInst) == sizeof(Instruction));
53 }
54 
55 std::ostream& ReturnInst::print(std::ostream& os) const {
56  os << "ret";
57  if(numChildren() > 0) {
58  os << " ";
59  printNameOrConst(os, getChild(0));
60  }
61  return os;
62 }
63 
64 /* ===--------------------------------------------------------------------=== */
65 // StoreInst implementation
66 /* ===--------------------------------------------------------------------=== */
67 
68 StoreInst::StoreInst(Context& ctx, Value* val, Value* ptr)
69  : Instruction{ctx, Type::getVoidTy(ctx)} {
70  addChild(val);
71  addChild(ptr);
72  static_assert(sizeof(StoreInst) == sizeof(Instruction));
73 }
74 
75 std::ostream& StoreInst::print(std::ostream& os) const {
76  os << "store ";
77  printNameOrConst(os, getChild(0)) << ", ";
78  printNameOrConst(os, getChild(1));
79  return os;
80 }
81 
82 /* ===--------------------------------------------------------------------=== */
83 // LoadInst implementation
84 /* ===--------------------------------------------------------------------=== */
85 
86 LoadInst::LoadInst(Context& ctx, Type* type, Value* ptr) : Instruction{ctx, type} {
87  addChild(ptr);
88  static_assert(sizeof(LoadInst) == sizeof(Instruction));
89 }
90 
91 std::ostream& LoadInst::print(std::ostream& os) const {
92  printName(os) << " = ";
93  os << "load " << *type() << ", ";
94  printNameOrConst(os, getChild(0));
95  return os;
96 }
97 
98 /* ===--------------------------------------------------------------------=== */
99 // CallInst implementation
100 /* ===--------------------------------------------------------------------=== */
101 
102 CallInst::CallInst(Context& ctx, Value* callee, utils::range_ref<Value*> args)
103  : Instruction{ctx, cast<FunctionType>(callee->type())->getReturnType()} {
104  addChild(callee);
105  args.for_each([this](Value* arg) { addChild(arg); });
106  static_assert(sizeof(CallInst) == sizeof(Instruction));
107 }
108 
109 std::ostream& CallInst::print(std::ostream& os) const {
110  if(!type()->isVoidType()) printName(os) << " = ";
111  os << "call " << getChild(0)->name() << "(";
112  for(unsigned i = 1; i < numChildren(); ++i) {
113  printNameOrConst(os, getChild(i));
114  if(i != numChildren() - 1) os << ", ";
115  }
116  os << ")";
117  if(isTerminator()) os << " noreturn";
118  return os;
119 }
120 
121 Function* CallInst::getCallee() const { return cast<Function>(getChild(0)); }
122 
123 bool CallInst::isTerminator() const { return getCallee()->isNoReturn(); }
124 
125 /* ===--------------------------------------------------------------------=== */
126 // BinaryInst implementation
127 /* ===--------------------------------------------------------------------=== */
128 
129 BinaryInst::BinaryInst(Context& ctx, BinOp binop, Value* lhs, Value* rhs)
130  : Instruction{ctx, lhs->type(), binop} {
131  addChild(lhs);
132  addChild(rhs);
133  static_assert(sizeof(BinaryInst) == sizeof(Instruction));
134 }
135 
136 std::ostream& BinaryInst::print(std::ostream& os) const {
137  printName(os) << " = ";
138  const char* name = BinOp_to_string(binop(), "unknown");
139  // Print name lower case
140  for(unsigned i = 0; name[i] != '\0'; ++i)
141  os << static_cast<char>(tolower(name[i]));
142  // Print operands
143  os << " " << *type() << ", ";
144  printNameOrConst(os, getChild(0)) << ", ";
145  printNameOrConst(os, getChild(1));
146  return os;
147 }
148 
149 /* ===--------------------------------------------------------------------=== */
150 // CmpInst implementation
151 /* ===--------------------------------------------------------------------=== */
152 
153 CmpInst::CmpInst(Context& ctx, Predicate pred, Value* lhs, Value* rhs)
154  : Instruction{ctx, Type::getInt1Ty(ctx), pred} {
155  addChild(lhs);
156  addChild(rhs);
157  static_assert(sizeof(CmpInst) == sizeof(Instruction));
158 }
159 
160 std::ostream& CmpInst::print(std::ostream& os) const {
161  printName(os) << " = cmp ";
162  auto pred = get<Predicate>();
163  const char* name = Predicate_to_string(pred, "unknown");
164  // Print name lower case
165  for(unsigned i = 0; name[i] != '\0'; ++i)
166  os << static_cast<char>(tolower(name[i]));
167  // Print operands
168  os << " " << *type() << " ";
169  printNameOrConst(os, getChild(0)) << ", ";
170  printNameOrConst(os, getChild(1));
171  return os;
172 }
173 
174 /* ===--------------------------------------------------------------------=== */
175 // AllocaInst implementation
176 /* ===--------------------------------------------------------------------=== */
177 
178 AllocaInst::AllocaInst(Context& ctx, Type* type)
179  : Instruction{ctx, Type::getPointerTy(ctx), type} {
180  static_assert(sizeof(AllocaInst) == sizeof(Instruction));
181 }
182 
183 std::ostream& AllocaInst::print(std::ostream& os) const {
184  auto allocType_ = get<Type*>();
185  return printName(os) << " = "
186  << "alloca " << *allocType_;
187 }
188 
189 /* ===--------------------------------------------------------------------=== */
190 // ICastInst implementation
191 /* ===--------------------------------------------------------------------=== */
192 
193 ICastInst::ICastInst(Context& ctx, CastOp op, Value* val, Type* destTy)
194  : Instruction{ctx, destTy, op} {
195  addChild(val);
196  static_assert(sizeof(ICastInst) == sizeof(Instruction));
197 }
198 
199 std::ostream& ICastInst::print(std::ostream& os) const {
200  printName(os) << " = ";
201  os << "icast ";
202  const char* name = CastOp_to_string(castop(), "unknown");
203  // Print name lower case
204  for(unsigned i = 0; name[i] != '\0'; ++i)
205  os << static_cast<char>(tolower(name[i]));
206  os << " ";
207  printNameOrConst(os, getChild(0)) << " to " << *type() << "";
208  return os;
209 }
210 
211 /* ===--------------------------------------------------------------------=== */
212 // GetElementPtrInst implementation
213 /* ===--------------------------------------------------------------------=== */
214 
215 GetElementPtrInst::GetElementPtrInst(Context& ctx, Value* ptr,
216  StructType* structTy,
217  utils::range_ref<Value*> indices)
218  : Instruction{ctx, Type::getPointerTy(ctx), structTy} {
219  addChild(ptr);
220  indices.for_each([this](auto* idx) { addChild(idx); });
221  static_assert(sizeof(GetElementPtrInst) == sizeof(Instruction));
222 }
223 
224 std::ostream& GetElementPtrInst::print(std::ostream& os) const {
225  printName(os) << " = ";
226  os << "getelementptr " << *getStructType() << ", ";
227  printNameOrConst(os, getChild(0));
228  for(unsigned i = 1; i < numChildren(); ++i) {
229  os << ", ";
230  printNameOrConst(os, getChild(i));
231  }
232  return os;
233 }
234 
235 } // namespace tir