Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r73617 - trunk/libs/spirit/example/qi/compiler_tutorial/conjure3
From: joel_at_[hidden]
Date: 2011-08-08 21:53:01


Author: djowel
Date: 2011-08-08 21:53:00 EDT (Mon, 08 Aug 2011)
New Revision: 73617
URL: http://svn.boost.org/trac/boost/changeset/73617

Log:
refactoring: moving low-level llvm stuff into separate classes
Text files modified:
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp | 140 ++++++++++++++++++++++------------------
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp | 91 ++++++++++++--------------
   2 files changed, 119 insertions(+), 112 deletions(-)

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp 2011-08-08 21:53:00 EDT (Mon, 08 Aug 2011)
@@ -17,6 +17,12 @@
 
 namespace client { namespace code_gen
 {
+ value::value()
+ : v(0),
+ is_lvalue_(false),
+ builder(0)
+ {}
+
     value::value(
         llvm::Value* v,
         bool is_lvalue_,
@@ -220,6 +226,32 @@
         );
     }
 
+ value llvm_compiler::val(unsigned int x)
+ {
+ return value(
+ llvm::ConstantInt::get(context(), llvm::APInt(int_size, x)),
+ false, &llvm_builder);
+ }
+
+ value llvm_compiler::val(int x)
+ {
+ return value(
+ llvm::ConstantInt::get(context(), llvm::APInt(int_size, x)),
+ false, &llvm_builder);
+ }
+
+ value llvm_compiler::val(bool x)
+ {
+ return value(
+ llvm::ConstantInt::get(context(), llvm::APInt(1, x)),
+ false, &llvm_builder);
+ }
+
+ value llvm_compiler::val(llvm::Value* v)
+ {
+ return value(v, false, &llvm_builder);
+ }
+
     namespace
     {
         // Create an alloca instruction in the entry block of
@@ -239,47 +271,29 @@
         }
     }
 
- lvalue::lvalue(llvm::IRBuilder<>& builder, char const* name)
- : value(
- create_entry_block_alloca(
- builder.GetInsertBlock()->getParent(),
- name,
- context()),
- true, &builder)
- {
- }
-
- value expression_compiler::val(unsigned int x)
+ value llvm_compiler::var(char const* name)
     {
- return value(
- llvm::ConstantInt::get(context(), llvm::APInt(int_size, x)),
- false, &builder);
- }
+ llvm::Function* function = llvm_builder.GetInsertBlock()->getParent();
+ llvm::IRBuilder<> builder(
+ &function->getEntryBlock(),
+ function->getEntryBlock().begin());
 
- value expression_compiler::val(int x)
- {
- return value(
- llvm::ConstantInt::get(context(), llvm::APInt(int_size, x)),
- false, &builder);
- }
+ llvm::AllocaInst* alloca = builder.CreateAlloca(
+ llvm::Type::getIntNTy(context(), int_size), 0, name);
 
- value expression_compiler::val(bool x)
- {
- return value(
- llvm::ConstantInt::get(context(), llvm::APInt(1, x)),
- false, &builder);
+ return value(alloca, true, &llvm_builder);
     }
 
- value expression_compiler::call(
+ value llvm_compiler::call(
         llvm::Function* callee,
         std::vector<llvm::Value*> const& args)
     {
         return value(
- builder.CreateCall(callee, args.begin(), args.end(), "call_tmp"),
- false, &builder);
+ llvm_builder.CreateCall(callee, args.begin(), args.end(), "call_tmp"),
+ false, &llvm_builder);
     }
 
- void compiler::init_fpm()
+ void llvm_compiler::init_fpm()
     {
         // Set up the optimizer pipeline. Start with registering info about how the
         // target lays out data structures.
@@ -342,7 +356,7 @@
             {
                 if (!operand.is_lvalue())
                 {
- error_handler(x.id, "++ needs an lvalue");
+ error_handler(x.id, "++ needs an var");
                     return val();
                 }
 
@@ -354,7 +368,7 @@
             {
                 if (!operand.is_lvalue())
                 {
- error_handler(x.id, "-- needs an lvalue");
+ error_handler(x.id, "-- needs an var");
                     return val();
                 }
 
@@ -536,7 +550,7 @@
             return val();
         }
 
- lvalue lhs = named_values[x.lhs.name];
+ value lhs = named_values[x.lhs.name];
         value rhs = (*this)(x.rhs);
         if (!rhs.is_valid())
             return val();
@@ -585,12 +599,12 @@
                 return false;
         }
 
- lvalue var(builder, name.c_str());
+ value var_ = var(name.c_str());
         if (init)
- var.assign(init);
+ var_.assign(init);
 
         // Remember this binding.
- named_values[name] = var;
+ named_values[name] = var_;
         return true;
     }
 
@@ -627,7 +641,7 @@
         if (!condition.is_valid())
             return false;
 
- llvm::Function* function = builder.GetInsertBlock()->getParent();
+ llvm::Function* function = builder().GetInsertBlock()->getParent();
 
         // Create blocks for the then and else cases. Insert the 'then' block at the
         // end of the function.
