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.
@@ -0,0 +1,73 @@
1
+ #define __STDC_LIMIT_MACROS
2
+
3
+ #include "llvm/Module.h"
4
+ #include "llvm/DerivedTypes.h"
5
+ #include "llvm/Constants.h"
6
+ #include "llvm/Instructions.h"
7
+ #include "llvm/ModuleProvider.h"
8
+ #include "llvm/PassManager.h"
9
+ #include "llvm/LinkAllPasses.h"
10
+ #include "llvm/Target/TargetData.h"
11
+ #include "llvm/Transforms/Scalar.h"
12
+ #include "llvm/Analysis/Verifier.h"
13
+ #include "llvm/ExecutionEngine/JIT.h"
14
+ #include "llvm/ExecutionEngine/Interpreter.h"
15
+ #include "llvm/ExecutionEngine/GenericValue.h"
16
+ #include "llvm/Support/IRBuilder.h"
17
+ #include <iostream>
18
+ using namespace llvm;
19
+
20
+ #include "ruby.h"
21
+
22
+ extern VALUE cLLVMRuby;
23
+ extern VALUE cLLVMValue;
24
+ extern VALUE cLLVMUser;
25
+ extern VALUE cLLVMUse;
26
+ extern VALUE cLLVMModule;
27
+ extern VALUE cLLVMFunction;
28
+ extern VALUE cLLVMBasicBlock;
29
+ extern VALUE cLLVMBuilder;
30
+ extern VALUE cLLVMType;
31
+ extern VALUE cLLVMPointerType;
32
+ extern VALUE cLLVMStructType;
33
+ extern VALUE cLLVMArrayType;
34
+ extern VALUE cLLVMVectorType;
35
+ extern VALUE cLLVMFunctionType;
36
+ extern VALUE cLLVMInstruction;
37
+ extern VALUE cLLVMBinaryOperator;
38
+ extern VALUE cLLVMAllocationInst;
39
+
40
+ #define HANDLE_TERM_INST(Num, Opcode, Klass) extern VALUE cLLVM##Klass;
41
+ #define HANDLE_MEMORY_INST(Num, Opcode, Klass) extern VALUE cLLVM##Klass;
42
+ #define HANDLE_OTHER_INST(Num, Opcode, Klass) extern VALUE cLLVM##Klass;
43
+ #include "llvm/Instruction.def"
44
+
45
+ extern VALUE cLLVMBinaryOps;
46
+ extern VALUE cLLVMPhi;
47
+ extern VALUE cLLVMPassManager;
48
+
49
+ #define LLVM_VAL(obj) ((Value*)DATA_PTR(obj))
50
+ #define LLVM_USER(obj) ((User*)DATA_PTR(obj))
51
+ #define LLVM_USE(obj) ((Use*)DATA_PTR(obj))
52
+ #define LLVM_TYPE(obj) ((Type*)DATA_PTR(obj))
53
+ #define LLVM_FUNC_TYPE(obj) ((FunctionType*)DATA_PTR(obj))
54
+ #define LLVM_MODULE(obj) ((Module*)DATA_PTR(obj))
55
+ #define LLVM_FUNCTION(obj) ((Function*)DATA_PTR(obj))
56
+ #define LLVM_BASIC_BLOCK(obj) ((BasicBlock*)DATA_PTR(obj))
57
+ #define LLVM_INSTRUCTION(obj) ((Instruction*)DATA_PTR(obj))
58
+ #define LLVM_PHI(obj) ((PHINode*)DATA_PTR(obj))
59
+
60
+ #define CHECK_TYPE(val, klass)\
61
+ if(!rb_obj_is_kind_of(val, klass)) {\
62
+ rb_raise(rb_eTypeError, "wrong argument type: %s given, expected %s", rb_obj_classname(val), rb_class2name(klass));\
63
+ }
64
+
65
+ extern "C" {
66
+ VALUE llvm_value_wrap(Value*);
67
+ VALUE llvm_user_wrap(User*);
68
+ VALUE llvm_use_wrap(Use*);
69
+ VALUE llvm_function_wrap(Function*);
70
+ VALUE llvm_basic_block_wrap(BasicBlock*);
71
+ VALUE llvm_function_create_block(VALUE);
72
+ VALUE llvm_instruction_wrap(Instruction*);
73
+ }
@@ -0,0 +1,146 @@
1
+ require 'llvmruby'
2
+
3
+ class Fixnum
4
+ def llvm(type = LLVM::MACHINE_WORD)
5
+ LLVM::Value.get_constant(type, self)
6
+ end
7
+ end
8
+
9
+ class Float
10
+ def llvm
11
+ LLVM::Value.get_float_constant(self)
12
+ end
13
+ end
14
+
15
+ class Object
16
+ def immediate
17
+ LLVM::Value.get_immediate_constant(self)
18
+ end
19
+ end
20
+
21
+ class LLVM::Value
22
+ def llvm
23
+ self
24
+ end
25
+
26
+ def immediate
27
+ self
28
+ end
29
+ end
30
+
31
+ module LLVM
32
+ # enum llvm::Type::TypeID
33
+ VoidTyID, FloatTyID, DoubleTyID, X86_FP80TyID, FP128TyID, PPC_FP128TyID, LabelTyID, IntegerTyID,
34
+ FunctionTyID, StructTyID, ArrayTyID, PointerTyID, OpaqueTyID, VectorTyID = (0..13).to_a
35
+
36
+ class Builder
37
+ def self.add_bin_op(op)
38
+ define_method(op.downcase) do |x, y|
39
+ bin_op(Instruction.const_get(op), x, y)
40
+ end
41
+ end
42
+
43
+ bin_ops = ['Add', 'Sub', 'Mul', 'UDiv', 'SDiv', 'FDiv', 'URem', 'SRem', 'FRem']
44
+ bin_ops += ['Shl', 'LShr', 'AShr', 'And', 'Or', 'Xor']
45
+ bin_ops.each {|op| add_bin_op(op)}
46
+
47
+ Instruction.constants.grep(/^ICMP_/) do |pred|
48
+ define_method(pred.downcase) do |x, y|
49
+ icmp(Instruction.const_get(pred), x, y)
50
+ end
51
+ end
52
+
53
+ Instruction.constants.grep(/^FCMP_/) do |pred|
54
+ define_method(pred.downcase) do |x, y|
55
+ fcmp(Instruction.const_get(pred), x, y)
56
+ end
57
+ end
58
+
59
+ def self.define_cast(name, inst)
60
+ define_method(name) do |val, dest_type|
61
+ cast(inst, val, dest_type)
62
+ end
63
+ end
64
+
65
+ define_cast(:trunc, Instruction::Trunc)
66
+ define_cast(:zext, Instruction::ZExt)
67
+ define_cast(:sext, Instruction::SExt)
68
+ define_cast(:fp_to_si, Instruction::FPToSI)
69
+ define_cast(:fp_to_ui, Instruction::FPToUI)
70
+ define_cast(:ui_to_fp, Instruction::UIToFP)
71
+ define_cast(:si_to_fp, Instruction::SIToFP)
72
+ define_cast(:fp_trunc, Instruction::FPTrunc)
73
+ define_cast(:fp_ext, Instruction::FPExt)
74
+ define_cast(:ptr_to_int, Instruction::PtrToInt)
75
+ define_cast(:int_to_ptr, Instruction::IntToPtr)
76
+ define_cast(:bit_cast, Instruction::BitCast)
77
+
78
+ def write(&b)
79
+ instance_eval(&b)
80
+ end
81
+ end
82
+
83
+ # describe structures used by the ruby 1.8/1.9 interpreters
84
+ module RubyInternals
85
+ FIXNUM_FLAG = 0x1.llvm
86
+ CHAR = Type::Int8Ty
87
+ P_CHAR = Type::pointer(CHAR)
88
+ LONG = MACHINE_WORD
89
+ INT = Type::Int32Ty
90
+ VALUE = MACHINE_WORD
91
+ P_VALUE = Type::pointer(VALUE)
92
+ ID = MACHINE_WORD
93
+ RBASIC = Type::struct([VALUE, VALUE])
94
+ RARRAY = Type::struct([RBASIC, LONG, LONG, P_VALUE])
95
+ P_RARRAY = Type::pointer(RARRAY)
96
+ RSTRING = Type::struct([RBASIC, LONG, P_CHAR, VALUE])
97
+ P_RSTRING = Type::pointer(RSTRING)
98
+ end
99
+
100
+ # include this into the builder to get methods for manipulating ruby values
101
+ module RubyHelpers
102
+ include RubyInternals
103
+
104
+ def fixnum?(val)
105
+ self.and(FIXNUM_FLAG, val)
106
+ end
107
+
108
+ def num2fix(val)
109
+ shifted = shl(val, 1.llvm)
110
+ xor(FIXNUM_FLAG, shifted)
111
+ end
112
+
113
+ def fix2int(val)
114
+ x = xor(FIXNUM_FLAG, val)
115
+ lshr(val, 1.llvm)
116
+ end
117
+
118
+ def slen(str)
119
+ val_ptr = int_to_ptr(str, P_RSTRING)
120
+ len_ptr = struct_gep(val_ptr, 1)
121
+ load(len_ptr)
122
+ end
123
+
124
+ def alen(ary)
125
+ val_ptr = int_to_ptr(ary, P_RARRAY)
126
+ len_ptr = struct_gep(val_ptr, 1)
127
+ load(len_ptr)
128
+ end
129
+
130
+ def aref(ary, idx)
131
+ val_ptr = int_to_ptr(ary, P_RARRAY)
132
+ data_ptr = struct_gep(val_ptr, 3)
133
+ data_ptr = load(data_ptr)
134
+ slot_n = gep(data_ptr, idx.llvm)
135
+ load(slot_n)
136
+ end
137
+
138
+ def aset(ary, idx, set)
139
+ val_ptr = int_to_ptr(ary, P_RARRAY)
140
+ data_ptr = struct_gep(val_ptr, 3)
141
+ data_ptr = load(data_ptr)
142
+ slot_n = gep(data_ptr, idx.llvm)
143
+ store(set, slot_n)
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,352 @@
1
+ require 'llvm'
2
+ include LLVM
3
+ include RubyInternals
4
+
5
+ class Symbol
6
+ # turn a symbol object_id into a VALUE
7
+ # from gc.c, symbols object_id's are calculated like this:
8
+ # SYM2ID(x) = RSHIFT((unsigned long)x,8)
9
+ # object_id = (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG;
10
+ def llvm
11
+ (((object_id/20) << 8) | 0xe).llvm(MACHINE_WORD)
12
+ end
13
+ end
14
+
15
+ class Object
16
+ def llvm
17
+ LLVM::Value.get_immediate_constant(self)
18
+ end
19
+
20
+ def llvm_send(f)
21
+ # for now, pass the receiver as the first argument
22
+ ExecutionEngine.runFunction(f, self)
23
+ end
24
+ end
25
+
26
+ class Builder
27
+ include RubyHelpers
28
+
29
+ def self.set_globals(b)
30
+ @@stack = b.alloca(VALUE, 100)
31
+ @@stack_ptr = b.alloca(P_VALUE, 0)
32
+ b.store(@@stack, @@stack_ptr)
33
+ @@locals = b.alloca(VALUE, 100)
34
+ end
35
+
36
+ def stack
37
+ @@stack
38
+ end
39
+
40
+ def stack_ptr
41
+ @@stack_ptr
42
+ end
43
+
44
+ def push(val)
45
+ sp = load(stack_ptr)
46
+ store(val, sp)
47
+ new_sp = gep(sp, 1.llvm)
48
+ store(new_sp, stack_ptr)
49
+ end
50
+
51
+ def pop
52
+ sp = load(stack_ptr)
53
+ new_sp = gep(sp, -1.llvm)
54
+ store(new_sp, stack_ptr)
55
+ load(new_sp)
56
+ end
57
+
58
+ def peek(n = 1)
59
+ sp = load(stack_ptr)
60
+ peek_sp = gep(sp, (-n).llvm)
61
+ load(peek_sp)
62
+ end
63
+
64
+ def topn(n)
65
+ sp = load(stack_ptr)
66
+ idx = sub((-1).llvm(Type::Int32Ty), n)
67
+ top_sp = gep(sp, idx)
68
+ load(top_sp)
69
+ end
70
+
71
+ def locals
72
+ @@locals
73
+ end
74
+ end
75
+
76
+ class OpCodeBuilder
77
+ def initialize(mod, func, rb_funcs)
78
+ @mod = mod
79
+ @func = func
80
+ @rb_funcs = rb_funcs
81
+ end
82
+
83
+ def get_self
84
+ @func.arguments.first
85
+ end
86
+
87
+ def nop(b, oprnd)
88
+ end
89
+
90
+ def putnil(b, oprnd)
91
+ b.push(nil.immediate)
92
+ end
93
+
94
+ def putself(b, oprnd)
95
+ b.push(get_self)
96
+ end
97
+
98
+ def putobject(b, oprnd)
99
+ b.push(oprnd.llvm)
100
+ end
101
+
102
+ def pop(b, oprnd)
103
+ b.pop
104
+ end
105
+
106
+ def dup(b, oprnd)
107
+ b.push(b.peek)
108
+ end
109
+
110
+ def swap(b, oprn)
111
+ v1 = b.pop
112
+ v2 = b.pop
113
+ b.push(v1)
114
+ b.push(v2)
115
+ end
116
+
117
+ def setlocal(b, oprnd)
118
+ v = b.pop
119
+ local_slot = b.gep(b.locals, oprnd.llvm)
120
+ b.store(v, local_slot)
121
+ end
122
+
123
+ def getlocal(b, oprnd)
124
+ local_slot = b.gep(b.locals, oprnd.llvm)
125
+ val = b.load(local_slot)
126
+ b.push(val)
127
+ end
128
+
129
+ def opt_plus(b, oprnd)
130
+ v1 = b.fix2int(b.pop)
131
+ v2 = b.fix2int(b.pop)
132
+ sum = b.add(v1, v2)
133
+ b.push(b.num2fix(sum))
134
+ end
135
+
136
+ def opt_minus(b, oprnd)
137
+ v1 = b.fix2int(b.pop)
138
+ v2 = b.fix2int(b.pop)
139
+ sum = b.sub(v2, v1)
140
+ b.push(b.num2fix(sum))
141
+ end
142
+
143
+ def opt_mult(b, oprnd)
144
+ v1 = b.fix2int(b.pop)
145
+ v2 = b.fix2int(b.pop)
146
+ mul = b.mul(v1, v2)
147
+ b.push(b.num2fix(mul))
148
+ end
149
+
150
+ def opt_aref(b, oprnd)
151
+ idx = b.fix2int(b.pop)
152
+ ary = b.pop
153
+ out = b.aref(ary, idx)
154
+ b.push(out)
155
+ end
156
+
157
+ def opt_aset(b, oprnd)
158
+ set = b.pop
159
+ idx = b.fix2int(b.pop)
160
+ ary = b.pop
161
+ b.call(@rb_funcs[:rb_ary_store], ary, idx, set)
162
+ b.push(set)
163
+ end
164
+
165
+ def opt_length(b, oprnd)
166
+ recv = b.pop
167
+ len = b.alen(recv)
168
+ len = b.num2fix(len)
169
+ b.push(len)
170
+ end
171
+
172
+ def opt_lt(b, oprnd)
173
+ obj = b.pop
174
+ recv = b.pop
175
+ x = b.fix2int(recv)
176
+ y = b.fix2int(obj)
177
+ val = b.icmp_slt(x, y)
178
+ val = b.int_cast(val, LONG, false)
179
+ val = b.mul(val, 2.llvm)
180
+ b.push(val)
181
+ end
182
+
183
+ def opt_gt(b, oprnd)
184
+ obj = b.pop
185
+ recv = b.pop
186
+ x = b.fix2int(recv)
187
+ y = b.fix2int(obj)
188
+ val = b.icmp_sgt(x, y)
189
+ val = b.int_cast(val, LONG, false)
190
+ val = b.mul(val, 2.llvm)
191
+ b.push(val)
192
+ end
193
+
194
+ def opt_ge(b, oprnd)
195
+ obj = b.pop
196
+ recv = b.pop
197
+ x = b.fix2int(recv)
198
+ y = b.fix2int(obj)
199
+ val = b.icmp_sge(x, y)
200
+ val = b.int_cast(val, LONG, false)
201
+ val = b.mul(val, 2.llvm)
202
+ b.push(val)
203
+ end
204
+
205
+ def getinstancevariable(b, oprnd)
206
+ id = b.call(@rb_funcs[:rb_to_id], oprnd.llvm)
207
+ v = b.call(@rb_funcs[:rb_ivar_get], get_self, id)
208
+ b.push(v)
209
+ end
210
+
211
+ def setinstancevariable(b, oprnd)
212
+ new_val = b.peek
213
+ id = b.call(@rb_funcs[:rb_to_id], oprnd.llvm)
214
+ b.call(@rb_funcs[:rb_ivar_set], get_self, id, new_val)
215
+ end
216
+
217
+ def newarray(b, oprnd)
218
+ ary = b.call(@rb_funcs[:rb_ary_new])
219
+ b.push(ary)
220
+ end
221
+
222
+ def newhash(b, oprnd)
223
+ hash = b.call(@rb_funcs[:rb_hash_new])
224
+ i = oprnd.llvm(Type::Int32Ty) # This is an integer not a fixnum
225
+
226
+ entry_block = @func.create_block
227
+ loop_block = @func.create_block
228
+ exit_block = @func.create_block
229
+
230
+ b.br(entry_block)
231
+ b.set_insert_point(entry_block)
232
+ cmp = b.icmp_sgt(i, 0.llvm(Type::Int32Ty))
233
+ b.cond_br(cmp, loop_block, exit_block)
234
+
235
+ b.set_insert_point(loop_block)
236
+ idx = b.phi(Type::Int32Ty)
237
+ idx.add_incoming(i, entry_block)
238
+ next_idx = b.sub(idx, 2.llvm(Type::Int32Ty))
239
+ idx.add_incoming(next_idx, loop_block)
240
+
241
+ n_1 = b.sub(idx, 1.llvm(Type::Int32Ty))
242
+ n_2 = b.sub(idx, 2.llvm(Type::Int32Ty))
243
+ b.call(@rb_funcs[:rb_hash_aset], hash, b.topn(n_1), b.topn(n_2))
244
+
245
+ cmp = b.icmp_sgt(next_idx, 0.llvm(Type::Int32Ty))
246
+ b.cond_br(cmp, loop_block, exit_block)
247
+
248
+ b.set_insert_point(exit_block)
249
+ b.push(hash)
250
+ end
251
+
252
+ def send(b, oprnd)
253
+ recv = nil.immediate
254
+ id = b.call(@rb_funcs[:rb_to_id], :inspect.immediate)
255
+ argc = 0.llvm(Type::Int32Ty)
256
+ val = b.call(@rb_funcs[:rb_funcall2], recv, id, argc, b.stack)
257
+ b.push(val)
258
+ end
259
+ end
260
+
261
+ class RubyVM
262
+ def self.start
263
+ @module = LLVM::Module.new('ruby_vm')
264
+ ExecutionEngine.get(@module)
265
+
266
+ @rb_ary_new = @module.external_function('rb_ary_new', ftype(VALUE, []))
267
+ @rb_hash_new = @module.external_function('rb_hash_new', ftype(VALUE, []))
268
+ @rb_hash_aset = @module.external_function('rb_hash_aset', ftype(VALUE, [VALUE, VALUE, VALUE]))
269
+ @rb_ary_store = @module.external_function('rb_ary_store', ftype(VALUE, [VALUE, LONG, VALUE]))
270
+ @rb_to_id = @module.external_function('rb_to_id', ftype(VALUE, [VALUE]))
271
+ @rb_ivar_get = @module.external_function('rb_ivar_get', ftype(VALUE, [VALUE, ID]))
272
+ @rb_ivar_set = @module.external_function('rb_ivar_set', ftype(VALUE, [VALUE, ID, VALUE]))
273
+ @rb_funcall2 = @module.external_function('rb_funcall2', ftype(VALUE, [VALUE, ID, INT, P_VALUE]))
274
+
275
+ @rb_funcs = {
276
+ :rb_ary_new => @rb_ary_new,
277
+ :rb_hash_new => @rb_hash_new,
278
+ :rb_hash_aset => @rb_hash_aset,
279
+ :rb_ary_store => @rb_ary_store,
280
+ :rb_to_id => @rb_to_id,
281
+ :rb_ivar_get => @rb_ivar_get,
282
+ :rb_ivar_set => @rb_ivar_set,
283
+ :rb_funcall2 => @rb_funcall2
284
+ }
285
+
286
+ @func_n = 0
287
+ end
288
+
289
+ def self.ftype(ret, args)
290
+ Type.function(ret, args)
291
+ end
292
+
293
+ def self.call_bytecode(bytecode, farg)
294
+ f = compile_bytecode(bytecode)
295
+ ExecutionEngine.run_function(f, nil, farg)
296
+ end
297
+
298
+ def self.method_send(recv, compiled_method, farg = nil)
299
+ ExecutionEngine.run_function(compiled_method, recv, farg)
300
+ end
301
+
302
+ def self.compile_bytecode(bytecode)
303
+ f = @module.get_or_insert_function("vm_func#{@func_n}", Type.function(VALUE, [VALUE, VALUE]))
304
+ @func_n += 1
305
+
306
+ get_self = f.arguments[0]
307
+
308
+ entry_block = f.create_block
309
+ b = entry_block.builder
310
+ Builder.set_globals(b)
311
+ b.push(f.arguments[1])
312
+
313
+ blocks = bytecode.map { f.create_block }
314
+ exit_block = f.create_block
315
+ blocks << exit_block
316
+ b.br(blocks.first)
317
+
318
+ op_builder = OpCodeBuilder.new(@module, f, @rb_funcs)
319
+
320
+ bytecode.each_with_index do |opcode, i|
321
+ op, arg = opcode
322
+
323
+ block = blocks[i]
324
+ b.set_insert_point(block)
325
+
326
+ case op
327
+ when :jump
328
+ b.br(blocks[arg])
329
+ when :branchif
330
+ v = b.pop
331
+ cmp = b.icmp_eq(v, 0.llvm)
332
+ b.cond_br(cmp, blocks[i+1], blocks[arg])
333
+ when :branchunless
334
+ v = b.pop
335
+ cmp = b.icmp_eq(v, 0.llvm)
336
+ b.cond_br(cmp, blocks[arg], blocks[i+1])
337
+ else
338
+ op_builder.__send__(op, b, arg)
339
+ end
340
+
341
+ if op != :jump && op != :branchif && op != :branchunless
342
+ b.br(blocks[i+1])
343
+ end
344
+ end
345
+
346
+ b = exit_block.builder
347
+ ret_val = b.pop
348
+ b.return(ret_val)
349
+
350
+ f
351
+ end
352
+ end