Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r73576 - trunk/libs/spirit/example/qi/compiler_tutorial/conjure3
From: joel_at_[hidden]
Date: 2011-08-06 12:31:44


Author: djowel
Date: 2011-08-06 12:31:43 EDT (Sat, 06 Aug 2011)
New Revision: 73576
URL: http://svn.boost.org/trac/boost/changeset/73576

Log:
Better llvm abstraction
Text files modified:
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp | 232 ++++++++++++++++++++++++---------------
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp | 39 ++++--
   2 files changed, 170 insertions(+), 101 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-06 12:31:43 EDT (Sat, 06 Aug 2011)
@@ -32,24 +32,6 @@
         builder(rhs.builder)
     {}
 
- value::value(unsigned int x)
- : v(llvm::ConstantInt::get(context(), llvm::APInt(int_size, x))),
- is_lvalue_(false),
- builder(0)
- {}
-
- value::value(int x)
- : v(llvm::ConstantInt::get(context(), llvm::APInt(int_size, x))),
- is_lvalue_(false),
- builder(0)
- {}
-
- value::value(bool x)
- : v(llvm::ConstantInt::get(context(), llvm::APInt(1, x))),
- is_lvalue_(false),
- builder(0)
- {}
-
     value::operator llvm::Value*() const
     {
         if (is_lvalue_)
@@ -76,6 +58,51 @@
         return *this;
     }
 
+ value operator-(value a)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateNeg(a, "neg_tmp"),
+ false, a.builder
+ );
+ }
+
+ value not_(value a)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateNot(a, "not_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator+(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateAdd(a, b, "add_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator-(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateSub(a, b, "sub_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator^(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateXor(a, b, "xor_tmp"),
+ false, a.builder
+ );
+ }
+
     namespace
     {
         // Create an alloca instruction in the entry block of
@@ -105,6 +132,36 @@
     {
     }
 
+ value expression_compiler::val(unsigned int x)
+ {
+ return value(
+ llvm::ConstantInt::get(context(), llvm::APInt(int_size, x)),
+ false, &builder);
+ }
+
+ value expression_compiler::val(int x)
+ {
+ return value(
+ llvm::ConstantInt::get(context(), llvm::APInt(int_size, x)),
+ false, &builder);
+ }
+
+ value expression_compiler::val(bool x)
+ {
+ return value(
+ llvm::ConstantInt::get(context(), llvm::APInt(1, x)),
+ false, &builder);
+ }
+
+ value expression_compiler::call(
+ llvm::Function* callee,
+ std::vector<llvm::Value*> const& args)
+ {
+ return value(
+ builder.CreateCall(callee, args.begin(), args.end(), "call_tmp"),
+ false, &builder);
+ }
+
     void compiler::init_fpm()
     {
         // Set up the optimizer pipeline. Start with registering info about how the
@@ -128,12 +185,12 @@
 
     value compiler::operator()(unsigned int x)
     {
- return value(x);
+ return val(x);
     }
 
     value compiler::operator()(bool x)
     {
- return value(x);
+ return val(x);
     }
 
     value compiler::operator()(ast::literal const& x)
@@ -147,7 +204,7 @@
         if (named_values.find(x.name) == named_values.end())
         {
             error_handler(x.id, "Undeclared variable: " + x.name);
- return value();
+ return val();
         }
         return named_values[x.name];
     }
@@ -156,28 +213,23 @@
     {
         value operand = boost::apply_visitor(*this, x.operand_);
         if (!operand)
- return value();
+ return val();
 
         switch (x.operator_)
         {
- case token_ids::compl_:
- return builder.CreateXor(
- operand, value(-1), "compl_tmp");
- case token_ids::minus:
- return builder.CreateNeg(operand, "neg_tmp");
- case token_ids::not_:
- return builder.CreateNot(operand, "not_tmp");
- case token_ids::plus:
- return operand;
+ case token_ids::compl_: return operand ^ val(-1);
+ case token_ids::minus: return -operand;
+ case token_ids::not_: return not_(operand);
+ case token_ids::plus: return operand;
             case token_ids::plus_plus:
             {
                 if (!operand.is_lvalue())
                 {
                     // $$$ JDG Error here $$$
- return value();
+ return val();
                 }
 
- value r = builder.CreateAdd(operand, value(1), "add_tmp");
+ value r = operand + val(1);
                 operand.assign(r);
                 return operand;
             }
@@ -186,16 +238,16 @@
                 if (!operand.is_lvalue())
                 {
                     // $$$ JDG Error here $$$
- return value();
+ return val();
                 }
 
- value r = builder.CreateSub(operand, value(1), "sub_tmp");
+ value r = operand - val(1);
                 operand.assign(r);
                 return operand;
             }
             default:
                 BOOST_ASSERT(0);
- return value();
+ return val();
         }
     }
 
@@ -205,13 +257,13 @@
         if (!callee)
         {
             error_handler(x.function_name.id, "Function not found: " + x.function_name.name);
- return value();
+ return val();
         }
 
         if (callee->arg_size() != x.args.size())
         {
             error_handler(x.function_name.id, "Wrong number of arguments: " + x.function_name.name);
- return value();
+ return val();
         }
 
         std::vector<llvm::Value*> args;
@@ -219,10 +271,10 @@
         {
             args.push_back((*this)(expr));
             if (args.back() == 0)
- return value();
+ return val();
         }
 
- return builder.CreateCall(callee, args.begin(), args.end(), "calltmp");
+ return call(callee, args);
     }
 
     namespace
