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_VM_HPP)
8 #define BOOST_SPIRIT_CONJURE_VM_HPP
9 
10 #include <llvm/ExecutionEngine/ExecutionEngine.h>
11 #include <llvm/ExecutionEngine/JIT.h>
12 #include <llvm/LLVMContext.h>
13 #include <llvm/Module.h>
14 #include <llvm/Target/TargetData.h>
15 #include <llvm/Target/TargetSelect.h>
16 
17 #include <boost/assert.hpp>
18 
19 namespace client
20 {
21     class vmachine;
22 
23     ///////////////////////////////////////////////////////////////////////////
24     //  A light wrapper to a function pointer returning int and accepting
25     //  from 0 to 3 arguments, where arity is determined at runtime.
26     ///////////////////////////////////////////////////////////////////////////
27     class function
28     {
29     public:
30 
31         typedef int result_type;
32 
operator ()() const33         int operator()() const
34         {
35             BOOST_ASSERT(fptr != 0);
36             BOOST_ASSERT(arity() == 0);
37             int (*fp)() = (int(*)())(intptr_t)fptr;
38             return fp();
39         }
40 
operator ()(int _1) const41         int operator()(int _1) const
42         {
43             BOOST_ASSERT(fptr != 0);
44             BOOST_ASSERT(arity() == 1);
45             int (*fp)(int) = (int(*)(int))(intptr_t)fptr;
46             return fp(_1);
47         }
48 
operator ()(int _1,int _2) const49         int operator()(int _1, int _2) const
50         {
51             BOOST_ASSERT(fptr != 0);
52             BOOST_ASSERT(arity() == 2);
53             int (*fp)(int, int) = (int(*)(int, int))(intptr_t)fptr;
54             return fp(_1, _2);
55         }
56 
operator ()(int _1,int _2,int _3) const57         int operator()(int _1, int _2, int _3) const
58         {
59             BOOST_ASSERT(fptr != 0);
60             BOOST_ASSERT(arity() == 3);
61             int (*fp)(int, int, int) = (int(*)(int, int, int))(intptr_t)fptr;
62             return fp(_1, _2, _3);
63         }
64 
arity() const65         unsigned arity() const { return arity_; }
operator !() const66         bool operator!() const { return fptr == 0; }
67 
68     private:
69 
70         friend class vmachine;
function(void * fptr,unsigned arity_)71         function(void* fptr, unsigned arity_)
72             : fptr(fptr), arity_(arity_) {}
73 
74         void* fptr;
75         unsigned arity_;
76     };
77 
78     ///////////////////////////////////////////////////////////////////////////
79     //  The Virtual Machine (light wrapper over LLVM JIT)
80     ///////////////////////////////////////////////////////////////////////////
81     class vmachine
82     {
83     public:
84 
85         vmachine();
86 
module() const87         llvm::Module* module() const
88         {
89             return module_;
90         }
91 
execution_engine() const92         llvm::ExecutionEngine* execution_engine() const
93         {
94             return execution_engine_;
95         }
96 
print_assembler() const97         void print_assembler() const
98         {
99             module_->dump();
100         }
101 
get_function(char const * name)102         function get_function(char const* name)
103         {
104             llvm::Function* callee = module_->getFunction(name);
105             if (callee == 0)
106                 return function(0, 0);
107 
108             // JIT the function
109             void *fptr = execution_engine_->getPointerToFunction(callee);
110             return function(fptr, callee->arg_size());
111         }
112 
113     private:
114 
115         llvm::Module* module_;
116         llvm::ExecutionEngine* execution_engine_;
117     };
118 }
119 
120 #endif
121 
122