c8c65757c6
[SVN r82191]
312 lines
9.1 KiB
C++
312 lines
9.1 KiB
C++
/*=============================================================================
|
|
Copyright (c) 2001-2011 Joel de Guzman
|
|
|
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
=============================================================================*/
|
|
#if !defined(BOOST_SPIRIT_CONJURE_COMPILER_HPP)
|
|
#define BOOST_SPIRIT_CONJURE_COMPILER_HPP
|
|
|
|
#include "ast.hpp"
|
|
#include "error_handler.hpp"
|
|
#include "vm.hpp"
|
|
#include <map>
|
|
|
|
#include <boost/function.hpp>
|
|
#include <boost/shared_ptr.hpp>
|
|
#include <boost/spirit/include/phoenix_core.hpp>
|
|
#include <boost/spirit/include/phoenix_function.hpp>
|
|
#include <boost/spirit/include/phoenix_operator.hpp>
|
|
#include <boost/iterator/transform_iterator.hpp>
|
|
|
|
#include <llvm/DerivedTypes.h>
|
|
#include <llvm/Constants.h>
|
|
#include <llvm/LLVMContext.h>
|
|
#include <llvm/Module.h>
|
|
#include <llvm/PassManager.h>
|
|
#include <llvm/Analysis/Verifier.h>
|
|
#include <llvm/Analysis/Passes.h>
|
|
#include <llvm/Transforms/Scalar.h>
|
|
#include <llvm/Support/IRBuilder.h>
|
|
|
|
namespace client { namespace code_gen
|
|
{
|
|
unsigned const int_size = 32;
|
|
struct compiler;
|
|
struct llvm_compiler;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// The Value (light abstraction of an LLVM::Value)
|
|
///////////////////////////////////////////////////////////////////////////
|
|
struct value
|
|
{
|
|
value();
|
|
value(value const& rhs);
|
|
|
|
value& operator=(value const& rhs);
|
|
bool is_lvalue() const;
|
|
bool is_valid() const;
|
|
operator bool() const;
|
|
|
|
value& assign(value const& rhs);
|
|
|
|
void name(char const* id);
|
|
void name(std::string const& id);
|
|
|
|
friend value operator-(value a);
|
|
friend value operator!(value a);
|
|
friend value operator+(value a, value b);
|
|
friend value operator-(value a, value b);
|
|
friend value operator*(value a, value b);
|
|
friend value operator/(value a, value b);
|
|
friend value operator%(value a, value b);
|
|
|
|
friend value operator&(value a, value b);
|
|
friend value operator|(value a, value b);
|
|
friend value operator^(value a, value b);
|
|
friend value operator<<(value a, value b);
|
|
friend value operator>>(value a, value b);
|
|
|
|
friend value operator==(value a, value b);
|
|
friend value operator!=(value a, value b);
|
|
friend value operator<(value a, value b);
|
|
friend value operator<=(value a, value b);
|
|
friend value operator>(value a, value b);
|
|
friend value operator>=(value a, value b);
|
|
|
|
private:
|
|
|
|
struct to_llvm_value;
|
|
friend struct to_llvm_value;
|
|
friend struct llvm_compiler;
|
|
|
|
value(
|
|
llvm::Value* v,
|
|
bool is_lvalue_,
|
|
llvm::IRBuilder<>* builder);
|
|
|
|
llvm::LLVMContext& context() const
|
|
{ return llvm::getGlobalContext(); }
|
|
|
|
operator llvm::Value*() const;
|
|
|
|
llvm::Value* v;
|
|
bool is_lvalue_;
|
|
llvm::IRBuilder<>* builder;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// The Basic Block (light abstraction of an LLVM::BasicBlock)
|
|
///////////////////////////////////////////////////////////////////////////
|
|
struct function;
|
|
|
|
struct basic_block
|
|
{
|
|
basic_block()
|
|
: b(0) {}
|
|
|
|
bool has_terminator() const;
|
|
bool is_valid() const;
|
|
|
|
private:
|
|
|
|
basic_block(llvm::BasicBlock* b)
|
|
: b(b) {}
|
|
|
|
operator llvm::BasicBlock*() const
|
|
{ return b; }
|
|
|
|
friend struct llvm_compiler;
|
|
friend struct function;
|
|
llvm::BasicBlock* b;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// The Function (light abstraction of an LLVM::Function)
|
|
///////////////////////////////////////////////////////////////////////////
|
|
struct llvm_compiler;
|
|
|
|
struct function
|
|
{
|
|
private:
|
|
|
|
struct to_value;
|
|
typedef llvm::Function::arg_iterator arg_iterator;
|
|
typedef boost::transform_iterator<
|
|
to_value, arg_iterator>
|
|
arg_val_iterator;
|
|
|
|
public:
|
|
|
|
typedef boost::iterator_range<arg_val_iterator> arg_range;
|
|
|
|
function()
|
|
: f(0), c(c) {}
|
|
|
|
std::string name() const;
|
|
|
|
std::size_t arg_size() const;
|
|
arg_range args() const;
|
|
|
|
void add(basic_block const& b);
|
|
void erase_from_parent();
|
|
basic_block last_block();
|
|
bool empty() const;
|
|
|
|
bool is_valid() const;
|
|
void verify() const;
|
|
|
|
private:
|
|
|
|
function(llvm::Function* f, llvm_compiler* c)
|
|
: f(f), c(c) {}
|
|
|
|
operator llvm::Function*() const;
|
|
|
|
friend struct llvm_compiler;
|
|
llvm::Function* f;
|
|
llvm_compiler* c;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// The LLVM Compiler. Lower level compiler (does not deal with ASTs)
|
|
///////////////////////////////////////////////////////////////////////////
|
|
struct llvm_compiler
|
|
{
|
|
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 var(char const* name);
|
|
value var(std::string const& name);
|
|
|
|
template <typename Container>
|
|
value call(function callee, Container const& args);
|
|
|
|
function get_function(char const* name);
|
|
function get_function(std::string const& name);
|
|
function get_current_function();
|
|
|
|
function declare_function(
|
|
bool void_return
|
|
, std::string const& name
|
|
, std::size_t nargs);
|
|
|
|
basic_block make_basic_block(
|
|
char const* name
|
|
, function parent = function()
|
|
, basic_block before = basic_block());
|
|
|
|
basic_block get_insert_block();
|
|
void set_insert_point(basic_block b);
|
|
|
|
void conditional_branch(
|
|
value cond, basic_block true_br, basic_block false_br);
|
|
void branch(basic_block b);
|
|
|
|
void return_();
|
|
void return_(value v);
|
|
|
|
void optimize_function(function f);
|
|
|
|
protected:
|
|
|
|
llvm::LLVMContext& context() const
|
|
{ return llvm::getGlobalContext(); }
|
|
|
|
llvm::IRBuilder<>& builder()
|
|
{ return llvm_builder; }
|
|
|
|
private:
|
|
|
|
friend struct function::to_value;
|
|
|
|
value val(llvm::Value* v);
|
|
|
|
template <typename C>
|
|
llvm::Value* call_impl(
|
|
function callee,
|
|
C const& args);
|
|
|
|
void init_fpm();
|
|
llvm::IRBuilder<> llvm_builder;
|
|
vmachine& vm;
|
|
llvm::FunctionPassManager fpm;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// The main compiler. Generates code from our AST.
|
|
///////////////////////////////////////////////////////////////////////////
|
|
struct compiler : llvm_compiler
|
|
{
|
|
typedef value result_type;
|
|
|
|
template <typename ErrorHandler>
|
|
compiler(vmachine& vm, ErrorHandler& error_handler_)
|
|
: llvm_compiler(vm)
|
|
{
|
|
using namespace boost::phoenix::arg_names;
|
|
namespace phx = boost::phoenix;
|
|
using boost::phoenix::function;
|
|
|
|
error_handler = function<ErrorHandler>(error_handler_)(
|
|
"Error! ", _2, phx::cref(error_handler_.iters)[_1]);
|
|
}
|
|
|
|
value operator()(ast::nil) { BOOST_ASSERT(0); return val(); }
|
|
value operator()(unsigned int x);
|
|
value operator()(bool x);
|
|
value operator()(ast::primary_expr const& x);
|
|
value operator()(ast::identifier const& x);
|
|
value operator()(ast::unary_expr const& x);
|
|
value operator()(ast::function_call const& x);
|
|
value operator()(ast::expression const& x);
|
|
value operator()(ast::assignment const& x);
|
|
|
|
bool operator()(ast::variable_declaration const& x);
|
|
bool operator()(ast::statement_list const& x);
|
|
bool operator()(ast::statement const& x);
|
|
bool operator()(ast::if_statement const& x);
|
|
bool operator()(ast::while_statement const& x);
|
|
bool operator()(ast::return_statement const& x);
|
|
bool operator()(ast::function const& x);
|
|
bool operator()(ast::function_list const& x);
|
|
|
|
private:
|
|
|
|
value compile_binary_expression(
|
|
value lhs, value rhs, token_ids::type op);
|
|
|
|
value compile_expression(
|
|
int min_precedence,
|
|
value lhs,
|
|
std::list<ast::operation>::const_iterator& rest_begin,
|
|
std::list<ast::operation>::const_iterator rest_end);
|
|
|
|
struct statement_compiler;
|
|
statement_compiler& as_statement();
|
|
|
|
function function_decl(ast::function const& x);
|
|
void function_allocas(ast::function const& x, 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> locals;
|
|
basic_block return_block;
|
|
value return_var;
|
|
};
|
|
}}
|
|
|
|
#endif
|