@@ -294,31 +346,31 @@
     {
         switch (op)
         {
- case token_ids::plus: return builder.CreateAdd(lhs, rhs, "addtmp");
- case token_ids::minus: return builder.CreateSub(lhs, rhs, "subtmp");
- case token_ids::times: return builder.CreateMul(lhs, rhs, "multmp");
- case token_ids::divide: return builder.CreateSDiv(lhs, rhs, "divtmp");
- case token_ids::mod: return builder.CreateSRem(lhs, rhs, "modtmp");
-
- case token_ids::bit_or: return builder.CreateOr(lhs, rhs, "ortmp");
- case token_ids::bit_xor: return builder.CreateXor(lhs, rhs, "xortmp");
- case token_ids::bit_and: return builder.CreateAnd(lhs, rhs, "andtmp");
- case token_ids::shift_left: return builder.CreateShl(lhs, rhs, "shltmp");
- case token_ids::shift_right: return builder.CreateLShr(lhs, rhs, "shrtmp");
-
- case token_ids::equal: return builder.CreateICmpEQ(lhs, rhs, "eqtmp");
- case token_ids::not_equal: return builder.CreateICmpNE(lhs, rhs, "netmp");
- case token_ids::less: return builder.CreateICmpSLT(lhs, rhs, "slttmp");
- case token_ids::less_equal: return builder.CreateICmpSLE(lhs, rhs, "sletmp");
- case token_ids::greater: return builder.CreateICmpSGT(lhs, rhs, "sgttmp");
- case token_ids::greater_equal: return builder.CreateICmpSGE(lhs, rhs, "sgetmp");
+ case token_ids::plus: return builder.CreateAdd(lhs, rhs, "add_tmp");
+ case token_ids::minus: return builder.CreateSub(lhs, rhs, "sub_tmp");
+ case token_ids::times: return builder.CreateMul(lhs, rhs, "mul_tmp");
+ case token_ids::divide: return builder.CreateSDiv(lhs, rhs, "div_tmp");
+ case token_ids::mod: return builder.CreateSRem(lhs, rhs, "mod_tmp");
+
+ case token_ids::bit_or: return builder.CreateOr(lhs, rhs, "or_tmp");
+ case token_ids::bit_xor: return builder.CreateXor(lhs, rhs, "xor_tmp");
+ case token_ids::bit_and: return builder.CreateAnd(lhs, rhs, "and_tmp");
+ case token_ids::shift_left: return builder.CreateShl(lhs, rhs, "shl_tmp");
+ case token_ids::shift_right: return builder.CreateLShr(lhs, rhs, "shr_tmp");
+
+ case token_ids::equal: return builder.CreateICmpEQ(lhs, rhs, "eq_tmp");
+ case token_ids::not_equal: return builder.CreateICmpNE(lhs, rhs, "ne_tmp");
+ case token_ids::less: return builder.CreateICmpSLT(lhs, rhs, "slt_tmp");
+ case token_ids::less_equal: return builder.CreateICmpSLE(lhs, rhs, "sle_tmp");
+ case token_ids::greater: return builder.CreateICmpSGT(lhs, rhs, "sgt_tmp");
+ case token_ids::greater_equal: return builder.CreateICmpSGE(lhs, rhs, "sge_tmp");
 
- case token_ids::logical_or: return builder.CreateOr(lhs, rhs, "ortmp");
- case token_ids::logical_and: return builder.CreateAnd(lhs, rhs, "andtmp");
+ case token_ids::logical_or: return builder.CreateOr(lhs, rhs, "or_tmp");
+ case token_ids::logical_and: return builder.CreateAnd(lhs, rhs, "and_tmp");
 
             default:
                 BOOST_ASSERT(0);
- return value();
+ return val();
         }
     }
 
