2 #include <boost/foreach.hpp>
4 #include <core/assert.hh>
5 #include <ast/cast-tables.hh>
7 #include "llvm-asm-generator-visitor.hh"
11 LLVMAsmGeneratorVisitor::LLVMAsmGeneratorVisitor(std::ostream
& 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) \
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; \
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()
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())
59 (*it
)->type
->accept(*this);
60 out_
<< " %$" << (*it
)->name
;
63 out_
<< ")" << std::endl
;
67 LLVMAsmGeneratorVisitor::visit(const FunctionDecl
& node
)
70 writeFunctionHeader(node
);
74 LLVMAsmGeneratorVisitor::visit(const Function
& node
)
77 writeFunctionHeader(node
);
78 out_
<< "{" << std::endl
;
80 BOOST_FOREACH (VarDecl
* var
, *node
.args
)
90 BOOST_FOREACH (VarDecl
* var
, *node
.args
)
94 symbol
.name
= "$" + var
->name
;
95 symbol
.type
= var
->type
;
96 symbol
.address
= &addr
;
100 node
.block
->accept(*this);
101 out_
<< "}" << std::endl
;
105 LLVMAsmGeneratorVisitor::visit(const VarDecl
& node
)
109 out_
<< " %" << node
.name
<< " = alloca ";
110 node
.type
->accept(*this);
115 LLVMAsmGeneratorVisitor::visit(const LoadVar
& node
)
117 assert(node
.from
->type
);
119 out_
<< " %" << node
.to
<< " = load ";
120 node
.from
->type
->accept(*this);
122 node
.from
->accept(*this);
127 LLVMAsmGeneratorVisitor::visit(const StoreVar
& node
)
130 assert(node
.value
->type
);
133 node
.value
->type
->accept(*this);
134 node
.value
->accept(*this);
136 node
.value
->type
->accept(*this);
137 out_
<< "* %" << node
.name
<< std::endl
;
141 LLVMAsmGeneratorVisitor::visit(const AssignExp
& node
)
143 out_
<< " %" << node
.dest
->name
<< " = ";
144 if (node
.value
->nodeType
== NumberExp::nodeTypeId() ||
145 node
.value
->nodeType
== IdExp::nodeTypeId())
148 node
.value
->type
->accept(*this);
150 node
.value
->accept(*this);
153 node
.value
->accept(*this);
157 #define GEN_BINARY_EXP_EXT(Name, Type, Instr) \
159 LLVMAsmGeneratorVisitor::Name(const Type & node) \
162 unreferencedType(node.type)->accept(*this); \
163 node.left->accept(*this); \
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) \
191 LLVMAsmGeneratorVisitor::visit(const Type_ & node) \
193 Type * type = unreferencedType(node.left->type); \
195 if (type->nodeType == FloatType::nodeTypeId() || \
196 type->nodeType == DoubleType::nodeTypeId()) \
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()) \
216 type->accept(*this); \
217 node.left->accept(*this); \
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) \
231 LLVMAsmGeneratorVisitor::visit(const Type & node) \
234 node.left->accept(*this); \
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) \
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); \
265 LLVMAsmGeneratorVisitor::visit(const NegExp
& node
)
268 node
.type
->accept(*this);
269 if (AST_IS_FLOATING_POINT_TYPE(node
.type
))
273 node
.exp
->accept(*this);
277 LLVMAsmGeneratorVisitor::visit(const BangExp
& node
)
279 out_
<< "xor i1 1, ";
280 node
.exp
->accept(*this);
284 LLVMAsmGeneratorVisitor::visit(const NotExp
& node
)
287 node
.type
->accept(*this);
289 node
.exp
->accept(*this);
293 LLVMAsmGeneratorVisitor::visit(const Exp
& /* node */)
295 assert_msg(false, "unimplemented method");
299 LLVMAsmGeneratorVisitor::visit(const VoidExp
& /* node */)
304 LLVMAsmGeneratorVisitor::visit(const IdExp
& node
)
306 out_
<< "%" << node
.symbol
->name
;
310 LLVMAsmGeneratorVisitor::visit(const CallExp
& node
)
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())
321 unreferencedType((*it
)->type
)->accept(*this);
322 (*it
)->accept(*this);
326 if (node
.type
->nodeType
== VoidType::nodeTypeId())
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
;
337 out_
<< std::setprecision(1000) << node
.number
;
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
;
348 LLVMAsmGeneratorVisitor::visit(const Goto
& node
)
350 out_
<< " br label %" << node
.label
<< std::endl
;
354 LLVMAsmGeneratorVisitor::visit(const Return
& node
)
359 node
.exp
->type
->accept(*this);
360 node
.exp
->accept(*this);
365 #define VISIT_COND_BRANCH(Type) \
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
)
378 LLVMAsmGeneratorVisitor::visit(const ConditionalBranch
& node
)
381 node
.cond
->accept(*this);
382 out_
<< ", label %" << node
.trueLabel
->name
<< ", label %"
383 << node
.falseLabel
->name
<< std::endl
;
387 LLVMAsmGeneratorVisitor::visit(const Type
& /*node*/)
389 //assert_msg(false, "we should never reach this code");
393 LLVMAsmGeneratorVisitor::visit(const NumberType
& /*node*/)
395 assert_msg(false, "we should never reach this code");
399 LLVMAsmGeneratorVisitor::visit(const BoolType
& /*node*/)
405 LLVMAsmGeneratorVisitor::visit(const VoidType
& /*node*/)
411 LLVMAsmGeneratorVisitor::visit(const IntegerType
& node
)
413 out_
<< "i" << node
.size
<< " ";
417 LLVMAsmGeneratorVisitor::visit(const FloatType
& /*node*/)
423 LLVMAsmGeneratorVisitor::visit(const DoubleType
& /*node*/)
429 LLVMAsmGeneratorVisitor::visit(const PointerType
& node
)
431 node
.type
->accept(*this);
436 LLVMAsmGeneratorVisitor::visit(const ReferenceType
& node
)
438 node
.type
->accept(*this);
443 LLVMAsmGeneratorVisitor::visit(const CastExp
& node
)
445 Type
* from
= node
.exp
->type
;
446 Type
* to
= node
.type
;
450 castTableKey_t key
= std::make_pair(from
->nodeType
, to
->nodeType
);
451 assert(castTable_
.count(key
) > 0);
452 (this->*castTable_
[key
])(node
);
456 LLVMAsmGeneratorVisitor::castBoolToBool(const CastExp
& node
)
458 out_
<< "add i1 0, ";
459 node
.exp
->accept(*this);
463 #define SIMPLE_CAST(Type1, Type2, CastInstr) \
465 LLVMAsmGeneratorVisitor::cast##Type1##To##Type2(const CastExp & node) \
467 out_ << CastInstr" "; \
468 node.exp->type->accept(*this); \
470 node.exp->accept(*this); \
472 node.type->accept(*this); \
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")
483 LLVMAsmGeneratorVisitor::castBoolToInteger(const CastExp
& node
)
485 IntegerType
* to
= reinterpret_cast<IntegerType
*>(node
.type
);
489 out_
<< "add i1 0, ";
490 node
.exp
->accept(*this);
495 node
.exp
->accept(*this);
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);
514 if (from
->size
> to
->size
)
516 else if (from
->isSigned
)
520 out_
<< " i" << from
->size
<< " ";
521 node
.exp
->accept(*this);
522 out_
<< " to i" << to
->size
;
525 #define INTEGER_TO_FLOAT(Float, Str) \
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")
542 LLVMAsmGeneratorVisitor::castIntegerToBool(const ast::CastExp
& node
)
545 node
.exp
->type
->accept(*this);
547 node
.exp
->accept(*this);
550 #define FLOAT_TO_BOOL(Type, Str) \
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")