rltk 1.2.0 → 2.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.
- data/README.md +610 -0
- data/Rakefile +156 -21
- data/lib/rltk/ast.rb +179 -127
- data/lib/rltk/cfg.rb +131 -38
- data/lib/rltk/cg/basic_block.rb +167 -0
- data/lib/rltk/cg/bindings.rb +136 -0
- data/lib/rltk/cg/builder.rb +1095 -0
- data/lib/rltk/cg/context.rb +51 -0
- data/lib/rltk/cg/execution_engine.rb +172 -0
- data/lib/rltk/cg/function.rb +224 -0
- data/lib/rltk/cg/generated_bindings.rb +6158 -0
- data/lib/rltk/cg/generated_extended_bindings.rb +43 -0
- data/lib/rltk/cg/generic_value.rb +98 -0
- data/lib/rltk/cg/instruction.rb +498 -0
- data/lib/rltk/cg/llvm.rb +51 -0
- data/lib/rltk/cg/memory_buffer.rb +62 -0
- data/lib/rltk/cg/module.rb +328 -0
- data/lib/rltk/cg/pass_manager.rb +201 -0
- data/lib/rltk/cg/support.rb +29 -0
- data/lib/rltk/cg/type.rb +510 -0
- data/lib/rltk/cg/value.rb +1207 -0
- data/lib/rltk/cg.rb +33 -0
- data/lib/rltk/lexer.rb +135 -85
- data/lib/rltk/lexers/calculator.rb +4 -1
- data/lib/rltk/lexers/ebnf.rb +1 -4
- data/lib/rltk/parser.rb +360 -196
- data/lib/rltk/token.rb +29 -4
- data/lib/rltk/util/abstract_class.rb +25 -0
- data/lib/rltk/util/monkeys.rb +125 -0
- data/lib/rltk/version.rb +5 -2
- data/test/tc_ast.rb +11 -11
- data/test/tc_lexer.rb +41 -41
- data/test/tc_parser.rb +123 -97
- data/test/ts_rltk.rb +50 -0
- metadata +181 -87
- data/README +0 -390
@@ -0,0 +1,1207 @@
|
|
1
|
+
# Author: Chris Wailes <chris.wailes@gmail.com>
|
2
|
+
# Project: Ruby Language Toolkit
|
3
|
+
# Date: 2012/03/15
|
4
|
+
# Description: This file defines LLVM Value classes.
|
5
|
+
|
6
|
+
############
|
7
|
+
# Requires #
|
8
|
+
############
|
9
|
+
|
10
|
+
# Ruby Language Toolkit
|
11
|
+
require 'rltk/util/abstract_class'
|
12
|
+
require 'rltk/cg/bindings'
|
13
|
+
require 'rltk/cg/type'
|
14
|
+
|
15
|
+
#######################
|
16
|
+
# Classes and Modules #
|
17
|
+
#######################
|
18
|
+
|
19
|
+
module RLTK::CG # :nodoc:
|
20
|
+
|
21
|
+
# This class represents LLVM IR "data", including integer and float
|
22
|
+
# literals, functions, and constant arrays, structs, and vectors.
|
23
|
+
class Value
|
24
|
+
include BindingClass
|
25
|
+
|
26
|
+
# Instantiate a Value object from a pointer. This should never be
|
27
|
+
# done by library users, and is only used internally.
|
28
|
+
#
|
29
|
+
# @param [FFI::Pointer] ptr Pointer to an LLVM value.
|
30
|
+
def initialize(ptr)
|
31
|
+
@ptr = check_type(ptr, FFI::Pointer, 'ptr')
|
32
|
+
end
|
33
|
+
|
34
|
+
# Compare one Value to another.
|
35
|
+
#
|
36
|
+
# @param [Value] other Another value object.
|
37
|
+
#
|
38
|
+
# @return [Boolean]
|
39
|
+
def ==(other)
|
40
|
+
other.is_a?(Value) and @ptr == other.ptr
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [AttrCollection] Proxy object for inspecing a value's attributes.
|
44
|
+
def attributes
|
45
|
+
@attributes ||= AttrCollection.new(@ptr)
|
46
|
+
end
|
47
|
+
alias :attrs :attributes
|
48
|
+
|
49
|
+
# Bitcast a value to a given type.
|
50
|
+
#
|
51
|
+
# @param [Type] type Type to cast to.
|
52
|
+
#
|
53
|
+
# @return [ConstExpr]
|
54
|
+
def bitcast(type)
|
55
|
+
ConstExpr.new(Bindings.const_bit_cast(@ptr, check_cg_type(type)))
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [Boolean] If this value is a constant.
|
59
|
+
def constant?
|
60
|
+
Bindings.is_constant(@ptr).to_bool
|
61
|
+
end
|
62
|
+
|
63
|
+
# Print the LLVM IR representation of this value to standard out.
|
64
|
+
#
|
65
|
+
# @return [void]
|
66
|
+
def dump
|
67
|
+
Bindings.dump_value(@ptr)
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [Fixnum] Hashed value of the pointer representing this value.
|
71
|
+
def hash
|
72
|
+
@ptr.address.hash
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [String] Name of this value in LLVM IR.
|
76
|
+
def name
|
77
|
+
Bindings.get_value_name(@ptr)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Set the name of this value in LLVM IR.
|
81
|
+
#
|
82
|
+
# @param [String] str Name of the value in LLVM IR.
|
83
|
+
#
|
84
|
+
# @return [String] *str*
|
85
|
+
def name=(str)
|
86
|
+
returning(str) { Bindings.set_value_name(@ptr, check_type(str, String)) }
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [Boolean] If the value is null or not.
|
90
|
+
def null?
|
91
|
+
Bindings.is_null(@ptr).to_bool
|
92
|
+
end
|
93
|
+
|
94
|
+
# Truncate a value to a given type.
|
95
|
+
#
|
96
|
+
# @param [Type] type Type to truncate to.
|
97
|
+
#
|
98
|
+
# @return [ConstExpr]
|
99
|
+
def trunc(type)
|
100
|
+
ConstExpr.new(Bindings.const_trunc(check_cg_type(type)))
|
101
|
+
end
|
102
|
+
|
103
|
+
# Truncate or bitcast a value to the given type as is appropriate.
|
104
|
+
#
|
105
|
+
# @param [Type] type Type to cast or truncate to.
|
106
|
+
#
|
107
|
+
# @return [ConstExpr]
|
108
|
+
def trunc_or_bitcast(type)
|
109
|
+
ConstExpr.new(Bindings.const_trunc_or_bit_cast(check_cg_type(type)))
|
110
|
+
end
|
111
|
+
|
112
|
+
# @return [Type] Type of this value.
|
113
|
+
def type
|
114
|
+
@type ||= Type.from_ptr(Bindings.type_of(@ptr))
|
115
|
+
end
|
116
|
+
|
117
|
+
# @return [Boolean] If the value is undefined or not.
|
118
|
+
def undefined?
|
119
|
+
Bindings.is_undef(@ptr).to_bool
|
120
|
+
end
|
121
|
+
|
122
|
+
# Zero extend the value to the length of *type*.
|
123
|
+
#
|
124
|
+
# @param [Type] type Type to extend the value to.
|
125
|
+
#
|
126
|
+
# @return [ConstExpr]
|
127
|
+
def zextend(type)
|
128
|
+
ConstExpr.new(Bindings.const_z_ext(check_cg_type(type)))
|
129
|
+
end
|
130
|
+
|
131
|
+
# Zero extend or bitcast the value to the given type as is appropriate.
|
132
|
+
#
|
133
|
+
# @param [Type] type Type to cast or extend to.
|
134
|
+
#
|
135
|
+
# @return [ConstExpr]
|
136
|
+
def zextend_or_bitcast(type)
|
137
|
+
ConstExpr.new(Bindings.const_z_ext_or_bit_cast(check_cg_type(type)))
|
138
|
+
end
|
139
|
+
|
140
|
+
# This class is used to access a {Value Value's} attributes.
|
141
|
+
class AttrCollection
|
142
|
+
@@add_method = :add_attribute
|
143
|
+
@@del_method = :remove_attribute
|
144
|
+
|
145
|
+
# @param [Value] value Value for which this is a proxy.
|
146
|
+
def initialize(value)
|
147
|
+
@attributes = Array.new
|
148
|
+
@value = value
|
149
|
+
end
|
150
|
+
|
151
|
+
# Add the given attribute to a value.
|
152
|
+
#
|
153
|
+
# @see Bindings._enum_attribute_
|
154
|
+
#
|
155
|
+
# @param [Symbol] attribute Attribute to add.
|
156
|
+
#
|
157
|
+
# @return [void]
|
158
|
+
def add(attribute)
|
159
|
+
if not @attributes.include?(attribute)
|
160
|
+
@attributes << attribute
|
161
|
+
Bindings.send(@@add_method, @value, attribute)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
alias :'<<' :add
|
165
|
+
|
166
|
+
# Test to see if an attribute has been set on a value.
|
167
|
+
#
|
168
|
+
# @see Bindings._enum_attribute_
|
169
|
+
#
|
170
|
+
# @param [Symbol] attribute Attribute to check.
|
171
|
+
#
|
172
|
+
# @return [Boolean]
|
173
|
+
def include?(attribute)
|
174
|
+
@attributes.include?(attribute)
|
175
|
+
end
|
176
|
+
|
177
|
+
# Remove the given attribute from a value.
|
178
|
+
#
|
179
|
+
# @see Bindings._enum_attribute_
|
180
|
+
#
|
181
|
+
# @param [Symbol] attribute Attribute to remove.
|
182
|
+
#
|
183
|
+
# @return [void]
|
184
|
+
def remove(attribute)
|
185
|
+
if @attributes.include?(attribute)
|
186
|
+
@attributes.delete(attribute)
|
187
|
+
Bindings.send(@@del_method, @value, attribute)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
alias :'>>' :remove
|
191
|
+
|
192
|
+
# @return [String] Textual representation of the enabled attributes.
|
193
|
+
def to_s
|
194
|
+
@attributes.to_s
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# An empty class definition for completeness and future use.
|
200
|
+
class Argument < Value; end
|
201
|
+
|
202
|
+
# A base class for a wide variety of classes.
|
203
|
+
#
|
204
|
+
# @abstract
|
205
|
+
class User < Value
|
206
|
+
include AbstractClass
|
207
|
+
|
208
|
+
# @return [OperandCollection] Proxy object for accessing a value's operands.
|
209
|
+
def operands
|
210
|
+
@operands ||= OperandCollection.new(self)
|
211
|
+
end
|
212
|
+
|
213
|
+
# This class is used to access a {User User's} operands.
|
214
|
+
class OperandCollection
|
215
|
+
include Enumerable
|
216
|
+
|
217
|
+
# @param [User] user User object for which this is a proxy.
|
218
|
+
def initialize(user)
|
219
|
+
@user = user
|
220
|
+
end
|
221
|
+
|
222
|
+
# Access the operand at the given index.
|
223
|
+
#
|
224
|
+
# @param [Integer] index
|
225
|
+
#
|
226
|
+
# @return [Value, nil] Value object representing the operand at *index* if one exists.
|
227
|
+
def [](index)
|
228
|
+
if (ptr = Bindings.get_operand(@user, index)).null? then nil else Value.new(ptr) end
|
229
|
+
end
|
230
|
+
|
231
|
+
# Set the operand at the given index.
|
232
|
+
#
|
233
|
+
# @param [Integer] index Index of operand to set.
|
234
|
+
# @param [Value] value Value to set as operand.
|
235
|
+
#
|
236
|
+
# @return [void]
|
237
|
+
def []=(index, value)
|
238
|
+
Bindings.set_operand(@user, index, check_type(value, Value, 'value'))
|
239
|
+
end
|
240
|
+
|
241
|
+
# An iterator for each operand inside this collection.
|
242
|
+
#
|
243
|
+
# @yieldparam val [Value]
|
244
|
+
#
|
245
|
+
# @return [Enumerator] Returns an Enumerator if no block is given.
|
246
|
+
def each
|
247
|
+
return to_enum(:each) unless block_given?
|
248
|
+
|
249
|
+
self.size.times { |i| yield self[i] }
|
250
|
+
|
251
|
+
self
|
252
|
+
end
|
253
|
+
|
254
|
+
# @return [Integer] Number of operands.
|
255
|
+
def size
|
256
|
+
Bindings.get_num_operands(@user)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
# All classes representing constant values inherit from this class.
|
262
|
+
#
|
263
|
+
# @abstract
|
264
|
+
class Constant < User
|
265
|
+
include AbstractClass
|
266
|
+
|
267
|
+
# Create a new constant from a pointer or a type. As a library user
|
268
|
+
# you should never pass a pointer in here as that is only used
|
269
|
+
# internally.
|
270
|
+
#
|
271
|
+
# @param [FFI::Pointer, Type] overloaded Pointer to existing constant or a Type.
|
272
|
+
def initialize(overloaded)
|
273
|
+
@ptr =
|
274
|
+
case overloaded
|
275
|
+
when FFI::Pointer
|
276
|
+
overloaded
|
277
|
+
|
278
|
+
when Type
|
279
|
+
Bindings.send(@@initializer, @type = overloaded)
|
280
|
+
else
|
281
|
+
raise 'New must be passed either a Type or a FFI::Pointer.'
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
# Bitcast a constant to a given type.
|
286
|
+
#
|
287
|
+
# @param [Type] type
|
288
|
+
#
|
289
|
+
# @return [ConstExpr]
|
290
|
+
def bitcast_to(type)
|
291
|
+
ConstantExpr.new(Bindings.const_bit_cast(@ptr, check_cg_type(type)))
|
292
|
+
end
|
293
|
+
|
294
|
+
# Get a pointer to an element of a constant value.
|
295
|
+
#
|
296
|
+
# @param [Array<Value>] indices A Ruby array of Value objects representing indicies into the constant value.
|
297
|
+
#
|
298
|
+
# @return [ConstantExpr] LLVM Value object representing a pointer to a LLVM Value object.
|
299
|
+
def get_element_ptr(*indices)
|
300
|
+
indicies_ptr = FFI::MemoryPointer.new(:pointer, indices.length)
|
301
|
+
indices_ptr.write_array_of_pointer(indices)
|
302
|
+
|
303
|
+
ConstantExpr.new(Bindings.const_gep(@ptr, indices_ptr, indices.length))
|
304
|
+
end
|
305
|
+
alias :gep :get_element_ptr
|
306
|
+
|
307
|
+
# Get a pointer to an element of a constant value, ensuring that the
|
308
|
+
# pointer is within the bounds of the value.
|
309
|
+
#
|
310
|
+
# @param [Array<Value>] indices A Ruby array of Value objects representing indicies into the constant value.
|
311
|
+
#
|
312
|
+
# @return [ConstantExpr] LLVM Value object representing a pointer to a LLVM Value object.
|
313
|
+
def get_element_ptr_in_bounds(*indices)
|
314
|
+
indices_ptr = FFI::MemoryPointer.new(:pointer, indices.length)
|
315
|
+
indices_ptr.write_array_of_pointer(indices)
|
316
|
+
|
317
|
+
ConstantExpr.new(Bindings.const_in_bounds_gep(@ptr, indices_ptr, indices.length))
|
318
|
+
end
|
319
|
+
alias :inbounds_gep :get_element_ptr_in_bounds
|
320
|
+
end
|
321
|
+
|
322
|
+
# This class represents a wide range of values returned by various
|
323
|
+
# operations.
|
324
|
+
class ConstantExpr < Constant
|
325
|
+
# Constant expressions can only be instantiated from a pointer, and
|
326
|
+
# should never be instantiated by library users.
|
327
|
+
#
|
328
|
+
# @param [FFI::Pointer] ptr
|
329
|
+
def initialize(ptr)
|
330
|
+
@ptr = type_check(ptr, FFI::Pointer, 'ptr')
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
# A constant null value.
|
335
|
+
class ConstantNull < Constant
|
336
|
+
@@initializer = :const_null
|
337
|
+
end
|
338
|
+
|
339
|
+
# A constant null pointer value.
|
340
|
+
class ConstantNullPtr < Constant
|
341
|
+
@@initializer = :const_pointer_null
|
342
|
+
end
|
343
|
+
|
344
|
+
# A constant undefined value.
|
345
|
+
class ConstantUndef < Constant
|
346
|
+
@@initializer = :get_undef
|
347
|
+
end
|
348
|
+
|
349
|
+
# All constant aggregate values inherit from this class.
|
350
|
+
#
|
351
|
+
# @abstract
|
352
|
+
class ConstantAggregate < Constant
|
353
|
+
include AbstractClass
|
354
|
+
|
355
|
+
# Extract values from a constant aggregate value.
|
356
|
+
#
|
357
|
+
# @param [Array<Value>] indices Array of values representing indices into the aggregate.
|
358
|
+
#
|
359
|
+
# @return [ConstantExpr] Extracted values.
|
360
|
+
def extract(*indices)
|
361
|
+
indices_ptr = FFI::MemoryPointer.new(:uint, indices.length)
|
362
|
+
indices_ptr.write_array_of_uint(indices)
|
363
|
+
|
364
|
+
ConstantExpr.new(Bindings.const_extract_value(@ptr, indices_ptr, indices.length))
|
365
|
+
end
|
366
|
+
|
367
|
+
# Insert values into a constant aggregate value.
|
368
|
+
#
|
369
|
+
# @param [Value] value Value to insert.
|
370
|
+
# @param [Array<Value>] indices Array of values representing indices into the aggregate.
|
371
|
+
#
|
372
|
+
# @return [ConstantExpr] New aggregate representation with inserted values.
|
373
|
+
def insert(value, indices)
|
374
|
+
indices_ptr = FFI::MemoryPointer.new(:uint, indices.length)
|
375
|
+
indices_ptr.write_array_of_uint(indices)
|
376
|
+
|
377
|
+
ConstantExpr.new(Bindings.const_insert_value(@ptr, value, indices_ptr, inicies.length))
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
# A constant array value.
|
382
|
+
class ConstantArray < ConstantAggregate
|
383
|
+
# Create a new constant array value.
|
384
|
+
#
|
385
|
+
# @example Using array of values:
|
386
|
+
# ConstantArray.new(Int32Type, [Int32.new(0), Int32.new(1)])
|
387
|
+
#
|
388
|
+
# @example Using size:
|
389
|
+
# ConstantArray.new(Int32Type, 2) { |i| Int32.new(i) }
|
390
|
+
#
|
391
|
+
# @yieldparam index [Integer] Index of the value in the array.
|
392
|
+
#
|
393
|
+
# @param [Type] element_type Type of values in this aggregate.
|
394
|
+
# @param [Array<Value>, Integer] size_or_values Number of values or array of values.
|
395
|
+
# @param [Proc] block Block evaluated if size is specified.
|
396
|
+
def initialize(element_type, size_or_values, &block)
|
397
|
+
vals_ptr = make_ptr_to_elements(size_or_values, &block)
|
398
|
+
@type = ArrayType.new(element_type = check_cg_type(element_type, Type, 'element_type'))
|
399
|
+
@ptr = Bindings.const_array(element_type, vals_ptr, vals_ptr.size / vals_ptr.type_size)
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
# A sub-class of {ConstantArray} specifically for holding strings.
|
404
|
+
class ConstantString < ConstantArray
|
405
|
+
# Create a new constant string value.
|
406
|
+
#
|
407
|
+
# @param [String] string Sting to turn into a value.
|
408
|
+
# @param [Boolean] null_terminate To null terminate the string or not.
|
409
|
+
# @param [Context, nil] context Context in which to create the value.
|
410
|
+
def initialize(string, null_terminate = true, context = nil)
|
411
|
+
@type = ArrayType.new(Int8Type)
|
412
|
+
|
413
|
+
@ptr =
|
414
|
+
if context
|
415
|
+
Bindings.const_string_in_context(check_type(context, Context, 'context'), string, string.length, null_terminate.to_i)
|
416
|
+
else
|
417
|
+
Bindings.const_string(string, string.length, null_terminate.to_i)
|
418
|
+
end
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
# A constant struct value.
|
423
|
+
class ConstantStruct < ConstantAggregate
|
424
|
+
# Create a new constant struct value.
|
425
|
+
#
|
426
|
+
# @example Using array of values:
|
427
|
+
# ConstantStruct.new([Int32.new(0), Int64.new(1), Int32.new(2), Int64.new(3)])
|
428
|
+
#
|
429
|
+
# @example Using size:
|
430
|
+
# ConstantStruct.new(4) { |i| if i % 2 == 0 then Int32.new(i) else Int64.new(i) end }
|
431
|
+
#
|
432
|
+
# @yieldparam index [Integer] Index of the value in the struct.
|
433
|
+
#
|
434
|
+
# @param [Array<Value>, Integer] size_or_values Number of values or array of values.
|
435
|
+
# @param [Boolean] packed Are the types packed already, or should they be re-arranged to save space?
|
436
|
+
# @param [Context, nil] context Context in which to create the value.
|
437
|
+
# @param [Proc] block Block evaluated if size is specified.
|
438
|
+
def initialize(size_or_values, packed = false, context = nil, &block)
|
439
|
+
vals_ptr = make_ptr_to_elements(size_or_values, &block)
|
440
|
+
|
441
|
+
@ptr =
|
442
|
+
if context
|
443
|
+
Bindings.const_struct_in_context(check_type(context, Context, 'context'), vals_ptr, vals_ptr.size / vals_ptr.type_size, packed.to_i)
|
444
|
+
else
|
445
|
+
Bindings.const_struct(vals_ptr, vals_ptr.size / vals_ptr.type_size, packed.to_i)
|
446
|
+
end
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
# A constant vector value used for SIMD instructions.
|
451
|
+
class ConstantVector < Constant
|
452
|
+
# Create a new constant vector value.
|
453
|
+
#
|
454
|
+
# @example Using array of values:
|
455
|
+
# ConstantVector.new([Int32.new(0), Int32.new(1)])
|
456
|
+
#
|
457
|
+
# @example Using size:
|
458
|
+
# ConstantVector.new(2) { |i| Int32.new(i) }
|
459
|
+
#
|
460
|
+
# @yieldparam index [Integer] Index of the value in the vector.
|
461
|
+
#
|
462
|
+
# @param [FFI::Pointer, Array<Value>, Integer] size_or_values Number of values or array of values.
|
463
|
+
# @param [Proc] block Block evaluated if size is specified.
|
464
|
+
def initialize(size_or_values, &block)
|
465
|
+
@ptr =
|
466
|
+
if size_or_values.is_a?(FFI::Pointer)
|
467
|
+
size_or_values
|
468
|
+
else
|
469
|
+
vals_ptr = make_ptr_to_elements(size_or_values, &block)
|
470
|
+
|
471
|
+
Bindings.const_vector(vals_ptr, vals_ptr.size / vals_ptr.type_size)
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
# @param [Integer] index Index of desired element.
|
476
|
+
#
|
477
|
+
# @return [ConstExpr] Extracted element.
|
478
|
+
def extract_element(index)
|
479
|
+
ConstExpr.new(Bindings.const_extract_element(@ptr, index))
|
480
|
+
end
|
481
|
+
|
482
|
+
# @param [Value] element Value to insert into the vector.
|
483
|
+
# @param [Integer] index Index to insert the value at.
|
484
|
+
#
|
485
|
+
# @return [ConstExpr] New vector representation with inserted value.
|
486
|
+
def insert_element(element, index)
|
487
|
+
ConstExpr.new(Bindings.const_insert_element(@ptr, element, index))
|
488
|
+
end
|
489
|
+
|
490
|
+
# @param [ConstantVector] other Other vector to shuffle with this one.
|
491
|
+
# @param [ConstantVector] mask Mask to use when shuffling.
|
492
|
+
#
|
493
|
+
# @return [ConstantVector] New vector formed by shuffling the two vectors together using the mask.
|
494
|
+
def shuffle(other, mask)
|
495
|
+
ConstantVector.new(Bindings.const_shuffle_vector(@ptr, other, mask))
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
# All number constants inherit from this class.
|
500
|
+
#
|
501
|
+
# @abstract
|
502
|
+
class ConstantNumber < Constant
|
503
|
+
include AbstractClass
|
504
|
+
|
505
|
+
# @return [Type] The corresponding Type sub-class that is used to represent the type of this value.
|
506
|
+
def self.type
|
507
|
+
@type ||= RLTK::CG.const_get(self.short_name + 'Type').instance
|
508
|
+
end
|
509
|
+
|
510
|
+
# @return [Type] The corresponding Type sub-class that is used to represent the type of this value.
|
511
|
+
def type
|
512
|
+
self.class.type
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
516
|
+
# All integer constants inherit from this class.
|
517
|
+
#
|
518
|
+
# @abstract
|
519
|
+
class ConstantInteger < ConstantNumber
|
520
|
+
include AbstractClass
|
521
|
+
|
522
|
+
# @return [Boolean] If the integer is signed or not.
|
523
|
+
attr_reader :signed
|
524
|
+
|
525
|
+
# The constructor for ConstantInteger's various sub-classes. This
|
526
|
+
# constructor is a bit complicated due to having two overloaded
|
527
|
+
# parameters, but once you see the valid combinations it is a bit
|
528
|
+
# simpler.
|
529
|
+
#
|
530
|
+
# @example Constant (signed) integer from Ruby Integer:
|
531
|
+
# Int32.new(128)
|
532
|
+
#
|
533
|
+
# @example Constant (signed) base 8 integer from Ruby String:
|
534
|
+
# Int32.new('72', 8)
|
535
|
+
#
|
536
|
+
# @example Constant integer of all 1s:
|
537
|
+
# Int32.new
|
538
|
+
#
|
539
|
+
# @param [FFI::Pointer, Integer, String, nil] overloaded0 Pointer to a ConstantInteger, value, or string representing value.
|
540
|
+
# @param [Boolean, Integer] overloaded1 Signed or unsigned (when overloaded0 is Integer) or base used to decode string value.
|
541
|
+
# @param [Integer] size Optional length of string to use.
|
542
|
+
def initialize(overloaded0 = nil, overloaded1 = nil, size = nil)
|
543
|
+
@ptr =
|
544
|
+
case overloaded0
|
545
|
+
when FFI::Pointer
|
546
|
+
overloaded0
|
547
|
+
|
548
|
+
when Integer
|
549
|
+
@signed = overloaded1 or true
|
550
|
+
|
551
|
+
Bindings.const_int(self.type, overloaded0, @signed.to_i)
|
552
|
+
|
553
|
+
when String
|
554
|
+
base = overloaded1 or 10
|
555
|
+
|
556
|
+
if size
|
557
|
+
Bindings.const_int_of_string_and_size(self.type, overloaded0, size, base)
|
558
|
+
else
|
559
|
+
Bindings.const_int_of_string(self.type, overloaded0, base)
|
560
|
+
end
|
561
|
+
else
|
562
|
+
@signed = true
|
563
|
+
|
564
|
+
Bindings.const_all_ones(self.type)
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
########
|
569
|
+
# Math #
|
570
|
+
########
|
571
|
+
|
572
|
+
# Addition
|
573
|
+
|
574
|
+
# Add this value with another value.
|
575
|
+
#
|
576
|
+
# @param [ConstantInteger] rhs
|
577
|
+
#
|
578
|
+
# @return [ConstantInteger] Instance of the same class.
|
579
|
+
def +(rhs)
|
580
|
+
self.class.new(Bindings.const_add(@ptr, rhs))
|
581
|
+
end
|
582
|
+
|
583
|
+
# Add this value with another value. Performs no signed wrap
|
584
|
+
# addition.
|
585
|
+
#
|
586
|
+
# @param [ConstantInteger] rhs
|
587
|
+
#
|
588
|
+
# @return [ConstantInteger] Instance of the same class.
|
589
|
+
def nsw_add(rhs)
|
590
|
+
self.class.new(Bindings.const_nsw_add(@ptr, rhs))
|
591
|
+
end
|
592
|
+
|
593
|
+
# Add this value with another value. Performs no unsigned wrap
|
594
|
+
# addition.
|
595
|
+
#
|
596
|
+
# @param [ConstantInteger] rhs
|
597
|
+
#
|
598
|
+
# @return [ConstantInteger] Instance of the same class.
|
599
|
+
def nuw_add(rhs)
|
600
|
+
self.class.new(Bindings.const_nuw_add(@ptr, rhs))
|
601
|
+
end
|
602
|
+
|
603
|
+
# Subtraction
|
604
|
+
|
605
|
+
# Subtract a value from this value.
|
606
|
+
#
|
607
|
+
# @param [ConstantInteger] rhs
|
608
|
+
#
|
609
|
+
# @return [ConstantInteger] Instance of the same class.
|
610
|
+
def -(rhs)
|
611
|
+
self.class.new(Bindings.const_sub(@ptr, rhs))
|
612
|
+
end
|
613
|
+
|
614
|
+
# Subtract a value from this value. Performs no signed wrap
|
615
|
+
# subtraction.
|
616
|
+
#
|
617
|
+
# @param [ConstantInteger] rhs
|
618
|
+
#
|
619
|
+
# @return [ConstantInteger] Instance of the same class.
|
620
|
+
def nsw_sub(rhs)
|
621
|
+
self.class.new(Bindings.const_nsw_sub(@ptr, rhs))
|
622
|
+
end
|
623
|
+
|
624
|
+
# Subtract a value from this value. Performs no unsigned wrap
|
625
|
+
# subtraction.
|
626
|
+
#
|
627
|
+
# @param [ConstantInteger] rhs
|
628
|
+
#
|
629
|
+
# @return [ConstantInteger] Instance of the same class.
|
630
|
+
def nuw_sub(rhs)
|
631
|
+
self.class.new(Bindings.const_nuw_sub(@ptr, rhs))
|
632
|
+
end
|
633
|
+
|
634
|
+
# Multiplication
|
635
|
+
|
636
|
+
# Multiply this value with another value.
|
637
|
+
#
|
638
|
+
# @param [ConstantInteger] rhs
|
639
|
+
#
|
640
|
+
# @return [ConstantInteger] Instance of the same class.
|
641
|
+
def *(rhs)
|
642
|
+
self.class.new(Bindings.const_mul(@ptr, rhs))
|
643
|
+
end
|
644
|
+
|
645
|
+
# Multiply this value with another value. Perform no signed wrap
|
646
|
+
# multiplication.
|
647
|
+
#
|
648
|
+
# @param [ConstantInteger] rhs
|
649
|
+
#
|
650
|
+
# @return [ConstantInteger] Instance of the same class.
|
651
|
+
def nsw_mul(rhs)
|
652
|
+
self.class.new(Bindings.const_nsw_mul(@ptr, rhs))
|
653
|
+
end
|
654
|
+
|
655
|
+
# Multiply this value with another value. Perform no unsigned wrap
|
656
|
+
# multiplication.
|
657
|
+
#
|
658
|
+
# @param [ConstantInteger] rhs
|
659
|
+
#
|
660
|
+
# @return [ConstantInteger] Instance of the same class.
|
661
|
+
def nuw_mul(rhs)
|
662
|
+
self.class.new(Bindings.const_nuw_mul(@ptr, rhs))
|
663
|
+
end
|
664
|
+
|
665
|
+
# Division
|
666
|
+
|
667
|
+
# Divide this value by another value. Uses signed division.
|
668
|
+
#
|
669
|
+
# @param [ConstantInteger] rhs
|
670
|
+
#
|
671
|
+
# @return [ConstantInteger] Instance of the same class.
|
672
|
+
def /(rhs)
|
673
|
+
self.class.new(Bindings.const_s_div(@ptr, rhs))
|
674
|
+
end
|
675
|
+
|
676
|
+
# Divide this value by another value. Uses exact signed division.
|
677
|
+
#
|
678
|
+
# @param [ConstantInteger] rhs
|
679
|
+
#
|
680
|
+
# @return [ConstantInteger] Instance of the same class.
|
681
|
+
def extact_sdiv(rhs)
|
682
|
+
self.class.new(Bindings.const_extact_s_div(@ptr, rhs))
|
683
|
+
end
|
684
|
+
|
685
|
+
# Divide this value by another value. Uses unsigned division.
|
686
|
+
#
|
687
|
+
# @param [ConstantInteger] rhs
|
688
|
+
#
|
689
|
+
# @return [ConstantInteger] Instance of the same class.
|
690
|
+
def udiv(rhs)
|
691
|
+
self.class.new(Bindings.const_u_div(@ptr, rhs))
|
692
|
+
end
|
693
|
+
|
694
|
+
# Remainder
|
695
|
+
|
696
|
+
# Modulo this value by another value. Uses signed modulo.
|
697
|
+
#
|
698
|
+
# @param [ConstantInteger] rhs
|
699
|
+
#
|
700
|
+
# @return [ConstantInteger] Instance of the same class.
|
701
|
+
def %(rhs)
|
702
|
+
self.class.new(Bindings.const_s_rem(@ptr, rhs))
|
703
|
+
end
|
704
|
+
|
705
|
+
# Modulo this value by another value. Uses unsigned modulo.
|
706
|
+
#
|
707
|
+
# @param [ConstantInteger] rhs
|
708
|
+
#
|
709
|
+
# @return [ConstantInteger] Instance of the same class.
|
710
|
+
def urem(rhs)
|
711
|
+
self.class.new(Bindings.const_u_rem(@ptr, rhs))
|
712
|
+
end
|
713
|
+
|
714
|
+
# Negation
|
715
|
+
|
716
|
+
# Negate this value.
|
717
|
+
#
|
718
|
+
# @return [ConstantInteger] Instance of the same class
|
719
|
+
def -@
|
720
|
+
self.class.new(Bindings.const_neg(@ptr))
|
721
|
+
end
|
722
|
+
|
723
|
+
# Negate this value. Uses no signed wrap negation.
|
724
|
+
#
|
725
|
+
# @return [ConstantInteger] Instance of the same class
|
726
|
+
def nsw_neg
|
727
|
+
self.class.new(Bindings.const_nsw_neg(@ptr))
|
728
|
+
end
|
729
|
+
|
730
|
+
# Negate this value. Uses no unsigned wrap negation.
|
731
|
+
#
|
732
|
+
# @return [ConstantInteger] Instance of the same class
|
733
|
+
def nuw_neg
|
734
|
+
self.class.new(Bindings.const_nuw_neg(@ptr))
|
735
|
+
end
|
736
|
+
|
737
|
+
######################
|
738
|
+
# Bitwise Operations #
|
739
|
+
######################
|
740
|
+
|
741
|
+
# A wrapper method around the {#shift_left} and {#shift_right}
|
742
|
+
# methods.
|
743
|
+
#
|
744
|
+
# @param [:left, :right] dir The direction to shift.
|
745
|
+
# @param [Integer] bits Number of bits to shift.
|
746
|
+
# @param [:arithmetic, :logical] mode Shift mode for right shifts.
|
747
|
+
#
|
748
|
+
# @return [ConstantInteger] Instance of the same class.
|
749
|
+
def shift(dir, bits, mode = :arithmetic)
|
750
|
+
case dir
|
751
|
+
when :left then shift_left(bits)
|
752
|
+
when :right then shift_right(bits, mode)
|
753
|
+
end
|
754
|
+
end
|
755
|
+
|
756
|
+
# Shift the value left a specific number of bits.
|
757
|
+
#
|
758
|
+
# @param [Integer] bits Number of bits to shift.
|
759
|
+
#
|
760
|
+
# @return [ConstantInteger] Instance of the same class.
|
761
|
+
def shift_left(bits)
|
762
|
+
self.class.new(Bindings.const_shl(@ptr, bits))
|
763
|
+
end
|
764
|
+
alias :shl :shift_left
|
765
|
+
alias :<< :shift_left
|
766
|
+
|
767
|
+
# Shift the value right a specific number of bits.
|
768
|
+
#
|
769
|
+
# @param [Integer] bits Number of bits to shift.
|
770
|
+
# @param [:arithmetic, :logical] mode Shift mode.
|
771
|
+
#
|
772
|
+
# @return [ConstantInteger] Instance of the same class.
|
773
|
+
def shift_right(bits, mode = :arithmetic)
|
774
|
+
case mode
|
775
|
+
when :arithmetic then ashr(bits)
|
776
|
+
when :logical then lshr(bits)
|
777
|
+
end
|
778
|
+
end
|
779
|
+
|
780
|
+
# Arithmetic right shift.
|
781
|
+
#
|
782
|
+
# @param [Integer] bits Number of bits to shift.
|
783
|
+
#
|
784
|
+
# @return [ConstantInteger] Instance of the same class.
|
785
|
+
def ashr(bits)
|
786
|
+
self.class.new(Bindings.const_a_shr(@ptr, bits))
|
787
|
+
end
|
788
|
+
alias :>> :ashr
|
789
|
+
|
790
|
+
# Logical right shift.
|
791
|
+
#
|
792
|
+
# @param [Integer] bits Number of bits to shift.
|
793
|
+
#
|
794
|
+
# @return [ConstantInteger] Instance of the same class.
|
795
|
+
def lshr(bits)
|
796
|
+
self.class.new(Bindings.const_l_shr(@ptr, bits))
|
797
|
+
end
|
798
|
+
|
799
|
+
# Bitwise AND this value with another.
|
800
|
+
#
|
801
|
+
# @param [ConstantInteger] rhs
|
802
|
+
#
|
803
|
+
# @return [ConstantInteger] Instance of the same class.
|
804
|
+
def and(rhs)
|
805
|
+
self.class.new(Bindings.const_and(@ptr, rhs))
|
806
|
+
end
|
807
|
+
|
808
|
+
# Bitwise OR this value with another.
|
809
|
+
#
|
810
|
+
# @param [ConstantInteger] rhs
|
811
|
+
#
|
812
|
+
# @return [ConstantInteger] Instance of the same class.
|
813
|
+
def or(rhs)
|
814
|
+
self.class.new(Bindings.const_or(@ptr, rhs))
|
815
|
+
end
|
816
|
+
|
817
|
+
# Bitwise XOR this value with another.
|
818
|
+
#
|
819
|
+
# @param [ConstantInteger] rhs
|
820
|
+
#
|
821
|
+
# @return [ConstantInteger] Instance of the same class.
|
822
|
+
def xor(rhs)
|
823
|
+
self.class.new(Bindings.const_xor(@ptr, rhs))
|
824
|
+
end
|
825
|
+
|
826
|
+
# Bitwise NOT this value.
|
827
|
+
#
|
828
|
+
# @return [ConstantInteger] Instance of the same class.
|
829
|
+
def not
|
830
|
+
self.class.new(Bindings.const_not(@ptr))
|
831
|
+
end
|
832
|
+
|
833
|
+
#################
|
834
|
+
# Miscellaneous #
|
835
|
+
#################
|
836
|
+
|
837
|
+
# Cast this constant integer to another number type.
|
838
|
+
#
|
839
|
+
# @param [NumberType] type Desired type to cast to.
|
840
|
+
# @param [Boolean] signed Is the value signed or not.
|
841
|
+
#
|
842
|
+
# @return [ConstantNumber] This value as as the given type.
|
843
|
+
def cast(type, signed = true)
|
844
|
+
type.value_class.new(Bindings.const_int_cast(@ptr, check_cg_type(type, NumberType), signed.to_i))
|
845
|
+
end
|
846
|
+
|
847
|
+
# Compare this value to another value.
|
848
|
+
#
|
849
|
+
# @see Bindings._enum_int_predicate_
|
850
|
+
#
|
851
|
+
# @param [Symbol] pred An integer predicate.
|
852
|
+
# @param [ConstantInteger] rhs Value to compare to.
|
853
|
+
#
|
854
|
+
# @return [Int1] Value used to represent a Boolean value.
|
855
|
+
def cmp(pred, rhs)
|
856
|
+
Int1.new(Bindings.const_i_cmp(pred, @ptr, rhs))
|
857
|
+
end
|
858
|
+
|
859
|
+
# Convert this integer to a float.
|
860
|
+
#
|
861
|
+
# @param [RealType] type Type of float to convert to.
|
862
|
+
#
|
863
|
+
# @return [ConstantReal] This value as a floating point value of the given type.
|
864
|
+
def to_f(type)
|
865
|
+
type.value_class.new(Bindings.send(@signed ? :const_si_to_fp : :const_ui_to_fp, @ptr, check_cg_type(type, FloatingPointType)))
|
866
|
+
end
|
867
|
+
|
868
|
+
# Get the value of this constant as a signed or unsigned long long.
|
869
|
+
#
|
870
|
+
# @param [:sign, :zero] extension Extension method.
|
871
|
+
#
|
872
|
+
# @return [Integer]
|
873
|
+
def value(extension = :sign)
|
874
|
+
case extension
|
875
|
+
when :sign then Bindings.const_int_get_s_ext_value(@ptr)
|
876
|
+
when :zero then Bindings.const_int_get_z_ext_value(@ptr)
|
877
|
+
end
|
878
|
+
end
|
879
|
+
end
|
880
|
+
|
881
|
+
# 1 bit integer value. Often used to represent Boolean values.
|
882
|
+
class Int1 < ConstantInteger; end
|
883
|
+
# 8 bit (1 byte) integer value.
|
884
|
+
class Int8 < ConstantInteger; end
|
885
|
+
# 16 bit (2 byte) integer value.
|
886
|
+
class Int16 < ConstantInteger; end
|
887
|
+
# 32 bit (4 byte) integer value.
|
888
|
+
class Int32 < ConstantInteger; end
|
889
|
+
# 64 bit (8 byte) integer value.
|
890
|
+
class Int64 < ConstantInteger; end
|
891
|
+
|
892
|
+
# The native integer value class on the current (not the target) platform.
|
893
|
+
NativeInt = RLTK::CG.const_get("Int#{FFI.type_size(:int) * 8}")
|
894
|
+
|
895
|
+
# A constant Int 1 representing the Boolean value TRUE.
|
896
|
+
TRUE = Int1.new(-1)
|
897
|
+
# A constant Int 1 representing the Boolean value FALSE.
|
898
|
+
FALSE = Int1.new( 0)
|
899
|
+
|
900
|
+
# All real constants inherit from this class.
|
901
|
+
#
|
902
|
+
# @abstract
|
903
|
+
class ConstantReal < ConstantNumber
|
904
|
+
include AbstractClass
|
905
|
+
|
906
|
+
# Create a constant real number using a Ruby value or a string.
|
907
|
+
#
|
908
|
+
# @param [::Float, String] num_or_string Ruby value or string representation of a float.
|
909
|
+
# @param [Integer, nil] size Optional length of string to use.
|
910
|
+
def initialize(num_or_string, size = nil)
|
911
|
+
@ptr =
|
912
|
+
if num_or_string.is_a?(::Float)
|
913
|
+
Bindings.const_real(self.type, num_or_string)
|
914
|
+
|
915
|
+
elsif size
|
916
|
+
Bindings.const_real_of_string_and_size(self.type, num_or_string, size)
|
917
|
+
|
918
|
+
else
|
919
|
+
Bindings.const_real_of_string(self.type, num_or_string)
|
920
|
+
end
|
921
|
+
end
|
922
|
+
|
923
|
+
# Negate this value.
|
924
|
+
#
|
925
|
+
# @return [ConstantReal] Instance of the same class
|
926
|
+
def -@
|
927
|
+
self.class.new(Bindings.const_f_neg(@ptr))
|
928
|
+
end
|
929
|
+
|
930
|
+
# Add this value with another value.
|
931
|
+
#
|
932
|
+
# @param [ConstantReal] rhs
|
933
|
+
#
|
934
|
+
# @return [ConstantReal] Instance of the same class.
|
935
|
+
def +(rhs)
|
936
|
+
self.class.new(Bindings.const_f_add(@ptr, rhs))
|
937
|
+
end
|
938
|
+
|
939
|
+
# Subtract a value from this value.
|
940
|
+
#
|
941
|
+
# @param [ConstantReal] rhs
|
942
|
+
#
|
943
|
+
# @return [ConstantReal] Instance of the same class.
|
944
|
+
def -(rhs)
|
945
|
+
self.class.new(Bindings.const_f_sub(@ptr, rhs))
|
946
|
+
end
|
947
|
+
|
948
|
+
# Multiply this value with another value.
|
949
|
+
#
|
950
|
+
# @param [ConstantReal] rhs
|
951
|
+
#
|
952
|
+
# @return [ConstantReal] Instance of the same class.
|
953
|
+
def *(rhs)
|
954
|
+
self.class.new(Bindings.const_f_mul(@ptr, rhs))
|
955
|
+
end
|
956
|
+
|
957
|
+
# Divide this value by another value.
|
958
|
+
#
|
959
|
+
# @param [ConstantReal] rhs
|
960
|
+
#
|
961
|
+
# @return [ConstantReal] Instance of the same class.
|
962
|
+
def /(rhs)
|
963
|
+
self.class.new(Bindings.const_f_div(@ptr, rhs))
|
964
|
+
end
|
965
|
+
|
966
|
+
# Modulo this value by another value.
|
967
|
+
#
|
968
|
+
# @param [ConstantReal] rhs
|
969
|
+
#
|
970
|
+
# @return [ConstantReal] Instance of the same class.
|
971
|
+
def %(rhs)
|
972
|
+
self.class.new(Bindings.const_f_remm(@ptr, rhs))
|
973
|
+
end
|
974
|
+
|
975
|
+
# Compare this value to another value.
|
976
|
+
#
|
977
|
+
# @see Bindings._enum_real_predicate_
|
978
|
+
#
|
979
|
+
# @param [Symbol] pred An real predicate.
|
980
|
+
# @param [ConstantReal] rhs Value to compare to.
|
981
|
+
#
|
982
|
+
# @return [Int1] Value used to represent a Boolean value.
|
983
|
+
def cmp(pred, rhs)
|
984
|
+
Int1.new(Bindings.const_f_cmp(pred, @ptr, rhs))
|
985
|
+
end
|
986
|
+
|
987
|
+
# Cast this constant real to another number type.
|
988
|
+
#
|
989
|
+
# @param [NumberType] type Desired type to cast to.
|
990
|
+
#
|
991
|
+
# @return [ConstantNumber] Constant number of given type.
|
992
|
+
def cast(type)
|
993
|
+
type.value_class.new(Bindings.const_fp_cast(@ptr, check_cg_type(type, NumberType)))
|
994
|
+
end
|
995
|
+
|
996
|
+
# Convert this real number into an integer.
|
997
|
+
#
|
998
|
+
# @param [BasicIntType] type Type to convert to.
|
999
|
+
# @param [Boolean] signed Should the result be a signed integer or not.
|
1000
|
+
#
|
1001
|
+
# @return [
|
1002
|
+
def to_i(type = NativeIntType, signed = true)
|
1003
|
+
type.value_class.new(Bindings.send(signed ? :const_fp_to_si : :const_fp_to_ui, @ptr, check_cg_type(type, BasicIntType)))
|
1004
|
+
end
|
1005
|
+
|
1006
|
+
# Extend a constant real number to a larger size.
|
1007
|
+
#
|
1008
|
+
# @param [RealType] type Type to extend to.
|
1009
|
+
#
|
1010
|
+
# @return [ConstantReal] This value as a real of the given type.
|
1011
|
+
def extend(type)
|
1012
|
+
type.value_class.new(Bindings.const_fp_ext(@ptr, check_cg_type(type, RealType)))
|
1013
|
+
end
|
1014
|
+
|
1015
|
+
# Truncate a constant real number to a smaller size.
|
1016
|
+
#
|
1017
|
+
# @param [RealType] type Type to truncate to.
|
1018
|
+
#
|
1019
|
+
# @return [ConstantReal] This value as a real of the given type.
|
1020
|
+
def truncate(type)
|
1021
|
+
type.value_class.new(Bindings.const_fp_trunc(@ptr, check_cg_type(type, RealType)))
|
1022
|
+
end
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
# A double precision floating point number value.
|
1026
|
+
class Double < ConstantReal; end
|
1027
|
+
# A single precision floating point number type.
|
1028
|
+
class Float < ConstantReal; end
|
1029
|
+
# A 128 bit (16 byte) floating point number type.
|
1030
|
+
class FP128 < ConstantReal; end
|
1031
|
+
# A 128 bit (16 byte) floating point number type for the PPC architecture.
|
1032
|
+
class PPCFP128 < ConstantReal; end
|
1033
|
+
# A 80 bit (10 byte) floating point number type for the x86 architecture.
|
1034
|
+
class X86FP80 < ConstantReal; end
|
1035
|
+
|
1036
|
+
# This class represents global constants, variables, and functions.
|
1037
|
+
class GlobalValue < Constant
|
1038
|
+
# Global values can only be instantiated using a pointer, and as such
|
1039
|
+
# should not be created directly by library users.
|
1040
|
+
#
|
1041
|
+
# @param [FFI::Pointer] ptr
|
1042
|
+
def initialize(ptr)
|
1043
|
+
@ptr = check_type(ptr, FFI::Pointer, 'ptr')
|
1044
|
+
end
|
1045
|
+
|
1046
|
+
# Get the byte alignment of this value.
|
1047
|
+
#
|
1048
|
+
# @return [Integer]
|
1049
|
+
def alignment
|
1050
|
+
Bindings.get_alignment(@ptr)
|
1051
|
+
end
|
1052
|
+
|
1053
|
+
# Set the byte alignment of this value.
|
1054
|
+
#
|
1055
|
+
# @param [Integer] bytes
|
1056
|
+
#
|
1057
|
+
# @return [void]
|
1058
|
+
def alignment=(bytes)
|
1059
|
+
Bindings.set_alignment(@ptr, bytes)
|
1060
|
+
end
|
1061
|
+
|
1062
|
+
# Check if this value is a declaration.
|
1063
|
+
#
|
1064
|
+
# @return [Boolean]
|
1065
|
+
def declaration?
|
1066
|
+
Bindings.is_declaration(@ptr).to_bool
|
1067
|
+
end
|
1068
|
+
|
1069
|
+
# Check if this value is a global constant.
|
1070
|
+
#
|
1071
|
+
# @return [Boolean]
|
1072
|
+
def global_constant?
|
1073
|
+
Bindings.is_global_constant(@ptr).to_bool
|
1074
|
+
end
|
1075
|
+
|
1076
|
+
# Set this value as a global constant or not.
|
1077
|
+
#
|
1078
|
+
# @param [Boolean] flag
|
1079
|
+
#
|
1080
|
+
# @return [void]
|
1081
|
+
def global_constant=(flag)
|
1082
|
+
Bindings.set_global_constant(@ptr, flag.to_i)
|
1083
|
+
end
|
1084
|
+
|
1085
|
+
# Get this value's initializer.
|
1086
|
+
#
|
1087
|
+
# @return [Value]
|
1088
|
+
def initializer
|
1089
|
+
Value.new(Bindings.get_initializer(@ptr))
|
1090
|
+
end
|
1091
|
+
|
1092
|
+
# Set this value's initializer.
|
1093
|
+
#
|
1094
|
+
# @param [Value] val
|
1095
|
+
#
|
1096
|
+
# @return [void]
|
1097
|
+
def initializer=(val)
|
1098
|
+
Bindings.set_initializer(@ptr, check_type(val, Value, 'val'))
|
1099
|
+
end
|
1100
|
+
|
1101
|
+
# Get this value's linkage type.
|
1102
|
+
#
|
1103
|
+
# @see Bindings._enum_linkage_
|
1104
|
+
#
|
1105
|
+
# @return [Symbol]
|
1106
|
+
def linkage
|
1107
|
+
Bindings.get_linkage(@ptr)
|
1108
|
+
end
|
1109
|
+
|
1110
|
+
# Set this value's linkage type.
|
1111
|
+
#
|
1112
|
+
# @see Bindings._enum_linkage_
|
1113
|
+
#
|
1114
|
+
# @param [Symbol] linkage
|
1115
|
+
#
|
1116
|
+
# @return [void]
|
1117
|
+
def linkage=(linkage)
|
1118
|
+
Bindings.set_linkage(@ptr, linkage)
|
1119
|
+
end
|
1120
|
+
|
1121
|
+
# Get this value's section string.
|
1122
|
+
#
|
1123
|
+
# @return [String]
|
1124
|
+
def section
|
1125
|
+
Bindings.get_section(@ptr)
|
1126
|
+
end
|
1127
|
+
|
1128
|
+
# Set this value's section string.
|
1129
|
+
#
|
1130
|
+
# @param [String] section
|
1131
|
+
#
|
1132
|
+
# @return [void]
|
1133
|
+
def section=(section)
|
1134
|
+
Bindings.set_section(@ptr, section)
|
1135
|
+
end
|
1136
|
+
|
1137
|
+
# Get this value's visibility.
|
1138
|
+
#
|
1139
|
+
# @see Bindings._enum_visibility_
|
1140
|
+
#
|
1141
|
+
# @return [String]
|
1142
|
+
def visibility
|
1143
|
+
Bindings.get_visibility(@ptr)
|
1144
|
+
end
|
1145
|
+
|
1146
|
+
# Set this value's visibility.
|
1147
|
+
#
|
1148
|
+
# @see Bindings._enum_visibility_
|
1149
|
+
#
|
1150
|
+
# @param [Symbol] vis
|
1151
|
+
#
|
1152
|
+
# @return [void]
|
1153
|
+
def visibility=(vis)
|
1154
|
+
Bindings.set_visibility(@ptr, vis)
|
1155
|
+
end
|
1156
|
+
end
|
1157
|
+
|
1158
|
+
# This class represents global aliases.
|
1159
|
+
class GlobalAlias < GlobalValue
|
1160
|
+
end
|
1161
|
+
|
1162
|
+
# This class represents global variables.
|
1163
|
+
class GlobalVariable < GlobalValue
|
1164
|
+
# Check to see if this global variable is thread local.
|
1165
|
+
#
|
1166
|
+
# @return [Boolean]
|
1167
|
+
def thread_local?
|
1168
|
+
Bindings.is_thread_local(@ptr).to_bool
|
1169
|
+
end
|
1170
|
+
|
1171
|
+
# Set this global variable as thread local or not.
|
1172
|
+
#
|
1173
|
+
# @param [Boolean] local
|
1174
|
+
#
|
1175
|
+
# @return [void]
|
1176
|
+
def thread_local=(local)
|
1177
|
+
Bindings.set_thread_local(@ptr, local.to_i)
|
1178
|
+
end
|
1179
|
+
end
|
1180
|
+
end
|
1181
|
+
|
1182
|
+
####################
|
1183
|
+
# Helper Functions #
|
1184
|
+
####################
|
1185
|
+
|
1186
|
+
# A helper function for creating constant array, vector, and struct types.
|
1187
|
+
# This method should never be used by library users.
|
1188
|
+
#
|
1189
|
+
# @param [Array<RLTK::CG::Value>, Integer] size_or_values Number of values or array of values.
|
1190
|
+
# @param [Proc] block Block evaluated if size is specified.
|
1191
|
+
#
|
1192
|
+
# @return [FFI::MemoryPointer] An array of pointers to LLVM Values.
|
1193
|
+
def make_ptr_to_elements(size_or_values, &block)
|
1194
|
+
values =
|
1195
|
+
case size_or_values
|
1196
|
+
when Integer
|
1197
|
+
raise ArgumentError, 'Block not given.' if not block_given?
|
1198
|
+
|
1199
|
+
::Array.new(size_or_values, &block)
|
1200
|
+
else
|
1201
|
+
size_or_values
|
1202
|
+
end
|
1203
|
+
|
1204
|
+
returning(FFI::MemoryPointer.new(:pointer, values.size)) do |ptr|
|
1205
|
+
ptr.write_array_of_pointer(values)
|
1206
|
+
end
|
1207
|
+
end
|