@@ -335,7 +387,7 @@
             token_ids::type op = rest_begin->operator_;
             value rhs = boost::apply_visitor(*this, rest_begin->operand_);
             if (!rhs)
- return value();
+ return val();
             ++rest_begin;
 
             while ((rest_begin != rest_end) &&
@@ -355,7 +407,7 @@
     {
         value lhs = boost::apply_visitor(*this, x.first);
         if (!lhs)
- return value();
+ return val();
         std::list<ast::operation>::const_iterator rest_begin = x.rest.begin();
         return compile_expression(0, lhs, rest_begin, x.rest.end());
     }
@@ -365,13 +417,13 @@
         if (named_values.find(x.lhs.name) == named_values.end())
         {
             error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
- return value();
+ return val();
         }
 
         lvalue lhs = named_values[x.lhs.name];
         value rhs = (*this)(x.rhs);
         if (!rhs)
- return value();
+ return val();
 
         if (x.operator_ == token_ids::assign)
         {
@@ -383,46 +435,48 @@
         switch (x.operator_)
         {
             case token_ids::plus_assign:
- result = builder.CreateAdd(lhs, rhs, "addtmp");
+ result = builder.CreateAdd(lhs, rhs, "add_tmp");
                 break;
 
             case token_ids::minus_assign:
- result = builder.CreateSub(lhs, rhs, "subtmp");
+ result = builder.CreateSub(lhs, rhs, "sub_tmp");
                 break;
 
             case token_ids::times_assign:
- result = builder.CreateMul(lhs, rhs, "multmp");
+ result = builder.CreateMul(lhs, rhs, "mul_tmp");
                 break;
 
             case token_ids::divide_assign:
- result = builder.CreateSDiv(lhs, rhs, "divtmp");
+ result = builder.CreateSDiv(lhs, rhs, "div_tmp");
                 break;
 
             case token_ids::mod_assign:
- result = builder.CreateSRem(lhs, rhs, "modtmp");
+ result = builder.CreateSRem(lhs, rhs, "mod_tmp");
                 break;
 
             case token_ids::bit_and_assign:
- result = builder.CreateAnd(lhs, rhs, "andtmp");
+ result = builder.CreateAnd(lhs, rhs, "and_tmp");
                 break;
 
             case token_ids::bit_xor_assign:
- result = builder.CreateXor(lhs, rhs, "xortmp");
+ result = builder.CreateXor(lhs, rhs, "xor_tmp");
                 break;
 
             case token_ids::bit_or_assign:
- result = builder.CreateOr(lhs, rhs, "ortmp");
+ result = builder.CreateOr(lhs, rhs, "or_tmp");
                 break;
 
             case token_ids::shift_left_assign:
- result = builder.CreateShl(lhs, rhs, "shltmp");
+ result = builder.CreateShl(lhs, rhs, "shl_tmp");
                 break;
 
             case token_ids::shift_right_assign:
- result = builder.CreateLShr(lhs, rhs, "shrtmp");
+ result = builder.CreateLShr(lhs, rhs, "shr_tmp");
                 break;
 
- default: BOOST_ASSERT(0); return value();
+ default:
+ BOOST_ASSERT(0);
+ return val();
         }
 
         lhs.assign(result);
@@ -438,7 +492,7 @@
         }
 
         value init;
- std::string const& var = x.lhs.name;
+ std::string const& name = x.lhs.name;
 
         if (x.rhs) // if there's an RHS initializer
         {
@@ -447,12 +501,12 @@
                 return false;
         }
 
- lvalue alloca(builder, var.c_str());
+ lvalue var(builder, name.c_str());
         if (init)
- alloca.assign(init);
+ var.assign(init);
 
         // Remember this binding.
- named_values[var] = alloca;
+ named_values[name] = var;
         return true;
     }
 
