cast bool -> float
[ozulis.git] / src / ast / llvm-generator-visitor.cc
blobc757520c836546ffb7234190bcce4ddb73d77c51
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, FloatType, castBoolToFloat);
31 ADD_CAST_TABLE_ENTRY(BoolType, DoubleType, castBoolToDouble);
32 ADD_CAST_TABLE_ENTRY(IntegerType, IntegerType, castIntegerToInteger);
33 ADD_CAST_TABLE_ENTRY(FloatType, DoubleType, castFloatToDouble);
36 LLVMGeneratorVisitor::~LLVMGeneratorVisitor()
40 void
41 LLVMGeneratorVisitor::visit(const Function & node)
43 out_ << "define void @" << node.name << "() {" << std::endl;
44 super_t::visit(node);
45 out_ << " ret void" << std::endl
46 << "}" << std::endl;
49 void
50 LLVMGeneratorVisitor::visit(const VarDecl & node)
52 assert(node.type);
54 out_ << " %" << node.name << " = alloca ";
55 node.type->accept(*this);
56 out_ << std::endl;
59 void
60 LLVMGeneratorVisitor::visit(const LoadVar & node)
62 assert(node.type);
64 out_ << " %" << node.to << " = load ";
65 node.type->accept(*this);
66 out_ << " * %" << node.name << std::endl;
69 void
70 LLVMGeneratorVisitor::visit(const StoreVar & node)
72 assert(node.value);
73 assert(node.value->type);
75 out_ << " store ";
76 node.value->type->accept(*this);
77 node.value->accept(*this);
78 out_ << ", ";
79 node.value->type->accept(*this);
80 out_ << " * %" << node.name << std::endl;
83 void
84 LLVMGeneratorVisitor::visit(const AssignExp & node)
86 out_ << " %" << node.dest->name << " = ";
87 node.value->accept(*this);
88 out_ << std::endl;
91 #define GEN_BINARY_EXP(Type, Instr) \
92 void \
93 LLVMGeneratorVisitor::visit(const Type & node) \
94 { \
95 out_ << Instr" "; \
96 node.type->accept(*this); \
97 node.left->accept(*this); \
98 out_ << ", "; \
99 node.right->accept(*this); \
102 GEN_BINARY_EXP(AddExp, "add")
103 GEN_BINARY_EXP(SubExp, "sub")
104 GEN_BINARY_EXP(MulExp, "mul")
105 GEN_BINARY_EXP(DivExp, "sdiv") /// @todo play with udiv and sdiv instructions
106 GEN_BINARY_EXP(ModExp, "srem") /// @todo play with urem and srem instructions
108 GEN_BINARY_EXP(AndExp, "and")
109 GEN_BINARY_EXP(OrExp, "or")
110 GEN_BINARY_EXP(XorExp, "xor")
112 GEN_BINARY_EXP(ShlExp, "shl")
113 GEN_BINARY_EXP(AShrExp, "ashr")
114 GEN_BINARY_EXP(LShrExp, "lshr")
116 GEN_BINARY_EXP(EqExp, "icmp eq")
117 GEN_BINARY_EXP(NeqExp, "icmp ne")
118 GEN_BINARY_EXP(LtExp, "icmp slt")
119 GEN_BINARY_EXP(LtEqExp, "icmp sle")
120 GEN_BINARY_EXP(GtExp, "icmp sgt")
121 GEN_BINARY_EXP(GtEqExp, "icmp sge")
123 // void
124 // LLVMGeneratorVisitor::visit(const EqExp & node)
125 // {
127 // }
129 void
130 LLVMGeneratorVisitor::visit(const IdExp & node)
132 out_ << "%" << node.name;
135 void
136 LLVMGeneratorVisitor::visit(const TmpResultExp & node)
138 out_ << "%" << node.name;
141 void
142 LLVMGeneratorVisitor::visit(const NumberExp & node)
144 if (node.type->nodeType == FloatType::nodeTypeId())
145 out_ << std::setprecision(1000) << (float)node.number;
146 else
147 out_ << std::setprecision(1000) << node.number;
150 void
151 LLVMGeneratorVisitor::visit(const Label & node)
153 out_ << " br label %" << node.name << " ; dummy branch to start a block" << std::endl
154 << node.name << ":" << std::endl;
157 void
158 LLVMGeneratorVisitor::visit(const Goto & node)
160 out_ << " br label %" << node.label << std::endl;
163 void
164 LLVMGeneratorVisitor::visit(const If & node)
166 assert(node.ifTrue->nodeType == Label::nodeTypeId());
167 assert(node.ifFalse->nodeType == Label::nodeTypeId());
169 Label * trueLabel = reinterpret_cast<Label *>(node.ifTrue);
170 Label * falseLabel = reinterpret_cast<Label *>(node.ifFalse);
172 out_ << " br i1 ";
173 node.cond->accept(*this);
174 out_ << ", label %" << trueLabel->name << ", label %"
175 << falseLabel->name << std::endl;
178 void
179 LLVMGeneratorVisitor::visit(const Type & /*node*/)
181 //assert_msg(false, "we should never reach this code");
184 void
185 LLVMGeneratorVisitor::visit(const NumberType & /*node*/)
187 assert_msg(false, "we should never reach this code");
190 void
191 LLVMGeneratorVisitor::visit(const BoolType & /*node*/)
193 out_ << " i1 ";
196 void
197 LLVMGeneratorVisitor::visit(const IntegerType & node)
199 out_ << " i" << node.size << " ";
202 void
203 LLVMGeneratorVisitor::visit(const FloatType & /*node*/)
205 out_ << " float ";
208 void
209 LLVMGeneratorVisitor::visit(const DoubleType & /*node*/)
211 out_ << " double ";
214 void
215 LLVMGeneratorVisitor::visit(const CastExp & node)
217 Type * from = node.exp->type;
218 Type * to = node.type;
220 assert(from);
221 assert(to);
222 castTableKey_t key = std::make_pair(from->nodeType, to->nodeType);
223 assert(castTable_.count(key) > 0);
224 (this->*castTable_[key])(node);
227 void
228 LLVMGeneratorVisitor::castBoolToBool(const CastExp & node)
230 out_ << "add i1 0, ";
231 node.exp->accept(*this);
232 return;
235 #define SIMPLE_NUMBER_CAST(Type1, Type2, CastInstr, DestType) \
236 void \
237 LLVMGeneratorVisitor::cast##Type1##To##Type2(const CastExp & node) \
239 out_ << CastInstr; \
240 node.exp->accept(*this); \
241 out_ << DestType; \
242 return; \
245 SIMPLE_NUMBER_CAST(Bool, Float, "sitofp i1 ", " to float")
246 SIMPLE_NUMBER_CAST(Bool, Double, "sitofp i1 ", " to double")
247 SIMPLE_NUMBER_CAST(Float, Double, "fpext float ", " to double")
249 void
250 LLVMGeneratorVisitor::castIntegerToInteger(const CastExp & node)
252 IntegerType * from = reinterpret_cast<IntegerType *>(node.exp->type);
253 IntegerType * to = reinterpret_cast<IntegerType *>(node.type);
255 if (from->size == to->size)
257 out_ << "add i" << to->size << " 0, ";
258 node.exp->accept(*this);
259 return;
262 if (from->size > to->size)
263 out_ << "trunc";
264 else if (from->isSigned)
265 out_ << "sext";
266 else
267 out_ << "zext";
268 out_ << " i" << from->size << " ";
269 node.exp->accept(*this);
270 out_ << " to i" << to->size;