The compiler is now a Singleton
[ozulis.git] / src / ast / llvm-asm-generator-visitor.cc
blob06439783307400e1a8bff71ab1e214c6a1f0f3e7
1 #include <iomanip>
2 #include <boost/foreach.hpp>
4 #include <core/assert.hh>
5 #include <ast/cast-tables.hh>
7 #include "llvm-asm-generator-visitor.hh"
9 namespace ast
11 LLVMAsmGeneratorVisitor::LLVMAsmGeneratorVisitor(std::ostream & out)
12 : super_t(),
13 castTable_(),
14 out_(out)
16 assert_msg(out.good(), "The output for llvm assembly is not valid.");
17 out_ << std::setprecision(1000);
19 #define ADD_CAST_TABLE_ENTRY(Type1, Type2) \
20 do { \
21 castTableKey_t key = std::make_pair(Type1##Type::nodeTypeId(), \
22 Type2##Type::nodeTypeId()); \
23 assert_msg(!castTable_.count(key), \
24 "the same key has been insterted two times"); \
25 castTable_[key] = &LLVMAsmGeneratorVisitor::cast##Type1##To##Type2; \
26 } while (0)
28 ADD_CAST_TABLE_ENTRY(Bool, Bool);
29 ADD_CAST_TABLE_ENTRY(Bool, Integer);
30 ADD_CAST_TABLE_ENTRY(Bool, Float);
31 ADD_CAST_TABLE_ENTRY(Bool, Double);
32 ADD_CAST_TABLE_ENTRY(Integer, Bool);
33 ADD_CAST_TABLE_ENTRY(Integer, Integer);
34 ADD_CAST_TABLE_ENTRY(Integer, Float);
35 ADD_CAST_TABLE_ENTRY(Integer, Double);
36 ADD_CAST_TABLE_ENTRY(Float, Double);
37 ADD_CAST_TABLE_ENTRY(Float, Bool);
38 ADD_CAST_TABLE_ENTRY(Double, Bool);
40 ADD_CAST_TABLE_ENTRY(Integer, Pointer);
41 ADD_CAST_TABLE_ENTRY(Pointer, Integer);
44 LLVMAsmGeneratorVisitor::~LLVMAsmGeneratorVisitor()
48 void
49 LLVMAsmGeneratorVisitor::writeFunctionHeader(const FunctionDecl & node)
51 node.returnType->accept(*this);
52 out_ << " @" << node.name << "(";
54 for (std::vector<VarDecl *>::iterator it = node.args->begin();
55 it != node.args->end(); it++)
57 if (it != node.args->begin())
58 out_ << ", ";
59 (*it)->type->accept(*this);
60 out_ << " %$" << (*it)->name;
63 out_ << ")" << std::endl;
66 void
67 LLVMAsmGeneratorVisitor::visit(const FunctionDecl & node)
69 out_ << "declare ";
70 writeFunctionHeader(node);
73 void
74 LLVMAsmGeneratorVisitor::visit(const Function & node)
76 out_ << "define ";
77 writeFunctionHeader(node);
78 out_ << "{" << std::endl;
80 BOOST_FOREACH (VarDecl * var, *node.args)
81 var->accept(*this);
83 StoreVar sv;
84 IdExp id;
85 Symbol symbol;
86 MemoryAddress addr;
88 sv.value = &id;
89 id.symbol = &symbol;
90 BOOST_FOREACH (VarDecl * var, *node.args)
92 sv.name = var->name;
93 id.type = var->type;
94 symbol.name = "$" + var->name;
95 symbol.type = var->type;
96 symbol.address = &addr;
97 sv.accept(*this);
100 node.block->accept(*this);
101 out_ << "}" << std::endl;
104 void
105 LLVMAsmGeneratorVisitor::visit(const VarDecl & node)
107 assert(node.type);
109 out_ << " %" << node.name << " = alloca ";
110 node.type->accept(*this);
111 out_ << std::endl;
114 void
115 LLVMAsmGeneratorVisitor::visit(const LoadVar & node)
117 assert(node.from->type);
119 out_ << " %" << node.to << " = load ";
120 node.from->type->accept(*this);
121 out_ << " ";
122 node.from->accept(*this);
123 out_ << std::endl;
126 void
127 LLVMAsmGeneratorVisitor::visit(const StoreVar & node)
129 assert(node.value);
130 assert(node.value->type);
132 out_ << " store ";
133 node.value->type->accept(*this);
134 node.value->accept(*this);
135 out_ << ", ";
136 node.value->type->accept(*this);
137 out_ << "* %" << node.name << std::endl;
140 void
141 LLVMAsmGeneratorVisitor::visit(const AssignExp & node)
143 out_ << " %" << node.dest->name << " = ";
144 if (node.value->nodeType == NumberExp::nodeTypeId() ||
145 node.value->nodeType == IdExp::nodeTypeId())
147 out_ << "add ";
148 node.value->type->accept(*this);
149 out_ << " 0, ";
150 node.value->accept(*this);
152 else
153 node.value->accept(*this);
154 out_ << std::endl;
157 #define GEN_BINARY_EXP_EXT(Name, Type, Instr) \
158 void \
159 LLVMAsmGeneratorVisitor::Name(const Type & node) \
161 out_ << Instr" "; \
162 unreferencedType(node.type)->accept(*this); \
163 node.left->accept(*this); \
164 out_ << ", "; \
165 node.right->accept(*this); \
168 #define GEN_BINARY_EXP(Type, Instr) GEN_BINARY_EXP_EXT(visit, Type, Instr)
170 GEN_BINARY_EXP(AddExp, "add")
171 GEN_BINARY_EXP(SubExp, "sub")
172 GEN_BINARY_EXP(MulExp, "mul")
173 GEN_BINARY_EXP_EXT(visitUDivExp, DivExp, "udiv")
174 GEN_BINARY_EXP_EXT(visitSDivExp, DivExp, "sdiv")
175 GEN_BINARY_EXP_EXT(visitFDivExp, DivExp, "fdiv")
176 GEN_BINARY_EXP_EXT(visitUModExp, ModExp, "urem")
177 GEN_BINARY_EXP_EXT(visitSModExp, ModExp, "srem")
178 GEN_BINARY_EXP_EXT(visitFModExp, ModExp, "frem")
180 GEN_BINARY_EXP(AndExp, "and")
181 GEN_BINARY_EXP(OrExp, "or")
182 GEN_BINARY_EXP(XorExp, "xor")
184 GEN_BINARY_EXP(ShlExp, "shl")
185 GEN_BINARY_EXP(AShrExp, "ashr")
186 GEN_BINARY_EXP(LShrExp, "lshr")
188 /// @todo check this is correct.
189 #define GEN_CMP_EXP(Type_, Instr) \
190 void \
191 LLVMAsmGeneratorVisitor::visit(const Type_ & node) \
193 Type * type = unreferencedType(node.left->type); \
195 if (type->nodeType == FloatType::nodeTypeId() || \
196 type->nodeType == DoubleType::nodeTypeId()) \
197 out_ << "fcmp o"; \
198 else \
200 out_ << "icmp "; \
201 if (node.nodeType == LtExp::nodeTypeId() || \
202 node.nodeType == LtEqExp::nodeTypeId() || \
203 node.nodeType == GtExp::nodeTypeId() || \
204 node.nodeType == GtEqExp::nodeTypeId()) \
206 if (type->nodeType == IntegerType::nodeTypeId()) \
208 IntegerType * itype = reinterpret_cast<IntegerType *>(type); \
209 out_ << (itype->isSigned ? "s" : "u"); \
211 else if (type->nodeType == BoolType::nodeTypeId()) \
212 out_ << "u"; \
215 out_ << Instr" "; \
216 type->accept(*this); \
217 node.left->accept(*this); \
218 out_ << ", "; \
219 node.right->accept(*this); \
222 GEN_CMP_EXP(EqExp, "eq")
223 GEN_CMP_EXP(NeqExp, "ne")
224 GEN_CMP_EXP(LtExp, "lt")
225 GEN_CMP_EXP(LtEqExp, "le")
226 GEN_CMP_EXP(GtExp, "gt")
227 GEN_CMP_EXP(GtEqExp, "ge")
229 #define GEN_BINARY_BOOL_EXP(Type, Op) \
230 void \
231 LLVMAsmGeneratorVisitor::visit(const Type & node) \
233 out_ << Op " i1 "; \
234 node.left->accept(*this); \
235 out_ << ", "; \
236 node.right->accept(*this); \
239 GEN_BINARY_BOOL_EXP(AndAndExp, "and ")
240 GEN_BINARY_BOOL_EXP(OrOrExp, "or ")
242 #define GEN_DIV_MOD_EXP(Name) \
243 void \
244 LLVMAsmGeneratorVisitor::visit(const Name##Exp & node) \
246 if (node.type->nodeType == BoolType::nodeTypeId()) \
247 visitU##Name##Exp(node); \
248 else if (node.type->nodeType == FloatType::nodeTypeId() || \
249 node.type->nodeType == DoubleType::nodeTypeId()) \
250 visitF##Name##Exp(node); \
251 else if (node.type->nodeType == IntegerType::nodeTypeId()) \
253 IntegerType * type = reinterpret_cast<IntegerType *>(node.type); \
254 type->isSigned ? visitS##Name##Exp(node) : visitU##Name##Exp(node); \
256 else \
257 assert(false); \
260 GEN_DIV_MOD_EXP(Div)
261 GEN_DIV_MOD_EXP(Mod)
264 void
265 LLVMAsmGeneratorVisitor::visit(const NegExp & node)
267 out_ << "sub ";
268 node.type->accept(*this);
269 if (AST_IS_FLOATING_POINT_TYPE(node.type))
270 out_ << " 0.0, ";
271 else
272 out_ << " 0, ";
273 node.exp->accept(*this);
276 void
277 LLVMAsmGeneratorVisitor::visit(const BangExp & node)
279 out_ << "xor i1 1, ";
280 node.exp->accept(*this);
283 void
284 LLVMAsmGeneratorVisitor::visit(const NotExp & node)
286 out_ << "xor ";
287 node.type->accept(*this);
288 out_ << " -1, ";
289 node.exp->accept(*this);
292 void
293 LLVMAsmGeneratorVisitor::visit(const Exp & /* node */)
295 assert_msg(false, "unimplemented method");
298 void
299 LLVMAsmGeneratorVisitor::visit(const VoidExp & /* node */)
303 void
304 LLVMAsmGeneratorVisitor::visit(const IdExp & node)
306 out_ << "%" << node.symbol->name;
309 void
310 LLVMAsmGeneratorVisitor::visit(const CallExp & node)
312 out_ << " call ";
313 node.type->accept(*this);
314 out_ << " @" << node.id << "(";
316 for (CallExp::args_t::iterator it = node.args->begin();
317 it != node.args->end(); it++)
319 if (it != node.args->begin())
320 out_ << ", ";
321 unreferencedType((*it)->type)->accept(*this);
322 (*it)->accept(*this);
325 out_ << ")";
326 if (node.type->nodeType == VoidType::nodeTypeId())
327 out_ << std::endl;
330 void
331 LLVMAsmGeneratorVisitor::visit(const NumberExp & node)
333 if (node.type->nodeType == FloatType::nodeTypeId())
334 /// @todo find the right way to print floating point numbers
335 out_ << std::setprecision(1000) << (float)node.number;
336 else
337 out_ << std::setprecision(1000) << node.number;
340 void
341 LLVMAsmGeneratorVisitor::visit(const Label & node)
343 out_ << " br label %" << node.name << " ; dummy branch to start a block" << std::endl
344 << node.name << ":" << std::endl;
347 void
348 LLVMAsmGeneratorVisitor::visit(const Goto & node)
350 out_ << " br label %" << node.label << std::endl;
353 void
354 LLVMAsmGeneratorVisitor::visit(const Return & node)
356 assert(node.exp);
358 out_ << " ret ";
359 node.exp->type->accept(*this);
360 node.exp->accept(*this);
361 out_ << std::endl;
364 #if 0
365 #define VISIT_COND_BRANCH(Type) \
366 void \
367 LLVMAsmGeneratorVisitor::visit(const Type & node) \
369 visit((ConditionalBranch)node); \
372 VISIT_COND_BRANCH(If)
373 VISIT_COND_BRANCH(While)
374 VISIT_COND_BRANCH(DoWhile)
375 #endif
377 void
378 LLVMAsmGeneratorVisitor::visit(const ConditionalBranch & node)
380 out_ << " br i1 ";
381 node.cond->accept(*this);
382 out_ << ", label %" << node.trueLabel->name << ", label %"
383 << node.falseLabel->name << std::endl;
386 void
387 LLVMAsmGeneratorVisitor::visit(const Type & /*node*/)
389 //assert_msg(false, "we should never reach this code");
392 void
393 LLVMAsmGeneratorVisitor::visit(const NumberType & /*node*/)
395 assert_msg(false, "we should never reach this code");
398 void
399 LLVMAsmGeneratorVisitor::visit(const BoolType & /*node*/)
401 out_ << "i1 ";
404 void
405 LLVMAsmGeneratorVisitor::visit(const VoidType & /*node*/)
407 out_ << "void ";
410 void
411 LLVMAsmGeneratorVisitor::visit(const IntegerType & node)
413 out_ << "i" << node.size << " ";
416 void
417 LLVMAsmGeneratorVisitor::visit(const FloatType & /*node*/)
419 out_ << "float ";
422 void
423 LLVMAsmGeneratorVisitor::visit(const DoubleType & /*node*/)
425 out_ << "double ";
428 void
429 LLVMAsmGeneratorVisitor::visit(const PointerType & node)
431 node.type->accept(*this);
432 out_ << "*";
435 void
436 LLVMAsmGeneratorVisitor::visit(const ReferenceType & node)
438 node.type->accept(*this);
439 out_ << "*";
442 void
443 LLVMAsmGeneratorVisitor::visit(const CastExp & node)
445 Type * from = node.exp->type;
446 Type * to = node.type;
448 assert(from);
449 assert(to);
450 castTableKey_t key = std::make_pair(from->nodeType, to->nodeType);
451 assert(castTable_.count(key) > 0);
452 (this->*castTable_[key])(node);
455 void
456 LLVMAsmGeneratorVisitor::castBoolToBool(const CastExp & node)
458 out_ << "add i1 0, ";
459 node.exp->accept(*this);
460 return;
463 #define SIMPLE_CAST(Type1, Type2, CastInstr) \
464 void \
465 LLVMAsmGeneratorVisitor::cast##Type1##To##Type2(const CastExp & node) \
467 out_ << CastInstr" "; \
468 node.exp->type->accept(*this); \
469 out_ << " "; \
470 node.exp->accept(*this); \
471 out_ << " to "; \
472 node.type->accept(*this); \
473 return; \
476 SIMPLE_CAST(Bool, Float, "uitofp")
477 SIMPLE_CAST(Bool, Double, "uitofp")
478 SIMPLE_CAST(Float, Double, "fpext")
479 SIMPLE_CAST(Integer, Pointer, "inttoptr")
480 SIMPLE_CAST(Pointer, Integer, "ptrtoint")
482 void
483 LLVMAsmGeneratorVisitor::castBoolToInteger(const CastExp & node)
485 IntegerType * to = reinterpret_cast<IntegerType *>(node.type);
487 if (to->size == 1)
489 out_ << "add i1 0, ";
490 node.exp->accept(*this);
492 else
494 out_ << "zext i1 ";
495 node.exp->accept(*this);
496 out_ << "to ";
497 to->accept(*this);
501 void
502 LLVMAsmGeneratorVisitor::castIntegerToInteger(const CastExp & node)
504 IntegerType * from = reinterpret_cast<IntegerType *>(node.exp->type);
505 IntegerType * to = reinterpret_cast<IntegerType *>(node.type);
507 if (from->size == to->size)
509 out_ << "add i" << to->size << " 0, ";
510 node.exp->accept(*this);
511 return;
514 if (from->size > to->size)
515 out_ << "trunc";
516 else if (from->isSigned)
517 out_ << "sext";
518 else
519 out_ << "zext";
520 out_ << " i" << from->size << " ";
521 node.exp->accept(*this);
522 out_ << " to i" << to->size;
525 #define INTEGER_TO_FLOAT(Float, Str) \
526 void \
527 LLVMAsmGeneratorVisitor::castIntegerTo##Float(const CastExp & node) \
529 IntegerType * from = \
530 reinterpret_cast<IntegerType *>(node.exp->type); \
532 out_ << (from->isSigned ? "sitofp " : "uitofp "); \
533 from->accept(*this); \
534 node.exp->accept(*this); \
535 out_ << " to " Str; \
538 INTEGER_TO_FLOAT(Float, "float")
539 INTEGER_TO_FLOAT(Double, "double")
541 void
542 LLVMAsmGeneratorVisitor::castIntegerToBool(const ast::CastExp & node)
544 out_ << "icmp ne ";
545 node.exp->type->accept(*this);
546 out_ << "0, ";
547 node.exp->accept(*this);
550 #define FLOAT_TO_BOOL(Type, Str) \
551 void \
552 LLVMAsmGeneratorVisitor::cast##Type##ToBool(const ast::CastExp & /*node*/) \
554 /** @todo throw a warning */ \
555 assert_msg(false, "casting float to bool is a non sense."); \
558 FLOAT_TO_BOOL(Float, "float")
559 FLOAT_TO_BOOL(Double, "double")