public
Description: LLVM bindings for Ruby
Homepage: http://llvmruby.org
Clone URL: git://github.com/tombagby/llvmruby.git
commit  799f27a8b33a6a96760d808784b3e34ba624fe4c
tree    cf273fb74175fe4b333b308184168b176510ceee
parent  86dc62620c7efb3e5cb10889af328c9675f449b2
llvmruby / ext / llvm_instruction.cpp
100644 221 lines (181 sloc) 5.795 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#include "llvmruby.h"
#include <sstream>
 
extern VALUE cLLVMInstruction;
extern VALUE cLLVMBinaryOps;
 
extern "C" {
 
#define LAST_INSTRUCTION_NUM 100
VALUE gInstructionClasses[LAST_INSTRUCTION_NUM];
 
VALUE
llvm_instruction_wrap(Instruction* i) {
   return Data_Wrap_Struct(gInstructionClasses[i->getOpcode()], NULL, NULL, i);
}
 
VALUE
llvm_instruction_inspect(VALUE self) {
  Instruction *i = LLVM_INSTRUCTION(self);
  std::ostringstream strstrm;
  strstrm << *i;
  return rb_str_new2(strstrm.str().c_str());
}
 
VALUE
llvm_instruction_get_opcode_name(VALUE self) {
  Instruction *i = LLVM_INSTRUCTION(self);
  std::string name = i->getOpcodeName();
  return rb_str_new2(name.c_str());
}
 
#define DATA_GET_TERMINATOR_INST TerminatorInst *ti; Data_Get_Struct(self, TerminatorInst, ti);
 
VALUE
llvm_terminator_inst_num_successors(VALUE self) {
  DATA_GET_TERMINATOR_INST
  return INT2FIX(ti->getNumSuccessors());
}
 
VALUE
llvm_terminator_inst_get_successor(VALUE self, VALUE ridx) {
  DATA_GET_TERMINATOR_INST
  BasicBlock *bb = ti->getSuccessor(FIX2INT(ridx));
  return llvm_basic_block_wrap(bb);
}
 
VALUE
llvm_terminator_inst_set_successor(VALUE self, VALUE ridx, VALUE rbb) {
  DATA_GET_TERMINATOR_INST
 
  BasicBlock *bb;
  Data_Get_Struct(rbb, BasicBlock, bb);
 
  ti->setSuccessor(FIX2INT(ridx), bb);
  return rbb;
}
 
#define DATA_GET_BRANCH_INST BranchInst *bi; Data_Get_Struct(self, BranchInst, bi);
 
VALUE
llvm_branch_inst_is_unconditional(VALUE self) {
  DATA_GET_BRANCH_INST
  return bi->isUnconditional() ? Qtrue : Qfalse;
}
 
VALUE
llvm_branch_inst_is_conditional(VALUE self) {
  DATA_GET_BRANCH_INST
  return bi->isConditional() ? Qtrue : Qfalse;
}
 
VALUE
llvm_branch_inst_get_condition(VALUE self) {
  DATA_GET_BRANCH_INST
  return llvm_value_wrap(bi->getCondition());
}
 
VALUE
llvm_branch_inst_set_condition(VALUE self, VALUE rv) {
  DATA_GET_BRANCH_INST
  
  Value *v;
  Data_Get_Struct(rv, Value, v);
 
  bi->setCondition(v);
  return rv;
}
 
#define DATA_GET_SWITCH_INST SwitchInst *si; Data_Get_Struct(self, SwitchInst, si);
 
VALUE
llvm_switch_inst_get_default_dest(VALUE self) {
  DATA_GET_SWITCH_INST
  BasicBlock *bb = si->getDefaultDest();
  return llvm_basic_block_wrap(bb);
}
 
VALUE
llvm_switch_inst_get_num_cases(VALUE self) {
  DATA_GET_SWITCH_INST
  return INT2FIX(si->getNumCases());
}
 
VALUE
llvm_switch_inst_add_case(VALUE self, VALUE rci, VALUE rbb) {
  DATA_GET_SWITCH_INST
  
  ConstantInt *ci;
  Data_Get_Struct(rci, ConstantInt, ci);
 
  BasicBlock *bb;
  Data_Get_Struct(rbb, BasicBlock, bb);
 
  si->addCase(ci, bb);
  return self;
}
 
#define DATA_GET_ALLOCATION_INST AllocationInst *ai; Data_Get_Struct(self, AllocationInst, ai);
 
VALUE
llvm_allocation_inst_is_array_allocation(VALUE self) {
  DATA_GET_ALLOCATION_INST
  return ai->isArrayAllocation() ? true : false;
}
 
VALUE
llvm_allocation_inst_array_size(VALUE self) {
  DATA_GET_ALLOCATION_INST
  return llvm_value_wrap(ai->getArraySize());
}
 
VALUE
llvm_allocation_inst_allocated_type(VALUE self) {
  DATA_GET_ALLOCATION_INST
  Type *at = const_cast<Type*>(ai->getAllocatedType());
  return Data_Wrap_Struct(cLLVMType, NULL, NULL, at);
}
 
VALUE
llvm_allocation_inst_alignment(VALUE self) {
  DATA_GET_ALLOCATION_INST
  return INT2FIX(ai->getAlignment());
}
 
#define DEFINE_INST(type, name) rb_define_const(cLLVMInstruction, #name, INT2FIX(Instruction::name));
#define DEFINE_BINARY_INST(name) DEFINE_INST(cLLVMBinaryOps, name)
#define DEFINE_PRED(name) rb_define_const(cLLVMInstruction, #name, INT2FIX(ICmpInst::name));
#define DEFINE_FPRED(name) rb_define_const(cLLVMInstruction, #name, INT2FIX(FCmpInst::name));
#define DEFINE_CAST(name) rb_define_const(cLLVMInstruction, #name, INT2FIX(Instruction::name));
 
void init_instructions() {
  for(int i = 0; i < LAST_INSTRUCTION_NUM; ++i) {
    gInstructionClasses[i] = cLLVMInstruction;
  }
 
  // Need to be able to quickly look up at runtime Ruby classes cooresponding to LLVM classes
#define HANDLE_TERM_INST(Num, Opcode, Klass) gInstructionClasses[Num] = cLLVM##Klass;
#define HANDLE_BINARY_INST(Num, Opcode, Klass) gInstructionClasses[Num] = cLLVM##Klass;
#include "llvm/Instruction.def"
  
  // Standard binary operators
  DEFINE_BINARY_INST(Add)
  DEFINE_BINARY_INST(Sub)
  DEFINE_BINARY_INST(Mul)
  DEFINE_BINARY_INST(UDiv)
  DEFINE_BINARY_INST(SDiv)
  DEFINE_BINARY_INST(FDiv)
  DEFINE_BINARY_INST(URem)
  DEFINE_BINARY_INST(SRem)
  DEFINE_BINARY_INST(FRem)
 
  // Logical operators (integer operands)
  DEFINE_BINARY_INST(Shl) // Shift left (logical)
  DEFINE_BINARY_INST(LShr) // Shift right (logical)
  DEFINE_BINARY_INST(AShr) // shift right (arithmetic)
  DEFINE_BINARY_INST(And)
  DEFINE_BINARY_INST(Or)
  DEFINE_BINARY_INST(Xor)
 
  // Integer predicates
  DEFINE_PRED(ICMP_EQ) // equal
  DEFINE_PRED(ICMP_NE) // not equal
  DEFINE_PRED(ICMP_UGT) // unsigned greater than
  DEFINE_PRED(ICMP_UGE) // unsigned greater or equal
  DEFINE_PRED(ICMP_ULT) // unsigned less than
  DEFINE_PRED(ICMP_ULE) // unsigned less or equal
  DEFINE_PRED(ICMP_SGT) // signed greater than
  DEFINE_PRED(ICMP_SGE) // signed greater or equal
  DEFINE_PRED(ICMP_SLT) // signed less than
  DEFINE_PRED(ICMP_SLE) // signed less or equal
 
  DEFINE_FPRED(FCMP_OEQ)
  DEFINE_FPRED(FCMP_OGT)
  DEFINE_FPRED(FCMP_OGE)
  DEFINE_FPRED(FCMP_OLT)
  DEFINE_FPRED(FCMP_OLE)
  DEFINE_FPRED(FCMP_ONE)
  DEFINE_FPRED(FCMP_ORD)
  DEFINE_FPRED(FCMP_UNO)
  DEFINE_FPRED(FCMP_UEQ)
  DEFINE_FPRED(FCMP_UGT)
  DEFINE_FPRED(FCMP_UGE)
  DEFINE_FPRED(FCMP_ULT)
  DEFINE_FPRED(FCMP_ULE)
  DEFINE_FPRED(FCMP_UNE)
 
  DEFINE_CAST(Trunc)
  DEFINE_CAST(ZExt)
  DEFINE_CAST(SExt)
  DEFINE_CAST(FPToUI)
  DEFINE_CAST(FPToSI)
  DEFINE_CAST(UIToFP)
  DEFINE_CAST(SIToFP)
  DEFINE_CAST(FPTrunc)
  DEFINE_CAST(FPExt)
  DEFINE_CAST(PtrToInt)
  DEFINE_CAST(IntToPtr)
  DEFINE_CAST(BitCast)
}
}