tombagby-llvmruby 0.0.1

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/Debug/bin
23
+
24
+ Once you have built LLVM, run extconf.rb giving it location of LLVM:
25
+
26
+ $ ruby extconf.rb --with-llvm-include=/$DIR/llvm/include --with-llvm-lib=/$DIR/llvm/Debug/lib
27
+
28
+ Run make
29
+
30
+ $ make
31
+
32
+ Run the tests (you will need Rake installed)
33
+
34
+ $ rake test
35
+
36
+ Look in test.rb to see examples of use and start messing around.
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
+
data/Rakefile ADDED
@@ -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
data/ext/extconf.rb ADDED
@@ -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,296 @@
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
+ //CHECK_TYPE(rv1, cLLVMValue);
53
+ //CHECK_TYPE(rv2, cLLVMValue);
54
+ DATA_GET_BUILDER
55
+
56
+ Instruction::BinaryOps bin_op = (Instruction::BinaryOps)FIX2INT(rbin_op);
57
+
58
+ Value *v1, *v2;
59
+ Data_Get_Struct(rv1, Value, v1);
60
+ Data_Get_Struct(rv2, Value, v2);
61
+ Value *res = builder->CreateBinOp(bin_op, v1, v2);
62
+ return llvm_value_wrap(res);
63
+ }
64
+
65
+ VALUE
66
+ llvm_builder_phi(VALUE self, VALUE type) {
67
+ CHECK_TYPE(type, cLLVMType);
68
+ DATA_GET_BUILDER
69
+ PHINode *v = builder->CreatePHI(LLVM_TYPE(type));
70
+ return Data_Wrap_Struct(cLLVMPhi, NULL, NULL, v);
71
+ }
72
+
73
+ VALUE
74
+ llvm_phi_add_incoming(VALUE self, VALUE val, VALUE rbb) {
75
+ CHECK_TYPE(val, cLLVMValue);
76
+ DATA_GET_BLOCK
77
+ PHINode *phi = LLVM_PHI(self);
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 llvm_value_wrap(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
+ return llvm_value_wrap(builder->CreateBr(bb));
96
+ }
97
+
98
+ VALUE
99
+ llvm_builder_cond_br(VALUE self, VALUE rcond, VALUE rtrue_block, VALUE rfalse_block) {
100
+ DATA_GET_BUILDER
101
+
102
+ Value *cond;
103
+ Data_Get_Struct(rcond, Value, cond);
104
+
105
+ BasicBlock *true_block, *false_block;
106
+ Data_Get_Struct(rtrue_block, BasicBlock, true_block);
107
+ Data_Get_Struct(rfalse_block, BasicBlock, false_block);
108
+
109
+ return llvm_value_wrap(builder->CreateCondBr(cond, true_block, false_block));
110
+ }
111
+
112
+ VALUE
113
+ llvm_builder_switch(VALUE self, VALUE rv, VALUE rdefault) {
114
+ DATA_GET_BUILDER
115
+
116
+ BasicBlock *deflt;
117
+ Data_Get_Struct(rdefault, BasicBlock, deflt);
118
+
119
+ Value *v;
120
+ Data_Get_Struct(rv, Value, v);
121
+
122
+ Value* switch_instr = builder->CreateSwitch(v, deflt);
123
+ return Data_Wrap_Struct(cLLVMSwitchInst, NULL, NULL, switch_instr);
124
+ }
125
+
126
+ VALUE
127
+ llvm_builder_malloc(VALUE self, VALUE rtype, VALUE rsize) {
128
+ DATA_GET_BUILDER
129
+
130
+ const Type *type;
131
+ Data_Get_Struct(rtype, Type, type);
132
+
133
+ Value *size = ConstantInt::get(Type::Int32Ty, FIX2INT(rsize));
134
+ Value *v = builder->CreateMalloc(type, size);
135
+ return llvm_value_wrap(v);
136
+ }
137
+
138
+ VALUE
139
+ llvm_builder_free(VALUE self, VALUE rptr) {
140
+ DATA_GET_BUILDER
141
+ Value *v = LLVM_VAL(rptr);
142
+ builder->CreateFree(v);
143
+ return Qtrue;
144
+ }
145
+
146
+ VALUE
147
+ llvm_builder_alloca(VALUE self, VALUE rtype, VALUE rsize) {
148
+ DATA_GET_BUILDER
149
+
150
+ const Type* type;
151
+ Data_Get_Struct(rtype, Type, type);
152
+
153
+ Value *size = ConstantInt::get(Type::Int32Ty, FIX2INT(rsize));
154
+ Value *v = builder->CreateAlloca(type, size);
155
+ return llvm_value_wrap(v);
156
+ }
157
+
158
+ VALUE
159
+ llvm_builder_load(VALUE self, VALUE rptr) {
160
+ DATA_GET_BUILDER
161
+
162
+ Value *ptr;
163
+ Data_Get_Struct(rptr, Value, ptr);
164
+ return llvm_value_wrap(builder->CreateLoad(ptr));
165
+ }
166
+
167
+ VALUE
168
+ llvm_builder_store(VALUE self, VALUE rv, VALUE rptr) {
169
+ DATA_GET_BUILDER
170
+
171
+ Value *v, *ptr;
172
+ Data_Get_Struct(rv, Value, v);
173
+ Data_Get_Struct(rptr, Value, ptr);
174
+ return llvm_value_wrap(builder->CreateStore(v, ptr));
175
+ }
176
+
177
+ VALUE
178
+ llvm_builder_icmp(VALUE self, VALUE pred, VALUE lhs, VALUE rhs) {
179
+ DATA_GET_BUILDER
180
+
181
+ CmpInst::Predicate p = (CmpInst::Predicate)FIX2INT(pred);
182
+ Value *v = builder->CreateICmp(p, LLVM_VAL(lhs), LLVM_VAL(rhs));
183
+ return llvm_value_wrap(v);
184
+ }
185
+
186
+ VALUE
187
+ llvm_builder_fcmp(VALUE self, VALUE pred, VALUE lhs, VALUE rhs) {
188
+ DATA_GET_BUILDER
189
+
190
+ CmpInst::Predicate p = (CmpInst::Predicate)FIX2INT(pred);
191
+ Value *v = builder->CreateFCmp(p, LLVM_VAL(lhs), LLVM_VAL(rhs));
192
+ return llvm_value_wrap(v);
193
+ }
194
+
195
+ VALUE
196
+ llvm_builder_gep(VALUE self, VALUE rptr, VALUE ridx) {
197
+ DATA_GET_BUILDER
198
+
199
+ Value *ptr, *idx;
200
+ Data_Get_Struct(rptr, Value, ptr);
201
+ Data_Get_Struct(ridx, Value, idx);
202
+ return llvm_value_wrap(builder->CreateGEP(ptr, idx));
203
+ }
204
+
205
+ VALUE
206
+ llvm_builder_struct_gep(VALUE self, VALUE rptr, VALUE ridx) {
207
+ DATA_GET_BUILDER
208
+
209
+ Value *ptr;
210
+ Data_Get_Struct(rptr, Value, ptr);
211
+ return llvm_value_wrap(builder->CreateStructGEP(ptr, FIX2INT(ridx)));
212
+ }
213
+
214
+ VALUE
215
+ llvm_builder_cast(VALUE self, VALUE rop, VALUE rv, VALUE rdest_ty) {
216
+ DATA_GET_BUILDER
217
+
218
+ Instruction::CastOps op = (Instruction::CastOps)FIX2INT(rop);
219
+
220
+ Value *v;
221
+ Data_Get_Struct(rv, Value, v);
222
+
223
+ Type *dest_ty;
224
+ Data_Get_Struct(rdest_ty, Type, dest_ty);
225
+
226
+ return llvm_value_wrap(builder->CreateCast(op, v, dest_ty));
227
+ }
228
+
229
+ VALUE
230
+ llvm_builder_int_to_ptr(VALUE self, VALUE ri, VALUE rtype) {
231
+ DATA_GET_BUILDER
232
+
233
+ Value *i;
234
+ Data_Get_Struct(ri, Value, i);
235
+
236
+ const Type* type;
237
+ Data_Get_Struct(rtype, Type, type);
238
+
239
+ return llvm_value_wrap(builder->CreateIntToPtr(i, type));
240
+ }
241
+
242
+ VALUE llvm_builder_int_cast(VALUE self, VALUE i, VALUE type, VALUE sign) {
243
+ DATA_GET_BUILDER
244
+ bool isSigned = (sign != Qnil && sign != Qfalse);
245
+ return llvm_value_wrap(builder->CreateIntCast(LLVM_VAL(i), LLVM_TYPE(type), isSigned));
246
+ }
247
+
248
+ VALUE
249
+ llvm_builder_call(int argc, VALUE* argv, VALUE self) {
250
+ DATA_GET_BUILDER
251
+
252
+ Function *callee = LLVM_FUNCTION(argv[0]);
253
+ int num_args = argc-1;
254
+ Value** args = (Value**)alloca(num_args*sizeof(Value*));
255
+ for(int i = 0; i < num_args; ++i) {
256
+ args[i] = LLVM_VAL(argv[i+1]);
257
+ }
258
+ return llvm_value_wrap(builder->CreateCall(callee, args, args+num_args));
259
+ }
260
+
261
+ VALUE
262
+ llvm_builder_insert_element(VALUE self, VALUE rv, VALUE rnv, VALUE ridx) {
263
+ DATA_GET_BUILDER
264
+
265
+ Value *v, *nv, *idx;
266
+ Data_Get_Struct(rv, Value, v);
267
+ Data_Get_Struct(rnv, Value, nv);
268
+ Data_Get_Struct(ridx, Value, idx);
269
+
270
+ return llvm_value_wrap(builder->CreateInsertElement(v, nv, idx));
271
+ }
272
+
273
+ VALUE
274
+ llvm_builder_extract_element(VALUE self, VALUE rv, VALUE ridx) {
275
+ DATA_GET_BUILDER
276
+
277
+ Value *v, *idx;
278
+ Data_Get_Struct(rv, Value, v);
279
+ Data_Get_Struct(ridx, Value, idx);
280
+
281
+ return llvm_value_wrap(builder->CreateExtractElement(v, idx));
282
+ }
283
+
284
+ VALUE
285
+ llvm_builder_get_global(VALUE self) {
286
+ GlobalVariable *g = new GlobalVariable(Type::Int64Ty, false, GlobalValue::ExternalLinkage, 0, "shakalaka");
287
+ return llvm_value_wrap(g);
288
+ }
289
+
290
+ VALUE
291
+ llvm_builder_create_global_string_ptr(VALUE self, VALUE str) {
292
+ DATA_GET_BUILDER
293
+ Value *v = builder->CreateGlobalStringPtr(StringValuePtr(str));
294
+ return llvm_value_wrap(v);
295
+ }
296
+ }
@@ -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
+ }
@@ -0,0 +1,125 @@
1
+ #include "llvmruby.h"
2
+ #include <sstream>
3
+
4
+ extern VALUE cLLVMInstruction;
5
+ extern VALUE cLLVMBinaryOps;
6
+
7
+ extern "C" {
8
+
9
+ VALUE
10
+ llvm_instruction_wrap(Instruction* i) {
11
+ return Data_Wrap_Struct(cLLVMInstruction, NULL, NULL, i);
12
+ }
13
+
14
+ VALUE
15
+ llvm_instruction_inspect(VALUE self) {
16
+ Instruction *i = LLVM_INSTRUCTION(self);
17
+ std::ostringstream strstrm;
18
+ strstrm << *i;
19
+ return rb_str_new2(strstrm.str().c_str());
20
+ }
21
+
22
+ VALUE
23
+ llvm_instruction_get_opcode_name(VALUE self) {
24
+ Instruction *i = LLVM_INSTRUCTION(self);
25
+ std::string name = i->getOpcodeName();
26
+ return rb_str_new2(name.c_str());
27
+ }
28
+
29
+ #define DATA_GET_SWITCH_INST SwitchInst *si; Data_Get_Struct(self, SwitchInst, si);
30
+
31
+ VALUE
32
+ llvm_switch_inst_get_default_dest(VALUE self) {
33
+ DATA_GET_SWITCH_INST
34
+ BasicBlock *bb = si->getDefaultDest();
35
+ return llvm_basic_block_wrap(bb);
36
+ }
37
+
38
+ VALUE
39
+ llvm_switch_inst_get_num_cases(VALUE self) {
40
+ DATA_GET_SWITCH_INST
41
+ return INT2FIX(si->getNumCases());
42
+ }
43
+
44
+ VALUE
45
+ llvm_switch_inst_add_case(VALUE self, VALUE rci, VALUE rbb) {
46
+ DATA_GET_SWITCH_INST
47
+
48
+ ConstantInt *ci;
49
+ Data_Get_Struct(rci, ConstantInt, ci);
50
+
51
+ BasicBlock *bb;
52
+ Data_Get_Struct(rbb, BasicBlock, bb);
53
+
54
+ si->addCase(ci, bb);
55
+ return self;
56
+ }
57
+
58
+
59
+ #define DEFINE_INST(type, name) rb_define_const(cLLVMInstruction, #name, INT2FIX(Instruction::name));
60
+ #define DEFINE_BINARY_INST(name) DEFINE_INST(cLLVMBinaryOps, name)
61
+ #define DEFINE_PRED(name) rb_define_const(cLLVMInstruction, #name, INT2FIX(ICmpInst::name));
62
+ #define DEFINE_FPRED(name) rb_define_const(cLLVMInstruction, #name, INT2FIX(FCmpInst::name));
63
+ #define DEFINE_CAST(name) rb_define_const(cLLVMInstruction, #name, INT2FIX(Instruction::name));
64
+
65
+ void init_instructions() {
66
+ // Standard binary operators
67
+ DEFINE_BINARY_INST(Add)
68
+ DEFINE_BINARY_INST(Sub)
69
+ DEFINE_BINARY_INST(Mul)
70
+ DEFINE_BINARY_INST(UDiv)
71
+ DEFINE_BINARY_INST(SDiv)
72
+ DEFINE_BINARY_INST(FDiv)
73
+ DEFINE_BINARY_INST(URem)
74
+ DEFINE_BINARY_INST(SRem)
75
+ DEFINE_BINARY_INST(FRem)
76
+
77
+ // Logical operators (integer operands)
78
+ DEFINE_BINARY_INST(Shl) // Shift left (logical)
79
+ DEFINE_BINARY_INST(LShr) // Shift right (logical)
80
+ DEFINE_BINARY_INST(AShr) // shift right (arithmetic)
81
+ DEFINE_BINARY_INST(And)
82
+ DEFINE_BINARY_INST(Or)
83
+ DEFINE_BINARY_INST(Xor)
84
+
85
+ // Integer predicates
86
+ DEFINE_PRED(ICMP_EQ) // equal
87
+ DEFINE_PRED(ICMP_NE) // not equal
88
+ DEFINE_PRED(ICMP_UGT) // unsigned greater than
89
+ DEFINE_PRED(ICMP_UGE) // unsigned greater or equal
90
+ DEFINE_PRED(ICMP_ULT) // unsigned less than
91
+ DEFINE_PRED(ICMP_ULE) // unsigned less or equal
92
+ DEFINE_PRED(ICMP_SGT) // signed greater than
93
+ DEFINE_PRED(ICMP_SGE) // signed greater or equal
94
+ DEFINE_PRED(ICMP_SLT) // signed less than
95
+ DEFINE_PRED(ICMP_SLE) // signed less or equal
96
+
97
+ DEFINE_FPRED(FCMP_OEQ)
98
+ DEFINE_FPRED(FCMP_OGT)
99
+ DEFINE_FPRED(FCMP_OGE)
100
+ DEFINE_FPRED(FCMP_OLT)
101
+ DEFINE_FPRED(FCMP_OLE)
102
+ DEFINE_FPRED(FCMP_ONE)
103
+ DEFINE_FPRED(FCMP_ORD)
104
+ DEFINE_FPRED(FCMP_UNO)
105
+ DEFINE_FPRED(FCMP_UEQ)
106
+ DEFINE_FPRED(FCMP_UGT)
107
+ DEFINE_FPRED(FCMP_UGE)
108
+ DEFINE_FPRED(FCMP_ULT)
109
+ DEFINE_FPRED(FCMP_ULE)
110
+ DEFINE_FPRED(FCMP_UNE)
111
+
112
+ DEFINE_CAST(Trunc)
113
+ DEFINE_CAST(ZExt)
114
+ DEFINE_CAST(SExt)
115
+ DEFINE_CAST(FPToUI)
116
+ DEFINE_CAST(FPToSI)
117
+ DEFINE_CAST(UIToFP)
118
+ DEFINE_CAST(SIToFP)
119
+ DEFINE_CAST(FPTrunc)
120
+ DEFINE_CAST(FPExt)
121
+ DEFINE_CAST(PtrToInt)
122
+ DEFINE_CAST(IntToPtr)
123
+ DEFINE_CAST(BitCast)
124
+ }
125
+ }