@@ -638,79 +652,79 @@
         if (x.else_)
         {
             else_block = llvm::BasicBlock::Create(context(), "if.else");
- builder.CreateCondBr(condition, then_block, else_block);
+ builder().CreateCondBr(condition, then_block, else_block);
         }
         else
         {
             exit_block = llvm::BasicBlock::Create(context(), "if.end");
- builder.CreateCondBr(condition, then_block, exit_block);
+ builder().CreateCondBr(condition, then_block, exit_block);
         }
 
         // Emit then value.
- builder.SetInsertPoint(then_block);
+ builder().SetInsertPoint(then_block);
         if (!(*this)(x.then))
             return false;
         if (then_block->getTerminator() == 0)
         {
             if (exit_block == 0)
                 exit_block = llvm::BasicBlock::Create(context(), "if.end");
- builder.CreateBr(exit_block);
+ builder().CreateBr(exit_block);
         }
         // Codegen of 'then' can change the current block, update then_block
- then_block = builder.GetInsertBlock();
+ then_block = builder().GetInsertBlock();
 
         if (x.else_)
         {
             // Emit else block.
             function->getBasicBlockList().push_back(else_block);
- builder.SetInsertPoint(else_block);
+ builder().SetInsertPoint(else_block);
             if (!(*this)(*x.else_))
                 return false;
             if (else_block->getTerminator() == 0)
             {
                 if (exit_block == 0)
                     exit_block = llvm::BasicBlock::Create(context(), "if.end");
- builder.CreateBr(exit_block);
+ builder().CreateBr(exit_block);
             }
             // Codegen of 'else' can change the current block, update else_block
- else_block = builder.GetInsertBlock();
+ else_block = builder().GetInsertBlock();
         }
 
         if (exit_block != 0)
         {
             // Emit exit block
             function->getBasicBlockList().push_back(exit_block);
- builder.SetInsertPoint(exit_block);
+ builder().SetInsertPoint(exit_block);
         }
         return true;
     }
 
     bool compiler::operator()(ast::while_statement const& x)
     {
- llvm::Function* function = builder.GetInsertBlock()->getParent();
+ llvm::Function* function = builder().GetInsertBlock()->getParent();
 
         llvm::BasicBlock* cond_block = llvm::BasicBlock::Create(context(), "while.cond", function);
         llvm::BasicBlock* body_block = llvm::BasicBlock::Create(context(), "while.body");
         llvm::BasicBlock* exit_block = llvm::BasicBlock::Create(context(), "while.end");
 
- builder.CreateBr(cond_block);
- builder.SetInsertPoint(cond_block);
+ builder().CreateBr(cond_block);
+ builder().SetInsertPoint(cond_block);
         value condition = (*this)(x.condition);
         if (!condition.is_valid())
             return false;
- builder.CreateCondBr(condition, body_block, exit_block);
+ builder().CreateCondBr(condition, body_block, exit_block);
         function->getBasicBlockList().push_back(body_block);
- builder.SetInsertPoint(body_block);
+ builder().SetInsertPoint(body_block);
 
         if (!(*this)(x.body))
             return false;
 
         if (body_block->getTerminator() == 0)
- builder.CreateBr(cond_block); // loop back
+ builder().CreateBr(cond_block); // loop back
 
         // Emit exit block
         function->getBasicBlockList().push_back(exit_block);
- builder.SetInsertPoint(exit_block);
+ builder().SetInsertPoint(exit_block);
 
         return true;
     }
@@ -745,7 +759,7 @@
             return_var.assign(return_val);
         }
 
- builder.CreateBr(return_block);
+ builder().CreateBr(return_block);
         return true;
     }
 
@@ -815,10 +829,10 @@
         BOOST_FOREACH(ast::identifier const& arg, x.args)
         {
             // Create an arg_ for this variable.
- lvalue arg_(builder, arg.name.c_str());
+ value arg_ = var(arg.name.c_str());
 
             // Store the initial value into the arg_.
- arg_.assign(value(iter));
+ arg_.assign(val(iter));
 
             // Add arguments to variable symbol table.
             named_values[arg.name] = arg_;
@@ -828,7 +842,7 @@
         if (!void_return)
         {
             // Create an alloca for the return value
- return_var = lvalue(builder, "return.val");
+ return_var = var("return.val");
         }
     }
 
@@ -847,7 +861,7 @@
             // Create a new basic block to start insertion into.
             llvm::BasicBlock* block =
                 llvm::BasicBlock::Create(context(), "entry", function);
- builder.SetInsertPoint(block);
+ builder().SetInsertPoint(block);
 
             function_allocas(x, function);
             return_block = llvm::BasicBlock::Create(context(), "return");
@@ -865,17 +879,17 @@
             // If the last block is unterminated, connect it to return_block
             if (last_block->getTerminator() == 0)
             {
- builder.SetInsertPoint(last_block);
- builder.CreateBr(return_block);
+ builder().SetInsertPoint(last_block);
+ builder().CreateBr(return_block);
             }
 
             function->getBasicBlockList().push_back(return_block);