@@ -604,7 +658,7 @@
             value return_val = (*this)(*x.expr);
             if (!return_val)
                 return false;
- return_alloca.assign(return_val);
+ return_var.assign(return_val);
         }
 
         builder.CreateBr(return_block);
@@ -671,26 +725,26 @@
 
     void compiler::function_allocas(ast::function const& x, llvm::Function* function)
     {
- // CreateArgumentAllocas - Create an alloca for each argument and register the
+ // Create an variables for each argument and register the
         // argument in the symbol table so that references to it will succeed.
         llvm::Function::arg_iterator iter = function->arg_begin();
         BOOST_FOREACH(ast::identifier const& arg, x.args)
         {
- // Create an alloca for this variable.
- lvalue alloca(builder, arg.name.c_str());
+ // Create an arg_ for this variable.
+ lvalue arg_(builder, arg.name.c_str());
 
- // Store the initial value into the alloca.
- alloca.assign(value(iter));
+ // Store the initial value into the arg_.
+ arg_.assign(value(iter));
 
             // Add arguments to variable symbol table.
- named_values[arg.name] = alloca;
+ named_values[arg.name] = arg_;
             ++iter;
         }
 
         if (!void_return)
         {
             // Create an alloca for the return value
- return_alloca = lvalue(builder, "return.val");
+ return_var = lvalue(builder, "return.val");
         }
     }
 
@@ -737,7 +791,7 @@
             if (void_return)
                 builder.CreateRetVoid();
             else
- builder.CreateRet(return_alloca);
+ 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-06 12:31:43 EDT (Sat, 06 Aug 2011)
@@ -31,33 +31,39 @@
 namespace client { namespace code_gen
 {
     unsigned const int_size = 32;
+ struct compiler;
+ struct expression_compiler;
 
     ///////////////////////////////////////////////////////////////////////////
     // The Value (light abstraction of an LLVM::Value
     ///////////////////////////////////////////////////////////////////////////
     struct value
     {
- value(
- llvm::Value* v = 0,
- bool is_lvalue_ = false,
- llvm::IRBuilder<>* builder = 0);
-
         value(value const& rhs);
 
- explicit value(unsigned int x);
- explicit value(int x);
- explicit value(bool x);
-
         operator llvm::Value*() const;
- bool operator!() const { return v == 0; }
 
         value& operator=(value const& rhs);
         bool is_lvalue() const { return is_lvalue_; }
 
         value& assign(value const& rhs);
 
+ friend value operator-(value a);
+ friend value not_(value a);
+ friend value operator+(value a, value b);
+ friend value operator-(value a, value b);
+ friend value operator^(value a, value b);
+
     protected:
 
+ friend struct compiler;
+ friend struct expression_compiler;
+
+ value(
+ llvm::Value* v = 0,
+ bool is_lvalue_ = false,
+ llvm::IRBuilder<>* builder = 0);
+
         llvm::LLVMContext& context() const
         { return llvm::getGlobalContext(); }
 
@@ -90,6 +96,15 @@
           : builder(context())
         {}
 
+ value val() { return value(); }
+ value val(unsigned int x);
+ value val(int x);
+ value val(bool x);
+
+ value call(
+ llvm::Function* callee,
+ std::vector<llvm::Value*> const& args);
+
     protected:
 
         llvm::LLVMContext& context() const
@@ -120,7 +135,7 @@
             init_fpm();
         }
 
- value operator()(ast::nil) { BOOST_ASSERT(0); return 0; }
+ value operator()(ast::nil) { BOOST_ASSERT(0); return val(); }
         value operator()(unsigned int x);
         value operator()(bool x);
         value operator()(ast::literal const& x);
@@ -149,7 +164,7 @@
         std::string current_function_name;
         std::map<std::string, lvalue> named_values;
         llvm::BasicBlock* return_block;
- lvalue return_alloca;
+ lvalue return_var;
 
         vmachine& vm;
         llvm::FunctionPassManager fpm;


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