made the cast float->bool throw an error
[ozulis.git] / src / ast / llvm-generator-visitor.cc
blob25074d413452b8951990c20cd39d9c88e06bf4f7
1 #include <iomanip>
3 #include <core/assert.hh>
5 #include "llvm-generator-visitor.hh"
7 namespace ast
9 LLVMGeneratorVisitor::LLVMGeneratorVisitor(std::ostream & out)
10 : super_t(),
11 castTable_(),
12 out_(out)
14 assert_msg(out.good(), "The output for llvm assembly is not valid.");
16 //out_.setf(std::ios::hex, std::ios::basefield);
17 //out_.setf(std::ios::showbase);
20 #define ADD_CAST_TABLE_ENTRY(Type1, Type2) \
21 do { \
22 castTableKey_t key = std::make_pair(Type1##Type::nodeTypeId(), \
23 Type2##Type::nodeTypeId()); \
24 assert_msg(!castTable_.count(key), \
25 "the same key has been insterted two times"); \
26 castTable_[key] = &LLVMGeneratorVisitor::cast##Type1##To##Type2; \
27 } while (0)
29 ADD_CAST_TABLE_ENTRY(Bool, Bool);
30 ADD_CAST_TABLE_ENTRY(Bool, Integer);
31 ADD_CAST_TABLE_ENTRY(Bool, Float);
32 ADD_CAST_TABLE_ENTRY(Bool, Double);
33 ADD_CAST_TABLE_ENTRY(Integer, Bool);
34 ADD_CAST_TABLE_ENTRY(Integer, Integer);
35 ADD_CAST_TABLE_ENTRY(Integer, Float);
36 ADD_CAST_TABLE_ENTRY(Integer, Double);
37 ADD_CAST_TABLE_ENTRY(Float, Double);
38 ADD_CAST_TABLE_ENTRY(Float, Bool);
39 ADD_CAST_TABLE_ENTRY(Double, Bool);
42 LLVMGeneratorVisitor::~LLVMGeneratorVisitor()
46 void
47 LLVMGeneratorVisitor::visit(const Function & node)
49 out_ << "define void @" << node.name << "() {" << std::endl;
50 super_t::visit(node);
51 out_ << " ret void" << std::endl
52 << "}" << std::endl;
55 void
56 LLVMGeneratorVisitor::visit(const VarDecl & node)
58 assert(node.type);
60 out_ << " %" << node.name << " = alloca ";
61 node.type->accept(*this);
62 out_ << std::endl;
65 void
66 LLVMGeneratorVisitor::visit(const LoadVar & node)
68 assert(node.type);
70 out_ << " %" << node.to << " = load ";
71 node.type->accept(*this);
72 out_ << " * %" << node.name << std::endl;
75 void
76 LLVMGeneratorVisitor::visit(const StoreVar & node)
78 assert(node.value);
79 assert(node.value->type);
81 out_ << " store ";
82 node.value->type->accept(*this);
83 node.value->accept(*this);
84 out_ << ", ";
85 node.value->type->accept(*this);
86 out_ << " * %" << node.name << std::endl;
89 void
90 LLVMGeneratorVisitor::visit(const AssignExp & node)
92 out_ << " %" << node.dest->name << " = ";
93 node.value->accept(*this);
94 out_ << std::endl;
97 #define GEN_BINARY_EXP_EXT(Name, Type, Instr) \
98 void \
99 LLVMGeneratorVisitor::Name(const Type & node) \
101 out_ << Instr" "; \
102 node.type->accept(*this); \
103 node.left->accept(*this); \
104 out_ << ", "; \
105 node.right->accept(*this); \
108 #define GEN_BINARY_EXP(Type, Instr) GEN_BINARY_EXP_EXT(visit, Type, Instr)
110 GEN_BINARY_EXP(AddExp, "add")
111 GEN_BINARY_EXP(SubExp, "sub")
112 GEN_BINARY_EXP(MulExp, "mul")
113 GEN_BINARY_EXP_EXT(visitUDivExp, DivExp, "udiv")
114 GEN_BINARY_EXP_EXT(visitSDivExp, DivExp, "sdiv")
115 GEN_BINARY_EXP_EXT(visitFDivExp, DivExp, "fdiv")
116 GEN_BINARY_EXP_EXT(visitUModExp, ModExp, "urem")
117 GEN_BINARY_EXP_EXT(visitSModExp, ModExp, "srem")
118 GEN_BINARY_EXP_EXT(visitFModExp, ModExp, "frem")
120 GEN_BINARY_EXP(AndExp, "and")
121 GEN_BINARY_EXP(OrExp, "or")
122 GEN_BINARY_EXP(XorExp, "xor")
124 GEN_BINARY_EXP(ShlExp, "shl")
125 GEN_BINARY_EXP(AShrExp, "ashr")
126 GEN_BINARY_EXP(LShrExp, "lshr")
128 /// @todo check this is correct.
129 #define GEN_CMP_EXP(Type, Instr) \
130 void \
131 LLVMGeneratorVisitor::visit(const Type & node) \
133 if (node.type->nodeType == FloatType::nodeTypeId() || \
134 node.type->nodeType == DoubleType::nodeTypeId()) \
135 out_ << "fcmp o"; \
136 else \
138 out_ << "icmp "; \
139 if (node.nodeType == LtExp::nodeTypeId() || \
140 node.nodeType == LtEqExp::nodeTypeId() || \
141 node.nodeType == GtExp::nodeTypeId() || \
142 node.nodeType == GtEqExp::nodeTypeId()) \
144 if (node.type->nodeType == IntegerType::nodeTypeId()) \
146 IntegerType * itype = reinterpret_cast<IntegerType *>(node.type); \
147 out_ << (itype->isSigned ? "s" : "u"); \
149 else if (node.type->nodeType == BoolType::nodeTypeId()) \
150 out_ << "u"; \
153 out_ << Instr" "; \
154 node.type->accept(*this); \
155 node.left->accept(*this); \
156 out_ << ", "; \
157 node.right->accept(*this); \
160 GEN_CMP_EXP(EqExp, "eq")
161 GEN_CMP_EXP(NeqExp, "ne")
162 GEN_CMP_EXP(LtExp, "lt")
163 GEN_CMP_EXP(LtEqExp, "le")
164 GEN_CMP_EXP(GtExp, "gt")
165 GEN_CMP_EXP(GtEqExp, "ge")
167 #define GEN_BINARY_BOOL_EXP(Type, Op) \
168 void \
169 LLVMGeneratorVisitor::visit(const Type & node) \
171 out_ << Op " i1 "; \
172 node.left->accept(*this); \
173 out_ << ", "; \
174 node.right->accept(*this); \
177 GEN_BINARY_BOOL_EXP(AndAndExp, "and ")
178 GEN_BINARY_BOOL_EXP(OrOrExp, "or ")
180 #define GEN_DIV_MOD_EXP(Name) \
181 void \
182 LLVMGeneratorVisitor::visit(const Name##Exp & node) \
184 if (node.type->nodeType == BoolType::nodeTypeId()) \
185 visitU##Name##Exp(node); \
186 else if (node.type->nodeType == FloatType::nodeTypeId() || \
187 node.type->nodeType == DoubleType::nodeTypeId()) \
188 visitF##Name##Exp(node); \
189 else if (node.type->nodeType == IntegerType::nodeTypeId()) \
191 IntegerType * type = reinterpret_cast<IntegerType *>(node.type); \
192 type->isSigned ? visitS##Name##Exp(node) : visitU##Name##Exp(node); \
194 else \
195 assert(false); \
198 GEN_DIV_MOD_EXP(Div)
199 GEN_DIV_MOD_EXP(Mod)
201 // void
202 // LLVMGeneratorVisitor::visit(const EqExp & node)
203 // {
205 // }
207 void
208 LLVMGeneratorVisitor::visit(const IdExp & node)
210 out_ << "%" << node.name;
213 void
214 LLVMGeneratorVisitor::visit(const TmpResultExp & node)
216 out_ << "%" << node.name;
219 void
220 LLVMGeneratorVisitor::visit(const NumberExp & node)
222 if (node.type->nodeType == FloatType::nodeTypeId())
223 /// @todo find the right way to print floating point numbers
224 out_ << std::setprecision(1000) << (float)node.number;
225 else
226 out_ << std::setprecision(1000) << node.number;
229 void
230 LLVMGeneratorVisitor::visit(const Label & node)
232 out_ << " br label %" << node.name << " ; dummy branch to start a block" << std::endl
233 << node.name << ":" << std::endl;
236 void
237 LLVMGeneratorVisitor::visit(const Goto & node)
239 out_ << " br label %" << node.label << std::endl;
242 void
243 LLVMGeneratorVisitor::visit(const If & node)
245 assert(node.ifTrue->nodeType == Label::nodeTypeId());
246 assert(node.ifFalse->nodeType == Label::nodeTypeId());
248 Label * trueLabel = reinterpret_cast<Label *>(node.ifTrue);
249 Label * falseLabel = reinterpret_cast<Label *>(node.ifFalse);
251 out_ << " br i1 ";
252 node.cond->accept(*this);
253 out_ << ", label %" << trueLabel->name << ", label %"
254 << falseLabel->name << std::endl;
257 void
258 LLVMGeneratorVisitor::visit(const Type & /*node*/)
260 //assert_msg(false, "we should never reach this code");
263 void
264 LLVMGeneratorVisitor::visit(const NumberType & /*node*/)
266 assert_msg(false, "we should never reach this code");
269 void
270 LLVMGeneratorVisitor::visit(const BoolType & /*node*/)
272 out_ << " i1 ";
275 void
276 LLVMGeneratorVisitor::visit(const IntegerType & node)
278 out_ << " i" << node.size << " ";
281 void
282 LLVMGeneratorVisitor::visit(const FloatType & /*node*/)
284 out_ << " float ";
287 void
288 LLVMGeneratorVisitor::visit(const DoubleType & /*node*/)
290 out_ << " double ";
293 void
294 LLVMGeneratorVisitor::visit(const CastExp & node)
296 Type * from = node.exp->type;
297 Type * to = node.type;
299 assert(from);
300 assert(to);
301 castTableKey_t key = std::make_pair(from->nodeType, to->nodeType);
302 assert(castTable_.count(key) > 0);
303 (this->*castTable_[key])(node);
306 void
307 LLVMGeneratorVisitor::castBoolToBool(const CastExp & node)
309 out_ << "add i1 0, ";
310 node.exp->accept(*this);
311 return;
314 #define SIMPLE_NUMBER_CAST(Type1, Type2, CastInstr, DestType) \
315 void \
316 LLVMGeneratorVisitor::cast##Type1##To##Type2(const CastExp & node) \
318 out_ << CastInstr; \
319 node.exp->accept(*this); \
320 out_ << DestType; \
321 return; \
324 SIMPLE_NUMBER_CAST(Bool, Float, "uitofp i1 ", " to float")
325 SIMPLE_NUMBER_CAST(Bool, Double, "uitofp i1 ", " to double")
326 SIMPLE_NUMBER_CAST(Float, Double, "fpext float ", " to double")
328 void
329 LLVMGeneratorVisitor::castBoolToInteger(const CastExp & node)
331 IntegerType * to = reinterpret_cast<IntegerType *>(node.type);
333 if (to->size == 1)
335 out_ << "add i1 0, ";
336 node.exp->accept(*this);
338 else
340 out_ << "zext i1 ";
341 node.exp->accept(*this);
342 out_ << " to ";
343 to->accept(*this);
347 void
348 LLVMGeneratorVisitor::castIntegerToInteger(const CastExp & node)
350 IntegerType * from = reinterpret_cast<IntegerType *>(node.exp->type);
351 IntegerType * to = reinterpret_cast<IntegerType *>(node.type);
353 if (from->size == to->size)
355 out_ << "add i" << to->size << " 0, ";
356 node.exp->accept(*this);
357 return;
360 if (from->size > to->size)
361 out_ << "trunc";
362 else if (from->isSigned)
363 out_ << "sext";
364 else
365 out_ << "zext";
366 out_ << " i" << from->size << " ";
367 node.exp->accept(*this);
368 out_ << " to i" << to->size;
371 #define INTEGER_TO_FLOAT(Float, Str) \
372 void \
373 LLVMGeneratorVisitor::castIntegerTo##Float(const CastExp & node) \
375 IntegerType * from = \
376 reinterpret_cast<IntegerType *>(node.exp->type); \
378 out_ << (from->isSigned ? "sitofp " : "uitofp "); \
379 from->accept(*this); \
380 node.exp->accept(*this); \
381 out_ << " to " Str; \
384 INTEGER_TO_FLOAT(Float, "float")
385 INTEGER_TO_FLOAT(Double, "double")
387 void
388 LLVMGeneratorVisitor::castIntegerToBool(const ast::CastExp & node)
390 out_ << "icmp ne ";
391 node.exp->type->accept(*this);
392 out_ << "0, ";
393 node.exp->accept(*this);
396 #define FLOAT_TO_BOOL(Type, Str) \
397 void \
398 LLVMGeneratorVisitor::cast##Type##ToBool(const ast::CastExp & node) \
400 /** @todo throw a warning */ \
401 assert_msg(false, "casting float to bool is a non sense."); \
404 FLOAT_TO_BOOL(Float, "float")
405 FLOAT_TO_BOOL(Double, "double")