plessl-llvmruby 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +21 -0
- data/README +76 -0
- data/Rakefile +31 -0
- data/ext/extconf.rb +14 -0
- data/ext/llvm_basicblock.cpp +299 -0
- data/ext/llvm_function.cpp +48 -0
- data/ext/llvm_instruction.cpp +259 -0
- data/ext/llvm_module.cpp +189 -0
- data/ext/llvm_use.cpp +9 -0
- data/ext/llvm_user.cpp +71 -0
- data/ext/llvm_value.cpp +254 -0
- data/ext/llvmruby.c +328 -0
- data/ext/llvmruby.h +73 -0
- data/lib/llvm.rb +146 -0
- data/lib/ruby_vm.rb +352 -0
- data/lib/version.rb +11 -0
- data/test/byteswap.bc +0 -0
- data/test/test_basic.rb +340 -0
- data/test/test_basic_block.rb +80 -0
- data/test/test_instructions.rb +112 -0
- data/test/test_read_bitcode.rb +38 -0
- data/test/test_ruby_vm.rb +172 -0
- data/test/test_user.rb +72 -0
- data/test/test_value.rb +63 -0
- metadata +87 -0
@@ -0,0 +1,259 @@
|
|
1
|
+
#include "llvmruby.h"
|
2
|
+
#include <sstream>
|
3
|
+
|
4
|
+
extern VALUE cLLVMInstruction;
|
5
|
+
extern VALUE cLLVMBinaryOps;
|
6
|
+
|
7
|
+
extern "C" {
|
8
|
+
|
9
|
+
#define LAST_INSTRUCTION_NUM 100
|
10
|
+
VALUE gInstructionClasses[LAST_INSTRUCTION_NUM];
|
11
|
+
|
12
|
+
#define DATA_GET_INSTRUCTION Instruction *i; Data_Get_Struct(self, Instruction, i);
|
13
|
+
|
14
|
+
VALUE
|
15
|
+
llvm_instruction_wrap(Instruction* i) {
|
16
|
+
return Data_Wrap_Struct(gInstructionClasses[i->getOpcode()], NULL, NULL, i);
|
17
|
+
}
|
18
|
+
|
19
|
+
VALUE
|
20
|
+
llvm_instruction_inspect(VALUE self) {
|
21
|
+
Instruction *i = LLVM_INSTRUCTION(self);
|
22
|
+
std::ostringstream strstrm;
|
23
|
+
strstrm << *i;
|
24
|
+
return rb_str_new2(strstrm.str().c_str());
|
25
|
+
}
|
26
|
+
|
27
|
+
VALUE
|
28
|
+
llvm_instruction_get_opcode_name(VALUE self) {
|
29
|
+
Instruction *i = LLVM_INSTRUCTION(self);
|
30
|
+
std::string name = i->getOpcodeName();
|
31
|
+
return rb_str_new2(name.c_str());
|
32
|
+
}
|
33
|
+
|
34
|
+
VALUE
|
35
|
+
llvm_instruction_may_read_from_memory(VALUE self) {
|
36
|
+
DATA_GET_INSTRUCTION
|
37
|
+
return i->mayReadFromMemory() ? Qtrue : Qfalse;
|
38
|
+
}
|
39
|
+
|
40
|
+
VALUE
|
41
|
+
llvm_instruction_may_write_to_memory(VALUE self) {
|
42
|
+
DATA_GET_INSTRUCTION
|
43
|
+
return i->mayWriteToMemory() ? Qtrue : Qfalse;
|
44
|
+
}
|
45
|
+
|
46
|
+
VALUE
|
47
|
+
llvm_instruction_is_identical_to(VALUE self, VALUE ri2) {
|
48
|
+
DATA_GET_INSTRUCTION
|
49
|
+
CHECK_TYPE(ri2, cLLVMInstruction);
|
50
|
+
Instruction *i2 = LLVM_INSTRUCTION(ri2);
|
51
|
+
return i->isIdenticalTo(i2) ? Qtrue : Qfalse;
|
52
|
+
}
|
53
|
+
|
54
|
+
VALUE
|
55
|
+
llvm_instruction_is_same_operation_as(VALUE self, VALUE ri2) {
|
56
|
+
DATA_GET_INSTRUCTION
|
57
|
+
CHECK_TYPE(ri2, cLLVMInstruction);
|
58
|
+
Instruction *i2 = LLVM_INSTRUCTION(ri2);
|
59
|
+
return i->isSameOperationAs(i2) ? Qtrue : Qfalse;
|
60
|
+
}
|
61
|
+
|
62
|
+
VALUE
|
63
|
+
llvm_instruction_is_used_outside_of_block(VALUE self, VALUE rbb) {
|
64
|
+
DATA_GET_INSTRUCTION
|
65
|
+
CHECK_TYPE(rbb, cLLVMBasicBlock);
|
66
|
+
BasicBlock *bb = LLVM_BASIC_BLOCK(rbb);
|
67
|
+
return i->isUsedOutsideOfBlock(bb) ? Qtrue: Qfalse;
|
68
|
+
}
|
69
|
+
|
70
|
+
#define DATA_GET_TERMINATOR_INST TerminatorInst *ti; Data_Get_Struct(self, TerminatorInst, ti);
|
71
|
+
|
72
|
+
VALUE
|
73
|
+
llvm_terminator_inst_num_successors(VALUE self) {
|
74
|
+
DATA_GET_TERMINATOR_INST
|
75
|
+
return INT2FIX(ti->getNumSuccessors());
|
76
|
+
}
|
77
|
+
|
78
|
+
VALUE
|
79
|
+
llvm_terminator_inst_get_successor(VALUE self, VALUE ridx) {
|
80
|
+
DATA_GET_TERMINATOR_INST
|
81
|
+
BasicBlock *bb = ti->getSuccessor(FIX2INT(ridx));
|
82
|
+
return llvm_basic_block_wrap(bb);
|
83
|
+
}
|
84
|
+
|
85
|
+
VALUE
|
86
|
+
llvm_terminator_inst_set_successor(VALUE self, VALUE ridx, VALUE rbb) {
|
87
|
+
DATA_GET_TERMINATOR_INST
|
88
|
+
|
89
|
+
BasicBlock *bb;
|
90
|
+
Data_Get_Struct(rbb, BasicBlock, bb);
|
91
|
+
|
92
|
+
ti->setSuccessor(FIX2INT(ridx), bb);
|
93
|
+
return rbb;
|
94
|
+
}
|
95
|
+
|
96
|
+
#define DATA_GET_BRANCH_INST BranchInst *bi; Data_Get_Struct(self, BranchInst, bi);
|
97
|
+
|
98
|
+
VALUE
|
99
|
+
llvm_branch_inst_is_unconditional(VALUE self) {
|
100
|
+
DATA_GET_BRANCH_INST
|
101
|
+
return bi->isUnconditional() ? Qtrue : Qfalse;
|
102
|
+
}
|
103
|
+
|
104
|
+
VALUE
|
105
|
+
llvm_branch_inst_is_conditional(VALUE self) {
|
106
|
+
DATA_GET_BRANCH_INST
|
107
|
+
return bi->isConditional() ? Qtrue : Qfalse;
|
108
|
+
}
|
109
|
+
|
110
|
+
VALUE
|
111
|
+
llvm_branch_inst_get_condition(VALUE self) {
|
112
|
+
DATA_GET_BRANCH_INST
|
113
|
+
return llvm_value_wrap(bi->getCondition());
|
114
|
+
}
|
115
|
+
|
116
|
+
VALUE
|
117
|
+
llvm_branch_inst_set_condition(VALUE self, VALUE rv) {
|
118
|
+
DATA_GET_BRANCH_INST
|
119
|
+
|
120
|
+
Value *v;
|
121
|
+
Data_Get_Struct(rv, Value, v);
|
122
|
+
|
123
|
+
bi->setCondition(v);
|
124
|
+
return rv;
|
125
|
+
}
|
126
|
+
|
127
|
+
#define DATA_GET_SWITCH_INST SwitchInst *si; Data_Get_Struct(self, SwitchInst, si);
|
128
|
+
|
129
|
+
VALUE
|
130
|
+
llvm_switch_inst_get_default_dest(VALUE self) {
|
131
|
+
DATA_GET_SWITCH_INST
|
132
|
+
BasicBlock *bb = si->getDefaultDest();
|
133
|
+
return llvm_basic_block_wrap(bb);
|
134
|
+
}
|
135
|
+
|
136
|
+
VALUE
|
137
|
+
llvm_switch_inst_get_num_cases(VALUE self) {
|
138
|
+
DATA_GET_SWITCH_INST
|
139
|
+
return INT2FIX(si->getNumCases());
|
140
|
+
}
|
141
|
+
|
142
|
+
VALUE
|
143
|
+
llvm_switch_inst_add_case(VALUE self, VALUE rci, VALUE rbb) {
|
144
|
+
DATA_GET_SWITCH_INST
|
145
|
+
|
146
|
+
ConstantInt *ci;
|
147
|
+
Data_Get_Struct(rci, ConstantInt, ci);
|
148
|
+
|
149
|
+
BasicBlock *bb;
|
150
|
+
Data_Get_Struct(rbb, BasicBlock, bb);
|
151
|
+
|
152
|
+
si->addCase(ci, bb);
|
153
|
+
return self;
|
154
|
+
}
|
155
|
+
|
156
|
+
#define DATA_GET_ALLOCATION_INST AllocationInst *ai; Data_Get_Struct(self, AllocationInst, ai);
|
157
|
+
|
158
|
+
VALUE
|
159
|
+
llvm_allocation_inst_is_array_allocation(VALUE self) {
|
160
|
+
DATA_GET_ALLOCATION_INST
|
161
|
+
return ai->isArrayAllocation() ? true : false;
|
162
|
+
}
|
163
|
+
|
164
|
+
VALUE
|
165
|
+
llvm_allocation_inst_array_size(VALUE self) {
|
166
|
+
DATA_GET_ALLOCATION_INST
|
167
|
+
return llvm_value_wrap(ai->getArraySize());
|
168
|
+
}
|
169
|
+
|
170
|
+
VALUE
|
171
|
+
llvm_allocation_inst_allocated_type(VALUE self) {
|
172
|
+
DATA_GET_ALLOCATION_INST
|
173
|
+
Type *at = const_cast<Type*>(ai->getAllocatedType());
|
174
|
+
return Data_Wrap_Struct(cLLVMType, NULL, NULL, at);
|
175
|
+
}
|
176
|
+
|
177
|
+
VALUE
|
178
|
+
llvm_allocation_inst_alignment(VALUE self) {
|
179
|
+
DATA_GET_ALLOCATION_INST
|
180
|
+
return INT2FIX(ai->getAlignment());
|
181
|
+
}
|
182
|
+
|
183
|
+
#define DEFINE_INST(type, name) rb_define_const(cLLVMInstruction, #name, INT2FIX(Instruction::name));
|
184
|
+
#define DEFINE_BINARY_INST(name) DEFINE_INST(cLLVMBinaryOps, name)
|
185
|
+
#define DEFINE_PRED(name) rb_define_const(cLLVMInstruction, #name, INT2FIX(ICmpInst::name));
|
186
|
+
#define DEFINE_FPRED(name) rb_define_const(cLLVMInstruction, #name, INT2FIX(FCmpInst::name));
|
187
|
+
#define DEFINE_CAST(name) rb_define_const(cLLVMInstruction, #name, INT2FIX(Instruction::name));
|
188
|
+
|
189
|
+
void init_instructions() {
|
190
|
+
for(int i = 0; i < LAST_INSTRUCTION_NUM; ++i) {
|
191
|
+
gInstructionClasses[i] = cLLVMInstruction;
|
192
|
+
}
|
193
|
+
|
194
|
+
// Need to be able to quickly look up at runtime Ruby classes cooresponding to LLVM classes
|
195
|
+
#define HANDLE_TERM_INST(Num, Opcode, Klass) gInstructionClasses[Num] = cLLVM##Klass;
|
196
|
+
#define HANDLE_BINARY_INST(Num, Opcode, Klass) gInstructionClasses[Num] = cLLVM##Klass;
|
197
|
+
#define HANDLE_MEMORY_INST(Num, Opcode, Klass) gInstructionClasses[Num] = cLLVM##Klass;
|
198
|
+
#include "llvm/Instruction.def"
|
199
|
+
|
200
|
+
// Standard binary operators
|
201
|
+
DEFINE_BINARY_INST(Add)
|
202
|
+
DEFINE_BINARY_INST(Sub)
|
203
|
+
DEFINE_BINARY_INST(Mul)
|
204
|
+
DEFINE_BINARY_INST(UDiv)
|
205
|
+
DEFINE_BINARY_INST(SDiv)
|
206
|
+
DEFINE_BINARY_INST(FDiv)
|
207
|
+
DEFINE_BINARY_INST(URem)
|
208
|
+
DEFINE_BINARY_INST(SRem)
|
209
|
+
DEFINE_BINARY_INST(FRem)
|
210
|
+
|
211
|
+
// Logical operators (integer operands)
|
212
|
+
DEFINE_BINARY_INST(Shl) // Shift left (logical)
|
213
|
+
DEFINE_BINARY_INST(LShr) // Shift right (logical)
|
214
|
+
DEFINE_BINARY_INST(AShr) // shift right (arithmetic)
|
215
|
+
DEFINE_BINARY_INST(And)
|
216
|
+
DEFINE_BINARY_INST(Or)
|
217
|
+
DEFINE_BINARY_INST(Xor)
|
218
|
+
|
219
|
+
// Integer predicates
|
220
|
+
DEFINE_PRED(ICMP_EQ) // equal
|
221
|
+
DEFINE_PRED(ICMP_NE) // not equal
|
222
|
+
DEFINE_PRED(ICMP_UGT) // unsigned greater than
|
223
|
+
DEFINE_PRED(ICMP_UGE) // unsigned greater or equal
|
224
|
+
DEFINE_PRED(ICMP_ULT) // unsigned less than
|
225
|
+
DEFINE_PRED(ICMP_ULE) // unsigned less or equal
|
226
|
+
DEFINE_PRED(ICMP_SGT) // signed greater than
|
227
|
+
DEFINE_PRED(ICMP_SGE) // signed greater or equal
|
228
|
+
DEFINE_PRED(ICMP_SLT) // signed less than
|
229
|
+
DEFINE_PRED(ICMP_SLE) // signed less or equal
|
230
|
+
|
231
|
+
DEFINE_FPRED(FCMP_OEQ)
|
232
|
+
DEFINE_FPRED(FCMP_OGT)
|
233
|
+
DEFINE_FPRED(FCMP_OGE)
|
234
|
+
DEFINE_FPRED(FCMP_OLT)
|
235
|
+
DEFINE_FPRED(FCMP_OLE)
|
236
|
+
DEFINE_FPRED(FCMP_ONE)
|
237
|
+
DEFINE_FPRED(FCMP_ORD)
|
238
|
+
DEFINE_FPRED(FCMP_UNO)
|
239
|
+
DEFINE_FPRED(FCMP_UEQ)
|
240
|
+
DEFINE_FPRED(FCMP_UGT)
|
241
|
+
DEFINE_FPRED(FCMP_UGE)
|
242
|
+
DEFINE_FPRED(FCMP_ULT)
|
243
|
+
DEFINE_FPRED(FCMP_ULE)
|
244
|
+
DEFINE_FPRED(FCMP_UNE)
|
245
|
+
|
246
|
+
DEFINE_CAST(Trunc)
|
247
|
+
DEFINE_CAST(ZExt)
|
248
|
+
DEFINE_CAST(SExt)
|
249
|
+
DEFINE_CAST(FPToUI)
|
250
|
+
DEFINE_CAST(FPToSI)
|
251
|
+
DEFINE_CAST(UIToFP)
|
252
|
+
DEFINE_CAST(SIToFP)
|
253
|
+
DEFINE_CAST(FPTrunc)
|
254
|
+
DEFINE_CAST(FPExt)
|
255
|
+
DEFINE_CAST(PtrToInt)
|
256
|
+
DEFINE_CAST(IntToPtr)
|
257
|
+
DEFINE_CAST(BitCast)
|
258
|
+
}
|
259
|
+
}
|
data/ext/llvm_module.cpp
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
#include "llvmruby.h"
|
2
|
+
#include "llvm/Assembly/Parser.h"
|
3
|
+
#include "llvm/Bitcode/ReaderWriter.h"
|
4
|
+
#include "llvm/Analysis/Verifier.h"
|
5
|
+
#include "llvm/Support/MemoryBuffer.h"
|
6
|
+
#include <fstream>
|
7
|
+
#include <sstream>
|
8
|
+
|
9
|
+
extern "C" {
|
10
|
+
|
11
|
+
VALUE
|
12
|
+
llvm_module_allocate(VALUE klass) {
|
13
|
+
return Data_Wrap_Struct(klass, NULL, NULL, NULL);
|
14
|
+
}
|
15
|
+
|
16
|
+
VALUE
|
17
|
+
llvm_module_initialize(VALUE self, VALUE rname) {
|
18
|
+
Check_Type(rname, T_STRING);
|
19
|
+
DATA_PTR(self) = new Module(StringValuePtr(rname));
|
20
|
+
return self;
|
21
|
+
}
|
22
|
+
|
23
|
+
VALUE
|
24
|
+
llvm_module_get_or_insert_function(VALUE self, VALUE name, VALUE rtype) {
|
25
|
+
Check_Type(name, T_STRING);
|
26
|
+
CHECK_TYPE(rtype, cLLVMFunctionType);
|
27
|
+
|
28
|
+
Module *m = LLVM_MODULE(self);
|
29
|
+
FunctionType *type = LLVM_FUNC_TYPE(rtype);
|
30
|
+
Function *f = cast<Function>(m->getOrInsertFunction(StringValuePtr(name), type));
|
31
|
+
return llvm_function_wrap(f);
|
32
|
+
}
|
33
|
+
|
34
|
+
VALUE
|
35
|
+
llvm_module_get_function(VALUE self, VALUE name) {
|
36
|
+
Check_Type(name, T_STRING);
|
37
|
+
Module *m = LLVM_MODULE(self);
|
38
|
+
Function *f = m->getFunction(StringValuePtr(name));
|
39
|
+
return llvm_function_wrap(f);
|
40
|
+
}
|
41
|
+
|
42
|
+
VALUE
|
43
|
+
llvm_module_global_variable(VALUE self, VALUE rtype, VALUE rinitializer) {
|
44
|
+
Module *m = LLVM_MODULE(self);
|
45
|
+
Type *type = LLVM_TYPE(rtype);
|
46
|
+
Constant *initializer = (Constant*)DATA_PTR(rinitializer);
|
47
|
+
GlobalVariable *gv = new GlobalVariable(type, true, GlobalValue::InternalLinkage, initializer, "", m);
|
48
|
+
return llvm_value_wrap(gv);
|
49
|
+
}
|
50
|
+
|
51
|
+
|
52
|
+
VALUE
|
53
|
+
llvm_module_inspect(VALUE self) {
|
54
|
+
Module *m = LLVM_MODULE(self);
|
55
|
+
std::ostringstream strstrm;
|
56
|
+
strstrm << *m;
|
57
|
+
return rb_str_new2(strstrm.str().c_str());
|
58
|
+
}
|
59
|
+
|
60
|
+
VALUE
|
61
|
+
llvm_pass_manager_allocate(VALUE klass) {
|
62
|
+
return Data_Wrap_Struct(klass, NULL, NULL, NULL);
|
63
|
+
}
|
64
|
+
|
65
|
+
VALUE
|
66
|
+
llvm_pass_manager_initialize(VALUE self) {
|
67
|
+
PassManager *pm = new PassManager;
|
68
|
+
DATA_PTR(self) = pm;
|
69
|
+
return self;
|
70
|
+
}
|
71
|
+
|
72
|
+
VALUE
|
73
|
+
llvm_pass_manager_run(VALUE self, VALUE module) {
|
74
|
+
PassManager *pm = (PassManager*) DATA_PTR(self);
|
75
|
+
Module *m = LLVM_MODULE(module);
|
76
|
+
|
77
|
+
pm->add(new TargetData(m));
|
78
|
+
pm->add(createVerifierPass());
|
79
|
+
pm->add(createLowerSetJmpPass());
|
80
|
+
pm->add(createRaiseAllocationsPass());
|
81
|
+
pm->add(createCFGSimplificationPass());
|
82
|
+
pm->add(createPromoteMemoryToRegisterPass());
|
83
|
+
pm->add(createGlobalOptimizerPass());
|
84
|
+
pm->add(createGlobalDCEPass());
|
85
|
+
pm->add(createFunctionInliningPass());
|
86
|
+
|
87
|
+
pm->run(*m);
|
88
|
+
return Qtrue;
|
89
|
+
}
|
90
|
+
|
91
|
+
static ExecutionEngine *EE = NULL;
|
92
|
+
|
93
|
+
VALUE
|
94
|
+
llvm_execution_engine_get(VALUE klass, VALUE module) {
|
95
|
+
CHECK_TYPE(module, cLLVMModule);
|
96
|
+
|
97
|
+
Module *m = LLVM_MODULE(module);
|
98
|
+
ExistingModuleProvider *MP = new ExistingModuleProvider(m);
|
99
|
+
|
100
|
+
if(EE == NULL) {
|
101
|
+
EE = ExecutionEngine::create(MP, false);
|
102
|
+
} else {
|
103
|
+
EE->addModuleProvider(MP);
|
104
|
+
}
|
105
|
+
|
106
|
+
return Qtrue;
|
107
|
+
}
|
108
|
+
|
109
|
+
VALUE
|
110
|
+
llvm_module_external_function(VALUE self, VALUE name, VALUE type) {
|
111
|
+
Check_Type(name, T_STRING);
|
112
|
+
CHECK_TYPE(type, cLLVMFunctionType);
|
113
|
+
|
114
|
+
Module *module = LLVM_MODULE(self);
|
115
|
+
Function *f = Function::Create(
|
116
|
+
LLVM_FUNC_TYPE(type),
|
117
|
+
Function::ExternalLinkage,
|
118
|
+
StringValuePtr(name),
|
119
|
+
module
|
120
|
+
);
|
121
|
+
return Data_Wrap_Struct(cLLVMFunction, NULL, NULL, f);
|
122
|
+
}
|
123
|
+
|
124
|
+
VALUE
|
125
|
+
llvm_module_read_assembly(VALUE self, VALUE assembly) {
|
126
|
+
Check_Type(assembly, T_STRING);
|
127
|
+
|
128
|
+
ParseError e;
|
129
|
+
Module *module = ParseAssemblyString(
|
130
|
+
StringValuePtr(assembly),
|
131
|
+
LLVM_MODULE(self),
|
132
|
+
&e
|
133
|
+
);
|
134
|
+
//TODO How do we handle errors?
|
135
|
+
return Data_Wrap_Struct(cLLVMModule, NULL, NULL, module);
|
136
|
+
}
|
137
|
+
|
138
|
+
VALUE
|
139
|
+
llvm_module_read_bitcode(VALUE self, VALUE bitcode) {
|
140
|
+
Check_Type(bitcode, T_STRING);
|
141
|
+
|
142
|
+
MemoryBuffer *buf = MemoryBuffer::getMemBufferCopy(RSTRING(bitcode)->ptr,RSTRING(bitcode)->ptr+RSTRING(bitcode)->len);
|
143
|
+
Module *module = ParseBitcodeFile(buf);
|
144
|
+
delete buf;
|
145
|
+
return Data_Wrap_Struct(cLLVMModule, NULL, NULL, module);
|
146
|
+
}
|
147
|
+
|
148
|
+
|
149
|
+
VALUE
|
150
|
+
llvm_module_write_bitcode(VALUE self, VALUE file_name) {
|
151
|
+
Check_Type(file_name, T_STRING);
|
152
|
+
|
153
|
+
// Don't really know how to handle c++ streams well,
|
154
|
+
// dumping all into string buffer and then saving
|
155
|
+
std::ofstream file;
|
156
|
+
file.open(StringValuePtr(file_name));
|
157
|
+
WriteBitcodeToFile(LLVM_MODULE(self), file); // Convert value into a string.
|
158
|
+
return Qtrue;
|
159
|
+
}
|
160
|
+
|
161
|
+
VALUE
|
162
|
+
llvm_execution_engine_run_function(int argc, VALUE *argv, VALUE klass) {
|
163
|
+
if(argc < 1) { rb_raise(rb_eArgError, "Expected at least one argument"); }
|
164
|
+
CHECK_TYPE(argv[0], cLLVMFunction);
|
165
|
+
Function *func = LLVM_FUNCTION(argv[0]);
|
166
|
+
|
167
|
+
// Using run function is much slower than getting C function pointer
|
168
|
+
// and calling that, but it lets us pass in arbitrary numbers of
|
169
|
+
// arguments easily for now, which is nice
|
170
|
+
std::vector<GenericValue> arg_values;
|
171
|
+
for(int i = 1; i < argc; ++i) {
|
172
|
+
GenericValue arg_val;
|
173
|
+
arg_val.IntVal = APInt(sizeof(long)*8, argv[i]);
|
174
|
+
arg_values.push_back(arg_val);
|
175
|
+
}
|
176
|
+
|
177
|
+
GenericValue v = EE->runFunction(func, arg_values);
|
178
|
+
VALUE val = v.IntVal.getZExtValue();
|
179
|
+
return val;
|
180
|
+
}
|
181
|
+
|
182
|
+
/* For tests: assume no args, return uncoverted int and turn it into fixnum */
|
183
|
+
VALUE llvm_execution_engine_run_autoconvert(VALUE klass, VALUE func) {
|
184
|
+
std::vector<GenericValue> args;
|
185
|
+
GenericValue v = EE->runFunction(LLVM_FUNCTION(func), args);
|
186
|
+
VALUE val = INT2NUM(v.IntVal.getZExtValue());
|
187
|
+
return val;
|
188
|
+
}
|
189
|
+
}
|