hehe i know this one breaks compilation but i'll know what to do next time ;-)
[ozulis.git] / src / ast / llvm-generator-visitor.cc
blobfa46781315ca83b35aaa5e5f012d0ad495b8ea19
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, Method) \
21 do { \
22 castTableKey_t key = std::make_pair(Type1::nodeTypeId(), \
23 Type2::nodeTypeId()); \
24 assert_msg(!castTable_.count(key), \
25 "the same key has been insterted two times"); \
26 castTable_[key] = &LLVMGeneratorVisitor::Method; \
27 } while (0)
29 ADD_CAST_TABLE_ENTRY(BoolType, BoolType, castBoolToBool);
30 ADD_CAST_TABLE_ENTRY(BoolType, IntegerType, castBoolToInteger);
31 ADD_CAST_TABLE_ENTRY(BoolType, FloatType, castBoolToFloat);
32 ADD_CAST_TABLE_ENTRY(BoolType, DoubleType, castBoolToDouble);
33 ADD_CAST_TABLE_ENTRY(IntegerType, IntegerType, castIntegerToInteger);
34 ADD_CAST_TABLE_ENTRY(IntegerType, FloatType, castIntegerToFloat);
35 ADD_CAST_TABLE_ENTRY(IntegerType, DoubleType, castIntegerToDouble);
36 ADD_CAST_TABLE_ENTRY(FloatType, DoubleType, castFloatToDouble);
37 ADD_CAST_TABLE_ENTRY(DoubleType, BoolType, castDoubleToBool);
40 LLVMGeneratorVisitor::~LLVMGeneratorVisitor()
44 void
45 LLVMGeneratorVisitor::visit(const Function & node)
47 out_ << "define void @" << node.name << "() {" << std::endl;
48 super_t::visit(node);
49 out_ << " ret void" << std::endl
50 << "}" << std::endl;
53 void
54 LLVMGeneratorVisitor::visit(const VarDecl & node)
56 assert(node.type);
58 out_ << " %" << node.name << " = alloca ";
59 node.type->accept(*this);
60 out_ << std::endl;
63 void
64 LLVMGeneratorVisitor::visit(const LoadVar & node)
66 assert(node.type);
68 out_ << " %" << node.to << " = load ";
69 node.type->accept(*this);
70 out_ << " * %" << node.name << std::endl;
73 void
74 LLVMGeneratorVisitor::visit(const StoreVar & node)
76 assert(node.value);
77 assert(node.value->type);
79 out_ << " store ";
80 node.value->type->accept(*this);
81 node.value->accept(*this);
82 out_ << ", ";
83 node.value->type->accept(*this);
84 out_ << " * %" << node.name << std::endl;
87 void
88 LLVMGeneratorVisitor::visit(const AssignExp & node)
90 out_ << " %" << node.dest->name << " = ";
91 node.value->accept(*this);
92 out_ << std::endl;
95 #define GEN_BINARY_EXP_EXT(Name, Type, Instr) \
96 void \
97 LLVMGeneratorVisitor::Name(const Type & node) \
98 { \
99 out_ << Instr" "; \
100 node.type->accept(*this); \
101 node.left->accept(*this); \
102 out_ << ", "; \
103 node.right->accept(*this); \
106 #define GEN_BINARY_EXP(Type, Instr) GEN_BINARY_EXP_EXT(visit, Type, Instr)
108 GEN_BINARY_EXP(AddExp, "add")
109 GEN_BINARY_EXP(SubExp, "sub")
110 GEN_BINARY_EXP(MulExp, "mul")
111 GEN_BINARY_EXP_EXT(visitUDivExp, DivExp, "udiv")
112 GEN_BINARY_EXP_EXT(visitSDivExp, DivExp, "sdiv")
113 GEN_BINARY_EXP_EXT(visitFDivExp, DivExp, "fdiv")
114 GEN_BINARY_EXP_EXT(visitUModExp, ModExp, "urem")
115 GEN_BINARY_EXP_EXT(visitSModExp, ModExp, "srem")
116 GEN_BINARY_EXP_EXT(visitFModExp, ModExp, "frem")
118 GEN_BINARY_EXP(AndExp, "and")
119 GEN_BINARY_EXP(OrExp, "or")
120 GEN_BINARY_EXP(XorExp, "xor")
122 GEN_BINARY_EXP(ShlExp, "shl")
123 GEN_BINARY_EXP(AShrExp, "ashr")
124 GEN_BINARY_EXP(LShrExp, "lshr")
126 GEN_BINARY_EXP(EqExp, "icmp eq")
127 GEN_BINARY_EXP(NeqExp, "icmp ne")
128 GEN_BINARY_EXP(LtExp, "icmp slt")
129 GEN_BINARY_EXP(LtEqExp, "icmp sle")
130 GEN_BINARY_EXP(GtExp, "icmp sgt")
131 GEN_BINARY_EXP(GtEqExp, "icmp sge")
133 #define GEN_BINARY_BOOL_EXP(Type, Op) \
134 void \
135 LLVMGeneratorVisitor::visit(const Type & node) \
137 out_ << Op " i1 "; \
138 node.left->accept(*this); \
139 out_ << ", "; \
140 node.right->accept(*this); \
143 GEN_BINARY_BOOL_EXP(AndAndExp, "and ")
144 GEN_BINARY_BOOL_EXP(OrOrExp, "or ")
146 #define GEN_DIV_MOD_EXP(Name) \
147 void \
148 LLVMGeneratorVisitor::visit(const Name##Exp & node) \
150 if (node.type->nodeType == BoolType::nodeTypeId()) \
151 visitU##Name##Exp(node); \
152 else if (node.type->nodeType == FloatType::nodeTypeId() || \
153 node.type->nodeType == DoubleType::nodeTypeId()) \
154 visitF##Name##Exp(node); \
155 else if (node.type->nodeType == IntegerType::nodeTypeId()) \
157 IntegerType * type = reinterpret_cast<IntegerType *>(node.type); \
158 type->isSigned ? visitS##Name##Exp(node) : visitU##Name##Exp(node); \
160 else \
161 assert(false); \
164 GEN_DIV_MOD_EXP(Div)
165 GEN_DIV_MOD_EXP(Mod)
167 // void
168 // LLVMGeneratorVisitor::visit(const EqExp & node)
169 // {
171 // }
173 void
174 LLVMGeneratorVisitor::visit(const IdExp & node)
176 out_ << "%" << node.name;
179 void
180 LLVMGeneratorVisitor::visit(const TmpResultExp & node)
182 out_ << "%" << node.name;
185 void
186 LLVMGeneratorVisitor::visit(const NumberExp & node)
188 if (node.type->nodeType == FloatType::nodeTypeId())
189 out_ << std::setprecision(1000) << (float)node.number;
190 else
191 out_ << std::setprecision(1000) << node.number;
194 void
195 LLVMGeneratorVisitor::visit(const Label & node)
197 out_ << " br label %" << node.name << " ; dummy branch to start a block" << std::endl
198 << node.name << ":" << std::endl;
201 void
202 LLVMGeneratorVisitor::visit(const Goto & node)
204 out_ << " br label %" << node.label << std::endl;
207 void
208 LLVMGeneratorVisitor::visit(const If & node)
210 assert(node.ifTrue->nodeType == Label::nodeTypeId());
211 assert(node.ifFalse->nodeType == Label::nodeTypeId());
213 Label * trueLabel = reinterpret_cast<Label *>(node.ifTrue);
214 Label * falseLabel = reinterpret_cast<Label *>(node.ifFalse);
216 out_ << " br i1 ";
217 node.cond->accept(*this);
218 out_ << ", label %" << trueLabel->name << ", label %"
219 << falseLabel->name << std::endl;
222 void
223 LLVMGeneratorVisitor::visit(const Type & /*node*/)
225 //assert_msg(false, "we should never reach this code");
228 void
229 LLVMGeneratorVisitor::visit(const NumberType & /*node*/)
231 assert_msg(false, "we should never reach this code");
234 void
235 LLVMGeneratorVisitor::visit(const BoolType & /*node*/)
237 out_ << " i1 ";
240 void
241 LLVMGeneratorVisitor::visit(const IntegerType & node)
243 out_ << " i" << node.size << " ";
246 void
247 LLVMGeneratorVisitor::visit(const FloatType & /*node*/)
249 out_ << " float ";
252 void
253 LLVMGeneratorVisitor::visit(const DoubleType & /*node*/)
255 out_ << " double ";
258 void
259 LLVMGeneratorVisitor::visit(const CastExp & node)
261 Type * from = node.exp->type;
262 Type * to = node.type;
264 assert(from);
265 assert(to);
266 castTableKey_t key = std::make_pair(from->nodeType, to->nodeType);
267 assert(castTable_.count(key) > 0);
268 (this->*castTable_[key])(node);
271 void
272 LLVMGeneratorVisitor::castBoolToBool(const CastExp & node)
274 out_ << "add i1 0, ";
275 node.exp->accept(*this);
276 return;
279 #define SIMPLE_NUMBER_CAST(Type1, Type2, CastInstr, DestType) \
280 void \
281 LLVMGeneratorVisitor::cast##Type1##To##Type2(const CastExp & node) \
283 out_ << CastInstr; \
284 node.exp->accept(*this); \
285 out_ << DestType; \
286 return; \
289 SIMPLE_NUMBER_CAST(Bool, Float, "uitofp i1 ", " to float")
290 SIMPLE_NUMBER_CAST(Bool, Double, "uitofp i1 ", " to double")
291 SIMPLE_NUMBER_CAST(Float, Double, "fpext float ", " to double")
293 void
294 LLVMGeneratorVisitor::castBoolToInteger(const CastExp & node)
296 IntegerType * to = reinterpret_cast<IntegerType *>(node.type);
298 if (to->size == 1)
300 out_ << "add i1 0, ";
301 node.exp->accept(*this);
303 else
305 out_ << "zext i1 ";
306 node.exp->accept(*this);
307 out_ << " to ";
308 to->accept(*this);
312 void
313 LLVMGeneratorVisitor::castIntegerToInteger(const CastExp & node)
315 IntegerType * from = reinterpret_cast<IntegerType *>(node.exp->type);
316 IntegerType * to = reinterpret_cast<IntegerType *>(node.type);
318 if (from->size == to->size)
320 out_ << "add i" << to->size << " 0, ";
321 node.exp->accept(*this);
322 return;
325 if (from->size > to->size)
326 out_ << "trunc";
327 else if (from->isSigned)
328 out_ << "sext";
329 else
330 out_ << "zext";
331 out_ << " i" << from->size << " ";
332 node.exp->accept(*this);
333 out_ << " to i" << to->size;
336 #define INTEGER_TO_FLOAT(Float, Str) \
337 void \
338 LLVMGeneratorVisitor::castIntegerTo##Float(const CastExp & node) \
340 IntegerType * from = \
341 reinterpret_cast<IntegerType *>(node.exp->type); \
343 out_ << (from->isSigned ? "sitofp " : "uitofp "); \
344 from->accept(*this); \
345 node.exp->accept(*this); \
346 out_ << " to " Str; \
349 INTEGER_TO_FLOAT(Float, "float")
350 INTEGER_TO_FLOAT(Double, "double")