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 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
+ }