ruby-llvm 2.7.0
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/README.rdoc +28 -0
- data/lib/llvm.rb +15 -0
- data/lib/llvm/analysis.rb +46 -0
- data/lib/llvm/core.rb +520 -0
- data/lib/llvm/core/builder.rb +377 -0
- data/lib/llvm/core/context.rb +29 -0
- data/lib/llvm/core/module.rb +199 -0
- data/lib/llvm/core/pass_manager.rb +30 -0
- data/lib/llvm/core/type.rb +113 -0
- data/lib/llvm/core/value.rb +469 -0
- data/lib/llvm/execution_engine.rb +139 -0
- data/lib/llvm/target.rb +8 -0
- data/lib/llvm/transforms/scalar.rb +119 -0
- metadata +74 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
module LLVM
|
2
|
+
# The PassManager runs a queue of passes on a module. See
|
3
|
+
# http://llvm.org/docs/Passes.html for the list of available passes.
|
4
|
+
# Currently, only scalar transformation passes are supported.
|
5
|
+
class PassManager
|
6
|
+
def initialize(execution_engine)
|
7
|
+
ptr = C.LLVMCreatePassManager()
|
8
|
+
C.LLVMAddTargetData(
|
9
|
+
C.LLVMGetExecutionEngineTargetData(execution_engine), ptr)
|
10
|
+
@ptr = ptr
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_ptr # :nodoc:
|
14
|
+
@ptr
|
15
|
+
end
|
16
|
+
|
17
|
+
def <<(name)
|
18
|
+
send(:"#{name}!")
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def run(mod)
|
23
|
+
C.LLVMRunPassManager(self, mod)
|
24
|
+
end
|
25
|
+
|
26
|
+
def dispose
|
27
|
+
C.LLVMDisposePassManager(self)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module LLVM
|
2
|
+
class Type
|
3
|
+
class << self
|
4
|
+
private :new
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(ptr) # :nodoc:
|
8
|
+
@ptr = ptr
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_ptr # :nodoc:
|
12
|
+
@ptr
|
13
|
+
end
|
14
|
+
|
15
|
+
# LLVM's represents types uniquely, and supports pointer equality.
|
16
|
+
def ==(type)
|
17
|
+
case type
|
18
|
+
when LLVM::Type
|
19
|
+
@ptr == type.to_ptr
|
20
|
+
else
|
21
|
+
false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def size
|
26
|
+
Int64.from_ptr(C.LLVMSizeOf(self))
|
27
|
+
end
|
28
|
+
|
29
|
+
def align
|
30
|
+
Int64.from_ptr(C.LLVMAlignOf(self))
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.from_ptr(ptr)
|
34
|
+
ptr.null? ? nil : new(ptr)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.array(ty, sz = 0)
|
38
|
+
from_ptr(C.LLVMArrayType(LLVM::Type(ty), sz))
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.pointer(ty, address_space = 0)
|
42
|
+
from_ptr(C.LLVMPointerType(LLVM::Type(ty), address_space))
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.vector(ty, element_count)
|
46
|
+
from_ptr(C.LLVMVectorType(LLVM::Type(ty), element_count))
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.function(arg_types, result_type)
|
50
|
+
arg_types.map! { |ty| LLVM::Type(ty) }
|
51
|
+
arg_types_ptr = FFI::MemoryPointer.new(FFI.type_size(:pointer) * arg_types.size)
|
52
|
+
arg_types_ptr.write_array_of_pointer(arg_types)
|
53
|
+
from_ptr(C.LLVMFunctionType(LLVM::Type(result_type), arg_types_ptr, arg_types.size, 0))
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.struct(elt_types, is_packed)
|
57
|
+
elt_types.map! { |ty| LLVM::Type(ty) }
|
58
|
+
elt_types_ptr = FFI::MemoryPointer.new(FFI.type_size(:pointer) * elt_types.size)
|
59
|
+
elt_types_ptr.write_array_of_pointer(elt_types)
|
60
|
+
from_ptr(C.LLVMStructType(elt_types_ptr, elt_types.size, is_packed ? 1 : 0))
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.void
|
64
|
+
from_ptr(C.LLVMVoidType)
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.opaque
|
68
|
+
from_ptr(C.LLVMOpaqueType)
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.rec
|
72
|
+
h = opaque
|
73
|
+
ty = yield h
|
74
|
+
h.refine(ty)
|
75
|
+
ty
|
76
|
+
end
|
77
|
+
|
78
|
+
def refine(ty)
|
79
|
+
C.LLVMRefineType(self, ty)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def LLVM.Type(ty)
|
84
|
+
case ty
|
85
|
+
when LLVM::Type then ty
|
86
|
+
else ty.type
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def LLVM.Array(ty, sz = 0)
|
91
|
+
LLVM::Type.array(ty, sz)
|
92
|
+
end
|
93
|
+
|
94
|
+
def LLVM.Pointer(ty)
|
95
|
+
LLVM::Type.pointer(ty)
|
96
|
+
end
|
97
|
+
|
98
|
+
def LLVM.Vector(ty, sz)
|
99
|
+
LLVM::Type.vector(ty, sz)
|
100
|
+
end
|
101
|
+
|
102
|
+
def LLVM.Function(argtypes, rettype)
|
103
|
+
LLVM::Type.function(argtypes, rettype)
|
104
|
+
end
|
105
|
+
|
106
|
+
def LLVM.Struct(*elt_types)
|
107
|
+
LLVM::Type.struct(elt_types, false)
|
108
|
+
end
|
109
|
+
|
110
|
+
def LLVM.Void
|
111
|
+
LLVM::Type.void
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,469 @@
|
|
1
|
+
module LLVM
|
2
|
+
class Value
|
3
|
+
def self.from_ptr(ptr)
|
4
|
+
new(ptr) unless ptr.null?
|
5
|
+
end
|
6
|
+
|
7
|
+
class << self
|
8
|
+
private :new
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(ptr)
|
12
|
+
@ptr = ptr
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_ptr # :nodoc:
|
16
|
+
@ptr
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.type
|
20
|
+
raise NotImplementedError, "Value.type is abstract"
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.to_ptr
|
24
|
+
type.to_ptr
|
25
|
+
end
|
26
|
+
|
27
|
+
def type
|
28
|
+
Type.from_ptr(C.LLVMTypeOf(self))
|
29
|
+
end
|
30
|
+
|
31
|
+
def name
|
32
|
+
C.LLVMGetValueName(self)
|
33
|
+
end
|
34
|
+
|
35
|
+
def name=(str)
|
36
|
+
C.LLVMSetValueName(self, str)
|
37
|
+
str
|
38
|
+
end
|
39
|
+
|
40
|
+
def dump
|
41
|
+
C.LLVMDumpValue(self)
|
42
|
+
end
|
43
|
+
|
44
|
+
def constant?
|
45
|
+
case C.LLVMIsConstant(self)
|
46
|
+
when 0 then false
|
47
|
+
when 1 then true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def null?
|
52
|
+
case C.LLVMIsNull(self)
|
53
|
+
when 0 then false
|
54
|
+
when 1 then true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def undefined?
|
59
|
+
case C.LLVMIsUndef(self)
|
60
|
+
when 0 then false
|
61
|
+
when 1 then true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_attribute(attr)
|
66
|
+
C.LLVMAddAttribute(self, attr)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class Argument < Value
|
71
|
+
end
|
72
|
+
|
73
|
+
class BasicBlock < Value
|
74
|
+
def build(builder = nil)
|
75
|
+
if builder.nil?
|
76
|
+
builder = Builder.create
|
77
|
+
islocal = true
|
78
|
+
else
|
79
|
+
islocal = false
|
80
|
+
end
|
81
|
+
builder.position_at_end(self)
|
82
|
+
yield builder
|
83
|
+
ensure
|
84
|
+
builder.dispose
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class Constant < Value
|
89
|
+
def self.type
|
90
|
+
raise NotImplementedError, "Constant.type() is abstract."
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.null
|
94
|
+
from_ptr(C.LLVMConstNull(type))
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.undef
|
98
|
+
from_ptr(C.LLVMGetUndef(type))
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.null_ptr
|
102
|
+
from_ptr(C.LLVMConstPointerNull(type))
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class ConstantArray < Constant
|
107
|
+
def self.string(str, null_terminate = true)
|
108
|
+
from_ptr(C.LLVMConstString(str, null_terminate ? 0 : 1))
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.const(type, size)
|
112
|
+
vals = (0...size).map { |i| yield i }
|
113
|
+
from_ptr C.LLVMConstArray(type, vals, size)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class ConstantExpr < Constant
|
118
|
+
end
|
119
|
+
|
120
|
+
class ConstantInt < Constant
|
121
|
+
def self.all_ones
|
122
|
+
from_ptr(C.LLVMConstAllOnes(type))
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.from_i(n, signed = true)
|
126
|
+
from_ptr(C.LLVMConstInt(type, n, signed ? 1 : 0))
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.parse(str, radix = 10)
|
130
|
+
from_ptr(C.LLVMConstIntOfString(type, str, radix))
|
131
|
+
end
|
132
|
+
|
133
|
+
def -@
|
134
|
+
self.class.from_ptr(C.LLVMConstNeg(self))
|
135
|
+
end
|
136
|
+
|
137
|
+
def not
|
138
|
+
self.class.from_ptr(C.LLVMConstNot(self))
|
139
|
+
end
|
140
|
+
|
141
|
+
def +(rhs)
|
142
|
+
self.class.from_ptr(C.LLVMConstAdd(self, rhs))
|
143
|
+
end
|
144
|
+
|
145
|
+
def nsw_add(rhs)
|
146
|
+
self.class.from_ptr(C.LLVMConstNSWAdd(self, rhs))
|
147
|
+
end
|
148
|
+
|
149
|
+
def *(rhs)
|
150
|
+
self.class.from_ptr(C.LLVMConstMul(self, rhs))
|
151
|
+
end
|
152
|
+
|
153
|
+
def udiv(rhs)
|
154
|
+
self.class.from_ptr(C.LLVMConstUDiv(self, rhs))
|
155
|
+
end
|
156
|
+
|
157
|
+
def /(rhs)
|
158
|
+
self.class.from_ptr(C.LLVMConstSDiv(self, rhs))
|
159
|
+
end
|
160
|
+
|
161
|
+
def urem(rhs)
|
162
|
+
self.class.from_ptr(C.LLVMConstURem(self, rhs))
|
163
|
+
end
|
164
|
+
|
165
|
+
def rem(rhs)
|
166
|
+
self.class.from_ptr(C.LLVMConstSRem(self, rhs))
|
167
|
+
end
|
168
|
+
|
169
|
+
def and(rhs) # Ruby's && cannot be overloaded
|
170
|
+
self.class.from_ptr(C.LLVMConstAnd(self, rhs))
|
171
|
+
end
|
172
|
+
|
173
|
+
def or(rhs) # Nor is ||.
|
174
|
+
self.class.from_ptr(C.LLVMConstOr(self, rhs))
|
175
|
+
end
|
176
|
+
|
177
|
+
def xor(rhs) # Nor is ||.
|
178
|
+
self.class.from_ptr(C.LLVMConstXor(self, rhs))
|
179
|
+
end
|
180
|
+
|
181
|
+
def icmp(pred, rhs)
|
182
|
+
self.class.from_ptr(C.LLVMConstICmp(pred, self, rhs))
|
183
|
+
end
|
184
|
+
|
185
|
+
def <<(bits)
|
186
|
+
self.class.from_ptr(C.LLVMConstShl(self, rhs))
|
187
|
+
end
|
188
|
+
|
189
|
+
def >>(bits)
|
190
|
+
self.class.from_ptr(C.LLVMConstLShr(self, rhs))
|
191
|
+
end
|
192
|
+
|
193
|
+
def ashr(bits)
|
194
|
+
self.class.from_ptr(C.LLVMConstAShr(self, rhs))
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def LLVM.const_missing(const) # :nodoc:
|
199
|
+
case const.to_s
|
200
|
+
when /Int(\d+)/
|
201
|
+
width = $1.to_i
|
202
|
+
name = "Int#{width}"
|
203
|
+
eval <<-KLASS
|
204
|
+
class #{name} < ConstantInt
|
205
|
+
def self.type
|
206
|
+
Type.from_ptr(C.LLVMIntType(#{width}))
|
207
|
+
end
|
208
|
+
end
|
209
|
+
KLASS
|
210
|
+
const_get(name)
|
211
|
+
else
|
212
|
+
super
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# Native integer type
|
217
|
+
::LLVM::Int = const_get("Int#{NATIVE_INT_SIZE}")
|
218
|
+
|
219
|
+
def LLVM.Int(val)
|
220
|
+
case val
|
221
|
+
when LLVM::ConstantInt then val
|
222
|
+
when Integer then Int.from_i(val)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
class ConstantReal < Constant
|
227
|
+
def self.from_f(n)
|
228
|
+
from_ptr(C.LLVMConstReal(type, n))
|
229
|
+
end
|
230
|
+
|
231
|
+
def self.parse(str)
|
232
|
+
from_ptr(C.LLVMConstRealOfString(type, str))
|
233
|
+
end
|
234
|
+
|
235
|
+
def -@
|
236
|
+
self.class.from_ptr(C.LLVMConstFNeg(self))
|
237
|
+
end
|
238
|
+
|
239
|
+
def +(rhs)
|
240
|
+
self.class.from_ptr(C.LLVMConstFAdd(self, rhs))
|
241
|
+
end
|
242
|
+
|
243
|
+
def *(rhs)
|
244
|
+
self.class.from_ptr(C.LLVMConstFMul(self, rhs))
|
245
|
+
end
|
246
|
+
|
247
|
+
def /(rhs)
|
248
|
+
self.class.from_ptr(C.LLVMConstFDiv(self, rhs))
|
249
|
+
end
|
250
|
+
|
251
|
+
def rem(rhs)
|
252
|
+
self.class.from_ptr(C.LLVMConstFRem(self, rhs))
|
253
|
+
end
|
254
|
+
|
255
|
+
def fcmp(pred, rhs)
|
256
|
+
self.class.from_ptr(C.LLMVConstFCmp(pred, self, rhs))
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
class Float < ConstantReal
|
261
|
+
def self.type
|
262
|
+
Type.from_ptr(C.LLVMFloatType)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def LLVM.Float(val)
|
267
|
+
Float.from_f(val)
|
268
|
+
end
|
269
|
+
|
270
|
+
class Double < ConstantReal
|
271
|
+
def self.type
|
272
|
+
Type.from_ptr(C.LLVMDoubleType)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def LLVM.Double(val)
|
277
|
+
Double.from_f(val)
|
278
|
+
end
|
279
|
+
|
280
|
+
class ConstantStruct < Constant
|
281
|
+
def self.const(size, packed = false)
|
282
|
+
vals = (0..size).map { |i| yield i }
|
283
|
+
from_ptr(C.LLVMConstStruct(vals, size, packed ? 1 : 0))
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
class ConstantVector < Constant
|
288
|
+
def self.all_ones
|
289
|
+
from_ptr(C.LLVMConstAllOnes(type))
|
290
|
+
end
|
291
|
+
|
292
|
+
def self.const(size)
|
293
|
+
vals = (0..size).map { |i| yield i }
|
294
|
+
from_ptr(C.LLVMConstVector(vals, size))
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
class GlobalValue < Constant
|
299
|
+
def declaration?
|
300
|
+
C.LLVMIsDeclaration(self)
|
301
|
+
end
|
302
|
+
|
303
|
+
def linkage
|
304
|
+
C.LLVMGetLinkage(self)
|
305
|
+
end
|
306
|
+
|
307
|
+
def linkage=(linkage)
|
308
|
+
C.LLVMSetLinkage(self, linkage)
|
309
|
+
end
|
310
|
+
|
311
|
+
def section
|
312
|
+
C.LLVMGetSection(self)
|
313
|
+
end
|
314
|
+
|
315
|
+
def section=(section)
|
316
|
+
C.LLVMSetSection(self, section)
|
317
|
+
end
|
318
|
+
|
319
|
+
def visibility
|
320
|
+
C.LLVMGetVisibility(self)
|
321
|
+
end
|
322
|
+
|
323
|
+
def visibility=(viz)
|
324
|
+
C.LLVMSetVisibility(self, viz)
|
325
|
+
end
|
326
|
+
|
327
|
+
def alignment
|
328
|
+
C.LLVMGetAlignment(self)
|
329
|
+
end
|
330
|
+
|
331
|
+
def alignment=(bytes)
|
332
|
+
C.LLVMSetAlignment(self, bytes)
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
class Function < GlobalValue
|
337
|
+
def call_conv=(conv)
|
338
|
+
C.LLVMSetFunctionCallConv(self, conv)
|
339
|
+
conv
|
340
|
+
end
|
341
|
+
|
342
|
+
def add_attribute(attr)
|
343
|
+
C.LLVMAddFunctionAttr(self, attr)
|
344
|
+
end
|
345
|
+
|
346
|
+
def remove_attribute(attr)
|
347
|
+
C.LLVMRemoveFunctionAttr(self, attr)
|
348
|
+
end
|
349
|
+
|
350
|
+
def basic_blocks
|
351
|
+
@basic_block_collection ||= BasicBlockCollection.new(self)
|
352
|
+
end
|
353
|
+
|
354
|
+
class BasicBlockCollection
|
355
|
+
def initialize(fun)
|
356
|
+
@fun = fun
|
357
|
+
end
|
358
|
+
|
359
|
+
def size
|
360
|
+
C.LLVMCountBasicBlocks(@fun)
|
361
|
+
end
|
362
|
+
|
363
|
+
def append(name = "")
|
364
|
+
BasicBlock.from_ptr(C.LLVMAppendBasicBlock(@fun, name))
|
365
|
+
end
|
366
|
+
|
367
|
+
def entry
|
368
|
+
BasicBlock.from_ptr(C.LLVMGetEntryBasicBlock(@fun))
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
def params
|
373
|
+
@parameter_collection ||= ParameterCollection.new(self)
|
374
|
+
end
|
375
|
+
|
376
|
+
class ParameterCollection
|
377
|
+
def initialize(fun)
|
378
|
+
@fun = fun
|
379
|
+
end
|
380
|
+
|
381
|
+
def [](i)
|
382
|
+
Value.from_ptr(C.LLVMGetParam(@fun, i))
|
383
|
+
end
|
384
|
+
|
385
|
+
def size
|
386
|
+
C.LLVMCountParams(@fun)
|
387
|
+
end
|
388
|
+
|
389
|
+
include Enumerable
|
390
|
+
|
391
|
+
def each
|
392
|
+
0.upto(size-1) { |i| yield self[i] }
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
class GlobalAlias < GlobalValue
|
398
|
+
end
|
399
|
+
|
400
|
+
class GlobalVariable < GlobalValue
|
401
|
+
def initializer
|
402
|
+
Value.from_ptr(C.LLVMGetInitializer(self))
|
403
|
+
end
|
404
|
+
|
405
|
+
def initializer=(val)
|
406
|
+
C.LLVMSetInitializer(self, val)
|
407
|
+
end
|
408
|
+
|
409
|
+
def thread_local?
|
410
|
+
case C.LLVMIsThreadLocal(self)
|
411
|
+
when 0 then false
|
412
|
+
else true
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
def thread_local=(local)
|
417
|
+
C.LLVMSetThreadLocal(self, local ? 1 : 0)
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
class Instruction < Value
|
422
|
+
end
|
423
|
+
|
424
|
+
class CallInst < Instruction
|
425
|
+
def call_conv=(conv)
|
426
|
+
C.LLVMSetInstructionCallConv(self, conv)
|
427
|
+
conv
|
428
|
+
end
|
429
|
+
|
430
|
+
def call_conv
|
431
|
+
C.LLVMGetInstructionCallConv(self)
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
class Phi < Instruction
|
436
|
+
# Add incoming branches to a phi node by passing an alternating list
|
437
|
+
# of resulting values and basic blocks. e.g.
|
438
|
+
# phi.add_incoming(val1, block1, val2, block2, ...)
|
439
|
+
def add_incoming(*incoming)
|
440
|
+
vals, blocks = [], []
|
441
|
+
incoming.each_with_index do |node, i|
|
442
|
+
(i % 2 == 0 ? vals : blocks) << node
|
443
|
+
end
|
444
|
+
|
445
|
+
unless vals.size == blocks.size
|
446
|
+
raise ArgumentError, "Expected vals.size and blocks.size to match"
|
447
|
+
end
|
448
|
+
|
449
|
+
size = vals.size
|
450
|
+
FFI::MemoryPointer.new(FFI.type_size(:pointer) * size) do |vals_ptr|
|
451
|
+
vals_ptr.write_array_of_pointer(vals)
|
452
|
+
FFI::MemoryPointer.new(FFI.type_size(:pointer) * size) do |blocks_ptr|
|
453
|
+
blocks_ptr.write_array_of_pointer(blocks)
|
454
|
+
C.LLVMAddIncoming(self, vals_ptr, blocks_ptr, vals.size)
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
nil
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
class SwitchInst < Instruction
|
463
|
+
# Adds a case to a switch instruction. First the value to match on,
|
464
|
+
# then the basic block.
|
465
|
+
def add_case(val, block)
|
466
|
+
C.LLVMAddCase(self, val, block)
|
467
|
+
end
|
468
|
+
end
|
469
|
+
end
|