]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / spirit / example / qi / compiler_tutorial / conjure3 / compiler.cpp
1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3
4 Distributed under the Boost Software License, Version 1.0. (See accompanying
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 =============================================================================*/
7 #include "config.hpp"
8 #include "compiler.hpp"
9 #include "annotation.hpp"
10 #include "vm.hpp"
11
12 #include <boost/foreach.hpp>
13 #include <boost/variant/apply_visitor.hpp>
14 #include <boost/range/adaptor/transformed.hpp>
15 #include <boost/assert.hpp>
16 #include <boost/lexical_cast.hpp>
17 #include <set>
18
19 namespace client { namespace code_gen
20 {
21 value::value()
22 : v(0),
23 is_lvalue_(false),
24 builder(0)
25 {}
26
27 value::value(
28 llvm::Value* v,
29 bool is_lvalue_,
30 llvm::IRBuilder<>* builder)
31 : v(v),
32 is_lvalue_(is_lvalue_),
33 builder(builder)
34 {}
35
36 value::value(value const& rhs)
37 : v(rhs.v),
38 is_lvalue_(rhs.is_lvalue_),
39 builder(rhs.builder)
40 {}
41
42 bool value::is_lvalue() const
43 {
44 return is_lvalue_;
45 }
46
47 bool value::is_valid() const
48 {
49 return v != 0;
50 }
51
52 value::operator bool() const
53 {
54 return v != 0;
55 }
56
57 void value::name(char const* id)
58 {
59 v->setName(id);
60 }
61
62 void value::name(std::string const& id)
63 {
64 v->setName(id);
65 }
66
67 value::operator llvm::Value*() const
68 {
69 if (is_lvalue_)
70 {
71 BOOST_ASSERT(builder != 0);
72 return builder->CreateLoad(v, v->getName());
73 }
74 return v;
75 }
76
77 value& value::operator=(value const& rhs)
78 {
79 v = rhs.v;
80 is_lvalue_ = rhs.is_lvalue_;
81 builder = rhs.builder;
82 return *this;
83 }
84
85 value& value::assign(value const& rhs)
86 {
87 BOOST_ASSERT(is_lvalue());
88 BOOST_ASSERT(builder != 0);
89 builder->CreateStore(rhs, v);
90 return *this;
91 }
92
93 value operator-(value a)
94 {
95 BOOST_ASSERT(a.builder != 0);
96 return value(
97 a.builder->CreateNeg(a, "neg_tmp"),
98 false, a.builder
99 );
100 }
101
102 value operator!(value a)
103 {
104 BOOST_ASSERT(a.builder != 0);
105 return value(
106 a.builder->CreateNot(a, "not_tmp"),
107 false, a.builder
108 );
109 }
110
111 value operator+(value a, value b)
112 {
113 BOOST_ASSERT(a.builder != 0);
114 return value(
115 a.builder->CreateAdd(a, b, "add_tmp"),
116 false, a.builder
117 );
118 }
119
120 value operator-(value a, value b)
121 {
122 BOOST_ASSERT(a.builder != 0);
123 return value(
124 a.builder->CreateSub(a, b, "sub_tmp"),
125 false, a.builder
126 );
127 }
128
129 value operator*(value a, value b)
130 {
131 BOOST_ASSERT(a.builder != 0);
132 return value(
133 a.builder->CreateMul(a, b, "mul_tmp"),
134 false, a.builder
135 );
136 }
137
138 value operator/(value a, value b)
139 {
140 BOOST_ASSERT(a.builder != 0);
141 return value(
142 a.builder->CreateSDiv(a, b, "div_tmp"),
143 false, a.builder
144 );
145 }
146
147 value operator%(value a, value b)
148 {
149 BOOST_ASSERT(a.builder != 0);
150 return value(
151 a.builder->CreateSRem(a, b, "mod_tmp"),
152 false, a.builder
153 );
154 }
155
156 value operator&(value a, value b)
157 {
158 BOOST_ASSERT(a.builder != 0);
159 return value(
160 a.builder->CreateAnd(a, b, "and_tmp"),
161 false, a.builder
162 );
163 }
164
165 value operator|(value a, value b)
166 {
167 BOOST_ASSERT(a.builder != 0);
168 return value(
169 a.builder->CreateOr(a, b, "or_tmp"),
170 false, a.builder
171 );
172 }
173
174 value operator^(value a, value b)
175 {
176 BOOST_ASSERT(a.builder != 0);
177 return value(
178 a.builder->CreateXor(a, b, "xor_tmp"),
179 false, a.builder
180 );
181 }
182
183 value operator<<(value a, value b)
184 {
185 BOOST_ASSERT(a.builder != 0);
186 return value(
187 a.builder->CreateShl(a, b, "shl_tmp"),
188 false, a.builder
189 );
190 }
191
192 value operator>>(value a, value b)
193 {
194 BOOST_ASSERT(a.builder != 0);
195 return value(
196 a.builder->CreateLShr(a, b, "shr_tmp"),
197 false, a.builder
198 );
199 }
200
201 value operator==(value a, value b)
202 {
203 BOOST_ASSERT(a.builder != 0);
204 return value(
205 a.builder->CreateICmpEQ(a, b, "eq_tmp"),
206 false, a.builder
207 );
208 }
209
210 value operator!=(value a, value b)
211 {
212 BOOST_ASSERT(a.builder != 0);
213 return value(
214 a.builder->CreateICmpNE(a, b, "ne_tmp"),
215 false, a.builder
216 );
217 }
218
219 value operator<(value a, value b)
220 {
221 BOOST_ASSERT(a.builder != 0);
222 return value(
223 a.builder->CreateICmpSLT(a, b, "slt_tmp"),
224 false, a.builder
225 );
226 }
227
228 value operator<=(value a, value b)
229 {
230 BOOST_ASSERT(a.builder != 0);
231 return value(
232 a.builder->CreateICmpSLE(a, b, "sle_tmp"),
233 false, a.builder
234 );
235 }
236
237 value operator>(value a, value b)
238 {
239 BOOST_ASSERT(a.builder != 0);
240 return value(
241 a.builder->CreateICmpSGT(a, b, "sgt_tmp"),
242 false, a.builder
243 );
244 }
245
246 value operator>=(value a, value b)
247 {
248 BOOST_ASSERT(a.builder != 0);
249 return value(
250 a.builder->CreateICmpSGE(a, b, "sge_tmp"),
251 false, a.builder
252 );
253 }
254
255 struct function::to_value
256 {
257 typedef value result_type;
258 llvm_compiler* c;
259
260 to_value(llvm_compiler* c = 0) : c(c) {}
261
262 value operator()(llvm::Value& v) const
263 {
264 return c->val(&v);
265 }
266 };
267
268 bool basic_block::has_terminator() const
269 {
270 return b->getTerminator() != 0;
271 }
272
273 bool basic_block::is_valid() const
274 {
275 return b != 0;
276 }
277
278 function::operator llvm::Function*() const
279 {
280 return f;
281 }
282
283 std::size_t function::arg_size() const
284 {
285 return f->arg_size();
286 }
287
288 void function::add(basic_block const& b)
289 {
290 f->getBasicBlockList().push_back(b);
291 }
292
293 void function::erase_from_parent()
294 {
295 f->eraseFromParent();
296 }
297
298 basic_block function::last_block()
299 {
300 return &f->getBasicBlockList().back();
301 }
302
303 bool function::empty() const
304 {
305 return f->empty();
306 }
307
308 std::string function::name() const
309 {
310 return f->getName();
311 }
312
313 function::arg_range function::args() const
314 {
315 BOOST_ASSERT(c != 0);
316 arg_val_iterator first(f->arg_begin(), to_value());
317 arg_val_iterator last(f->arg_end(), to_value());
318 return arg_range(first, last);
319 }
320
321 bool function::is_valid() const
322 {
323 return f != 0;
324 }
325
326 void function::verify() const
327 {
328 llvm::verifyFunction(*f);
329 }
330
331 value llvm_compiler::val(unsigned int x)
332 {
333 return value(
334 llvm::ConstantInt::get(context(), llvm::APInt(int_size, x)),
335 false, &llvm_builder);
336 }
337
338 value llvm_compiler::val(int x)
339 {
340 return value(
341 llvm::ConstantInt::get(context(), llvm::APInt(int_size, x)),
342 false, &llvm_builder);
343 }
344
345 value llvm_compiler::val(bool x)
346 {
347 return value(
348 llvm::ConstantInt::get(context(), llvm::APInt(1, x)),
349 false, &llvm_builder);
350 }
351
352 value llvm_compiler::val(llvm::Value* v)
353 {
354 return value(v, false, &llvm_builder);
355 }
356
357 namespace
358 {
359 // Create an alloca instruction in the entry block of
360 // the function. This is used for mutable variables etc.
361 llvm::AllocaInst*
362 make_entry_block_alloca(
363 llvm::Function* f,
364 char const* name,
365 llvm::LLVMContext& context)
366 {
367 llvm::IRBuilder<> builder(
368 &f->getEntryBlock(),
369 f->getEntryBlock().begin());
370
371 return builder.CreateAlloca(
372 llvm::Type::getIntNTy(context, int_size), 0, name);
373 }
374 }
375
376 value llvm_compiler::var(char const* name)
377 {
378 llvm::Function* f = llvm_builder.GetInsertBlock()->getParent();
379 llvm::IRBuilder<> builder(
380 &f->getEntryBlock(),
381 f->getEntryBlock().begin());
382
383 llvm::AllocaInst* alloca = builder.CreateAlloca(
384 llvm::Type::getIntNTy(context(), int_size), 0, name);
385
386 return value(alloca, true, &llvm_builder);
387 }
388
389 struct value::to_llvm_value
390 {
391 typedef llvm::Value* result_type;
392 llvm::Value* operator()(value const& x) const
393 {
394 return x;
395 }
396 };
397
398 template <typename C>
399 llvm::Value* llvm_compiler::call_impl(
400 function callee,
401 C const& args_)
402 {
403 // Sigh. LLVM requires CreateCall arguments to be random access.
404 // It would have been better if it can accept forward iterators.
405 // I guess it needs the arguments to be in contiguous memory.
406 // So, we have to put the args into a temporary std::vector.
407 std::vector<llvm::Value*> args(
408 args_.begin(), args_.end());
409
410 // Check the args for null values. We can't have null values.
411 // Return 0 if we find one to flag error.
412 BOOST_FOREACH(llvm::Value* arg, args)
413 {
414 if (arg == 0)
415 return 0;
416 }
417
418 return llvm_builder.CreateCall(
419 callee, args.begin(), args.end(), "call_tmp");
420 }
421
422 template <typename Container>
423 value llvm_compiler::call(
424 function callee,
425 Container const& args)
426 {
427 llvm::Value* call = call_impl(
428 callee,
429 args | boost::adaptors::transformed(value::to_llvm_value()));
430
431 if (call == 0)
432 return val();
433 return value(call, false, &llvm_builder);
434 }
435
436 function llvm_compiler::get_function(char const* name)
437 {
438 return function(vm.module()->getFunction(name), this);
439 }
440
441 function llvm_compiler::get_current_function()
442 {
443 // get the current function
444 return function(llvm_builder.GetInsertBlock()->getParent(), this);
445 }
446
447 function llvm_compiler::declare_function(
448 bool void_return
449 , std::string const& name
450 , std::size_t nargs)
451 {
452 llvm::Type const* int_type =
453 llvm::Type::getIntNTy(context(), int_size);
454 llvm::Type const* void_type = llvm::Type::getVoidTy(context());
455
456 std::vector<llvm::Type const*> ints(nargs, int_type);
457 llvm::Type const* return_type = void_return ? void_type : int_type;
458
459 llvm::FunctionType* function_type =
460 llvm::FunctionType::get(void_return ? void_type : int_type, ints, false);
461
462 return function(llvm::Function::Create(
463 function_type, llvm::Function::ExternalLinkage,
464 name, vm.module()), this);
465 }
466
467 basic_block llvm_compiler::make_basic_block(
468 char const* name
469 , function parent
470 , basic_block before)
471 {
472 return llvm::BasicBlock::Create(context(), name, parent, before);
473 }
474
475 value llvm_compiler::var(std::string const& name)
476 {
477 return var(name.c_str());
478 }
479
480 function llvm_compiler::get_function(std::string const& name)
481 {
482 return get_function(name.c_str());
483 }
484
485 basic_block llvm_compiler::get_insert_block()
486 {
487 return llvm_builder.GetInsertBlock();
488 }
489
490 void llvm_compiler::set_insert_point(basic_block b)
491 {
492 llvm_builder.SetInsertPoint(b);
493 }
494
495 void llvm_compiler::conditional_branch(
496 value cond, basic_block true_br, basic_block false_br)
497 {
498 llvm_builder.CreateCondBr(cond, true_br, false_br);
499 }
500
501 void llvm_compiler::branch(basic_block b)
502 {
503 llvm_builder.CreateBr(b);
504 }
505
506 void llvm_compiler::return_()
507 {
508 llvm_builder.CreateRetVoid();
509 }
510
511 void llvm_compiler::return_(value v)
512 {
513 llvm_builder.CreateRet(v);
514 }
515
516 void llvm_compiler::optimize_function(function f)
517 {
518 // Optimize the function.
519 fpm.run(*f);
520 }
521
522 void llvm_compiler::init_fpm()
523 {
524 // Set up the optimizer pipeline. Start with registering info about how the
525 // target lays out data structures.
526 fpm.add(new llvm::TargetData(*vm.execution_engine()->getTargetData()));
527 // Provide basic AliasAnalysis support for GVN.
528 fpm.add(llvm::createBasicAliasAnalysisPass());
529 // Promote allocas to registers.
530 fpm.add(llvm::createPromoteMemoryToRegisterPass());
531 // Do simple "peephole" optimizations and bit-twiddling optzns.
532 fpm.add(llvm::createInstructionCombiningPass());
533 // Reassociate expressions.
534 fpm.add(llvm::createReassociatePass());
535 // Eliminate Common SubExpressions.
536 fpm.add(llvm::createGVNPass());
537 // Simplify the control flow graph (deleting unreachable blocks, etc).
538 fpm.add(llvm::createCFGSimplificationPass());
539
540 fpm.doInitialization();
541 }
542
543 value compiler::operator()(unsigned int x)
544 {
545 return val(x);
546 }
547
548 value compiler::operator()(bool x)
549 {
550 return val(x);
551 }
552
553 value compiler::operator()(ast::primary_expr const& x)
554 {
555 return boost::apply_visitor(*this, x.get());
556 }
557
558 value compiler::operator()(ast::identifier const& x)
559 {
560 // Look this variable up in the function.
561 if (locals.find(x.name) == locals.end())
562 {
563 error_handler(x.id, "Undeclared variable: " + x.name);
564 return val();
565 }
566 return locals[x.name];
567 }
568
569 value compiler::operator()(ast::unary_expr const& x)
570 {
571 value operand = boost::apply_visitor(*this, x.operand_);
572 if (!operand.is_valid())
573 return val();
574
575 switch (x.operator_)
576 {
577 case token_ids::compl_: return operand ^ val(-1);
578 case token_ids::minus: return -operand;
579 case token_ids::not_: return !operand;
580 case token_ids::plus: return operand;
581 case token_ids::plus_plus:
582 {
583 if (!operand.is_lvalue())
584 {
585 error_handler(x.id, "++ needs an var");
586 return val();
587 }
588
589 value r = operand + val(1);
590 operand.assign(r);
591 return operand;
592 }
593 case token_ids::minus_minus:
594 {
595 if (!operand.is_lvalue())
596 {
597 error_handler(x.id, "-- needs an var");
598 return val();
599 }
600
601 value r = operand - val(1);
602 operand.assign(r);
603 return operand;
604 }
605 default:
606 BOOST_ASSERT(0);
607 return val();
608 }
609 }
610
611 namespace
612 {
613 struct compile_args
614 {
615 compiler& c;
616 compile_args(compiler& c) : c(c) {}
617
618 typedef value result_type;
619 value operator()(ast::expression const& expr) const
620 {
621 return c(expr);
622 }
623 };
624 }
625
626 value compiler::operator()(ast::function_call const& x)
627 {
628 function callee = get_function(x.function_name.name);
629 if (!callee.is_valid())
630 {
631 error_handler(x.function_name.id,
632 "Function not found: " + x.function_name.name);
633 return val();
634 }
635
636 if (callee.arg_size() != x.args.size())
637 {
638 error_handler(x.function_name.id,
639 "Wrong number of arguments: " + x.function_name.name);
640 return val();
641 }
642
643 return call(callee,
644 x.args | boost::adaptors::transformed(compile_args(*this)));
645 }
646
647 namespace
648 {
649 int precedence[] = {
650 // precedence 1
651 1, // op_comma
652
653 // precedence 2
654 2, // op_assign
655 2, // op_plus_assign
656 2, // op_minus_assign
657 2, // op_times_assign
658 2, // op_divide_assign
659 2, // op_mod_assign
660 2, // op_bit_and_assign
661 2, // op_bit_xor_assign
662 2, // op_bitor_assign
663 2, // op_shift_left_assign
664 2, // op_shift_right_assign
665
666 // precedence 3
667 3, // op_logical_or
668
669 // precedence 4
670 4, // op_logical_and
671
672 // precedence 5
673 5, // op_bit_or
674
675 // precedence 6
676 6, // op_bit_xor
677
678 // precedence 7
679 7, // op_bit_and
680
681 // precedence 8
682 8, // op_equal
683 8, // op_not_equal
684
685 // precedence 9
686 9, // op_less
687 9, // op_less_equal
688 9, // op_greater
689 9, // op_greater_equal
690
691 // precedence 10
692 10, // op_shift_left
693 10, // op_shift_right
694
695 // precedence 11
696 11, // op_plus
697 11, // op_minus
698
699 // precedence 12
700 12, // op_times
701 12, // op_divide
702 12 // op_mod
703 };
704 }
705
706 inline int precedence_of(token_ids::type op)
707 {
708 return precedence[op & 0xFF];
709 }
710
711 value compiler::compile_binary_expression(
712 value lhs, value rhs, token_ids::type op)
713 {
714 switch (op)
715 {
716 case token_ids::plus: return lhs + rhs;
717 case token_ids::minus: return lhs - rhs;
718 case token_ids::times: return lhs * rhs;
719 case token_ids::divide: return lhs / rhs;
720 case token_ids::mod: return lhs % rhs;
721
722 case token_ids::logical_or:
723 case token_ids::bit_or: return lhs | rhs;
724
725 case token_ids::logical_and:
726 case token_ids::bit_and: return lhs & rhs;
727
728 case token_ids::bit_xor: return lhs ^ rhs;
729 case token_ids::shift_left: return lhs << rhs;
730 case token_ids::shift_right: return lhs >> rhs;
731
732 case token_ids::equal: return lhs == rhs;
733 case token_ids::not_equal: return lhs != rhs;
734 case token_ids::less: return lhs < rhs;
735 case token_ids::less_equal: return lhs <= rhs;
736 case token_ids::greater: return lhs > rhs;
737 case token_ids::greater_equal: return lhs >= rhs;
738
739 default: BOOST_ASSERT(0); return val();
740 }
741 }
742
743 // The Shunting-yard algorithm
744 value compiler::compile_expression(
745 int min_precedence,
746 value lhs,
747 std::list<ast::operation>::const_iterator& rest_begin,
748 std::list<ast::operation>::const_iterator rest_end)
749 {
750 while ((rest_begin != rest_end) &&
751 (precedence_of(rest_begin->operator_) >= min_precedence))
752 {
753 token_ids::type op = rest_begin->operator_;
754 value rhs = boost::apply_visitor(*this, rest_begin->operand_);
755 if (!rhs.is_valid())
756 return val();
757 ++rest_begin;
758
759 while ((rest_begin != rest_end) &&
760 (precedence_of(rest_begin->operator_) > precedence_of(op)))
761 {
762 token_ids::type next_op = rest_begin->operator_;
763 rhs = compile_expression(
764 precedence_of(next_op), rhs, rest_begin, rest_end);
765 }
766
767 lhs = compile_binary_expression(lhs, rhs, op);
768 }
769 return lhs;
770 }
771
772 value compiler::operator()(ast::expression const& x)
773 {
774 value lhs = boost::apply_visitor(*this, x.first);
775 if (!lhs.is_valid())
776 return val();
777 std::list<ast::operation>::const_iterator rest_begin = x.rest.begin();
778 return compile_expression(0, lhs, rest_begin, x.rest.end());
779 }
780
781 value compiler::operator()(ast::assignment const& x)
782 {
783 if (locals.find(x.lhs.name) == locals.end())
784 {
785 error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
786 return val();
787 }
788
789 value lhs = locals[x.lhs.name];
790 value rhs = (*this)(x.rhs);
791 if (!rhs.is_valid())
792 return val();
793
794 if (x.operator_ == token_ids::assign)
795 {
796 lhs.assign(rhs);
797 return lhs;
798 }
799
800 value result;
801 switch (x.operator_)
802 {
803 case token_ids::plus_assign: result = lhs + rhs; break;
804 case token_ids::minus_assign: result = lhs - rhs; break;
805 case token_ids::times_assign: result = lhs * rhs; break;
806 case token_ids::divide_assign: result = lhs / rhs; break;
807 case token_ids::mod_assign: result = lhs % rhs; break;
808 case token_ids::bit_and_assign: result = lhs & rhs; break;
809 case token_ids::bit_xor_assign: result = lhs ^ rhs; break;
810 case token_ids::bit_or_assign: result = lhs | rhs; break;
811 case token_ids::shift_left_assign: result = lhs << rhs; break;
812 case token_ids::shift_right_assign: result = lhs >> rhs; break;
813 default: BOOST_ASSERT(0); return val();
814 }
815
816 lhs.assign(result);
817 return lhs;
818 }
819
820 bool compiler::operator()(ast::variable_declaration const& x)
821 {
822 if (locals.find(x.lhs.name) != locals.end())
823 {
824 error_handler(x.lhs.id, "Duplicate variable: " + x.lhs.name);
825 return false;
826 }
827
828 value init;
829 std::string const& name = x.lhs.name;
830
831 if (x.rhs) // if there's an RHS initializer
832 {
833 init = (*this)(*x.rhs);
834 if (!init.is_valid()) // don't add the variable if the RHS fails
835 return false;
836 }
837
838 value var_ = var(name.c_str());
839 if (init.is_valid())
840 var_.assign(init);
841
842 // Remember this binding.
843 locals[name] = var_;
844 return true;
845 }
846
847 struct compiler::statement_compiler : compiler
848 {
849 typedef bool result_type;
850 };
851
852 compiler::statement_compiler& compiler::as_statement()
853 {
854 return *static_cast<statement_compiler*>(this);
855 }
856
857 bool compiler::operator()(ast::statement const& x)
858 {
859 if (boost::get<ast::nil>(&x) != 0) // empty statement
860 return true;
861 return boost::apply_visitor(as_statement(), x);
862 }
863
864 bool compiler::operator()(ast::statement_list const& x)
865 {
866 BOOST_FOREACH(ast::statement const& s, x)
867 {
868 if (!(*this)(s))
869 return false;
870 }
871 return true;
872 }
873
874 bool compiler::operator()(ast::if_statement const& x)
875 {
876 value condition = (*this)(x.condition);
877 if (!condition.is_valid())
878 return false;
879
880 function f = get_current_function();
881
882 // Create blocks for the then and else cases. Insert the 'then' block at the
883 // end of the function.
884 basic_block then_block = make_basic_block("if.then", f);
885 basic_block else_block;
886 basic_block exit_block;
887
888 if (x.else_)
889 {
890 else_block = make_basic_block("if.else");
891 conditional_branch(condition, then_block, else_block);
892 }
893 else
894 {
895 exit_block = make_basic_block("if.end");
896 conditional_branch(condition, then_block, exit_block);
897 }
898
899 // Emit then value.
900 set_insert_point(then_block);
901 if (!(*this)(x.then))
902 return false;
903 if (!then_block.has_terminator())
904 {
905 if (!exit_block.is_valid())
906 exit_block = make_basic_block("if.end");
907 branch(exit_block);
908 }
909 // Codegen of 'then' can change the current block, update then_block
910 then_block = get_insert_block();
911
912 if (x.else_)
913 {
914 // Emit else block.
915 f.add(else_block);
916 set_insert_point(else_block);
917 if (!(*this)(*x.else_))
918 return false;
919 if (!else_block.has_terminator())
920 {
921 if (!exit_block.is_valid())
922 exit_block = make_basic_block("if.end");
923 branch(exit_block);
924 }
925 // Codegen of 'else' can change the current block, update else_block
926 else_block = get_insert_block();
927 }
928
929 if (exit_block.is_valid())
930 {
931 // Emit exit block
932 f.add(exit_block);
933 set_insert_point(exit_block);
934 }
935 return true;
936 }
937
938 bool compiler::operator()(ast::while_statement const& x)
939 {
940 function f = get_current_function();
941
942 basic_block cond_block = make_basic_block("while.cond", f);
943 basic_block body_block = make_basic_block("while.body");
944 basic_block exit_block = make_basic_block("while.end");
945
946 branch(cond_block);
947 set_insert_point(cond_block);
948 value condition = (*this)(x.condition);
949 if (!condition.is_valid())
950 return false;
951 conditional_branch(condition, body_block, exit_block);
952 f.add(body_block);
953 set_insert_point(body_block);
954
955 if (!(*this)(x.body))
956 return false;
957
958 if (!body_block.has_terminator())
959 branch(cond_block); // loop back
960
961 // Emit exit block
962 f.add(exit_block);
963 set_insert_point(exit_block);
964
965 return true;
966 }
967
968 bool compiler::operator()(ast::return_statement const& x)
969 {
970 if (void_return)
971 {
972 if (x.expr)
973 {
974 error_handler(
975 x.id, "'void' function returning a value: ");
976 return false;
977 }
978 }
979 else
980 {
981 if (!x.expr)
982 {
983 error_handler(
984 x.id, current_function_name
985 + " function must return a value: ");
986 return false;
987 }
988 }
989
990 if (x.expr)
991 {
992 value return_val = (*this)(*x.expr);
993 if (!return_val.is_valid())
994 return false;
995 return_var.assign(return_val);
996 }
997
998 branch(return_block);
999 return true;
1000 }
1001
1002 function compiler::function_decl(ast::function const& x)
1003 {
1004 void_return = x.return_type == "void";
1005 current_function_name = x.function_name.name;
1006
1007 function f =
1008 declare_function(
1009 void_return
1010 , current_function_name
1011 , x.args.size());
1012
1013 // If function conflicted, the function already exixts. If it has a
1014 // body, don't allow redefinition or reextern.
1015 if (f.name() != current_function_name)
1016 {
1017 // Delete the one we just made and get the existing one.
1018 f.erase_from_parent();
1019 f = get_function(current_function_name);
1020
1021 // If function already has a body, reject this.
1022 if (!f.empty())
1023 {
1024 error_handler(
1025 x.function_name.id,
1026 "Duplicate function: " + x.function_name.name);
1027 return function();
1028 }
1029
1030 // If function took a different number of args, reject.
1031 if (f.arg_size() != x.args.size())
1032 {
1033 error_handler(
1034 x.function_name.id,
1035 "Redefinition of function with different # args: "
1036 + x.function_name.name);
1037 return function();
1038 }
1039
1040 // Set names for all arguments.
1041 function::arg_range rng = f.args();
1042 function::arg_range::const_iterator iter = rng.begin();
1043 BOOST_FOREACH(ast::identifier const& arg, x.args)
1044 {
1045 iter->name(arg.name);
1046 ++iter;
1047 }
1048 }
1049 return f;
1050 }
1051
1052 void compiler::function_allocas(ast::function const& x, function f)
1053 {
1054 // Create variables for each argument and register the
1055 // argument in the symbol table so that references to it will succeed.
1056 function::arg_range rng = f.args();
1057 function::arg_range::const_iterator iter = rng.begin();
1058 BOOST_FOREACH(ast::identifier const& arg, x.args)
1059 {
1060 // Create an arg_ for this variable.
1061 value arg_ = var(arg.name);
1062
1063 // Store the initial value into the arg_.
1064 arg_.assign(*iter);
1065
1066 // Add arguments to variable symbol table.
1067 locals[arg.name] = arg_;
1068 ++iter;
1069 }
1070
1071 if (!void_return)
1072 {
1073 // Create an alloca for the return value
1074 return_var = var("return.val");
1075 }
1076 }
1077
1078 bool compiler::operator()(ast::function const& x)
1079 {
1080 ///////////////////////////////////////////////////////////////////////
1081 // the signature:
1082 function f = function_decl(x);
1083 if (!f.is_valid())
1084 return false;
1085
1086 ///////////////////////////////////////////////////////////////////////
1087 // the body:
1088 if (x.body) // compile the body if this is not a prototype
1089 {
1090 // Create a new basic block to start insertion into.
1091 basic_block block = make_basic_block("entry", f);
1092 set_insert_point(block);
1093
1094 function_allocas(x, f);
1095 return_block = make_basic_block("return");
1096
1097 if (!(*this)(*x.body))
1098 {
1099 // Error reading body, remove function.
1100 f.erase_from_parent();
1101 return false;
1102 }
1103
1104 basic_block last_block = f.last_block();
1105
1106 // If the last block is unterminated, connect it to return_block
1107 if (!last_block.has_terminator())
1108 {
1109 set_insert_point(last_block);
1110 branch(return_block);
1111 }
1112
1113 f.add(return_block);
1114 set_insert_point(return_block);
1115
1116 if (void_return)
1117 return_();
1118 else
1119 return_(return_var);
1120
1121 // Validate the generated code, checking for consistency.
1122 f.verify();
1123
1124 // Optimize the function.
1125 optimize_function(f);
1126 }
1127
1128 return true;
1129 }
1130
1131 bool compiler::operator()(ast::function_list const& x)
1132 {
1133 BOOST_FOREACH(ast::function const& f, x)
1134 {
1135 locals.clear(); // clear the variables
1136 if (!(*this)(f))
1137 return false;
1138 }
1139 return true;
1140 }
1141 }}
1142