|
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