pass all expr tests
[ozulis.git] / src / ast / llvm-generator-visitor.cc
blob762c1e048225a60f1579c10167b27cc74c1a73c3
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);
39 LLVMGeneratorVisitor::~LLVMGeneratorVisitor()
43 void
44 LLVMGeneratorVisitor::visit(const Function & node)
46 out_ << "define void @" << node.name << "() {" << std::endl;
47 super_t::visit(node);
48 out_ << " ret void" << std::endl
49 << "}" << std::endl;
52 void
53 LLVMGeneratorVisitor::visit(const VarDecl & node)
55 assert(node.type);
57 out_ << " %" << node.name << " = alloca ";
58 node.type->accept(*this);
59 out_ << std::endl;
62 void
63 LLVMGeneratorVisitor::visit(const LoadVar & node)
65 assert(node.type);
67 out_ << " %" << node.to << " = load ";
68 node.type->accept(*this);
69 out_ << " * %" << node.name << std::endl;
72 void
73 LLVMGeneratorVisitor::visit(const StoreVar & node)
75 assert(node.value);
76 assert(node.value->type);
78 out_ << " store ";
79 node.value->type->accept(*this);
80 node.value->accept(*this);
81 out_ << ", ";
82 node.value->type->accept(*this);
83 out_ << " * %" << node.name << std::endl;
86 void
87 LLVMGeneratorVisitor::visit(const AssignExp & node)
89 out_ << " %" << node.dest->name << " = ";
90 node.value->accept(*this);
91 out_ << std::endl;
94 #define GEN_BINARY_EXP_EXT(Name, Type, Instr) \
95 void \
96 LLVMGeneratorVisitor::Name(const Type & node) \
97 { \
98 out_ << Instr" "; \
99 node.type->accept(*this); \
100 node.left->accept(*this); \
101 out_ << ", "; \
102 node.right->accept(*this); \
105 #define GEN_BINARY_EXP(Type, Instr) GEN_BINARY_EXP_EXT(visit, Type, Instr)
107 GEN_BINARY_EXP(AddExp, "add")
108 GEN_BINARY_EXP(SubExp, "sub")
109 GEN_BINARY_EXP(MulExp, "mul")
110 GEN_BINARY_EXP_EXT(visitUDivExp, DivExp, "udiv")
111 GEN_BINARY_EXP_EXT(visitSDivExp, DivExp, "sdiv")
112 GEN_BINARY_EXP_EXT(visitFDivExp, DivExp, "fdiv")
113 GEN_BINARY_EXP_EXT(visitUModExp, ModExp, "urem")
114 GEN_BINARY_EXP_EXT(visitSModExp, ModExp, "srem")
115 GEN_BINARY_EXP_EXT(visitFModExp, ModExp, "frem")
117 GEN_BINARY_EXP(AndExp, "and")
118 GEN_BINARY_EXP(OrExp, "or")
119 GEN_BINARY_EXP(XorExp, "xor")
121 GEN_BINARY_EXP(ShlExp, "shl")
122 GEN_BINARY_EXP(AShrExp, "ashr")
123 GEN_BINARY_EXP(LShrExp, "lshr")
125 GEN_BINARY_EXP(EqExp, "icmp eq")
126 GEN_BINARY_EXP(NeqExp, "icmp ne")
127 GEN_BINARY_EXP(LtExp, "icmp slt")
128 GEN_BINARY_EXP(LtEqExp, "icmp sle")
129 GEN_BINARY_EXP(GtExp, "icmp sgt")
130 GEN_BINARY_EXP(GtEqExp, "icmp sge")
132 #define GEN_DIV_MOD_EXP(Name) \
133 void \
134 LLVMGeneratorVisitor::visit(const Name##Exp & node) \
136 if (node.type->nodeType == BoolType::nodeTypeId()) \
137 visitU##Name##Exp(node); \
138 else if (node.type->nodeType == FloatType::nodeTypeId() || \
139 node.type->nodeType == DoubleType::nodeTypeId()) \
140 visitF##Name##Exp(node); \
141 else if (node.type->nodeType == IntegerType::nodeTypeId()) \
143 IntegerType * type = reinterpret_cast<IntegerType *>(node.type); \
144 type->isSigned ? visitS##Name##Exp(node) : visitU##Name##Exp(node); \
146 else \
147 assert(false); \
150 GEN_DIV_MOD_EXP(Div)
151 GEN_DIV_MOD_EXP(Mod)
153 // void
154 // LLVMGeneratorVisitor::visit(const EqExp & node)
155 // {
157 // }
159 void
160 LLVMGeneratorVisitor::visit(const IdExp & node)
162 out_ << "%" << node.name;
165 void
166 LLVMGeneratorVisitor::visit(const TmpResultExp & node)
168 out_ << "%" << node.name;
171 void
172 LLVMGeneratorVisitor::visit(const NumberExp & node)
174 if (node.type->nodeType == FloatType::nodeTypeId())
175 out_ << std::setprecision(1000) << (float)node.number;
176 else
177 out_ << std::setprecision(1000) << node.number;
180 void
181 LLVMGeneratorVisitor::visit(const Label & node)
183 out_ << " br label %" << node.name << " ; dummy branch to start a block" << std::endl
184 << node.name << ":" << std::endl;
187 void
188 LLVMGeneratorVisitor::visit(const Goto & node)
190 out_ << " br label %" << node.label << std::endl;
193 void
194 LLVMGeneratorVisitor::visit(const If & node)
196 assert(node.ifTrue->nodeType == Label::nodeTypeId());
197 assert(node.ifFalse->nodeType == Label::nodeTypeId());
199 Label * trueLabel = reinterpret_cast<Label *>(node.ifTrue);
200 Label * falseLabel = reinterpret_cast<Label *>(node.ifFalse);
202 out_ << " br i1 ";
203 node.cond->accept(*this);
204 out_ << ", label %" << trueLabel->name << ", label %"
205 << falseLabel->name << std::endl;
208 void
209 LLVMGeneratorVisitor::visit(const Type & /*node*/)
211 //assert_msg(false, "we should never reach this code");
214 void
215 LLVMGeneratorVisitor::visit(const NumberType & /*node*/)
217 assert_msg(false, "we should never reach this code");
220 void
221 LLVMGeneratorVisitor::visit(const BoolType & /*node*/)
223 out_ << " i1 ";
226 void
227 LLVMGeneratorVisitor::visit(const IntegerType & node)
229 out_ << " i" << node.size << " ";
232 void
233 LLVMGeneratorVisitor::visit(const FloatType & /*node*/)
235 out_ << " float ";
238 void
239 LLVMGeneratorVisitor::visit(const DoubleType & /*node*/)
241 out_ << " double ";
244 void
245 LLVMGeneratorVisitor::visit(const CastExp & node)
247 Type * from = node.exp->type;
248 Type * to = node.type;
250 assert(from);
251 assert(to);
252 castTableKey_t key = std::make_pair(from->nodeType, to->nodeType);
253 assert(castTable_.count(key) > 0);
254 (this->*castTable_[key])(node);
257 void
258 LLVMGeneratorVisitor::castBoolToBool(const CastExp & node)
260 out_ << "add i1 0, ";
261 node.exp->accept(*this);
262 return;
265 #define SIMPLE_NUMBER_CAST(Type1, Type2, CastInstr, DestType) \
266 void \
267 LLVMGeneratorVisitor::cast##Type1##To##Type2(const CastExp & node) \
269 out_ << CastInstr; \
270 node.exp->accept(*this); \
271 out_ << DestType; \
272 return; \
275 SIMPLE_NUMBER_CAST(Bool, Float, "uitofp i1 ", " to float")
276 SIMPLE_NUMBER_CAST(Bool, Double, "uitofp i1 ", " to double")
277 SIMPLE_NUMBER_CAST(Float, Double, "fpext float ", " to double")
279 void
280 LLVMGeneratorVisitor::castBoolToInteger(const CastExp & node)
282 IntegerType * to = reinterpret_cast<IntegerType *>(node.type);
284 if (to->size == 1)
286 out_ << "add i1 0, ";
287 node.exp->accept(*this);
289 else
291 out_ << "zext i1 ";
292 node.exp->accept(*this);
293 out_ << " to ";
294 to->accept(*this);
298 void
299 LLVMGeneratorVisitor::castIntegerToInteger(const CastExp & node)
301 IntegerType * from = reinterpret_cast<IntegerType *>(node.exp->type);
302 IntegerType * to = reinterpret_cast<IntegerType *>(node.type);
304 if (from->size == to->size)
306 out_ << "add i" << to->size << " 0, ";
307 node.exp->accept(*this);
308 return;
311 if (from->size > to->size)
312 out_ << "trunc";
313 else if (from->isSigned)
314 out_ << "sext";
315 else
316 out_ << "zext";
317 out_ << " i" << from->size << " ";
318 node.exp->accept(*this);
319 out_ << " to i" << to->size;
322 #define INTEGER_TO_FLOAT(Float, Str) \
323 void \
324 LLVMGeneratorVisitor::castIntegerTo##Float(const CastExp & node) \
326 IntegerType * from = \
327 reinterpret_cast<IntegerType *>(node.exp->type); \
329 out_ << (from->isSigned ? "sitofp " : "uitofp "); \
330 from->accept(*this); \
331 node.exp->accept(*this); \
332 out_ << " to " Str; \
335 INTEGER_TO_FLOAT(Float, "float")
336 INTEGER_TO_FLOAT(Double, "double")