ruby-llvm-next 10.0.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.
- checksums.yaml +7 -0
- data/LICENSE +30 -0
- data/README.md +67 -0
- data/ext/ruby-llvm-support/Rakefile +110 -0
- data/ext/ruby-llvm-support/support.cpp +32 -0
- data/lib/llvm.rb +29 -0
- data/lib/llvm/analysis.rb +49 -0
- data/lib/llvm/analysis_ffi.rb +77 -0
- data/lib/llvm/config.rb +10 -0
- data/lib/llvm/core.rb +97 -0
- data/lib/llvm/core/bitcode.rb +84 -0
- data/lib/llvm/core/bitcode_ffi.rb +132 -0
- data/lib/llvm/core/builder.rb +944 -0
- data/lib/llvm/core/context.rb +24 -0
- data/lib/llvm/core/module.rb +240 -0
- data/lib/llvm/core/pass_manager.rb +80 -0
- data/lib/llvm/core/type.rb +210 -0
- data/lib/llvm/core/value.rb +1005 -0
- data/lib/llvm/core_ffi.rb +6021 -0
- data/lib/llvm/execution_engine.rb +323 -0
- data/lib/llvm/execution_engine_ffi.rb +421 -0
- data/lib/llvm/linker.rb +16 -0
- data/lib/llvm/linker_ffi.rb +44 -0
- data/lib/llvm/support.rb +38 -0
- data/lib/llvm/target.rb +318 -0
- data/lib/llvm/target_ffi.rb +628 -0
- data/lib/llvm/transforms/builder.rb +107 -0
- data/lib/llvm/transforms/builder_ffi.rb +117 -0
- data/lib/llvm/transforms/ipo.rb +78 -0
- data/lib/llvm/transforms/ipo_ffi.rb +127 -0
- data/lib/llvm/transforms/scalar.rb +152 -0
- data/lib/llvm/transforms/scalar_ffi.rb +344 -0
- data/lib/llvm/transforms/vectorize.rb +22 -0
- data/lib/llvm/transforms/vectorize_ffi.rb +38 -0
- data/lib/llvm/version.rb +5 -0
- data/test/array_test.rb +38 -0
- data/test/basic_block_test.rb +87 -0
- data/test/binary_operations_test.rb +58 -0
- data/test/bitcode_test.rb +24 -0
- data/test/branch_test.rb +57 -0
- data/test/call_test.rb +82 -0
- data/test/comparisons_test.rb +66 -0
- data/test/conversions_test.rb +92 -0
- data/test/double_test.rb +34 -0
- data/test/equality_test.rb +89 -0
- data/test/function_test.rb +100 -0
- data/test/generic_value_test.rb +22 -0
- data/test/instruction_test.rb +30 -0
- data/test/ipo_test.rb +53 -0
- data/test/linker_test.rb +37 -0
- data/test/mcjit_test.rb +94 -0
- data/test/memory_access_test.rb +38 -0
- data/test/module_test.rb +93 -0
- data/test/parameter_collection_test.rb +28 -0
- data/test/pass_manager_builder_test.rb +53 -0
- data/test/phi_test.rb +33 -0
- data/test/select_test.rb +22 -0
- data/test/struct_test.rb +98 -0
- data/test/target_test.rb +113 -0
- data/test/test_helper.rb +62 -0
- data/test/type_test.rb +15 -0
- data/test/vector_test.rb +64 -0
- metadata +240 -0
@@ -0,0 +1,1005 @@
|
|
1
|
+
module LLVM
|
2
|
+
class Value
|
3
|
+
include PointerIdentity
|
4
|
+
|
5
|
+
# @private
|
6
|
+
def self.from_ptr(ptr)
|
7
|
+
return if ptr.null?
|
8
|
+
val = allocate
|
9
|
+
val.instance_variable_set(:@ptr, ptr)
|
10
|
+
val
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the Value type. This is abstract and is overidden by its subclasses.
|
14
|
+
def self.type
|
15
|
+
raise NotImplementedError, "#{name}.type() is abstract."
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.to_ptr
|
19
|
+
type.to_ptr
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the value's type.
|
23
|
+
def type
|
24
|
+
Type.from_ptr(C.type_of(self), nil)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the value's name.
|
28
|
+
def name
|
29
|
+
C.get_value_name(self)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Sets the value's name to str.
|
33
|
+
def name=(str)
|
34
|
+
C.set_value_name(self, str)
|
35
|
+
str
|
36
|
+
end
|
37
|
+
|
38
|
+
# Print the value's IR to stdout.
|
39
|
+
def dump
|
40
|
+
C.dump_value(self)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns whether the value is constant.
|
44
|
+
def constant?
|
45
|
+
case C.is_constant(self)
|
46
|
+
when 0 then false
|
47
|
+
when 1 then true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns whether the value is null.
|
52
|
+
def null?
|
53
|
+
case C.is_null(self)
|
54
|
+
when 0 then false
|
55
|
+
when 1 then true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns whether the value is undefined.
|
60
|
+
def undefined?
|
61
|
+
case C.is_undef(self)
|
62
|
+
when 0 then false
|
63
|
+
when 1 then true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Adds attr to this value's attributes.
|
68
|
+
def add_attribute(attr)
|
69
|
+
fun = param_parent
|
70
|
+
return unless fun
|
71
|
+
|
72
|
+
index = param_index(fun)
|
73
|
+
return unless index
|
74
|
+
|
75
|
+
fun.add_attribute(attr, index)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Removes the given attribute from the function.
|
79
|
+
def remove_attribute(attr)
|
80
|
+
fun = param_parent
|
81
|
+
return unless fun
|
82
|
+
|
83
|
+
index = param_index(fun)
|
84
|
+
return unless index
|
85
|
+
|
86
|
+
fun.remove_attribute(attr, index)
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
# get function this param belongs to
|
92
|
+
# return if it is not a param
|
93
|
+
def param_parent
|
94
|
+
valueref = C.get_param_parent(self)
|
95
|
+
return if valueref.null?
|
96
|
+
fun = LLVM::Function.from_ptr(valueref)
|
97
|
+
return if fun.null?
|
98
|
+
fun
|
99
|
+
end
|
100
|
+
|
101
|
+
# get index of this param by llvm count (+1 from parametercollection)
|
102
|
+
def param_index(fun)
|
103
|
+
index = fun.params.find_index(self)
|
104
|
+
return if index.nil?
|
105
|
+
index + 1
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
class Argument < Value
|
111
|
+
end
|
112
|
+
|
113
|
+
class BasicBlock < Value
|
114
|
+
# Creates a basic block for the given function with the given name.
|
115
|
+
def self.create(fun = nil, name = "")
|
116
|
+
from_ptr(C.append_basic_block(fun, name))
|
117
|
+
end
|
118
|
+
|
119
|
+
# Build the basic block with the given builder. Creates a new one if nil. Yields the builder.
|
120
|
+
def build(builder = nil)
|
121
|
+
if builder.nil?
|
122
|
+
builder = Builder.new
|
123
|
+
builder.position_at_end(self)
|
124
|
+
yield builder
|
125
|
+
builder.dispose
|
126
|
+
else
|
127
|
+
builder.position_at_end(self)
|
128
|
+
yield builder
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Returns the parent of this basic block (a Function).
|
133
|
+
def parent
|
134
|
+
fp = C.get_basic_block_parent(self)
|
135
|
+
LLVM::Function.from_ptr(fp) unless fp.null?
|
136
|
+
end
|
137
|
+
|
138
|
+
# Returns the next basic block in the sequence.
|
139
|
+
def next
|
140
|
+
ptr = C.get_next_basic_block(self)
|
141
|
+
BasicBlock.from_ptr(ptr) unless ptr.null?
|
142
|
+
end
|
143
|
+
|
144
|
+
# Returns the previous basic block in the sequence.
|
145
|
+
def previous
|
146
|
+
ptr = C.get_previous_basic_block(self)
|
147
|
+
BasicBlock.from_ptr(ptr) unless ptr.null?
|
148
|
+
end
|
149
|
+
|
150
|
+
# deprecated
|
151
|
+
def first_instruction
|
152
|
+
instructions.first
|
153
|
+
end
|
154
|
+
|
155
|
+
# deprecated
|
156
|
+
def last_instruction
|
157
|
+
instructions.last
|
158
|
+
end
|
159
|
+
|
160
|
+
# Returns an Enumerable of the Instructions in the current block.
|
161
|
+
def instructions
|
162
|
+
@instructions ||= InstructionCollection.new(self)
|
163
|
+
end
|
164
|
+
|
165
|
+
# @private
|
166
|
+
class InstructionCollection
|
167
|
+
include Enumerable
|
168
|
+
|
169
|
+
def initialize(block)
|
170
|
+
@block = block
|
171
|
+
end
|
172
|
+
|
173
|
+
# Iterates through each Instruction in the collection.
|
174
|
+
def each
|
175
|
+
return to_enum :each unless block_given?
|
176
|
+
inst, last = first, last
|
177
|
+
|
178
|
+
while inst
|
179
|
+
yield inst
|
180
|
+
break if inst == last
|
181
|
+
inst = inst.next
|
182
|
+
end
|
183
|
+
|
184
|
+
self
|
185
|
+
end
|
186
|
+
|
187
|
+
# Returns the first Instruction in the collection.
|
188
|
+
def first
|
189
|
+
ptr = C.get_first_instruction(@block)
|
190
|
+
LLVM::Instruction.from_ptr(ptr) unless ptr.null?
|
191
|
+
end
|
192
|
+
|
193
|
+
# Returns the last Instruction in the collection.
|
194
|
+
def last
|
195
|
+
ptr = C.get_last_instruction(@block)
|
196
|
+
LLVM::Instruction.from_ptr(ptr) unless ptr.null?
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
class User < Value
|
202
|
+
# Returns an Enumerable of the operands in this user.
|
203
|
+
def operands
|
204
|
+
@operand_collection ||= OperandCollection.new(self)
|
205
|
+
end
|
206
|
+
|
207
|
+
# @private
|
208
|
+
class OperandCollection
|
209
|
+
include Enumerable
|
210
|
+
|
211
|
+
def initialize(user)
|
212
|
+
@user = user
|
213
|
+
end
|
214
|
+
|
215
|
+
# Get a reference to an operand by index.
|
216
|
+
def [](i)
|
217
|
+
ptr = C.get_operand(@user, i)
|
218
|
+
Value.from_ptr(ptr) unless ptr.null?
|
219
|
+
end
|
220
|
+
|
221
|
+
# Set or replace an operand by index.
|
222
|
+
def []=(i, v)
|
223
|
+
C.set_operand(@user, i, v)
|
224
|
+
end
|
225
|
+
|
226
|
+
# Returns the number of operands in the collection.
|
227
|
+
def size
|
228
|
+
C.get_num_operands(@user)
|
229
|
+
end
|
230
|
+
|
231
|
+
# Iterates through each operand in the collection.
|
232
|
+
def each
|
233
|
+
return to_enum :each unless block_given?
|
234
|
+
0.upto(size - 1) { |i| yield self[i] }
|
235
|
+
self
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
class Constant < User
|
241
|
+
# Creates a null constant of Type.
|
242
|
+
def self.null(type)
|
243
|
+
from_ptr(C.const_null(type))
|
244
|
+
end
|
245
|
+
|
246
|
+
# Creates a undefined constant of Type.
|
247
|
+
def self.undef(type)
|
248
|
+
from_ptr(C.get_undef(type))
|
249
|
+
end
|
250
|
+
|
251
|
+
# Creates a null pointer constant of Type.
|
252
|
+
def self.null_ptr(type)
|
253
|
+
from_ptr(C.const_pointer_null(type))
|
254
|
+
end
|
255
|
+
|
256
|
+
# Bitcast this constant to Type.
|
257
|
+
def bitcast_to(type)
|
258
|
+
ConstantExpr.from_ptr(C.const_bit_cast(self, type))
|
259
|
+
end
|
260
|
+
|
261
|
+
# @deprecated
|
262
|
+
alias bit_cast bitcast_to
|
263
|
+
|
264
|
+
# Returns the element pointer at the given indices of the constant.
|
265
|
+
# For more information on gep go to: http://llvm.org/docs/GetElementPtr.html
|
266
|
+
def gep(*indices)
|
267
|
+
indices = Array(indices)
|
268
|
+
FFI::MemoryPointer.new(FFI.type_size(:pointer) * indices.size) do |indices_ptr|
|
269
|
+
indices_ptr.write_array_of_pointer(indices)
|
270
|
+
return ConstantExpr.from_ptr(
|
271
|
+
C.const_gep(self, indices_ptr, indices.size))
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
# Conversion to integer.
|
276
|
+
def ptr_to_int(type)
|
277
|
+
ConstantInt.from_ptr(C.const_ptr_to_int(self, type))
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
module Support
|
282
|
+
def allocate_pointers(size_or_values, &block)
|
283
|
+
if size_or_values.is_a?(Integer)
|
284
|
+
raise ArgumentError, 'block not given' unless block_given?
|
285
|
+
size = size_or_values
|
286
|
+
values = (0...size).map { |i| yield i }
|
287
|
+
else
|
288
|
+
values = size_or_values
|
289
|
+
size = values.size
|
290
|
+
end
|
291
|
+
FFI::MemoryPointer.new(:pointer, size).write_array_of_pointer(values)
|
292
|
+
end
|
293
|
+
|
294
|
+
module_function :allocate_pointers
|
295
|
+
end
|
296
|
+
|
297
|
+
class ConstantArray < Constant
|
298
|
+
def self.string(str, null_terminate = true)
|
299
|
+
from_ptr(C.const_string(str, str.length, null_terminate ? 0 : 1))
|
300
|
+
end
|
301
|
+
|
302
|
+
# ConstantArray.const(type, 3) {|i| ... } or
|
303
|
+
# ConstantArray.const(type, [...])
|
304
|
+
def self.const(type, size_or_values, &block)
|
305
|
+
vals = LLVM::Support.allocate_pointers(size_or_values, &block)
|
306
|
+
from_ptr C.const_array(type, vals, vals.size / vals.type_size)
|
307
|
+
end
|
308
|
+
|
309
|
+
def size
|
310
|
+
C.get_array_length(type)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
class ConstantExpr < Constant
|
315
|
+
end
|
316
|
+
|
317
|
+
class ConstantInt < Constant
|
318
|
+
def self.all_ones
|
319
|
+
from_ptr(C.const_all_ones(type))
|
320
|
+
end
|
321
|
+
|
322
|
+
# Creates a ConstantInt from an integer.
|
323
|
+
def self.from_i(n, signed = true)
|
324
|
+
from_ptr(C.const_int(type, n, signed ? 1 : 0))
|
325
|
+
end
|
326
|
+
|
327
|
+
def self.parse(str, radix = 10)
|
328
|
+
from_ptr(C.const_int_of_string(type, str, radix))
|
329
|
+
end
|
330
|
+
|
331
|
+
# Negation.
|
332
|
+
def -@
|
333
|
+
self.class.from_ptr(C.const_neg(self))
|
334
|
+
end
|
335
|
+
|
336
|
+
alias neg -@
|
337
|
+
|
338
|
+
# "No signed wrap" negation.
|
339
|
+
def nsw_neg
|
340
|
+
self.class.from_ptr(C.const_nsw_neg(self))
|
341
|
+
end
|
342
|
+
|
343
|
+
# "No unsigned wrap" negation.
|
344
|
+
def nuw_neg
|
345
|
+
self.class.from_ptr(C.const_nuw_neg(self))
|
346
|
+
end
|
347
|
+
|
348
|
+
# Addition.
|
349
|
+
def +(rhs)
|
350
|
+
self.class.from_ptr(C.const_add(self, rhs))
|
351
|
+
end
|
352
|
+
|
353
|
+
alias add +
|
354
|
+
|
355
|
+
# "No signed wrap" addition.
|
356
|
+
def nsw_add(rhs)
|
357
|
+
self.class.from_ptr(C.const_nsw_add(self, rhs))
|
358
|
+
end
|
359
|
+
|
360
|
+
# "No unsigned wrap" addition.
|
361
|
+
def nuw_add(rhs)
|
362
|
+
self.class.from_ptr(C.const_nuw_add(self, rhs))
|
363
|
+
end
|
364
|
+
|
365
|
+
# Subtraction.
|
366
|
+
def -(rhs)
|
367
|
+
self.class.from_ptr(C.const_sub(self, rhs))
|
368
|
+
end
|
369
|
+
|
370
|
+
alias sub -
|
371
|
+
|
372
|
+
# "No signed wrap" subtraction.
|
373
|
+
def nsw_sub(rhs)
|
374
|
+
self.class.from_ptr(C.const_nsw_sub(self, rhs))
|
375
|
+
end
|
376
|
+
|
377
|
+
# "No unsigned wrap" subtraction.
|
378
|
+
def nuw_sub(rhs)
|
379
|
+
self.class.from_ptr(C.const_nuw_sub(self, rhs))
|
380
|
+
end
|
381
|
+
|
382
|
+
# Multiplication.
|
383
|
+
def *(rhs)
|
384
|
+
self.class.from_ptr(C.const_mul(self, rhs))
|
385
|
+
end
|
386
|
+
|
387
|
+
alias mul *
|
388
|
+
|
389
|
+
# "No signed wrap" multiplication.
|
390
|
+
def nsw_mul(rhs)
|
391
|
+
self.class.from_ptr(C.const_nsw_mul(self, rhs))
|
392
|
+
end
|
393
|
+
|
394
|
+
# "No unsigned wrap" multiplication.
|
395
|
+
def nuw_mul(rhs)
|
396
|
+
self.class.from_ptr(C.const_nuw_mul(self, rhs))
|
397
|
+
end
|
398
|
+
|
399
|
+
# Unsigned division.
|
400
|
+
def udiv(rhs)
|
401
|
+
self.class.from_ptr(C.const_u_div(self, rhs))
|
402
|
+
end
|
403
|
+
|
404
|
+
# Signed division.
|
405
|
+
def /(rhs)
|
406
|
+
self.class.from_ptr(C.const_s_div(self, rhs))
|
407
|
+
end
|
408
|
+
|
409
|
+
# Unsigned remainder.
|
410
|
+
def urem(rhs)
|
411
|
+
self.class.from_ptr(C.const_u_rem(self, rhs))
|
412
|
+
end
|
413
|
+
|
414
|
+
# Signed remainder.
|
415
|
+
def rem(rhs)
|
416
|
+
self.class.from_ptr(C.const_s_rem(self, rhs))
|
417
|
+
end
|
418
|
+
|
419
|
+
# Boolean negation.
|
420
|
+
def ~@
|
421
|
+
self.class.from_ptr(C.const_not(self))
|
422
|
+
end
|
423
|
+
|
424
|
+
alias not ~
|
425
|
+
|
426
|
+
# Integer AND.
|
427
|
+
def &(rhs)
|
428
|
+
self.class.from_ptr(C.const_and(self, rhs))
|
429
|
+
end
|
430
|
+
|
431
|
+
alias and &
|
432
|
+
|
433
|
+
# Integer OR.
|
434
|
+
def |(rhs)
|
435
|
+
self.class.from_ptr(C.const_or(self, rhs))
|
436
|
+
end
|
437
|
+
|
438
|
+
alias or |
|
439
|
+
|
440
|
+
# Integer XOR.
|
441
|
+
def ^(rhs)
|
442
|
+
self.class.from_ptr(C.const_xor(self, rhs))
|
443
|
+
end
|
444
|
+
|
445
|
+
alias xor ^
|
446
|
+
|
447
|
+
# Shift left.
|
448
|
+
def <<(bits)
|
449
|
+
self.class.from_ptr(C.const_shl(self, bits))
|
450
|
+
end
|
451
|
+
|
452
|
+
alias shl <<
|
453
|
+
|
454
|
+
# Shift right.
|
455
|
+
def >>(bits)
|
456
|
+
self.class.from_ptr(C.const_l_shr(self, bits))
|
457
|
+
end
|
458
|
+
|
459
|
+
alias shr >>
|
460
|
+
|
461
|
+
# Arithmatic shift right.
|
462
|
+
def ashr(bits)
|
463
|
+
self.class.from_ptr(C.const_a_shr(self, bits))
|
464
|
+
end
|
465
|
+
|
466
|
+
# Integer comparison using the predicate specified via the first parameter.
|
467
|
+
# Predicate can be any of:
|
468
|
+
# :eq - equal to
|
469
|
+
# :ne - not equal to
|
470
|
+
# :ugt - unsigned greater than
|
471
|
+
# :uge - unsigned greater than or equal to
|
472
|
+
# :ult - unsigned less than
|
473
|
+
# :ule - unsigned less than or equal to
|
474
|
+
# :sgt - signed greater than
|
475
|
+
# :sge - signed greater than or equal to
|
476
|
+
# :slt - signed less than
|
477
|
+
# :sle - signed less than or equal to
|
478
|
+
def icmp(pred, rhs)
|
479
|
+
self.class.from_ptr(C.const_i_cmp(pred, self, rhs))
|
480
|
+
end
|
481
|
+
|
482
|
+
# Conversion to pointer.
|
483
|
+
def int_to_ptr(type)
|
484
|
+
ConstantExpr.from_ptr(C.const_int_to_ptr(self, type))
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
def self.const_missing(const)
|
489
|
+
case const.to_s
|
490
|
+
when /Int(\d+)/
|
491
|
+
width = Regexp.last_match(1).to_i
|
492
|
+
name = "Int#{width}"
|
493
|
+
eval <<-KLASS
|
494
|
+
class #{name} < ConstantInt
|
495
|
+
def self.type
|
496
|
+
Type.from_ptr(C.int_type(#{width}), :integer)
|
497
|
+
end
|
498
|
+
end
|
499
|
+
KLASS
|
500
|
+
const_get(name)
|
501
|
+
else
|
502
|
+
super
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
# Native integer type
|
507
|
+
bits = FFI.type_size(:int) * 8
|
508
|
+
::LLVM::Int = const_get("Int#{bits}")
|
509
|
+
|
510
|
+
# Creates a LLVM Int (subclass of ConstantInt) at the NATIVE_INT_SIZE from a integer (val).
|
511
|
+
def self.Int(val)
|
512
|
+
case val
|
513
|
+
when LLVM::ConstantInt then val
|
514
|
+
when Integer then Int.from_i(val)
|
515
|
+
when Value
|
516
|
+
return val if val.type.kind == :integer
|
517
|
+
raise "value not of integer type: #{val.type.kind}"
|
518
|
+
else raise "can't make an LLVM::ConstantInt from #{val.class.name}"
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
# Boolean values
|
523
|
+
::LLVM::TRUE = ::LLVM::Int1.from_i(-1)
|
524
|
+
::LLVM::FALSE = ::LLVM::Int1.from_i(0)
|
525
|
+
|
526
|
+
class ConstantReal < Constant
|
527
|
+
# Creates a ConstantReal from a float of Type.
|
528
|
+
def self.from_f(n)
|
529
|
+
from_ptr(C.const_real(type, n))
|
530
|
+
end
|
531
|
+
|
532
|
+
def self.parse(type, str)
|
533
|
+
from_ptr(C.const_real_of_string(type, str))
|
534
|
+
end
|
535
|
+
|
536
|
+
# Negation.
|
537
|
+
def -@
|
538
|
+
self.class.from_ptr(C.const_f_neg(self))
|
539
|
+
end
|
540
|
+
|
541
|
+
# Returns the result of adding this ConstantReal to rhs.
|
542
|
+
def +(rhs)
|
543
|
+
self.class.from_ptr(C.const_f_add(self, rhs))
|
544
|
+
end
|
545
|
+
|
546
|
+
# Returns the result of multiplying this ConstantReal by rhs.
|
547
|
+
def *(rhs)
|
548
|
+
self.class.from_ptr(C.const_f_mul(self, rhs))
|
549
|
+
end
|
550
|
+
|
551
|
+
# Returns the result of dividing this ConstantReal by rhs.
|
552
|
+
def /(rhs)
|
553
|
+
self.class.from_ptr(C.const_f_div(self, rhs))
|
554
|
+
end
|
555
|
+
|
556
|
+
# Remainder.
|
557
|
+
def rem(rhs)
|
558
|
+
self.class.from_ptr(C.const_f_rem(self, rhs))
|
559
|
+
end
|
560
|
+
|
561
|
+
# Floating point comparison using the predicate specified via the first
|
562
|
+
# parameter. Predicate can be any of:
|
563
|
+
# :ord - ordered
|
564
|
+
# :uno - unordered: isnan(X) | isnan(Y)
|
565
|
+
# :oeq - ordered and equal to
|
566
|
+
# :oeq - unordered and equal to
|
567
|
+
# :one - ordered and not equal to
|
568
|
+
# :one - unordered and not equal to
|
569
|
+
# :ogt - ordered and greater than
|
570
|
+
# :uge - unordered and greater than or equal to
|
571
|
+
# :olt - ordered and less than
|
572
|
+
# :ule - unordered and less than or equal to
|
573
|
+
# :oge - ordered and greater than or equal to
|
574
|
+
# :sge - unordered and greater than or equal to
|
575
|
+
# :ole - ordered and less than or equal to
|
576
|
+
# :sle - unordered and less than or equal to
|
577
|
+
# :true - always true
|
578
|
+
# :false- always false
|
579
|
+
def fcmp(pred, rhs)
|
580
|
+
self.class.from_ptr(C.llmv_const_f_cmp(pred, self, rhs))
|
581
|
+
end
|
582
|
+
end
|
583
|
+
|
584
|
+
class Float < ConstantReal
|
585
|
+
# Return a Type representation of the float.
|
586
|
+
def self.type
|
587
|
+
Type.from_ptr(C.float_type, :float)
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
# Create a LLVM::Float from a Ruby Float (val).
|
592
|
+
def self.Float(val)
|
593
|
+
Float.from_f(val)
|
594
|
+
end
|
595
|
+
|
596
|
+
class Double < ConstantReal
|
597
|
+
def self.type
|
598
|
+
Type.from_ptr(C.double_type, :double)
|
599
|
+
end
|
600
|
+
end
|
601
|
+
|
602
|
+
def self.Double(val)
|
603
|
+
Double.from_f(val)
|
604
|
+
end
|
605
|
+
|
606
|
+
class ConstantStruct < Constant
|
607
|
+
# ConstantStruct.const(size) {|i| ... } or
|
608
|
+
# ConstantStruct.const([...])
|
609
|
+
def self.const(size_or_values, packed = false, &block)
|
610
|
+
vals = LLVM::Support.allocate_pointers(size_or_values, &block)
|
611
|
+
from_ptr C.const_struct(vals, vals.size / vals.type_size, packed ? 1 : 0)
|
612
|
+
end
|
613
|
+
|
614
|
+
def self.named_const(type, size_or_values, &block)
|
615
|
+
vals = LLVM::Support.allocate_pointers(size_or_values, &block)
|
616
|
+
from_ptr C.const_named_struct(type, vals, vals.size / vals.type_size)
|
617
|
+
end
|
618
|
+
end
|
619
|
+
|
620
|
+
class ConstantVector < Constant
|
621
|
+
def self.all_ones
|
622
|
+
from_ptr(C.const_all_ones(type))
|
623
|
+
end
|
624
|
+
|
625
|
+
def self.const(size_or_values, &block)
|
626
|
+
vals = LLVM::Support.allocate_pointers(size_or_values, &block)
|
627
|
+
from_ptr(C.const_vector(vals, vals.size / vals.type_size))
|
628
|
+
end
|
629
|
+
|
630
|
+
def size
|
631
|
+
C.get_vector_size(type)
|
632
|
+
end
|
633
|
+
end
|
634
|
+
|
635
|
+
class GlobalValue < Constant
|
636
|
+
def declaration?
|
637
|
+
C.is_declaration(self)
|
638
|
+
end
|
639
|
+
|
640
|
+
def linkage
|
641
|
+
C.get_linkage(self)
|
642
|
+
end
|
643
|
+
|
644
|
+
def linkage=(linkage)
|
645
|
+
C.set_linkage(self, linkage)
|
646
|
+
end
|
647
|
+
|
648
|
+
def section
|
649
|
+
C.get_section(self)
|
650
|
+
end
|
651
|
+
|
652
|
+
def section=(section)
|
653
|
+
C.set_section(self, section)
|
654
|
+
end
|
655
|
+
|
656
|
+
def visibility
|
657
|
+
C.get_visibility(self)
|
658
|
+
end
|
659
|
+
|
660
|
+
def visibility=(viz)
|
661
|
+
C.set_visibility(self, viz)
|
662
|
+
end
|
663
|
+
|
664
|
+
def alignment
|
665
|
+
C.get_alignment(self)
|
666
|
+
end
|
667
|
+
|
668
|
+
def alignment=(bytes)
|
669
|
+
C.set_alignment(self, bytes)
|
670
|
+
end
|
671
|
+
|
672
|
+
def initializer
|
673
|
+
Value.from_ptr(C.get_initializer(self))
|
674
|
+
end
|
675
|
+
|
676
|
+
def initializer=(val)
|
677
|
+
C.set_initializer(self, val)
|
678
|
+
end
|
679
|
+
|
680
|
+
def global_constant?
|
681
|
+
C.is_global_constant(self) != 0
|
682
|
+
end
|
683
|
+
|
684
|
+
def global_constant=(flag)
|
685
|
+
if flag.kind_of?(Integer)
|
686
|
+
warn 'Warning: Passing Integer value to LLVM::GlobalValue#global_constant=(Boolean) is deprecated.'
|
687
|
+
flag = !flag.zero?
|
688
|
+
end
|
689
|
+
|
690
|
+
C.set_global_constant(self, flag ? 1 : 0)
|
691
|
+
end
|
692
|
+
|
693
|
+
def unnamed_addr?
|
694
|
+
C.has_unnamed_addr(self) != 0
|
695
|
+
end
|
696
|
+
|
697
|
+
def unnamed_addr=(flag)
|
698
|
+
C.set_unnamed_addr(self, flag ? 1 : 0)
|
699
|
+
end
|
700
|
+
|
701
|
+
def dll_storage_class
|
702
|
+
C.get_dll_storage_class(self)
|
703
|
+
end
|
704
|
+
|
705
|
+
def dll_storage_class=(klass)
|
706
|
+
C.set_dll_storage_class(self, klass)
|
707
|
+
end
|
708
|
+
end
|
709
|
+
|
710
|
+
class Function < GlobalValue
|
711
|
+
# Sets the function's calling convention and returns it.
|
712
|
+
def call_conv=(conv)
|
713
|
+
C.set_function_call_conv(self, conv)
|
714
|
+
conv
|
715
|
+
end
|
716
|
+
|
717
|
+
# Returns an Enumerable of the BasicBlocks in this function.
|
718
|
+
def basic_blocks
|
719
|
+
@basic_block_collection ||= BasicBlockCollection.new(self)
|
720
|
+
end
|
721
|
+
|
722
|
+
def type
|
723
|
+
Type.from_ptr(C.type_of(self), :pointer)
|
724
|
+
end
|
725
|
+
|
726
|
+
def function_type
|
727
|
+
type.element_type
|
728
|
+
end
|
729
|
+
|
730
|
+
# Adds attr to this value's attributes.
|
731
|
+
def add_attribute(attr, index = -1)
|
732
|
+
AttributeCollection.new(self, index).add(attr)
|
733
|
+
end
|
734
|
+
|
735
|
+
# Removes the given attribute from the function.
|
736
|
+
def remove_attribute(attr, index = -1)
|
737
|
+
AttributeCollection.new(self, index).remove(attr)
|
738
|
+
end
|
739
|
+
|
740
|
+
def attribute_count
|
741
|
+
function_attributes.count
|
742
|
+
end
|
743
|
+
|
744
|
+
def attributes
|
745
|
+
function_attributes.to_a
|
746
|
+
end
|
747
|
+
|
748
|
+
def function_attributes
|
749
|
+
AttributeCollection.new(self, -1)
|
750
|
+
end
|
751
|
+
|
752
|
+
def return_attributes
|
753
|
+
AttributeCollection.new(self, 0)
|
754
|
+
end
|
755
|
+
|
756
|
+
def param_attributes(index)
|
757
|
+
AttributeCollection.new(self, index)
|
758
|
+
end
|
759
|
+
|
760
|
+
class AttributeCollection
|
761
|
+
|
762
|
+
def initialize(fun, index)
|
763
|
+
@fun = fun
|
764
|
+
@index = index
|
765
|
+
end
|
766
|
+
|
767
|
+
def add(attr)
|
768
|
+
attr_kind_id = attribute_id(attr)
|
769
|
+
ctx = Context.global
|
770
|
+
attr_ref = C.create_enum_attribute(ctx, attr_kind_id, 0)
|
771
|
+
C.add_attribute_at_index(@fun, @index, attr_ref)
|
772
|
+
end
|
773
|
+
|
774
|
+
def remove(attr)
|
775
|
+
attr_kind_id = attribute_id(attr)
|
776
|
+
C.remove_enum_attribute_at_index(@fun, @index, attr_kind_id)
|
777
|
+
end
|
778
|
+
|
779
|
+
def count
|
780
|
+
C.get_attribute_count_at_index(@fun, @index)
|
781
|
+
end
|
782
|
+
|
783
|
+
def to_a
|
784
|
+
attr_refs = nil
|
785
|
+
n = count
|
786
|
+
FFI::MemoryPointer.new(:pointer, n) do |p|
|
787
|
+
C.get_attributes_at_index(@fun, @index, p)
|
788
|
+
attr_refs = p.read_array_of_type(:pointer, :read_pointer, n)
|
789
|
+
end
|
790
|
+
|
791
|
+
attr_refs.map { |e| C.get_enum_attribute_kind(e) }
|
792
|
+
end
|
793
|
+
|
794
|
+
private
|
795
|
+
|
796
|
+
def attribute_name(attr_name)
|
797
|
+
attr_name = attr_name.to_s
|
798
|
+
if attr_name =~ /_attribute$/
|
799
|
+
attr_name.chomp('_attribute').tr('_', '')
|
800
|
+
else
|
801
|
+
attr_name
|
802
|
+
end
|
803
|
+
end
|
804
|
+
|
805
|
+
def attribute_id(attr_name)
|
806
|
+
attr_mem = FFI::MemoryPointer.from_string(attribute_name(attr_name))
|
807
|
+
attr_kind_id = C.get_enum_attribute_kind_for_name(attr_mem, attr_mem.size - 1)
|
808
|
+
|
809
|
+
raise "No attribute named: #{attr_name}" if attr_kind_id.zero?
|
810
|
+
attr_kind_id
|
811
|
+
end
|
812
|
+
end
|
813
|
+
|
814
|
+
# @private
|
815
|
+
class BasicBlockCollection
|
816
|
+
include Enumerable
|
817
|
+
|
818
|
+
def initialize(fun)
|
819
|
+
@fun = fun
|
820
|
+
end
|
821
|
+
|
822
|
+
# Returns the number of BasicBlocks in the collection.
|
823
|
+
def size
|
824
|
+
C.count_basic_blocks(@fun)
|
825
|
+
end
|
826
|
+
|
827
|
+
# Iterates through each BasicBlock in the collection.
|
828
|
+
def each
|
829
|
+
return to_enum :each unless block_given?
|
830
|
+
|
831
|
+
ptr = C.get_first_basic_block(@fun)
|
832
|
+
0.upto(size - 1) do |i|
|
833
|
+
yield BasicBlock.from_ptr(ptr)
|
834
|
+
ptr = C.get_next_basic_block(ptr)
|
835
|
+
end
|
836
|
+
|
837
|
+
self
|
838
|
+
end
|
839
|
+
|
840
|
+
# Adds a BasicBlock with the given name to the end of the collection.
|
841
|
+
def append(name = "")
|
842
|
+
BasicBlock.create(@fun, name)
|
843
|
+
end
|
844
|
+
|
845
|
+
# Returns the entry BasicBlock in the collection. This is the block the
|
846
|
+
# function starts on.
|
847
|
+
def entry
|
848
|
+
BasicBlock.from_ptr(C.get_entry_basic_block(@fun))
|
849
|
+
end
|
850
|
+
|
851
|
+
# Returns the first BasicBlock in the collection.
|
852
|
+
def first
|
853
|
+
ptr = C.get_first_basic_block(@fun)
|
854
|
+
BasicBlock.from_ptr(ptr) unless ptr.null?
|
855
|
+
end
|
856
|
+
|
857
|
+
# Returns the last BasicBlock in the collection.
|
858
|
+
def last
|
859
|
+
ptr = C.get_last_basic_block(@fun)
|
860
|
+
BasicBlock.from_ptr(ptr) unless ptr.null?
|
861
|
+
end
|
862
|
+
end
|
863
|
+
|
864
|
+
# Returns an Enumerable of the parameters in the function.
|
865
|
+
def params
|
866
|
+
@parameter_collection ||= ParameterCollection.new(self)
|
867
|
+
end
|
868
|
+
|
869
|
+
# @private
|
870
|
+
class ParameterCollection
|
871
|
+
def initialize(fun)
|
872
|
+
@fun = fun
|
873
|
+
end
|
874
|
+
|
875
|
+
# Returns a Value representation of the parameter at the given index.
|
876
|
+
def [](i)
|
877
|
+
sz = size
|
878
|
+
i = sz + i if i < 0
|
879
|
+
return unless 0 <= i && i < sz
|
880
|
+
Value.from_ptr(C.get_param(@fun, i))
|
881
|
+
end
|
882
|
+
|
883
|
+
# Returns the number of paramters in the collection.
|
884
|
+
def size
|
885
|
+
C.count_params(@fun)
|
886
|
+
end
|
887
|
+
|
888
|
+
include Enumerable
|
889
|
+
|
890
|
+
# Iteraters through each parameter in the collection.
|
891
|
+
def each
|
892
|
+
return to_enum :each unless block_given?
|
893
|
+
0.upto(size - 1) { |i| yield self[i] }
|
894
|
+
self
|
895
|
+
end
|
896
|
+
end
|
897
|
+
|
898
|
+
def gc=(name)
|
899
|
+
C.set_gc(self, name)
|
900
|
+
end
|
901
|
+
|
902
|
+
def gc
|
903
|
+
C.get_gc(self)
|
904
|
+
end
|
905
|
+
end
|
906
|
+
|
907
|
+
class GlobalAlias < GlobalValue
|
908
|
+
end
|
909
|
+
|
910
|
+
class GlobalVariable < GlobalValue
|
911
|
+
def initializer
|
912
|
+
Value.from_ptr(C.get_initializer(self))
|
913
|
+
end
|
914
|
+
|
915
|
+
def initializer=(val)
|
916
|
+
C.set_initializer(self, val)
|
917
|
+
end
|
918
|
+
|
919
|
+
def thread_local?
|
920
|
+
case C.is_thread_local(self)
|
921
|
+
when 0 then false
|
922
|
+
else true
|
923
|
+
end
|
924
|
+
end
|
925
|
+
|
926
|
+
def thread_local=(local)
|
927
|
+
C.set_thread_local(self, local ? 1 : 0)
|
928
|
+
end
|
929
|
+
end
|
930
|
+
|
931
|
+
class Instruction < User
|
932
|
+
# Returns the parent of the instruction (a BasicBlock).
|
933
|
+
def parent
|
934
|
+
ptr = C.get_instruction_parent(self)
|
935
|
+
LLVM::BasicBlock.from_ptr(ptr) unless ptr.null?
|
936
|
+
end
|
937
|
+
|
938
|
+
# Returns the next instruction after this one.
|
939
|
+
def next
|
940
|
+
ptr = C.get_next_instruction(self)
|
941
|
+
LLVM::Instruction.from_ptr(ptr) unless ptr.null?
|
942
|
+
end
|
943
|
+
|
944
|
+
# Returns the previous instruction before this one.
|
945
|
+
def previous
|
946
|
+
ptr = C.get_previous_instruction(self)
|
947
|
+
LLVM::Instruction.from_ptr(ptr) unless ptr.null?
|
948
|
+
end
|
949
|
+
end
|
950
|
+
|
951
|
+
class CallInst < Instruction
|
952
|
+
# Sets the call convention to conv.
|
953
|
+
def call_conv=(conv)
|
954
|
+
C.set_instruction_call_conv(self, conv)
|
955
|
+
conv
|
956
|
+
end
|
957
|
+
|
958
|
+
# Returns the call insatnce's call convention.
|
959
|
+
def call_conv
|
960
|
+
C.get_instruction_call_conv(self)
|
961
|
+
end
|
962
|
+
end
|
963
|
+
|
964
|
+
# @private
|
965
|
+
class Phi < Instruction
|
966
|
+
# Add incoming branches to a phi node by passing an alternating list of
|
967
|
+
# resulting values and BasicBlocks. e.g.
|
968
|
+
# phi.add_incoming(val1, block1, val2, block2, ...)
|
969
|
+
def add_incoming(incoming)
|
970
|
+
blks = incoming.keys
|
971
|
+
vals = incoming.values_at(*blks)
|
972
|
+
size = incoming.size
|
973
|
+
|
974
|
+
FFI::MemoryPointer.new(FFI.type_size(:pointer) * size) do |vals_ptr|
|
975
|
+
vals_ptr.write_array_of_pointer(vals)
|
976
|
+
FFI::MemoryPointer.new(FFI.type_size(:pointer) * size) do |blks_ptr|
|
977
|
+
blks_ptr.write_array_of_pointer(blks)
|
978
|
+
C.add_incoming(self, vals_ptr, blks_ptr, vals.size)
|
979
|
+
end
|
980
|
+
end
|
981
|
+
|
982
|
+
nil
|
983
|
+
end
|
984
|
+
end
|
985
|
+
|
986
|
+
# @private
|
987
|
+
class SwitchInst < Instruction
|
988
|
+
# Adds a case to a switch instruction. First the value to match on, then
|
989
|
+
# the basic block.
|
990
|
+
def add_case(val, block)
|
991
|
+
C.add_case(self, val, block)
|
992
|
+
end
|
993
|
+
end
|
994
|
+
|
995
|
+
|
996
|
+
# @private
|
997
|
+
class IndirectBr < Instruction
|
998
|
+
# Adds a basic block reference as a destination for this indirect branch.
|
999
|
+
def add_dest(dest)
|
1000
|
+
C.add_destination(self, dest)
|
1001
|
+
end
|
1002
|
+
|
1003
|
+
alias :<< :add_dest
|
1004
|
+
end
|
1005
|
+
end
|