]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | #if !defined(BOOST_SPIRIT_CONJURE_COMPILER_HPP) | |
8 | #define BOOST_SPIRIT_CONJURE_COMPILER_HPP | |
9 | ||
10 | #include "ast.hpp" | |
11 | #include "error_handler.hpp" | |
12 | #include "vm.hpp" | |
13 | #include <map> | |
14 | ||
15 | #include <boost/function.hpp> | |
16 | #include <boost/shared_ptr.hpp> | |
1e59de90 TL |
17 | #include <boost/phoenix/core.hpp> |
18 | #include <boost/phoenix/function.hpp> | |
19 | #include <boost/phoenix/operator.hpp> | |
7c673cae FG |
20 | #include <boost/iterator/transform_iterator.hpp> |
21 | ||
22 | #include <llvm/DerivedTypes.h> | |
23 | #include <llvm/Constants.h> | |
24 | #include <llvm/LLVMContext.h> | |
25 | #include <llvm/Module.h> | |
26 | #include <llvm/PassManager.h> | |
27 | #include <llvm/Analysis/Verifier.h> | |
28 | #include <llvm/Analysis/Passes.h> | |
29 | #include <llvm/Transforms/Scalar.h> | |
30 | #include <llvm/Support/IRBuilder.h> | |
31 | ||
32 | namespace client { namespace code_gen | |
33 | { | |
34 | unsigned const int_size = 32; | |
35 | struct compiler; | |
36 | struct llvm_compiler; | |
37 | ||
38 | /////////////////////////////////////////////////////////////////////////// | |
39 | // The Value (light abstraction of an LLVM::Value) | |
40 | /////////////////////////////////////////////////////////////////////////// | |
41 | struct value | |
42 | { | |
43 | value(); | |
44 | value(value const& rhs); | |
45 | ||
46 | value& operator=(value const& rhs); | |
47 | bool is_lvalue() const; | |
48 | bool is_valid() const; | |
49 | operator bool() const; | |
50 | ||
51 | value& assign(value const& rhs); | |
52 | ||
53 | void name(char const* id); | |
54 | void name(std::string const& id); | |
55 | ||
56 | friend value operator-(value a); | |
57 | friend value operator!(value a); | |
58 | friend value operator+(value a, value b); | |
59 | friend value operator-(value a, value b); | |
60 | friend value operator*(value a, value b); | |
61 | friend value operator/(value a, value b); | |
62 | friend value operator%(value a, value b); | |
63 | ||
64 | friend value operator&(value a, value b); | |
65 | friend value operator|(value a, value b); | |
66 | friend value operator^(value a, value b); | |
67 | friend value operator<<(value a, value b); | |
68 | friend value operator>>(value a, value b); | |
69 | ||
70 | friend value operator==(value a, value b); | |
71 | friend value operator!=(value a, value b); | |
72 | friend value operator<(value a, value b); | |
73 | friend value operator<=(value a, value b); | |
74 | friend value operator>(value a, value b); | |
75 | friend value operator>=(value a, value b); | |
76 | ||
77 | private: | |
78 | ||
79 | struct to_llvm_value; | |
80 | friend struct to_llvm_value; | |
81 | friend struct llvm_compiler; | |
82 | ||
83 | value( | |
84 | llvm::Value* v, | |
85 | bool is_lvalue_, | |
86 | llvm::IRBuilder<>* builder); | |
87 | ||
88 | llvm::LLVMContext& context() const | |
89 | { return llvm::getGlobalContext(); } | |
90 | ||
91 | operator llvm::Value*() const; | |
92 | ||
93 | llvm::Value* v; | |
94 | bool is_lvalue_; | |
95 | llvm::IRBuilder<>* builder; | |
96 | }; | |
97 | ||
98 | /////////////////////////////////////////////////////////////////////////// | |
99 | // The Basic Block (light abstraction of an LLVM::BasicBlock) | |
100 | /////////////////////////////////////////////////////////////////////////// | |
101 | struct function; | |
102 | ||
103 | struct basic_block | |
104 | { | |
105 | basic_block() | |
106 | : b(0) {} | |
107 | ||
108 | bool has_terminator() const; | |
109 | bool is_valid() const; | |
110 | ||
111 | private: | |
112 | ||
113 | basic_block(llvm::BasicBlock* b) | |
114 | : b(b) {} | |
115 | ||
116 | operator llvm::BasicBlock*() const | |
117 | { return b; } | |
118 | ||
119 | friend struct llvm_compiler; | |
120 | friend struct function; | |
121 | llvm::BasicBlock* b; | |
122 | }; | |
123 | ||
124 | /////////////////////////////////////////////////////////////////////////// | |
125 | // The Function (light abstraction of an LLVM::Function) | |
126 | /////////////////////////////////////////////////////////////////////////// | |
127 | struct llvm_compiler; | |
128 | ||
129 | struct function | |
130 | { | |
131 | private: | |
132 | ||
133 | struct to_value; | |
134 | typedef llvm::Function::arg_iterator arg_iterator; | |
135 | typedef boost::transform_iterator< | |
136 | to_value, arg_iterator> | |
137 | arg_val_iterator; | |
138 | ||
139 | public: | |
140 | ||
141 | typedef boost::iterator_range<arg_val_iterator> arg_range; | |
142 | ||
143 | function() | |
144 | : f(0), c(c) {} | |
145 | ||
146 | std::string name() const; | |
147 | ||
148 | std::size_t arg_size() const; | |
149 | arg_range args() const; | |
150 | ||
151 | void add(basic_block const& b); | |
152 | void erase_from_parent(); | |
153 | basic_block last_block(); | |
154 | bool empty() const; | |
155 | ||
156 | bool is_valid() const; | |
157 | void verify() const; | |
158 | ||
159 | private: | |
160 | ||
161 | function(llvm::Function* f, llvm_compiler* c) | |
162 | : f(f), c(c) {} | |
163 | ||
164 | operator llvm::Function*() const; | |
165 | ||
166 | friend struct llvm_compiler; | |
167 | llvm::Function* f; | |
168 | llvm_compiler* c; | |
169 | }; | |
170 | ||
171 | /////////////////////////////////////////////////////////////////////////// | |
172 | // The LLVM Compiler. Lower level compiler (does not deal with ASTs) | |
173 | /////////////////////////////////////////////////////////////////////////// | |
174 | struct llvm_compiler | |
175 | { | |
176 | llvm_compiler(vmachine& vm) | |
177 | : llvm_builder(context()) | |
178 | , vm(vm) | |
179 | , fpm(vm.module()) | |
180 | { init_fpm(); } | |
181 | ||
182 | value val() { return value(); } | |
183 | value val(unsigned int x); | |
184 | value val(int x); | |
185 | value val(bool x); | |
186 | ||
187 | value var(char const* name); | |
188 | value var(std::string const& name); | |
189 | ||
190 | template <typename Container> | |
191 | value call(function callee, Container const& args); | |
192 | ||
193 | function get_function(char const* name); | |
194 | function get_function(std::string const& name); | |
195 | function get_current_function(); | |
196 | ||
197 | function declare_function( | |
198 | bool void_return | |
199 | , std::string const& name | |
200 | , std::size_t nargs); | |
201 | ||
202 | basic_block make_basic_block( | |
203 | char const* name | |
204 | , function parent = function() | |
205 | , basic_block before = basic_block()); | |
206 | ||
207 | basic_block get_insert_block(); | |
208 | void set_insert_point(basic_block b); | |
209 | ||
210 | void conditional_branch( | |
211 | value cond, basic_block true_br, basic_block false_br); | |
212 | void branch(basic_block b); | |
213 | ||
214 | void return_(); | |
215 | void return_(value v); | |
216 | ||
217 | void optimize_function(function f); | |
218 | ||
219 | protected: | |
220 | ||
221 | llvm::LLVMContext& context() const | |
222 | { return llvm::getGlobalContext(); } | |
223 | ||
224 | llvm::IRBuilder<>& builder() | |
225 | { return llvm_builder; } | |
226 | ||
227 | private: | |
228 | ||
229 | friend struct function::to_value; | |
230 | ||
231 | value val(llvm::Value* v); | |
232 | ||
233 | template <typename C> | |
234 | llvm::Value* call_impl( | |
235 | function callee, | |
236 | C const& args); | |
237 | ||
238 | void init_fpm(); | |
239 | llvm::IRBuilder<> llvm_builder; | |
240 | vmachine& vm; | |
241 | llvm::FunctionPassManager fpm; | |
242 | }; | |
243 | ||
244 | /////////////////////////////////////////////////////////////////////////// | |
245 | // The main compiler. Generates code from our AST. | |
246 | /////////////////////////////////////////////////////////////////////////// | |
247 | struct compiler : llvm_compiler | |
248 | { | |
249 | typedef value result_type; | |
250 | ||
251 | template <typename ErrorHandler> | |
252 | compiler(vmachine& vm, ErrorHandler& error_handler_) | |
253 | : llvm_compiler(vm) | |
254 | { | |
255 | using namespace boost::phoenix::arg_names; | |
256 | namespace phx = boost::phoenix; | |
257 | using boost::phoenix::function; | |
258 | ||
259 | error_handler = function<ErrorHandler>(error_handler_)( | |
260 | "Error! ", _2, phx::cref(error_handler_.iters)[_1]); | |
261 | } | |
262 | ||
263 | value operator()(ast::nil) { BOOST_ASSERT(0); return val(); } | |
264 | value operator()(unsigned int x); | |
265 | value operator()(bool x); | |
266 | value operator()(ast::primary_expr const& x); | |
267 | value operator()(ast::identifier const& x); | |
268 | value operator()(ast::unary_expr const& x); | |
269 | value operator()(ast::function_call const& x); | |
270 | value operator()(ast::expression const& x); | |
271 | value operator()(ast::assignment const& x); | |
272 | ||
273 | bool operator()(ast::variable_declaration const& x); | |
274 | bool operator()(ast::statement_list const& x); | |
275 | bool operator()(ast::statement const& x); | |
276 | bool operator()(ast::if_statement const& x); | |
277 | bool operator()(ast::while_statement const& x); | |
278 | bool operator()(ast::return_statement const& x); | |
279 | bool operator()(ast::function const& x); | |
280 | bool operator()(ast::function_list const& x); | |
281 | ||
282 | private: | |
283 | ||
284 | value compile_binary_expression( | |
285 | value lhs, value rhs, token_ids::type op); | |
286 | ||
287 | value compile_expression( | |
288 | int min_precedence, | |
289 | value lhs, | |
290 | std::list<ast::operation>::const_iterator& rest_begin, | |
291 | std::list<ast::operation>::const_iterator rest_end); | |
292 | ||
293 | struct statement_compiler; | |
294 | statement_compiler& as_statement(); | |
295 | ||
296 | function function_decl(ast::function const& x); | |
297 | void function_allocas(ast::function const& x, function function); | |
298 | ||
299 | boost::function< | |
300 | void(int tag, std::string const& what)> | |
301 | error_handler; | |
302 | ||
303 | bool void_return; | |
304 | std::string current_function_name; | |
305 | std::map<std::string, value> locals; | |
306 | basic_block return_block; | |
307 | value return_var; | |
308 | }; | |
309 | }} | |
310 | ||
311 | #endif |