- builder.SetInsertPoint(return_block);
+ builder().SetInsertPoint(return_block);
 
             if (void_return)
- builder.CreateRetVoid();
+ builder().CreateRetVoid();
             else
- builder.CreateRet(return_var);
+ builder().CreateRet(return_var);
 
             //~ vm.module()->dump();
 

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp 2011-08-08 21:53:00 EDT (Mon, 08 Aug 2011)
@@ -32,15 +32,15 @@
 {
     unsigned const int_size = 32;
     struct compiler;
- struct expression_compiler;
+ struct llvm_compiler;
 
     ///////////////////////////////////////////////////////////////////////////
     // The Value (light abstraction of an LLVM::Value
     ///////////////////////////////////////////////////////////////////////////
     struct value
     {
+ value();
         value(value const& rhs);
-
         operator llvm::Value*() const;
 
         value& operator=(value const& rhs);
@@ -72,50 +72,43 @@
 
     protected:
 
- friend struct compiler;
- friend struct expression_compiler;
+ friend struct llvm_compiler;
 
         value(
- llvm::Value* v = 0,
- bool is_lvalue_ = false,
- llvm::IRBuilder<>* builder = 0);
+ llvm::Value* v,
+ bool is_lvalue_,
+ llvm::IRBuilder<>* builder);
 
         llvm::LLVMContext& context() const
         { return llvm::getGlobalContext(); }
 
+ private:
+
         llvm::Value* v;
         bool is_lvalue_;
         llvm::IRBuilder<>* builder;
     };
 
- struct lvalue : value
- {
- lvalue()
- : value(0, true, 0)
- {}
-
- lvalue(
- llvm::AllocaInst* var,
- llvm::IRBuilder<>& builder)
- : value(var, true, &builder)
- {}
-
- lvalue(llvm::IRBuilder<>& builder, char const* name);
- };
-
     ///////////////////////////////////////////////////////////////////////////
- // The Expression Compiler
+ // The LLVM Compiler. Lower level compiler (does not deal with ASTs)
     ///////////////////////////////////////////////////////////////////////////
- struct expression_compiler
+ struct llvm_compiler
     {
- expression_compiler()
- : builder(context())
- {}
+ llvm_compiler(vmachine& vm)
+ : llvm_builder(context())
+ , vm(vm)
+ , fpm(vm.module())
+ {
+ init_fpm();
+ }
 
         value val() { return value(); }
         value val(unsigned int x);
         value val(int x);
         value val(bool x);
+ value val(llvm::Value* v);
+
+ value var(char const* name);
 
         value call(
             llvm::Function* callee,
@@ -126,20 +119,28 @@
         llvm::LLVMContext& context() const
         { return llvm::getGlobalContext(); }
 
- llvm::IRBuilder<> builder;
+ llvm::IRBuilder<>& builder()
+ { return llvm_builder; }
+
+ vmachine& vm; // $$$ protected for now $$$
+ llvm::FunctionPassManager fpm; // $$$ protected for now $$$
+
+ private:
+
+ void init_fpm();
+ llvm::IRBuilder<> llvm_builder;
     };
 
     ///////////////////////////////////////////////////////////////////////////
     // The Compiler
     ///////////////////////////////////////////////////////////////////////////
- struct compiler : expression_compiler
+ struct compiler : llvm_compiler
     {
         typedef value result_type;
 
         template <typename ErrorHandler>
         compiler(vmachine& vm, ErrorHandler& error_handler_)
- : vm(vm),
- fpm(vm.module())
+ : llvm_compiler(vm)
         {
             using namespace boost::phoenix::arg_names;
             namespace phx = boost::phoenix;
@@ -147,8 +148,6 @@
 
             error_handler = function<ErrorHandler>(error_handler_)(
                 "Error! ", _2, phx::cref(error_handler_.iters)[_1]);
-
- init_fpm();
         }
 
         value operator()(ast::nil) { BOOST_ASSERT(0); return val(); }
@@ -172,22 +171,6 @@
 
     private:
 
- boost::function<
- void(int tag, std::string const& what)>
- error_handler;
-
- bool void_return;
- std::string current_function_name;
- std::map<std::string, lvalue> named_values;
- llvm::BasicBlock* return_block;
- lvalue return_var;
-
- vmachine& vm;
- llvm::FunctionPassManager fpm;
-
- llvm::Module* init_llvm();
- void init_fpm();
-
         value compile_binary_expression(
             value lhs, value rhs, token_ids::type op);
 
@@ -202,6 +185,16 @@
 
         llvm::Function* function_decl(ast::function const& x);
         void function_allocas(ast::function const& x, llvm::Function* function);
+
+ boost::function<
+ void(int tag, std::string const& what)>
+ error_handler;
+
+ bool void_return;
+ std::string current_function_name;
+ std::map<std::string, value> named_values;
+ llvm::BasicBlock* return_block;
+ value return_var;
     };
 }}
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk