waj-ruby-llvm 2.9.2
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 +31 -0
- data/ext/ruby-llvm-support/Makefile.am +1 -0
- data/ext/ruby-llvm-support/Makefile.in +612 -0
- data/ext/ruby-llvm-support/config.guess +1500 -0
- data/ext/ruby-llvm-support/config.sub +1616 -0
- data/ext/ruby-llvm-support/configure +17190 -0
- data/ext/ruby-llvm-support/configure.ac +16 -0
- data/ext/ruby-llvm-support/depcomp +584 -0
- data/ext/ruby-llvm-support/install-sh +507 -0
- data/ext/ruby-llvm-support/libtool +9403 -0
- data/ext/ruby-llvm-support/ltmain.sh +8745 -0
- data/ext/ruby-llvm-support/missing +367 -0
- data/ext/ruby-llvm-support/src/Makefile.am +5 -0
- data/ext/ruby-llvm-support/src/Makefile.in +472 -0
- data/ext/ruby-llvm-support/src/support.cpp +12 -0
- data/lib/llvm.rb +12 -0
- data/lib/llvm/analysis.rb +62 -0
- data/lib/llvm/core.rb +598 -0
- data/lib/llvm/core/bitcode.rb +88 -0
- data/lib/llvm/core/builder.rb +851 -0
- data/lib/llvm/core/context.rb +22 -0
- data/lib/llvm/core/module.rb +232 -0
- data/lib/llvm/core/pass_manager.rb +76 -0
- data/lib/llvm/core/type.rb +173 -0
- data/lib/llvm/core/value.rb +782 -0
- data/lib/llvm/execution_engine.rb +169 -0
- data/lib/llvm/support.rb +22 -0
- data/lib/llvm/target.rb +9 -0
- data/lib/llvm/transforms/ipo.rb +23 -0
- data/lib/llvm/transforms/scalar.rb +136 -0
- data/test/array_test.rb +38 -0
- data/test/basic_block_test.rb +88 -0
- data/test/basic_test.rb +11 -0
- data/test/binary_operations_test.rb +58 -0
- data/test/bitcode_test.rb +25 -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 +86 -0
- data/test/double_test.rb +33 -0
- data/test/equality_test.rb +91 -0
- data/test/generic_value_test.rb +22 -0
- data/test/instruction_test.rb +32 -0
- data/test/ipo_test.rb +53 -0
- data/test/memory_access_test.rb +38 -0
- data/test/module_test.rb +21 -0
- data/test/parameter_collection_test.rb +28 -0
- data/test/phi_test.rb +33 -0
- data/test/select_test.rb +22 -0
- data/test/struct_test.rb +75 -0
- data/test/test_helper.rb +50 -0
- data/test/type_test.rb +15 -0
- data/test/vector_test.rb +64 -0
- metadata +133 -0
@@ -0,0 +1,782 @@
|
|
1
|
+
module LLVM
|
2
|
+
class Value
|
3
|
+
# @private
|
4
|
+
def self.from_ptr(ptr)
|
5
|
+
return if ptr.null?
|
6
|
+
val = allocate
|
7
|
+
val.instance_variable_set(:@ptr, ptr)
|
8
|
+
val
|
9
|
+
end
|
10
|
+
|
11
|
+
# @private
|
12
|
+
def to_ptr
|
13
|
+
@ptr
|
14
|
+
end
|
15
|
+
|
16
|
+
# Checks if the value is equal to other.
|
17
|
+
def ==(other)
|
18
|
+
case other
|
19
|
+
when LLVM::Value
|
20
|
+
@ptr == other.to_ptr
|
21
|
+
else
|
22
|
+
false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def hash
|
27
|
+
@ptr.address.hash
|
28
|
+
end
|
29
|
+
|
30
|
+
# Checks if the value is equal to other.
|
31
|
+
def eql?(other)
|
32
|
+
other.instance_of?(self.class) && self == other
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the Value type. This is abstract and is overidden by its subclasses.
|
36
|
+
def self.type
|
37
|
+
raise NotImplementedError, "#{self.name}.type() is abstract."
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.to_ptr
|
41
|
+
type.to_ptr
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns the value's type.
|
45
|
+
def type
|
46
|
+
Type.from_ptr(C.LLVMTypeOf(self))
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns the value's name.
|
50
|
+
def name
|
51
|
+
C.LLVMGetValueName(self)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Sets the value's name to str.
|
55
|
+
def name=(str)
|
56
|
+
C.LLVMSetValueName(self, str)
|
57
|
+
str
|
58
|
+
end
|
59
|
+
|
60
|
+
# Print the value's IR to stdout.
|
61
|
+
def dump
|
62
|
+
C.LLVMDumpValue(self)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns whether the value is constant.
|
66
|
+
def constant?
|
67
|
+
case C.LLVMIsConstant(self)
|
68
|
+
when 0 then false
|
69
|
+
when 1 then true
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns whether the value is null.
|
74
|
+
def null?
|
75
|
+
case C.LLVMIsNull(self)
|
76
|
+
when 0 then false
|
77
|
+
when 1 then true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Returns whether the value is undefined.
|
82
|
+
def undefined?
|
83
|
+
case C.LLVMIsUndef(self)
|
84
|
+
when 0 then false
|
85
|
+
when 1 then true
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Adds attr to this value's attributes.
|
90
|
+
def add_attribute(attr)
|
91
|
+
C.LLVMAddAttribute(self, attr)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class Argument < Value
|
96
|
+
end
|
97
|
+
|
98
|
+
class BasicBlock < Value
|
99
|
+
# Creates a basic block for the given function with the given name.
|
100
|
+
def self.create(fun = nil, name = "")
|
101
|
+
self.from_ptr(C.LLVMAppendBasicBlock(fun, name))
|
102
|
+
end
|
103
|
+
|
104
|
+
# Build the basic block with the given builder. Creates a new one if nil. Yields the builder.
|
105
|
+
def build(builder = nil)
|
106
|
+
if builder.nil?
|
107
|
+
builder = Builder.new
|
108
|
+
islocal = true
|
109
|
+
else
|
110
|
+
islocal = false
|
111
|
+
end
|
112
|
+
builder.position_at_end(self)
|
113
|
+
yield builder
|
114
|
+
ensure
|
115
|
+
builder.dispose if islocal
|
116
|
+
end
|
117
|
+
|
118
|
+
# Returns the parent of this basic block (a Function).
|
119
|
+
def parent
|
120
|
+
fp = C.LLVMGetBasicBlockParent(self)
|
121
|
+
LLVM::Function.from_ptr(fp) unless fp.null?
|
122
|
+
end
|
123
|
+
|
124
|
+
# Returns the next basic block in the sequence.
|
125
|
+
def next
|
126
|
+
ptr = C.LLVMGetNextBasicBlock(self)
|
127
|
+
BasicBlock.from_ptr(ptr) unless ptr.null?
|
128
|
+
end
|
129
|
+
|
130
|
+
# Returns the previous basic block in the sequence.
|
131
|
+
def previous
|
132
|
+
ptr = C.LLVMGetPreviousBasicBlock(self)
|
133
|
+
BasicBlock.from_ptr(ptr) unless ptr.null?
|
134
|
+
end
|
135
|
+
|
136
|
+
def first_instruction # deprecated
|
137
|
+
instructions.first
|
138
|
+
end
|
139
|
+
|
140
|
+
def last_instruction # deprecated
|
141
|
+
instructions.last
|
142
|
+
end
|
143
|
+
|
144
|
+
# Returns an Enumerable of the Instructions in the current block.
|
145
|
+
def instructions
|
146
|
+
@instructions ||= InstructionCollection.new(self)
|
147
|
+
end
|
148
|
+
|
149
|
+
# @private
|
150
|
+
class InstructionCollection
|
151
|
+
include Enumerable
|
152
|
+
|
153
|
+
def initialize(block)
|
154
|
+
@block = block
|
155
|
+
end
|
156
|
+
|
157
|
+
# Iterates through each Instruction in the collection.
|
158
|
+
def each
|
159
|
+
return to_enum :each unless block_given?
|
160
|
+
inst, last = first, last
|
161
|
+
|
162
|
+
while inst
|
163
|
+
yield inst
|
164
|
+
break if inst == last
|
165
|
+
inst = inst.next
|
166
|
+
end
|
167
|
+
|
168
|
+
self
|
169
|
+
end
|
170
|
+
|
171
|
+
# Returns the first Instruction in the collection.
|
172
|
+
def first
|
173
|
+
ptr = C.LLVMGetFirstInstruction(@block)
|
174
|
+
LLVM::Instruction.from_ptr(ptr) unless ptr.null?
|
175
|
+
end
|
176
|
+
|
177
|
+
# Returns the last Instruction in the collection.
|
178
|
+
def last
|
179
|
+
ptr = C.LLVMGetLastInstruction(@block)
|
180
|
+
LLVM::Instruction.from_ptr(ptr) unless ptr.null?
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
class User < Value
|
186
|
+
# Returns an Enumerable of the operands in this user.
|
187
|
+
def operands
|
188
|
+
@operand_collection ||= OperandCollection.new(self)
|
189
|
+
end
|
190
|
+
|
191
|
+
# @private
|
192
|
+
class OperandCollection
|
193
|
+
include Enumerable
|
194
|
+
|
195
|
+
def initialize(user)
|
196
|
+
@user = user
|
197
|
+
end
|
198
|
+
|
199
|
+
# Get a reference to an operand by index.
|
200
|
+
def [](i)
|
201
|
+
ptr = C.LLVMGetOperand(@user, i)
|
202
|
+
Value.from_ptr(ptr) unless ptr.null?
|
203
|
+
end
|
204
|
+
|
205
|
+
# Set or replace an operand by index.
|
206
|
+
def []=(i, v)
|
207
|
+
C.LLVMSetOperand(@user, i, v)
|
208
|
+
end
|
209
|
+
|
210
|
+
# Returns the number of operands in the collection.
|
211
|
+
def size
|
212
|
+
C.LLVMGetNumOperands(@user)
|
213
|
+
end
|
214
|
+
|
215
|
+
# Iterates through each operand in the collection.
|
216
|
+
def each
|
217
|
+
return to_enum :each unless block_given?
|
218
|
+
0.upto(size-1) { |i| yield self[i] }
|
219
|
+
self
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
class Constant < User
|
225
|
+
# Creates a null constant of Type.
|
226
|
+
def self.null(type)
|
227
|
+
from_ptr(C.LLVMConstNull(type))
|
228
|
+
end
|
229
|
+
|
230
|
+
# Creates a undefined constant of Type.
|
231
|
+
def self.undef(type)
|
232
|
+
from_ptr(C.LLVMGetUndef(type))
|
233
|
+
end
|
234
|
+
|
235
|
+
# Creates a null pointer constant of Type.
|
236
|
+
def self.null_ptr(type)
|
237
|
+
from_ptr(C.LLVMConstPointerNull(type))
|
238
|
+
end
|
239
|
+
|
240
|
+
# Bitcast this constant to Type.
|
241
|
+
def bitcast_to(type)
|
242
|
+
ConstantExpr.from_ptr(C.LLVMConstBitCast(self, type))
|
243
|
+
end
|
244
|
+
|
245
|
+
# Returns the element pointer at the given indices of the constant.
|
246
|
+
# For more information on gep go to: http://llvm.org/docs/GetElementPtr.html
|
247
|
+
def gep(*indices)
|
248
|
+
indices = Array(indices)
|
249
|
+
FFI::MemoryPointer.new(FFI.type_size(:pointer) * indices.size) do |indices_ptr|
|
250
|
+
indices_ptr.write_array_of_pointer(indices)
|
251
|
+
return ConstantExpr.from_ptr(
|
252
|
+
C.LLVMConstGEP(self, indices_ptr, indices.size))
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
module Support
|
258
|
+
def allocate_pointers(size_or_values, &block)
|
259
|
+
if size_or_values.is_a?(Integer)
|
260
|
+
raise ArgumentError, 'block not given' unless block_given?
|
261
|
+
size = size_or_values
|
262
|
+
values = (0...size).map { |i| yield i }
|
263
|
+
else
|
264
|
+
values = size_or_values
|
265
|
+
size = values.size
|
266
|
+
end
|
267
|
+
FFI::MemoryPointer.new(:pointer, size).write_array_of_pointer(values)
|
268
|
+
end
|
269
|
+
|
270
|
+
module_function :allocate_pointers
|
271
|
+
end
|
272
|
+
|
273
|
+
class ConstantArray < Constant
|
274
|
+
def self.string(str, null_terminate = true)
|
275
|
+
from_ptr(C.LLVMConstString(str, str.length, null_terminate ? 0 : 1))
|
276
|
+
end
|
277
|
+
|
278
|
+
# ConstantArray.const(type, 3) {|i| ... } or
|
279
|
+
# ConstantArray.const(type, [...])
|
280
|
+
def self.const(type, size_or_values, &block)
|
281
|
+
vals = LLVM::Support.allocate_pointers(size_or_values, &block)
|
282
|
+
from_ptr C.LLVMConstArray(type, vals, vals.size / vals.type_size)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
class ConstantExpr < Constant
|
287
|
+
end
|
288
|
+
|
289
|
+
class ConstantInt < Constant
|
290
|
+
def self.all_ones
|
291
|
+
from_ptr(C.LLVMConstAllOnes(type))
|
292
|
+
end
|
293
|
+
|
294
|
+
# Creates a ConstantInt from an integer.
|
295
|
+
def self.from_i(n, signed = true)
|
296
|
+
from_ptr(C.LLVMConstInt(type, n, signed ? 1 : 0))
|
297
|
+
end
|
298
|
+
|
299
|
+
def self.parse(str, radix = 10)
|
300
|
+
from_ptr(C.LLVMConstIntOfString(type, str, radix))
|
301
|
+
end
|
302
|
+
|
303
|
+
# Negation.
|
304
|
+
def -@
|
305
|
+
self.class.from_ptr(C.LLVMConstNeg(self))
|
306
|
+
end
|
307
|
+
|
308
|
+
# Boolean negation.
|
309
|
+
def not
|
310
|
+
self.class.from_ptr(C.LLVMConstNot(self))
|
311
|
+
end
|
312
|
+
|
313
|
+
# Addition.
|
314
|
+
def +(rhs)
|
315
|
+
self.class.from_ptr(C.LLVMConstAdd(self, rhs))
|
316
|
+
end
|
317
|
+
|
318
|
+
# "No signed wrap" addition. See
|
319
|
+
# http://llvm.org/docs/LangRef.html#i_add for discusison.
|
320
|
+
def nsw_add(rhs)
|
321
|
+
self.class.from_ptr(C.LLVMConstNSWAdd(self, rhs))
|
322
|
+
end
|
323
|
+
|
324
|
+
# Multiplication.
|
325
|
+
def *(rhs)
|
326
|
+
self.class.from_ptr(C.LLVMConstMul(self, rhs))
|
327
|
+
end
|
328
|
+
|
329
|
+
# Unsigned division.
|
330
|
+
def udiv(rhs)
|
331
|
+
self.class.from_ptr(C.LLVMConstUDiv(self, rhs))
|
332
|
+
end
|
333
|
+
|
334
|
+
# Signed division.
|
335
|
+
def /(rhs)
|
336
|
+
self.class.from_ptr(C.LLVMConstSDiv(self, rhs))
|
337
|
+
end
|
338
|
+
|
339
|
+
# Unsigned remainder.
|
340
|
+
def urem(rhs)
|
341
|
+
self.class.from_ptr(C.LLVMConstURem(self, rhs))
|
342
|
+
end
|
343
|
+
|
344
|
+
# Signed remainder.
|
345
|
+
def rem(rhs)
|
346
|
+
self.class.from_ptr(C.LLVMConstSRem(self, rhs))
|
347
|
+
end
|
348
|
+
|
349
|
+
# Integer AND.
|
350
|
+
def and(rhs)
|
351
|
+
self.class.from_ptr(C.LLVMConstAnd(self, rhs))
|
352
|
+
end
|
353
|
+
|
354
|
+
# Integer OR.
|
355
|
+
def or(rhs)
|
356
|
+
self.class.from_ptr(C.LLVMConstOr(self, rhs))
|
357
|
+
end
|
358
|
+
|
359
|
+
# Integer XOR.
|
360
|
+
def xor(rhs)
|
361
|
+
self.class.from_ptr(C.LLVMConstXor(self, rhs))
|
362
|
+
end
|
363
|
+
|
364
|
+
# Integer comparison using the predicate specified via the first parameter.
|
365
|
+
# Predicate can be any of:
|
366
|
+
# :eq - equal to
|
367
|
+
# :ne - not equal to
|
368
|
+
# :ugt - unsigned greater than
|
369
|
+
# :uge - unsigned greater than or equal to
|
370
|
+
# :ult - unsigned less than
|
371
|
+
# :ule - unsigned less than or equal to
|
372
|
+
# :sgt - signed greater than
|
373
|
+
# :sge - signed greater than or equal to
|
374
|
+
# :slt - signed less than
|
375
|
+
# :sle - signed less than or equal to
|
376
|
+
def icmp(pred, rhs)
|
377
|
+
self.class.from_ptr(C.LLVMConstICmp(pred, self, rhs))
|
378
|
+
end
|
379
|
+
|
380
|
+
# Shift left.
|
381
|
+
def <<(bits)
|
382
|
+
self.class.from_ptr(C.LLVMConstShl(self, bits))
|
383
|
+
end
|
384
|
+
|
385
|
+
# Shift right.
|
386
|
+
def >>(bits)
|
387
|
+
self.class.from_ptr(C.LLVMConstLShr(self, bits))
|
388
|
+
end
|
389
|
+
|
390
|
+
# Arithmatic shift right.
|
391
|
+
def ashr(bits)
|
392
|
+
self.class.from_ptr(C.LLVMConstAShr(self, bits))
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
def LLVM.const_missing(const)
|
397
|
+
case const.to_s
|
398
|
+
when /Int(\d+)/
|
399
|
+
width = $1.to_i
|
400
|
+
name = "Int#{width}"
|
401
|
+
eval <<-KLASS
|
402
|
+
class #{name} < ConstantInt
|
403
|
+
def self.type
|
404
|
+
IntType.from_ptr(C.LLVMIntType(#{width}))
|
405
|
+
end
|
406
|
+
end
|
407
|
+
KLASS
|
408
|
+
const_get(name)
|
409
|
+
else
|
410
|
+
super
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
# Native integer type
|
415
|
+
bits = FFI.type_size(:int) * 8
|
416
|
+
::LLVM::Int = const_get("Int#{bits}")
|
417
|
+
|
418
|
+
# Creates a LLVM Int (subclass of ConstantInt) at the NATIVE_INT_SIZE from a integer (val).
|
419
|
+
def LLVM.Int(val)
|
420
|
+
case val
|
421
|
+
when LLVM::ConstantInt then val
|
422
|
+
when Integer then Int.from_i(val)
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
# Boolean values
|
427
|
+
::LLVM::TRUE = ::LLVM::Int1.from_i(-1)
|
428
|
+
::LLVM::FALSE = ::LLVM::Int1.from_i(0)
|
429
|
+
|
430
|
+
class ConstantReal < Constant
|
431
|
+
# Creates a ConstantReal from a float of Type.
|
432
|
+
def self.from_f(n)
|
433
|
+
from_ptr(C.LLVMConstReal(type, n))
|
434
|
+
end
|
435
|
+
|
436
|
+
def self.parse(type, str)
|
437
|
+
from_ptr(C.LLVMConstRealOfString(type, str))
|
438
|
+
end
|
439
|
+
|
440
|
+
# Negation.
|
441
|
+
def -@
|
442
|
+
self.class.from_ptr(C.LLVMConstFNeg(self))
|
443
|
+
end
|
444
|
+
|
445
|
+
# Returns the result of adding this ConstantReal to rhs.
|
446
|
+
def +(rhs)
|
447
|
+
self.class.from_ptr(C.LLVMConstFAdd(self, rhs))
|
448
|
+
end
|
449
|
+
|
450
|
+
# Returns the result of multiplying this ConstantReal by rhs.
|
451
|
+
def *(rhs)
|
452
|
+
self.class.from_ptr(C.LLVMConstFMul(self, rhs))
|
453
|
+
end
|
454
|
+
|
455
|
+
# Returns the result of dividing this ConstantReal by rhs.
|
456
|
+
def /(rhs)
|
457
|
+
self.class.from_ptr(C.LLVMConstFDiv(self, rhs))
|
458
|
+
end
|
459
|
+
|
460
|
+
# Remainder.
|
461
|
+
def rem(rhs)
|
462
|
+
self.class.from_ptr(C.LLVMConstFRem(self, rhs))
|
463
|
+
end
|
464
|
+
|
465
|
+
# Floating point comparison using the predicate specified via the first
|
466
|
+
# parameter. Predicate can be any of:
|
467
|
+
# :ord - ordered
|
468
|
+
# :uno - unordered: isnan(X) | isnan(Y)
|
469
|
+
# :oeq - ordered and equal to
|
470
|
+
# :oeq - unordered and equal to
|
471
|
+
# :one - ordered and not equal to
|
472
|
+
# :one - unordered and not equal to
|
473
|
+
# :ogt - ordered and greater than
|
474
|
+
# :uge - unordered and greater than or equal to
|
475
|
+
# :olt - ordered and less than
|
476
|
+
# :ule - unordered and less than or equal to
|
477
|
+
# :oge - ordered and greater than or equal to
|
478
|
+
# :sge - unordered and greater than or equal to
|
479
|
+
# :ole - ordered and less than or equal to
|
480
|
+
# :sle - unordered and less than or equal to
|
481
|
+
# :true - always true
|
482
|
+
# :false- always false
|
483
|
+
def fcmp(pred, rhs)
|
484
|
+
self.class.from_ptr(C.LLMVConstFCmp(pred, self, rhs))
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
class Float < ConstantReal
|
489
|
+
# Return a Type representation of the float.
|
490
|
+
def self.type
|
491
|
+
Type.from_ptr(C.LLVMFloatType)
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
# Create a LLVM::Float from a Ruby Float (val).
|
496
|
+
def LLVM.Float(val)
|
497
|
+
Float.from_f(val)
|
498
|
+
end
|
499
|
+
|
500
|
+
class Double < ConstantReal
|
501
|
+
def self.type
|
502
|
+
Type.from_ptr(C.LLVMDoubleType)
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
def LLVM.Double(val)
|
507
|
+
Double.from_f(val)
|
508
|
+
end
|
509
|
+
|
510
|
+
class ConstantStruct < Constant
|
511
|
+
# ConstantStruct.const(size) {|i| ... } or
|
512
|
+
# ConstantStruct.const([...])
|
513
|
+
def self.const(size_or_values, packed = false, &block)
|
514
|
+
vals = LLVM::Support.allocate_pointers(size_or_values, &block)
|
515
|
+
from_ptr C.LLVMConstStruct(vals, vals.size / vals.type_size, packed ? 1 : 0)
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
class ConstantVector < Constant
|
520
|
+
def self.all_ones
|
521
|
+
from_ptr(C.LLVMConstAllOnes(type))
|
522
|
+
end
|
523
|
+
|
524
|
+
def self.const(size_or_values, &block)
|
525
|
+
vals = LLVM::Support.allocate_pointers(size_or_values, &block)
|
526
|
+
from_ptr(C.LLVMConstVector(vals, vals.size / vals.type_size))
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
class GlobalValue < Constant
|
531
|
+
def declaration?
|
532
|
+
C.LLVMIsDeclaration(self)
|
533
|
+
end
|
534
|
+
|
535
|
+
def linkage
|
536
|
+
C.LLVMGetLinkage(self)
|
537
|
+
end
|
538
|
+
|
539
|
+
def linkage=(linkage)
|
540
|
+
C.LLVMSetLinkage(self, linkage)
|
541
|
+
end
|
542
|
+
|
543
|
+
def section
|
544
|
+
C.LLVMGetSection(self)
|
545
|
+
end
|
546
|
+
|
547
|
+
def section=(section)
|
548
|
+
C.LLVMSetSection(self, section)
|
549
|
+
end
|
550
|
+
|
551
|
+
def visibility
|
552
|
+
C.LLVMGetVisibility(self)
|
553
|
+
end
|
554
|
+
|
555
|
+
def visibility=(viz)
|
556
|
+
C.LLVMSetVisibility(self, viz)
|
557
|
+
end
|
558
|
+
|
559
|
+
def alignment
|
560
|
+
C.LLVMGetAlignment(self)
|
561
|
+
end
|
562
|
+
|
563
|
+
def alignment=(bytes)
|
564
|
+
C.LLVMSetAlignment(self, bytes)
|
565
|
+
end
|
566
|
+
|
567
|
+
def initializer
|
568
|
+
Value.from_ptr(C.LLVMGetInitializer(self))
|
569
|
+
end
|
570
|
+
|
571
|
+
def initializer=(val)
|
572
|
+
C.LLVMSetInitializer(self, val)
|
573
|
+
end
|
574
|
+
|
575
|
+
def global_constant?
|
576
|
+
C.LLVMIsGlobalConstant(self)
|
577
|
+
end
|
578
|
+
|
579
|
+
def global_constant=(flag)
|
580
|
+
C.LLVMSetGlobalConstant(self, flag)
|
581
|
+
end
|
582
|
+
end
|
583
|
+
|
584
|
+
class Function < GlobalValue
|
585
|
+
# Sets the function's calling convention and returns it.
|
586
|
+
def call_conv=(conv)
|
587
|
+
C.LLVMSetFunctionCallConv(self, conv)
|
588
|
+
conv
|
589
|
+
end
|
590
|
+
|
591
|
+
# Adds the given attribute to the function.
|
592
|
+
def add_attribute(attr)
|
593
|
+
C.LLVMAddFunctionAttr(self, attr)
|
594
|
+
end
|
595
|
+
|
596
|
+
# Removes the given attribute from the function.
|
597
|
+
def remove_attribute(attr)
|
598
|
+
C.LLVMRemoveFunctionAttr(self, attr)
|
599
|
+
end
|
600
|
+
|
601
|
+
# Returns an Enumerable of the BasicBlocks in this function.
|
602
|
+
def basic_blocks
|
603
|
+
@basic_block_collection ||= BasicBlockCollection.new(self)
|
604
|
+
end
|
605
|
+
|
606
|
+
def type
|
607
|
+
FunctionType.from_ptr(C.LLVMTypeOf(self))
|
608
|
+
end
|
609
|
+
|
610
|
+
# @private
|
611
|
+
class BasicBlockCollection
|
612
|
+
include Enumerable
|
613
|
+
|
614
|
+
def initialize(fun)
|
615
|
+
@fun = fun
|
616
|
+
end
|
617
|
+
|
618
|
+
# Returns the number of BasicBlocks in the collection.
|
619
|
+
def size
|
620
|
+
C.LLVMCountBasicBlocks(@fun)
|
621
|
+
end
|
622
|
+
|
623
|
+
# Iterates through each BasicBlock in the collection.
|
624
|
+
def each
|
625
|
+
return to_enum :each unless block_given?
|
626
|
+
|
627
|
+
ptr = C.LLVMGetFirstBasicBlock(@fun)
|
628
|
+
0.upto(size-1) do |i|
|
629
|
+
yield BasicBlock.from_ptr(ptr)
|
630
|
+
ptr = C.LLVMGetNextBasicBlock(ptr)
|
631
|
+
end
|
632
|
+
|
633
|
+
self
|
634
|
+
end
|
635
|
+
|
636
|
+
# Adds a BasicBlock with the given name to the end of the collection.
|
637
|
+
def append(name = "")
|
638
|
+
BasicBlock.create(@fun, name)
|
639
|
+
end
|
640
|
+
|
641
|
+
# Returns the entry BasicBlock in the collection. This is the block the
|
642
|
+
# function starts on.
|
643
|
+
def entry
|
644
|
+
BasicBlock.from_ptr(C.LLVMGetEntryBasicBlock(@fun))
|
645
|
+
end
|
646
|
+
|
647
|
+
# Returns the first BasicBlock in the collection.
|
648
|
+
def first
|
649
|
+
ptr = C.LLVMGetFirstBasicBlock(@fun)
|
650
|
+
BasicBlock.from_ptr(ptr) unless ptr.null?
|
651
|
+
end
|
652
|
+
|
653
|
+
# Returns the last BasicBlock in the collection.
|
654
|
+
def last
|
655
|
+
ptr = C.LLVMGetLastBasicBlock(@fun)
|
656
|
+
BasicBlock.from_ptr(ptr) unless ptr.null?
|
657
|
+
end
|
658
|
+
end
|
659
|
+
|
660
|
+
# Returns an Enumerable of the parameters in the function.
|
661
|
+
def params
|
662
|
+
@parameter_collection ||= ParameterCollection.new(self)
|
663
|
+
end
|
664
|
+
|
665
|
+
# @private
|
666
|
+
class ParameterCollection
|
667
|
+
def initialize(fun)
|
668
|
+
@fun = fun
|
669
|
+
end
|
670
|
+
|
671
|
+
# Returns a Value representation of the parameter at the given index.
|
672
|
+
def [](i)
|
673
|
+
sz = self.size
|
674
|
+
i = sz + i if i < 0
|
675
|
+
return unless 0 <= i && i < sz
|
676
|
+
Value.from_ptr(C.LLVMGetParam(@fun, i))
|
677
|
+
end
|
678
|
+
|
679
|
+
# Returns the number of paramters in the collection.
|
680
|
+
def size
|
681
|
+
C.LLVMCountParams(@fun)
|
682
|
+
end
|
683
|
+
|
684
|
+
include Enumerable
|
685
|
+
|
686
|
+
# Iteraters through each parameter in the collection.
|
687
|
+
def each
|
688
|
+
return to_enum :each unless block_given?
|
689
|
+
0.upto(size-1) { |i| yield self[i] }
|
690
|
+
self
|
691
|
+
end
|
692
|
+
end
|
693
|
+
end
|
694
|
+
|
695
|
+
class GlobalAlias < GlobalValue
|
696
|
+
end
|
697
|
+
|
698
|
+
class GlobalVariable < GlobalValue
|
699
|
+
def initializer
|
700
|
+
Value.from_ptr(C.LLVMGetInitializer(self))
|
701
|
+
end
|
702
|
+
|
703
|
+
def initializer=(val)
|
704
|
+
C.LLVMSetInitializer(self, val)
|
705
|
+
end
|
706
|
+
|
707
|
+
def thread_local?
|
708
|
+
case C.LLVMIsThreadLocal(self)
|
709
|
+
when 0 then false
|
710
|
+
else true
|
711
|
+
end
|
712
|
+
end
|
713
|
+
|
714
|
+
def thread_local=(local)
|
715
|
+
C.LLVMSetThreadLocal(self, local ? 1 : 0)
|
716
|
+
end
|
717
|
+
end
|
718
|
+
|
719
|
+
class Instruction < User
|
720
|
+
# Returns the parent of the instruction (a BasicBlock).
|
721
|
+
def parent
|
722
|
+
ptr = C.LLVMGetInstructionParent(self)
|
723
|
+
LLVM::BasicBlock.from_ptr(ptr) unless ptr.null?
|
724
|
+
end
|
725
|
+
|
726
|
+
# Returns the next instruction after this one.
|
727
|
+
def next
|
728
|
+
ptr = C.LLVMGetNextInstruction(self)
|
729
|
+
LLVM::Instruction.from_ptr(ptr) unless ptr.null?
|
730
|
+
end
|
731
|
+
|
732
|
+
# Returns the previous instruction before this one.
|
733
|
+
def previous
|
734
|
+
ptr = C.LLVMGetPreviousInstruction(self)
|
735
|
+
LLVM::Instruction.from_ptr(ptr) unless ptr.null?
|
736
|
+
end
|
737
|
+
end
|
738
|
+
|
739
|
+
class CallInst < Instruction
|
740
|
+
# Sets the call convention to conv.
|
741
|
+
def call_conv=(conv)
|
742
|
+
C.LLVMSetInstructionCallConv(self, conv)
|
743
|
+
conv
|
744
|
+
end
|
745
|
+
|
746
|
+
# Returns the call insatnce's call convention.
|
747
|
+
def call_conv
|
748
|
+
C.LLVMGetInstructionCallConv(self)
|
749
|
+
end
|
750
|
+
end
|
751
|
+
|
752
|
+
# @private
|
753
|
+
class Phi < Instruction
|
754
|
+
# Add incoming branches to a phi node by passing an alternating list of
|
755
|
+
# resulting values and BasicBlocks. e.g.
|
756
|
+
# phi.add_incoming(val1, block1, val2, block2, ...)
|
757
|
+
def add_incoming(incoming)
|
758
|
+
blks = incoming.keys
|
759
|
+
vals = incoming.values_at(*blks)
|
760
|
+
size = incoming.size
|
761
|
+
|
762
|
+
FFI::MemoryPointer.new(FFI.type_size(:pointer) * size) do |vals_ptr|
|
763
|
+
vals_ptr.write_array_of_pointer(vals)
|
764
|
+
FFI::MemoryPointer.new(FFI.type_size(:pointer) * size) do |blks_ptr|
|
765
|
+
blks_ptr.write_array_of_pointer(blks)
|
766
|
+
C.LLVMAddIncoming(self, vals_ptr, blks_ptr, vals.size)
|
767
|
+
end
|
768
|
+
end
|
769
|
+
|
770
|
+
nil
|
771
|
+
end
|
772
|
+
end
|
773
|
+
|
774
|
+
# @private
|
775
|
+
class SwitchInst < Instruction
|
776
|
+
# Adds a case to a switch instruction. First the value to match on, then
|
777
|
+
# the basic block.
|
778
|
+
def add_case(val, block)
|
779
|
+
C.LLVMAddCase(self, val, block)
|
780
|
+
end
|
781
|
+
end
|
782
|
+
end
|