[visitors] ported llvm asm generator
[ozulis.git] / src / ozulis / visitors / llvm-asm-generator.cc
blobb8c0a2e9061119fb3ab856b02ed469dd604b401f
1 #include <iomanip>
2 #include <boost/foreach.hpp>
4 #include <ozulis/core/assert.hh>
5 #include <ozulis/ast/ast-cast.hh>
6 #include <ozulis/ast/cast-tables.hh>
7 #include <ozulis/visitors/browser.hh>
9 #include "llvm-asm-generator.hh"
11 namespace ozulis
13 namespace visitors
15 LLVMAsmGenerator::LLVMAsmGenerator(std::ostream & out)
16 : ConstVisitor<LLVMAsmGenerator>(),
17 castTable_(),
18 out_(out)
20 assert_msg(out.good(), "The output for llvm assembly is not valid.");
21 out_ << std::setprecision(1000);
23 #define ADD_CAST_TABLE_ENTRY(Type1, Type2) \
24 do { \
25 castTableKey_t key = std::make_pair(ast::Type1##Type::nodeTypeId(), \
26 ast::Type2##Type::nodeTypeId()); \
27 assert_msg(!castTable_.count(key), \
28 "the same key has been insterted two times"); \
29 castTable_[key] = &LLVMAsmGenerator::cast##Type1##To##Type2; \
30 } while (0)
32 ADD_CAST_TABLE_ENTRY(Bool, Bool);
33 ADD_CAST_TABLE_ENTRY(Bool, Integer);
34 ADD_CAST_TABLE_ENTRY(Bool, Float);
35 ADD_CAST_TABLE_ENTRY(Bool, Double);
36 ADD_CAST_TABLE_ENTRY(Integer, Bool);
37 ADD_CAST_TABLE_ENTRY(Integer, Integer);
38 ADD_CAST_TABLE_ENTRY(Integer, Float);
39 ADD_CAST_TABLE_ENTRY(Integer, Double);
40 ADD_CAST_TABLE_ENTRY(Float, Double);
41 ADD_CAST_TABLE_ENTRY(Float, Bool);
42 ADD_CAST_TABLE_ENTRY(Double, Bool);
44 ADD_CAST_TABLE_ENTRY(Integer, Pointer);
45 ADD_CAST_TABLE_ENTRY(Pointer, Integer);
48 LLVMAsmGenerator::~LLVMAsmGenerator()
52 void
53 LLVMAsmGenerator::writeFunctionHeader(const ast::FunctionDecl & node)
55 LLVMAsmGenerator::visit(*node.returnType, *this);
56 out_ << " @" << node.name << "(";
58 for (std::vector<ast::VarDecl *>::iterator it = node.args->begin();
59 it != node.args->end(); it++)
61 if (it != node.args->begin())
62 out_ << ", ";
63 LLVMAsmGenerator::visit(*(*it)->type, *this);
64 out_ << " %$" << (*it)->name;
67 out_ << ")" << std::endl;
70 static void visitFunctionDecl(const ast::Node & node_, LLVMAsmGenerator & ctx)
72 const ast::FunctionDecl node = reinterpret_cast<const ast::FunctionDecl &> (node_);
73 ctx.out_ << "declare ";
74 ctx.writeFunctionHeader(node);
77 static void visitFunction(const ast::Node & node_, LLVMAsmGenerator & ctx)
79 const ast::Function node = reinterpret_cast<const ast::Function &> (node_);
80 ctx.out_ << "define ";
81 ctx.writeFunctionHeader(node);
82 ctx.out_ << "{" << std::endl;
84 BOOST_FOREACH (ast::VarDecl * var, *node.args)
85 LLVMAsmGenerator::visit(*var, ctx);
87 ast::StoreVar sv;
88 ast::IdExp id;
89 ast::Symbol symbol;
90 ast::MemoryAddress addr;
92 sv.value = &id;
93 id.symbol = &symbol;
94 BOOST_FOREACH (ast::VarDecl * var, *node.args)
96 sv.name = var->name;
97 id.type = var->type;
98 symbol.name = "$" + var->name;
99 symbol.type = var->type;
100 symbol.address = &addr;
101 LLVMAsmGenerator::visit(sv, ctx);
104 LLVMAsmGenerator::visit(*node.block, ctx);
105 ctx.out_ << "}" << std::endl;
108 static void visitVarDecl(const ast::Node & node_, LLVMAsmGenerator & ctx)
110 const ast::VarDecl node = reinterpret_cast<const ast::VarDecl &> (node_);
111 assert(node.type);
113 ctx.out_ << " %" << node.name << " = alloca ";
114 LLVMAsmGenerator::visit(*node.type, ctx);
115 ctx.out_ << std::endl;
118 static void visitLoadVar(const ast::Node & node_, LLVMAsmGenerator & ctx)
120 const ast::LoadVar node = reinterpret_cast<const ast::LoadVar &> (node_);
121 assert(node.from->type);
123 ctx.out_ << " %" << node.to << " = load ";
124 LLVMAsmGenerator::visit(*node.from->type, ctx);
125 ctx.out_ << " ";
126 LLVMAsmGenerator::visit(*node.from, ctx);
127 ctx.out_ << std::endl;
130 static void visitStoreVar(const ast::Node & node_, LLVMAsmGenerator & ctx)
132 const ast::StoreVar node = reinterpret_cast<const ast::StoreVar &> (node_);
133 assert(node.value);
134 assert(node.value->type);
136 ctx.out_ << " store ";
137 LLVMAsmGenerator::visit(*node.value->type, ctx);
138 LLVMAsmGenerator::visit(*node.value, ctx);
139 ctx.out_ << ", ";
140 LLVMAsmGenerator::visit(*node.value->type, ctx);
141 ctx.out_ << "* %" << node.name << std::endl;
144 static void visitAssignExp(const ast::Node & node_, LLVMAsmGenerator & ctx)
146 const ast::AssignExp node = reinterpret_cast<const ast::AssignExp &> (node_);
147 ctx.out_ << " ";
148 LLVMAsmGenerator::visit(*node.dest, ctx);
149 ctx.out_ << " = ";
150 if (node.value->nodeType == ast::NumberExp::nodeTypeId() ||
151 node.value->nodeType == ast::IdExp::nodeTypeId())
153 ctx.out_ << "add ";
154 LLVMAsmGenerator::visit(*node.value->type, ctx);
155 ctx.out_ << " 0, ";
156 LLVMAsmGenerator::visit(*node.value, ctx);
158 else
159 LLVMAsmGenerator::visit(*node.value, ctx);
160 ctx.out_ << std::endl;
163 #define GEN_BINARY_EXP_EXT(Name, Type, Instr) \
164 static void Name(const ast::Node & node_, LLVMAsmGenerator & ctx) \
166 const ast::Type & node = reinterpret_cast<const ast::Type &> (node_); \
167 ctx.out_ << Instr" "; \
168 LLVMAsmGenerator::visit(*unreferencedType(node.type), ctx); \
169 LLVMAsmGenerator::visit(*node.left, ctx); \
170 ctx.out_ << ", "; \
171 LLVMAsmGenerator::visit(*node.right, ctx); \
174 #define GEN_BINARY_EXP(Type, Instr) GEN_BINARY_EXP_EXT(visit##Type, Type, Instr)
176 GEN_BINARY_EXP(AddExp, "add")
177 GEN_BINARY_EXP(SubExp, "sub")
178 GEN_BINARY_EXP(MulExp, "mul")
179 GEN_BINARY_EXP_EXT(visitUDivExp, DivExp, "udiv")
180 GEN_BINARY_EXP_EXT(visitSDivExp, DivExp, "sdiv")
181 GEN_BINARY_EXP_EXT(visitFDivExp, DivExp, "fdiv")
182 GEN_BINARY_EXP_EXT(visitUModExp, ModExp, "urem")
183 GEN_BINARY_EXP_EXT(visitSModExp, ModExp, "srem")
184 GEN_BINARY_EXP_EXT(visitFModExp, ModExp, "frem")
186 GEN_BINARY_EXP(AndExp, "and")
187 GEN_BINARY_EXP(OrExp, "or")
188 GEN_BINARY_EXP(XorExp, "xor")
190 GEN_BINARY_EXP(ShlExp, "shl")
191 GEN_BINARY_EXP(AShrExp, "ashr")
192 GEN_BINARY_EXP(LShrExp, "lshr")
194 /// @todo check this is correct.
195 #define GEN_CMP_EXP(Type_, Instr) \
196 static void visit##Type_(const ast::Node & node_, LLVMAsmGenerator & ctx) \
198 const ast::Type_ & node = reinterpret_cast<const ast::Type_ &> (node_); \
199 ast::Type * type = unreferencedType(node.left->type); \
201 if (type->nodeType == ast::FloatType::nodeTypeId() || \
202 type->nodeType == ast::DoubleType::nodeTypeId()) \
203 ctx.out_ << "fcmp o"; \
204 else \
206 ctx.out_ << "icmp "; \
207 if (node.nodeType == ast::LtExp::nodeTypeId() || \
208 node.nodeType == ast::LtEqExp::nodeTypeId() || \
209 node.nodeType == ast::GtExp::nodeTypeId() || \
210 node.nodeType == ast::GtEqExp::nodeTypeId()) \
212 if (type->nodeType == ast::IntegerType::nodeTypeId()) \
214 ast::IntegerType * itype = reinterpret_cast<ast::IntegerType *>(type); \
215 ctx.out_ << (itype->isSigned ? "s" : "u"); \
217 else if (type->nodeType == ast::BoolType::nodeTypeId()) \
218 ctx.out_ << "u"; \
221 ctx.out_ << Instr" "; \
222 LLVMAsmGenerator::visit(*type, ctx); \
223 LLVMAsmGenerator::visit(*node.left, ctx); \
224 ctx.out_ << ", "; \
225 LLVMAsmGenerator::visit(*node.right, ctx); \
228 GEN_CMP_EXP(EqExp, "eq")
229 GEN_CMP_EXP(NeqExp, "ne")
230 GEN_CMP_EXP(LtExp, "lt")
231 GEN_CMP_EXP(LtEqExp, "le")
232 GEN_CMP_EXP(GtExp, "gt")
233 GEN_CMP_EXP(GtEqExp, "ge")
235 #define GEN_BINARY_BOOL_EXP(Type, Op) \
236 static void visit##Type(const ast::Node & node_, LLVMAsmGenerator & ctx) \
238 const ast::Type node = reinterpret_cast<const ast::Type &> (node_); \
239 ctx.out_ << Op " i1 "; \
240 LLVMAsmGenerator::visit(*node.left, ctx); \
241 ctx.out_ << ", "; \
242 LLVMAsmGenerator::visit(*node.right, ctx); \
245 GEN_BINARY_BOOL_EXP(AndAndExp, "and ")
246 GEN_BINARY_BOOL_EXP(OrOrExp, "or ")
248 #define GEN_DIV_MOD_EXP(Name) \
249 static void visit##Name##Exp(const ast::Node & node_, LLVMAsmGenerator & ctx) \
251 const ast::Name##Exp node = reinterpret_cast<const ast::Name##Exp &> (node_); \
252 if (node.type->nodeType == ast::BoolType::nodeTypeId()) \
253 visitU##Name##Exp(node, ctx); \
254 else if (node.type->nodeType == ast::FloatType::nodeTypeId() || \
255 node.type->nodeType == ast::DoubleType::nodeTypeId()) \
256 visitF##Name##Exp(node, ctx); \
257 else if (node.type->nodeType == ast::IntegerType::nodeTypeId()) \
259 ast::IntegerType * type = reinterpret_cast<ast::IntegerType *>(node.type); \
260 type->isSigned ? \
261 visitS##Name##Exp(node, ctx) : visitU##Name##Exp(node, ctx); \
263 else \
264 assert(false); \
267 GEN_DIV_MOD_EXP(Div)
268 GEN_DIV_MOD_EXP(Mod)
271 static void visitNegExp(const ast::Node & node_, LLVMAsmGenerator & ctx)
273 const ast::NegExp node = reinterpret_cast<const ast::NegExp &> (node_);
274 ctx.out_ << "sub ";
275 LLVMAsmGenerator::visit(*node.type, ctx);
276 if (AST_IS_FLOATING_POINT_TYPE(node.type))
277 ctx.out_ << " 0.0, ";
278 else
279 ctx.out_ << " 0, ";
280 LLVMAsmGenerator::visit(*node.exp, ctx);
283 static void visitBangExp(const ast::Node & node_, LLVMAsmGenerator & ctx)
285 const ast::BangExp node = reinterpret_cast<const ast::BangExp &> (node_);
286 ctx.out_ << "xor i1 1, ";
287 LLVMAsmGenerator::visit(*node.exp, ctx);
290 static void visitNotExp(const ast::Node & node_, LLVMAsmGenerator & ctx)
292 const ast::NotExp node = reinterpret_cast<const ast::NotExp &> (node_);
293 ctx.out_ << "xor ";
294 LLVMAsmGenerator::visit(*node.type, ctx);
295 ctx.out_ << " -1, ";
296 LLVMAsmGenerator::visit(*node.exp, ctx);
299 static void visitExp(const ast::Node & /*node_*/, LLVMAsmGenerator & /*ctx*/)
301 assert_msg(false, "unimplemented method");
304 static void visitVoidExp(const ast::Node & /*node_*/, LLVMAsmGenerator & /*ctx*/)
308 static void visitIdExp(const ast::Node & node_, LLVMAsmGenerator & ctx)
310 const ast::IdExp node = reinterpret_cast<const ast::IdExp &> (node_);
311 ctx.out_ << "%" << node.symbol->name;
314 static void visitAtExp(const ast::Node & node_, LLVMAsmGenerator & ctx)
316 const ast::AtExp node = reinterpret_cast<const ast::AtExp &> (node_);
317 LLVMAsmGenerator::visit(*node.exp, ctx);
320 static void visitCallExp(const ast::Node & node_, LLVMAsmGenerator & ctx)
322 const ast::CallExp node = reinterpret_cast<const ast::CallExp &> (node_);
323 ctx.out_ << " call ";
324 LLVMAsmGenerator::visit(*node.type, ctx);
325 ctx.out_ << " @" << node.id << "(";
327 for (ast::CallExp::args_t::iterator it = node.args->begin();
328 it != node.args->end(); it++)
330 if (it != node.args->begin())
331 ctx.out_ << ", ";
332 LLVMAsmGenerator::visit(*unreferencedType((*it)->type), ctx);
333 LLVMAsmGenerator::visit(*(*it), ctx);
336 ctx.out_ << ")";
337 if (node.type->nodeType == ast::VoidType::nodeTypeId())
338 ctx.out_ << std::endl;
341 static void visitNumberExp(const ast::Node & node_, LLVMAsmGenerator & ctx)
343 const ast::NumberExp node = reinterpret_cast<const ast::NumberExp &> (node_);
344 if (node.type->nodeType == ast::FloatType::nodeTypeId())
345 /// @todo find the right way to print floating point numbers
346 ctx.out_ << std::setprecision(1000) << (float)node.number;
347 else
348 ctx.out_ << std::setprecision(1000) << node.number;
351 static void visitLabel(const ast::Node & node_, LLVMAsmGenerator & ctx)
353 const ast::Label node = reinterpret_cast<const ast::Label &> (node_);
354 ctx.out_ << " br label %" << node.name << " ; dummy branch to start a block" << std::endl
355 << node.name << ":" << std::endl;
358 static void visitGoto(const ast::Node & node_, LLVMAsmGenerator & ctx)
360 const ast::Goto node = reinterpret_cast<const ast::Goto &> (node_);
361 ctx.out_ << " br label %" << node.label << std::endl;
364 static void visitReturn(const ast::Node & node_, LLVMAsmGenerator & ctx)
366 const ast::Return node = reinterpret_cast<const ast::Return &> (node_);
367 assert(node.exp);
369 ctx.out_ << " ret ";
370 LLVMAsmGenerator::visit(*node.exp->type, ctx);
371 LLVMAsmGenerator::visit(*node.exp, ctx);
372 ctx.out_ << std::endl;
375 #if 0
376 #define VISIT_COND_BRANCH(Type) \
377 void \
378 LLVMAsmGenerator::visit(const Type & node) \
380 visit((ConditionalBranch)node); \
383 VISIT_COND_BRANCH(If)
384 VISIT_COND_BRANCH(While)
385 VISIT_COND_BRANCH(DoWhile)
386 #endif
388 static void visitConditionalBranch(const ast::Node & node_, LLVMAsmGenerator & ctx)
390 const ast::ConditionalBranch node = reinterpret_cast<const ast::ConditionalBranch &> (node_);
391 ctx.out_ << " br i1 ";
392 LLVMAsmGenerator::visit(*node.cond, ctx);
393 ctx.out_ << ", label %" << node.trueLabel->name << ", label %"
394 << node.falseLabel->name << std::endl;
397 static void visitType(const ast::Node & /*node_*/, LLVMAsmGenerator & /*ctx*/)
399 //assert_msg(false, "we should never reach this code");
402 static void visitNumberType(const ast::Node & /*node_*/, LLVMAsmGenerator & /*ctx*/)
404 assert_msg(false, "we should never reach this code");
407 static void visitBoolType(const ast::Node & node_, LLVMAsmGenerator & ctx)
409 const ast::BoolType node = reinterpret_cast<const ast::BoolType &> (node_);
410 ctx.out_ << "i1 ";
413 static void visitVoidType(const ast::Node & node_, LLVMAsmGenerator & ctx)
415 const ast::VoidType node = reinterpret_cast<const ast::VoidType &> (node_);
416 ctx.out_ << "void ";
419 static void visitIntegerType(const ast::Node & node_, LLVMAsmGenerator & ctx)
421 const ast::IntegerType node = reinterpret_cast<const ast::IntegerType &> (node_);
422 ctx.out_ << "i" << node.size << " ";
425 static void visitFloatType(const ast::Node & node_, LLVMAsmGenerator & ctx)
427 const ast::FloatType node = reinterpret_cast<const ast::FloatType &> (node_);
428 ctx.out_ << "float ";
431 static void visitDoubleType(const ast::Node & node_, LLVMAsmGenerator & ctx)
433 const ast::DoubleType node = reinterpret_cast<const ast::DoubleType &> (node_);
434 ctx.out_ << "double ";
437 static void visitPointerType(const ast::Node & node_, LLVMAsmGenerator & ctx)
439 const ast::PointerType node = reinterpret_cast<const ast::PointerType &> (node_);
440 LLVMAsmGenerator::visit(*node.type, ctx);
441 ctx.out_ << "*";
444 static void visitReferenceType(const ast::Node & node_, LLVMAsmGenerator & ctx)
446 const ast::ReferenceType node = reinterpret_cast<const ast::ReferenceType &> (node_);
447 LLVMAsmGenerator::visit(*node.type, ctx);
448 ctx.out_ << "*";
451 static void visitCastExp(const ast::Node & node_, LLVMAsmGenerator & ctx)
453 const ast::CastExp node = reinterpret_cast<const ast::CastExp &> (node_);
454 ast::Type * from = unreferencedType(node.exp->type);
455 ast::Type * to = unreferencedType(node.type);
457 assert(from);
458 assert(to);
459 LLVMAsmGenerator::castTableKey_t key =
460 std::make_pair(from->nodeType, to->nodeType);
461 assert(ctx.castTable_.count(key) > 0);
462 (ctx.*ctx.castTable_[key])(node);
465 void
466 LLVMAsmGenerator::castBoolToBool(const ast::CastExp & node)
468 out_ << "add i1 0, ";
469 LLVMAsmGenerator::visit(*node.exp, *this);
470 return;
473 #define SIMPLE_CAST(Type1, Type2, CastInstr) \
474 void \
475 LLVMAsmGenerator::cast##Type1##To##Type2(const ast::CastExp & node) \
477 out_ << CastInstr" "; \
478 LLVMAsmGenerator::visit(*node.exp->type, *this); \
479 out_ << " "; \
480 LLVMAsmGenerator::visit(*node.exp, *this); \
481 out_ << " to "; \
482 LLVMAsmGenerator::visit(*node.type, *this); \
483 return; \
486 SIMPLE_CAST(Bool, Float, "uitofp")
487 SIMPLE_CAST(Bool, Double, "uitofp")
488 SIMPLE_CAST(Float, Double, "fpext")
489 SIMPLE_CAST(Integer, Pointer, "inttoptr")
490 SIMPLE_CAST(Pointer, Integer, "ptrtoint")
492 void
493 LLVMAsmGenerator::castBoolToInteger(const ast::CastExp & node)
495 ast::IntegerType * to = reinterpret_cast<ast::IntegerType *>(node.type);
497 if (to->size == 1)
499 out_ << "add i1 0, ";
500 LLVMAsmGenerator::visit(*node.exp, *this);
502 else
504 out_ << "zext i1 ";
505 LLVMAsmGenerator::visit(*node.exp, *this);
506 out_ << "to ";
507 LLVMAsmGenerator::visit(*to, *this);
511 void
512 LLVMAsmGenerator::castIntegerToInteger(const ast::CastExp & node)
514 ast::IntegerType * from = ast::ast_cast<ast::IntegerType *>(node.exp->type);
515 ast::IntegerType * to = ast::ast_cast<ast::IntegerType *>(node.type);
517 if (from->size == to->size)
519 out_ << "add i" << to->size << " 0, ";
520 LLVMAsmGenerator::visit(*node.exp, *this);
521 return;
524 if (from->size > to->size)
525 out_ << "trunc";
526 else if (from->isSigned)
527 out_ << "sext";
528 else
529 out_ << "zext";
530 out_ << " i" << from->size << " ";
531 LLVMAsmGenerator::visit(*node.exp, *this);
532 out_ << " to i" << to->size;
535 #define INTEGER_TO_FLOAT(Float, Str) \
536 void \
537 LLVMAsmGenerator::castIntegerTo##Float(const ast::CastExp & node) \
539 ast::IntegerType * from = \
540 ast::ast_cast<ast::IntegerType *>(node.exp->type); \
542 out_ << (from->isSigned ? "sitofp " : "uitofp "); \
543 LLVMAsmGenerator::visit(*from, *this); \
544 LLVMAsmGenerator::visit(*node.exp, *this); \
545 out_ << " to " Str; \
548 INTEGER_TO_FLOAT(Float, "float")
549 INTEGER_TO_FLOAT(Double, "double")
551 void
552 LLVMAsmGenerator::castIntegerToBool(const ast::CastExp & node)
554 out_ << "icmp ne ";
555 LLVMAsmGenerator::visit(*node.exp->type, *this);
556 out_ << "0, ";
557 LLVMAsmGenerator::visit(*node.exp, *this);
560 #define FLOAT_TO_BOOL(Type, Str) \
561 void \
562 LLVMAsmGenerator::cast##Type##ToBool(const ast::CastExp & /*node*/) \
564 /** @todo throw a warning */ \
565 assert_msg(false, "casting float to bool is a non sense."); \
568 FLOAT_TO_BOOL(Float, "float")
569 FLOAT_TO_BOOL(Double, "double")
571 void
572 LLVMAsmGenerator::initBase()
574 #define REGISTER_METHOD(Class) \
575 registerMethod(ast::Class::nodeTypeId(), visit##Class)
577 REGISTER_METHOD(FunctionDecl);
578 REGISTER_METHOD(Function);
580 REGISTER_METHOD(VarDecl);
582 REGISTER_METHOD(LoadVar);
583 REGISTER_METHOD(StoreVar);
585 REGISTER_METHOD(Exp);
586 REGISTER_METHOD(VoidExp);
587 REGISTER_METHOD(IdExp);
588 REGISTER_METHOD(AtExp);
589 REGISTER_METHOD(NumberExp);
590 REGISTER_METHOD(CallExp);
592 REGISTER_METHOD(AssignExp);
593 REGISTER_METHOD(AddExp);
594 REGISTER_METHOD(SubExp);
595 REGISTER_METHOD(MulExp);
596 REGISTER_METHOD(DivExp);
597 REGISTER_METHOD(ModExp);
599 REGISTER_METHOD(AndExp);
600 REGISTER_METHOD(OrExp);
601 REGISTER_METHOD(XorExp);
603 REGISTER_METHOD(ShlExp);
604 REGISTER_METHOD(AShrExp);
605 REGISTER_METHOD(LShrExp);
607 REGISTER_METHOD(AndAndExp);
608 REGISTER_METHOD(OrOrExp);
610 REGISTER_METHOD(NotExp);
611 REGISTER_METHOD(BangExp);
612 REGISTER_METHOD(NegExp);
614 REGISTER_METHOD(EqExp);
615 REGISTER_METHOD(NeqExp);
616 REGISTER_METHOD(LtExp);
617 REGISTER_METHOD(LtEqExp);
618 REGISTER_METHOD(GtExp);
619 REGISTER_METHOD(GtEqExp);
621 REGISTER_METHOD(Label);
622 REGISTER_METHOD(Goto);
623 REGISTER_METHOD(Return);
624 REGISTER_METHOD(ConditionalBranch);
626 REGISTER_METHOD(Type);
627 REGISTER_METHOD(VoidType);
628 REGISTER_METHOD(BoolType);
629 REGISTER_METHOD(NumberType);
630 REGISTER_METHOD(IntegerType);
631 REGISTER_METHOD(FloatType);
632 REGISTER_METHOD(DoubleType);
633 REGISTER_METHOD(PointerType);
634 REGISTER_METHOD(ReferenceType);
636 REGISTER_METHOD(CastExp);
638 completeWith<ConstBrowser<LLVMAsmGenerator> >();