plessl-llvmruby 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/COPYING ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2008 Thomas Bagby
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README ADDED
@@ -0,0 +1,76 @@
1
+ * What's LLVMRuby
2
+
3
+ LLVMRuby is a set of bindings making the LLVM compiler infrastructure
4
+ (http://llvm.org) usable from Ruby. This extention allows using LLVM
5
+ as an abstract assembler and reflects a good chunk of the LLVM class
6
+ hierarchy into Ruby. Included is an example of using this to build
7
+ a simple JIT compiler, written entirely in Ruby, which is able to
8
+ interact with the native Ruby 1.8/1.9 data types.
9
+
10
+ * How to build
11
+
12
+ You must get LLVM from svn and build it separately:
13
+
14
+ $ svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
15
+
16
+ Make sure that you configure LLVM with PIC enabled:
17
+
18
+ $ ./configure --enable-pic
19
+
20
+ Add the llvm bin directory to your path, extconf needs to be able to find llvm-conf:
21
+
22
+ $ export PATH=$PATH:/$LLVMDIR/Release/bin
23
+
24
+ Run rake
25
+
26
+ $ rake
27
+
28
+ Run the tests (you will need Rake installed)
29
+
30
+ $ rake test
31
+
32
+ Look in test.rb to see examples of use and start messing around. The
33
+ project was recently reorganized in gem format with Ruby files in lib,
34
+ and C/CPP and extension in ext. You will need to either load the
35
+ library as a gem or make sure that both lib and ext dirs are in your
36
+ load path.
37
+
38
+ * Caveats
39
+
40
+ I created this using very latest LLVM (from svn, soon to be 2.4). Other
41
+ versions may not work. I have been trying to get the 2.3 released package
42
+ to work, only one conditional typedef is required, but it complaining about
43
+ fPIC stuff :(
44
+
45
+ I primarily develop this on my home machine which is 64bit Fedora. I
46
+ occasionally test it on a 32bit CentOS machine, and recently tested it
47
+ on a 32bit MacBook. It built and passed tests with no issues. My
48
+ knowledge of building either Ruby or LLVM on Windows is minimal. It
49
+ should be doable, but I don't believe LLVM currently is usable with
50
+ VC++, which is the main compiler for Ruby on Windows, so you may run
51
+ into fun times trying to figure out a good way to make that go.
52
+
53
+ * Things that definitely do not work right now
54
+
55
+ No attempt has been made to properly free LLVM objects. This probably
56
+ isn't hard, LLVM api has easy to deal with memory management. Many LLVM
57
+ objects end up owned by modules/execution engine and shouldn't be freed
58
+ normally anyway.
59
+
60
+ There needs to be a lot more exception raising when arguments are of wrong
61
+ number/type.
62
+
63
+ Malformed LLVM functions will cause the program to abort, even just
64
+ from calling verify on a module. This seems like a bug in LLVM.
65
+ Verification in theory is slow and should be used only for debugging, but
66
+ it would nice if tests did not abort and die because of missing block
67
+ terminators or whatever.
68
+
69
+ * Copying
70
+
71
+ See the file COPYING
72
+
73
+ * Author
74
+
75
+ For questions or answers, my email is: tomatobagby@gmail.com
76
+
@@ -0,0 +1,31 @@
1
+ require 'rake/testtask'
2
+
3
+ desc "Run the tests"
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'ext'
6
+ t.test_files = FileList['test/test*.rb']
7
+ t.warning = true
8
+ end
9
+
10
+ OBJ = "ext/llvmruby." + Config::CONFIG["DLEXT"]
11
+
12
+ file "ext/Makefile" do
13
+ #cmd = "extconf.rb --with-llvm-include=`llvm-config --includedir` --with-llvm-lib=`llvm-config --libdir`"
14
+ cmd = 'extconf.rb'
15
+ Dir.chdir("ext") { ruby(cmd) }
16
+ end
17
+
18
+ file OBJ => %w(ext/Makefile) + FileList["ext/*.{cpp,c,h}"] do
19
+ Dir.chdir("ext") { sh "make" }
20
+ end
21
+
22
+ desc "Compile llvmruby extensions"
23
+ task :compile => OBJ
24
+ task :default => :compile
25
+
26
+ desc "Remove compiled files"
27
+ task :clean do |t|
28
+ for file in FileList.new("ext/*.o", "ext/Makefile", "ext/mkmf.log", OBJ)
29
+ File.delete(file) rescue true
30
+ end
31
+ end
@@ -0,0 +1,14 @@
1
+ require 'mkmf'
2
+
3
+ extension_name = 'llvmruby'
4
+
5
+ dir_config(extension_name)
6
+ dir_config('llvm', `llvm-config --includedir`.strip, `llvm-config --libdir`.strip)
7
+
8
+ have_library('stdc++')
9
+ have_library('pthread')
10
+
11
+ with_ldflags(`llvm-config --libs all`) do
12
+ create_makefile(extension_name)
13
+ end
14
+
@@ -0,0 +1,299 @@
1
+ #include "llvmruby.h"
2
+
3
+ extern VALUE cLLVMBasicBlock;
4
+ extern VALUE cLLVMBuilder;
5
+
6
+ extern "C" {
7
+ VALUE
8
+ llvm_basic_block_wrap(BasicBlock* bb) {
9
+ return Data_Wrap_Struct(cLLVMBasicBlock, NULL, NULL, bb);
10
+ }
11
+
12
+ VALUE
13
+ llvm_basic_block_size(VALUE self) {
14
+ BasicBlock *bb = LLVM_BASIC_BLOCK(self);
15
+ return INT2NUM(bb->size());
16
+ }
17
+
18
+ VALUE
19
+ llvm_basic_block_get_instruction_list(VALUE self) {
20
+ BasicBlock *bb = LLVM_BASIC_BLOCK(self);
21
+ VALUE ins_array = rb_ary_new();
22
+ BasicBlock::iterator ins = bb->begin();
23
+ while(ins != bb->end()) {
24
+ Instruction *i = ins++;
25
+ rb_ary_push(ins_array, llvm_instruction_wrap(i));
26
+ }
27
+ return ins_array;
28
+ }
29
+
30
+ VALUE
31
+ llvm_basic_block_builder(VALUE self) {
32
+ BasicBlock* bb;
33
+ Data_Get_Struct(self, BasicBlock, bb);
34
+ IRBuilder<> *builder = new IRBuilder<>(bb);
35
+ return Data_Wrap_Struct(cLLVMBuilder, NULL, NULL, builder);
36
+ }
37
+
38
+ #define DATA_GET_BUILDER IRBuilder<> *builder; Data_Get_Struct(self, IRBuilder<>, builder);
39
+ #define DATA_GET_BLOCK BasicBlock *bb; CHECK_TYPE(rbb, cLLVMBasicBlock); Data_Get_Struct(rbb, BasicBlock, bb);
40
+
41
+ VALUE
42
+ llvm_builder_set_insert_point(VALUE self, VALUE rbb) {
43
+ DATA_GET_BUILDER
44
+ DATA_GET_BLOCK
45
+ builder->SetInsertPoint(bb);
46
+ return self;
47
+ }
48
+
49
+ VALUE
50
+ llvm_builder_bin_op(VALUE self, VALUE rbin_op, VALUE rv1, VALUE rv2) {
51
+ Check_Type(rbin_op, T_FIXNUM);
52
+ DATA_GET_BUILDER
53
+
54
+ Instruction::BinaryOps bin_op = (Instruction::BinaryOps)FIX2INT(rbin_op);
55
+
56
+ Value *v1, *v2;
57
+ Data_Get_Struct(rv1, Value, v1);
58
+ Data_Get_Struct(rv2, Value, v2);
59
+ Value *res = builder->CreateBinOp(bin_op, v1, v2);
60
+ return Data_Wrap_Struct(cLLVMBinaryOperator, NULL, NULL, res);
61
+ }
62
+
63
+ VALUE
64
+ llvm_builder_phi(VALUE self, VALUE type) {
65
+ CHECK_TYPE(type, cLLVMType);
66
+ DATA_GET_BUILDER
67
+ PHINode *v = builder->CreatePHI(LLVM_TYPE(type));
68
+ return Data_Wrap_Struct(cLLVMPhi, NULL, NULL, v);
69
+ }
70
+
71
+ VALUE
72
+ llvm_phi_add_incoming(VALUE self, VALUE val, VALUE rbb) {
73
+ CHECK_TYPE(val, cLLVMValue);
74
+
75
+ DATA_GET_BLOCK
76
+ PHINode *phi = LLVM_PHI(self);
77
+
78
+ phi->addIncoming(LLVM_VAL(val), bb);
79
+ return self;
80
+ }
81
+
82
+ VALUE
83
+ llvm_builder_return(VALUE self, VALUE rv) {
84
+ CHECK_TYPE(rv, cLLVMValue);
85
+ DATA_GET_BUILDER
86
+ return Data_Wrap_Struct(cLLVMReturnInst, NULL, NULL, builder->CreateRet(LLVM_VAL(rv)));
87
+ }
88
+
89
+ VALUE
90
+ llvm_builder_br(VALUE self, VALUE rblock) {
91
+ DATA_GET_BUILDER
92
+
93
+ BasicBlock *bb;
94
+ Data_Get_Struct(rblock, BasicBlock, bb);
95
+
96
+ Value *branch_instr = builder->CreateBr(bb);
97
+ return Data_Wrap_Struct(cLLVMBranchInst, NULL, NULL, branch_instr);
98
+ }
99
+
100
+ VALUE
101
+ llvm_builder_cond_br(VALUE self, VALUE rcond, VALUE rtrue_block, VALUE rfalse_block) {
102
+ DATA_GET_BUILDER
103
+
104
+ Value *cond;
105
+ Data_Get_Struct(rcond, Value, cond);
106
+
107
+ BasicBlock *true_block, *false_block;
108
+ Data_Get_Struct(rtrue_block, BasicBlock, true_block);
109
+ Data_Get_Struct(rfalse_block, BasicBlock, false_block);
110
+
111
+ Value *branch_instr = builder->CreateCondBr(cond, true_block, false_block);
112
+ return Data_Wrap_Struct(cLLVMBranchInst, NULL, NULL, branch_instr);
113
+ }
114
+
115
+ VALUE
116
+ llvm_builder_switch(VALUE self, VALUE rv, VALUE rdefault) {
117
+ DATA_GET_BUILDER
118
+
119
+ BasicBlock *deflt;
120
+ Data_Get_Struct(rdefault, BasicBlock, deflt);
121
+
122
+ Value *v;
123
+ Data_Get_Struct(rv, Value, v);
124
+
125
+ Instruction *switch_instr = builder->CreateSwitch(v, deflt);
126
+ return llvm_instruction_wrap(switch_instr);
127
+ }
128
+
129
+ VALUE
130
+ llvm_builder_malloc(VALUE self, VALUE rtype, VALUE rsize) {
131
+ DATA_GET_BUILDER
132
+
133
+ const Type *type;
134
+ Data_Get_Struct(rtype, Type, type);
135
+
136
+ Value *size = ConstantInt::get(Type::Int32Ty, FIX2INT(rsize));
137
+ Instruction *v = builder->CreateMalloc(type, size);
138
+ return llvm_instruction_wrap(v);
139
+ }
140
+
141
+ VALUE
142
+ llvm_builder_free(VALUE self, VALUE rptr) {
143
+ DATA_GET_BUILDER
144
+ Value *v = LLVM_VAL(rptr);
145
+ Instruction *free_inst = builder->CreateFree(v);
146
+ return llvm_instruction_wrap(free_inst);
147
+ }
148
+
149
+ VALUE
150
+ llvm_builder_alloca(VALUE self, VALUE rtype, VALUE rsize) {
151
+ DATA_GET_BUILDER
152
+
153
+ const Type* type;
154
+ Data_Get_Struct(rtype, Type, type);
155
+
156
+ Value *size = ConstantInt::get(Type::Int32Ty, FIX2INT(rsize));
157
+ Instruction *v = builder->CreateAlloca(type, size);
158
+ return Data_Wrap_Struct(cLLVMAllocationInst, NULL, NULL, v);
159
+ }
160
+
161
+ VALUE
162
+ llvm_builder_load(VALUE self, VALUE rptr) {
163
+ DATA_GET_BUILDER
164
+
165
+ Value *ptr;
166
+ Data_Get_Struct(rptr, Value, ptr);
167
+ return Data_Wrap_Struct(cLLVMLoadInst, NULL, NULL, builder->CreateLoad(ptr));
168
+ }
169
+
170
+ VALUE
171
+ llvm_builder_store(VALUE self, VALUE rv, VALUE rptr) {
172
+ DATA_GET_BUILDER
173
+
174
+ Value *v, *ptr;
175
+ Data_Get_Struct(rv, Value, v);
176
+ Data_Get_Struct(rptr, Value, ptr);
177
+ return Data_Wrap_Struct(cLLVMStoreInst, NULL, NULL, builder->CreateStore(v, ptr));
178
+ }
179
+
180
+ VALUE
181
+ llvm_builder_icmp(VALUE self, VALUE pred, VALUE lhs, VALUE rhs) {
182
+ DATA_GET_BUILDER
183
+
184
+ CmpInst::Predicate p = (CmpInst::Predicate)FIX2INT(pred);
185
+ Value *v = builder->CreateICmp(p, LLVM_VAL(lhs), LLVM_VAL(rhs));
186
+ return Data_Wrap_Struct(cLLVMICmpInst, NULL, NULL, v);
187
+ }
188
+
189
+ VALUE
190
+ llvm_builder_fcmp(VALUE self, VALUE pred, VALUE lhs, VALUE rhs) {
191
+ DATA_GET_BUILDER
192
+
193
+ CmpInst::Predicate p = (CmpInst::Predicate)FIX2INT(pred);
194
+ Value *v = builder->CreateFCmp(p, LLVM_VAL(lhs), LLVM_VAL(rhs));
195
+ return Data_Wrap_Struct(cLLVMFCmpInst, NULL, NULL, v);
196
+ }
197
+
198
+ VALUE
199
+ llvm_builder_gep(VALUE self, VALUE rptr, VALUE ridx) {
200
+ DATA_GET_BUILDER
201
+
202
+ Value *ptr, *idx;
203
+ Data_Get_Struct(rptr, Value, ptr);
204
+ Data_Get_Struct(ridx, Value, idx);
205
+ return llvm_value_wrap(builder->CreateGEP(ptr, idx));
206
+ }
207
+
208
+ VALUE
209
+ llvm_builder_struct_gep(VALUE self, VALUE rptr, VALUE ridx) {
210
+ DATA_GET_BUILDER
211
+
212
+ Value *ptr;
213
+ Data_Get_Struct(rptr, Value, ptr);
214
+ return llvm_value_wrap(builder->CreateStructGEP(ptr, FIX2INT(ridx)));
215
+ }
216
+
217
+ VALUE
218
+ llvm_builder_cast(VALUE self, VALUE rop, VALUE rv, VALUE rdest_ty) {
219
+ DATA_GET_BUILDER
220
+
221
+ Instruction::CastOps op = (Instruction::CastOps)FIX2INT(rop);
222
+
223
+ Value *v;
224
+ Data_Get_Struct(rv, Value, v);
225
+
226
+ Type *dest_ty;
227
+ Data_Get_Struct(rdest_ty, Type, dest_ty);
228
+
229
+ return llvm_value_wrap(builder->CreateCast(op, v, dest_ty));
230
+ }
231
+
232
+ VALUE
233
+ llvm_builder_int_to_ptr(VALUE self, VALUE ri, VALUE rtype) {
234
+ DATA_GET_BUILDER
235
+
236
+ Value *i;
237
+ Data_Get_Struct(ri, Value, i);
238
+
239
+ const Type* type;
240
+ Data_Get_Struct(rtype, Type, type);
241
+
242
+ return llvm_value_wrap(builder->CreateIntToPtr(i, type));
243
+ }
244
+
245
+ VALUE llvm_builder_int_cast(VALUE self, VALUE i, VALUE type, VALUE sign) {
246
+ DATA_GET_BUILDER
247
+ bool isSigned = (sign != Qnil && sign != Qfalse);
248
+ return llvm_value_wrap(builder->CreateIntCast(LLVM_VAL(i), LLVM_TYPE(type), isSigned));
249
+ }
250
+
251
+ VALUE
252
+ llvm_builder_call(int argc, VALUE* argv, VALUE self) {
253
+ DATA_GET_BUILDER
254
+
255
+ Function *callee = LLVM_FUNCTION(argv[0]);
256
+ int num_args = argc-1;
257
+ Value** args = (Value**)alloca(num_args*sizeof(Value*));
258
+ for(int i = 0; i < num_args; ++i) {
259
+ args[i] = LLVM_VAL(argv[i+1]);
260
+ }
261
+ return llvm_value_wrap(builder->CreateCall(callee, args, args+num_args));
262
+ }
263
+
264
+ VALUE
265
+ llvm_builder_insert_element(VALUE self, VALUE rv, VALUE rnv, VALUE ridx) {
266
+ DATA_GET_BUILDER
267
+
268
+ Value *v, *nv, *idx;
269
+ Data_Get_Struct(rv, Value, v);
270
+ Data_Get_Struct(rnv, Value, nv);
271
+ Data_Get_Struct(ridx, Value, idx);
272
+
273
+ return llvm_value_wrap(builder->CreateInsertElement(v, nv, idx));
274
+ }
275
+
276
+ VALUE
277
+ llvm_builder_extract_element(VALUE self, VALUE rv, VALUE ridx) {
278
+ DATA_GET_BUILDER
279
+
280
+ Value *v, *idx;
281
+ Data_Get_Struct(rv, Value, v);
282
+ Data_Get_Struct(ridx, Value, idx);
283
+
284
+ return llvm_value_wrap(builder->CreateExtractElement(v, idx));
285
+ }
286
+
287
+ VALUE
288
+ llvm_builder_get_global(VALUE self) {
289
+ GlobalVariable *g = new GlobalVariable(Type::Int64Ty, false, GlobalValue::ExternalLinkage, 0, "shakalaka");
290
+ return llvm_value_wrap(g);
291
+ }
292
+
293
+ VALUE
294
+ llvm_builder_create_global_string_ptr(VALUE self, VALUE str) {
295
+ DATA_GET_BUILDER
296
+ Value *v = builder->CreateGlobalStringPtr(StringValuePtr(str));
297
+ return llvm_value_wrap(v);
298
+ }
299
+ }
@@ -0,0 +1,48 @@
1
+ #include "llvmruby.h"
2
+ #include <sstream>
3
+
4
+ extern "C" {
5
+ VALUE
6
+ llvm_function_wrap(Function *f) {
7
+ return Data_Wrap_Struct(cLLVMFunction, NULL, NULL, f);
8
+ }
9
+
10
+ VALUE
11
+ llvm_function_create_block(VALUE self) {
12
+ BasicBlock *bb = BasicBlock::Create("bb", LLVM_FUNCTION(self));
13
+ return llvm_basic_block_wrap(bb);
14
+ }
15
+
16
+ VALUE
17
+ llvm_function_arguments(VALUE self) {
18
+ Function *f = LLVM_FUNCTION(self);
19
+ VALUE arg_array = rb_ary_new();
20
+ Function::arg_iterator args = f->arg_begin();
21
+ while(args != f->arg_end()) {
22
+ Value *arg = args++;
23
+ rb_ary_push(arg_array, llvm_value_wrap(arg));
24
+ }
25
+ return arg_array;
26
+ }
27
+
28
+ VALUE
29
+ llvm_function_inspect(VALUE self) {
30
+ Function *f = LLVM_FUNCTION(self);
31
+ std::ostringstream strstrm;
32
+ strstrm << *f;
33
+ return rb_str_new2(strstrm.str().c_str());
34
+ }
35
+
36
+ VALUE
37
+ llvm_function_get_basic_block_list(VALUE self) {
38
+ Function *f = LLVM_FUNCTION(self);
39
+ VALUE bb_array = rb_ary_new();
40
+ Function::iterator bbs = f->begin();
41
+ while(bbs != f->end()) {
42
+ BasicBlock *bb = bbs++;
43
+ rb_ary_push(bb_array, llvm_basic_block_wrap(bb));
44
+ }
45
+ return bb_array;
46
+ }
47
+
48
+ }