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.
@@ -0,0 +1,510 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/03/18
4
+ # Description: This file defines the various LLVM Types.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Standard Library
11
+ require 'singleton'
12
+
13
+ # Ruby Language Toolkit
14
+ require 'rltk/util/abstract_class'
15
+ require 'rltk/cg/bindings'
16
+ require 'rltk/cg/context'
17
+
18
+ #######################
19
+ # Classes and Modules #
20
+ #######################
21
+
22
+ module RLTK::CG # :nodoc:
23
+
24
+ # The Type class and its sub-classes are used to describe the size and
25
+ # structure of various data objects inside LLVM and how different
26
+ # operations interact with them. When instantiating objects of the
27
+ # {Value} class you will often need to pass in some type information.
28
+ #
29
+ # @abstract Root of the type class hierarchy.
30
+ class Type
31
+ include BindingClass
32
+ include AbstractClass
33
+
34
+ # Instantiate a Type object from a pointer. This function is used
35
+ # internally, and as a library user you should never have to call it.
36
+ #
37
+ # @param [FFI::Pointer] ptr
38
+ #
39
+ # @return [Type] A object of type Type or one of its sub-classes.
40
+ def self.from_ptr(ptr)
41
+ case Bindings.get_type_kind(ptr)
42
+ when :array then ArrayType.new(ptr)
43
+ when :double then DoubleType.new
44
+ when :float then FloatType.new
45
+ when :function then FunctionType.new(ptr)
46
+ when :fp128 then FP128Type.new
47
+ when :integer then IntType.new
48
+ when :label then LabelType.new
49
+ when :metadata then raise "Can't generate a Type object for objects of type Metadata."
50
+ when :pointer then PointerType.new(ptr)
51
+ when :ppc_fp128 then PPCFP128Type.new
52
+ when :struct then StructType.new(ptr)
53
+ when :vector then VectorType.new(ptr)
54
+ when :void then VoidType.new
55
+ when :x86_fp80 then X86FP80Type.new
56
+ when :x86_mmx then X86MMXType.new
57
+ end
58
+ end
59
+
60
+ # The default constructor for Type objects.
61
+ #
62
+ # @param [Context, nil] context An optional context in which to create the type.
63
+ def initialize(context = nil)
64
+ bname = Bindings.get_bname(self.class.short_name)
65
+
66
+ @ptr =
67
+ if context
68
+ Bindings.send((bname.to_s + '_in_context').to_sym, check_type(context, Context, 'context'))
69
+ else
70
+ Bindings.send(bname)
71
+ end
72
+ end
73
+
74
+ # @return [NativeInt] Alignment of the type.
75
+ def allignment
76
+ Int64.new(Bindings.align_of(@ptr))
77
+ end
78
+
79
+ # @return [Context] Context in which this type was created.
80
+ def context
81
+ Context.new(Bindings.get_type_context(@ptr))
82
+ end
83
+
84
+ # @return [Fixnum] Hashed value of the pointer representing this type.
85
+ def hash
86
+ @ptr.address.hash
87
+ end
88
+
89
+ # @see Bindings._enum_type_kind_
90
+ #
91
+ # @return [Symbol] The *kind* of this type.
92
+ def kind
93
+ Bindings.get_type_kind(@ptr)
94
+ end
95
+
96
+ # @return [NativeInt] Size of objects of this type.
97
+ def size
98
+ Int64.new(Bindings.size_of(@ptr))
99
+ end
100
+ end
101
+
102
+ # All types that are used to represent numbers inherit from this class.
103
+ #
104
+ # @abstract
105
+ class NumberType < Type
106
+ include AbstractClass
107
+
108
+ # @return [Value] The corresponding Value sub-class that is used to represent values of this type.
109
+ def self.value_class
110
+ begin
111
+ @value_class ||=
112
+ RLTK::CG.const_get(self.name.match(/::(.+)Type$/).captures.last.to_sym)
113
+
114
+ rescue
115
+ raise "#{self.name} has no value class."
116
+ end
117
+ end
118
+
119
+ # @return [Value] The corresponding Value sub-class that is used to represent values of this type.
120
+ def value_class
121
+ self.class.value_class
122
+ end
123
+ end
124
+
125
+ # All types that represent integers of a given width inherit from this class.
126
+ #
127
+ # @abstract
128
+ class BasicIntType < NumberType
129
+ include AbstractClass
130
+
131
+ # @return [Integer] Number of bits used to represent an integer type.
132
+ def width
133
+ @width ||= Bindings.get_int_type_width(@ptr)
134
+ end
135
+ end
136
+
137
+ # An integer of an arbitrary width.
138
+ class IntType < BasicIntType
139
+ # @param [Integer] width Width of new integer type.
140
+ # @param [Context] context Context in which to create the type.
141
+ #
142
+ # @raise [RuntimeError] Raises an error when width is <= 0.
143
+ def initialize(width, context = nil)
144
+ if width > 0
145
+ @ptr =
146
+ if context
147
+ Bindings.get_int_type_in_context(width, check_type(context, Context, 'context'))
148
+ else
149
+ Bidnings.get_int_type(width)
150
+ end
151
+ else
152
+ raise 'The width parameter must be greater then 0.'
153
+ end
154
+ end
155
+
156
+ # Overrides {NumberType#value_class}.
157
+ #
158
+ # @raise [RuntimeError] This function has no meaning in this class.
159
+ def value_class
160
+ raise 'The RLKT::CG::IntType class has no value class.'
161
+ end
162
+ end
163
+
164
+ # A class inherited by singleton integer type classes.
165
+ #
166
+ # @abstract
167
+ class SimpleIntType < BasicIntType
168
+ include AbstractClass
169
+ include Singleton
170
+ end
171
+
172
+ # A class inherited by all types representing floats.
173
+ #
174
+ # @abstract
175
+ class RealType < NumberType
176
+ include AbstractClass
177
+ include Singleton
178
+ end
179
+
180
+ # A class inherited by non-number singleton type classes.
181
+ #
182
+ # @abstract
183
+ class SimpleType < Type
184
+ include AbstractClass
185
+ include Singleton
186
+ end
187
+
188
+ # 1 bit integer type. Often used to represent Boolean values.
189
+ class Int1Type < SimpleIntType; end
190
+ # 8 bit (1 byte) integer type.
191
+ class Int8Type < SimpleIntType; end
192
+ # 16 bit (2 byte) integer type.
193
+ class Int16Type < SimpleIntType; end
194
+ # 32 bit (4 byte) integer type.
195
+ class Int32Type < SimpleIntType; end
196
+ # 64 bit (8 byte) integer type.
197
+ class Int64Type < SimpleIntType; end
198
+
199
+ # The native integer type on the current (not the target) platform.
200
+ NativeIntType = RLTK::CG.const_get("Int#{FFI.type_size(:int) * 8}Type")
201
+
202
+ # A double precision floating point number type.
203
+ class DoubleType < RealType; end
204
+ # A single precision floating point number type.
205
+ class FloatType < RealType; end
206
+ # A 128 bit (16 byte) floating point number type.
207
+ class FP128Type < RealType; end
208
+ # A 128 bit (16 byte) floating point number type for the PPC architecture.
209
+ class PPCFP128Type < RealType; end
210
+ # A 80 bit (10 byte) floating point number type for the x86 architecture.
211
+ class X86FP80Type < RealType; end
212
+
213
+ # A type for x86 MMX instructions.
214
+ class X86MMXType < SimpleType; end
215
+
216
+ # A type used in representing void pointers and functions that return no values.
217
+ class VoidType < SimpleType; end
218
+ # A type used to represent labels in LLVM IR.
219
+ class LabelType < SimpleType; end
220
+
221
+ # The common ancestor for array, pointer, and struct types.
222
+ #
223
+ # @abstract
224
+ class AggregateType < Type
225
+ include AbstractClass
226
+ end
227
+
228
+ # {ArrayType} and {PointerType} inherit from this class so they can share
229
+ # a constructor.
230
+ #
231
+ # @abstract
232
+ class SimpleAggregateType < AggregateType
233
+ include AbstractClass
234
+
235
+ # Used to initialize {ArrayType ArrayTypes} and {PointerType PointerTypes}.
236
+ #
237
+ # @param [FFI::Pointer, Type] overloaded Pointer to an existing aggregate type or a Type object that
238
+ # describes the objects that will be stored in an aggregate type.
239
+ def initialize(overloaded, size_or_address_space = 0)
240
+ @ptr =
241
+ case overloaded
242
+ when FFI::Pointer
243
+ overloaded
244
+ else
245
+ @element_type = check_cg_type(overloaded, Type, 'overloaded')
246
+ bname = Bindings.get_bname(self.class.short_name)
247
+
248
+ Bindings.send(bname, @element_type, size_or_address_space)
249
+ end
250
+ end
251
+
252
+ # @return [Type] Type of objects stored inside this aggregate.
253
+ def element_type
254
+ @element_type ||= Type.from_ptr(Bindings.get_element_type(@ptr))
255
+ end
256
+ end
257
+
258
+ # A Type describing an array that holds objects of a single given type.
259
+ class ArrayType < SimpleAggregateType
260
+ # @return [Integer] Number of elements in this array type.
261
+ def size
262
+ @length ||= Bindings.get_array_length(@ptr)
263
+ end
264
+ alias :length :size
265
+ end
266
+
267
+ # A Type describing a pointer to another type.
268
+ class PointerType < SimpleAggregateType
269
+ # @return [Integer] Address space of this pointer.
270
+ def address_space
271
+ @address_space ||= Bindings.get_pointer_address_space(@ptr)
272
+ end
273
+ end
274
+
275
+ # A type used to represent vector operations (SIMD). This is NOT an
276
+ # aggregate type.
277
+ class VectorType < Type
278
+ # Create a new vector type from a pointer or a type.
279
+ #
280
+ # @param [FFI::Pointer, Type] overloaded Pointer to existing vector type or Type of object stored in the vector.
281
+ # @param [Integer] size Number of objects in this vector type.
282
+ def initialize(overloaded, size = 0)
283
+ @ptr =
284
+ case overloaded
285
+ when FFI::Pointer
286
+ overloaded
287
+ else
288
+ @element_type = check_cg_type(overloaded, Type, 'overloaded')
289
+ bname = Bindings.get_bname(self.class.short_name)
290
+
291
+ Bindings.send(bname, @element_type, size)
292
+ end
293
+ end
294
+
295
+ # @return [Type] Type of object stored inside this vector.
296
+ def element_type
297
+ @element_type ||= Type.from_ptr(Bindings.get_element_type(@ptr))
298
+ end
299
+
300
+ # @return [Integer] Number of objects in this vector type.
301
+ def size
302
+ Bindings.get_vector_size(@ptr)
303
+ end
304
+ alias :length :size
305
+ end
306
+
307
+ # A type representing the return an argument types for a function.
308
+ class FunctionType < Type
309
+ # @return [Array<Type>] Types of this function type's arguments.
310
+ attr_reader :arg_types
311
+
312
+ # Create a new function type from a pointer or description of the
313
+ # return type and argument types.
314
+ #
315
+ # @param [FFI::Pointer, Type] overloaded Pointer to existing function type or the return type.
316
+ # @param [Array<Type>] arg_types Types of the function's arguments.
317
+ # @param [Boolean] varargs Weather or not this function has varargs.
318
+ def initialize(overloaded, arg_types = nil, varargs = false)
319
+ @ptr =
320
+ case overloaded
321
+ when FFI::Pointer
322
+ overloaded
323
+ else
324
+ @return_type = check_cg_type(overloaded, Type, 'return_type')
325
+ @arg_types = check_cg_array_type(arg_types, Type, 'arg_types').freeze
326
+
327
+ arg_types_ptr = FFI::MemoryPointer.new(:pointer, @arg_types.length)
328
+ arg_types_ptr.write_array_of_pointer(@arg_types)
329
+
330
+ Bindings.function_type(@return_type, arg_types_ptr, @arg_types.length, varargs.to_i)
331
+ end
332
+ end
333
+
334
+ # @return [Array<Type>] Types of this function type's arguments.
335
+ def argument_types
336
+ @arg_types ||=
337
+ begin
338
+ num_elements = Bindings.count_param_types(@ptr)
339
+
340
+ ret_ptr = FFI::MemoryPointer.new(:pointer)
341
+ Bindings.get_param_types(@ptr, ret_ptr)
342
+
343
+ types_ptr = ret_ptr.get_pointer(0)
344
+
345
+ types_ptr.get_array_of_pointer(0, num_elements).map { |ptr| Type.from_ptr(ptr) }
346
+ end
347
+ end
348
+ alias :arg_types :argument_types
349
+
350
+ # @return [Type] The return type of this function type.
351
+ def return_type
352
+ @return_type ||= Type.from_ptr(Bindings.get_return_type(@ptr))
353
+ end
354
+ end
355
+
356
+ # A type for representing an arbitrary collection of types.
357
+ class StructType < AggregateType
358
+ # Create a new struct type.
359
+ #
360
+ # @param [FFI::Pointer, Array<Type>] overloaded Pointer to an existing struct type or an array of types in the struct.
361
+ # @param [String, nil] name Name of the new struct type in LLVM IR.
362
+ # @param [Boolean] packed Are the types packed already, or should they be re-arranged to save space?
363
+ # @param [Context, nil] context Context in which to create this new type.
364
+ def initialize(overloaded, name = nil, packed = false, context = nil)
365
+ @ptr =
366
+ case overloaded
367
+ when FFI::Pointer
368
+ overloaded
369
+ else
370
+ # Check the types of the elements of the overloaded parameter.
371
+ @element_types = check_cg_array_type(overloaded, Type, 'overloaded')
372
+
373
+ el_types_ptr = FFI::MemoryPointer.new(:pointer, @element_types.length)
374
+ el_types_ptr.write_array_of_pointer(@element_types)
375
+
376
+ if name
377
+ @name = check_type(name, String, 'name')
378
+
379
+ returning Bindings.struct_create_named(Context.global, @name) do |ptr|
380
+ Bindings.struct_set_body(ptr, el_types_ptr, @element_types.length, packed.to_i) unless @element_types.empty?
381
+ end
382
+
383
+ elsif context
384
+ check_type(context, Context, 'context')
385
+
386
+ Bindings.struct_type_in_context(context, el_types_ptr, @element_types.length, is_packed.to_i)
387
+
388
+ else
389
+ Bindings.struct_type(el_types_ptr, @element_types.length, packed.to_i)
390
+ end
391
+ end
392
+ end
393
+
394
+ # @return [Array<Type>] Array of the types in this struct type.
395
+ def element_types
396
+ @element_types ||=
397
+ begin
398
+ num_elements = Bindings.count_struct_element_types(@ptr)
399
+
400
+ ret_ptr = FFI::MemoryPointer.new(:pointer)
401
+ Bindings.get_struct_element_types(@ptr, ret_ptr)
402
+
403
+ types_ptr = ret_ptr.get_pointer(0)
404
+
405
+ types_ptr.get_array_of_pointer(0, num_elements).map { |ptr| Type.from_ptr(ptr) }
406
+ end
407
+ end
408
+
409
+ # Set the types in the body of this struct type.
410
+ #
411
+ # @param [Array<Type>] el_types Array of types in the struct.
412
+ # @param [Boolean] packed Are the types packed already, or should they be re-arranged to save space?
413
+ #
414
+ # @return [void]
415
+ def element_types=(el_types, packed = false)
416
+ @element_types = check_cg_array_type(el_types, Type, 'el_types')
417
+
418
+ el_types_ptr = FFI::MemoryPointer.new(:pointer, @element_types.length)
419
+ el_types_ptr.write_array_of_pointer(@element_types)
420
+
421
+ Bindings.struct_set_body(@ptr, el_types_ptr, @element_types.length, packed.to_i)
422
+ end
423
+
424
+ # @return [String] Name of the struct type in LLVM IR.
425
+ def name
426
+ @name ||= Bindings.get_struct_name(@ptr)
427
+ end
428
+ end
429
+ end
430
+
431
+ ####################
432
+ # Helper Functions #
433
+ ####################
434
+
435
+ # This helper function checks to make sure that an object is a sub-class of
436
+ # {RLTK::CG::Type Type} or an instance of a sub-class of Type. If a class is
437
+ # passed in the *o* parameter it is expected to be a singleton class and will
438
+ # be instantiated via the *instance* method.
439
+ #
440
+ # @param [Type, Class] o Object to type check for code generation type.
441
+ # @param [Type] type Class the object should be an instance (or sub-class) of.
442
+ # @param [String] blame Variable name to blame for failed type checks.
443
+ # @param [Boolean] strict Strict or non-strict checking. Uses `instance_of?` and `is_a?` respectively.
444
+ #
445
+ # @raise [RuntimeError] An error is raise if a class is passed in parameter *o*
446
+ # that hasn't included the Singleton class, if the class passed in parameter
447
+ # *type* isn't a sub-class of {RLTK::CG::Type Type}, or if the type check
448
+ # fails.
449
+ #
450
+ # @return [Type] The object *o* or an instance of the class passed in parameter *o*.
451
+ def check_cg_type(o, type = RLTK::CG::Type, blame = 'type', strict = false)
452
+ if o.is_a?(Class)
453
+ type_ok = if strict then o == type else o.subclass_of?(type) end
454
+
455
+ if type_ok
456
+ if o.includes_module?(Singleton)
457
+ o.instance
458
+ else
459
+ raise "The #{o.name} class (passed as parameter #{blame}) must be instantiated directly."
460
+ end
461
+ else
462
+ raise "The #{o.name} class (passed as parameter #{blame} does not inherit from the #{type.name} class."
463
+ end
464
+ else
465
+ check_type(o, type, blame, strict)
466
+ end
467
+ end
468
+
469
+ # This helper function checks to make sure that an array of objects are all
470
+ # sub-classses of {RLTK::CG::Type Type} or instances of a sub-class of Type.
471
+ # If a class is present in the *array* parameter it is expected to be a
472
+ # singleton class and will be instantiated via the *instance* method.
473
+ #
474
+ # @param [Array<Type, Class>] array Array of objects to type check for code generation type.
475
+ # @param [Type] type Class the objects should be an instance (or sub-class) of.
476
+ # @param [String] blame Variable name to blame for failed type checks.
477
+ # @param [Boolean] strict Strict or non-strict checking. Uses `instance_of?` and `is_a?` respectively.
478
+ #
479
+ # @raise [RuntimeError] An error is raise if a class is passed in *array* that
480
+ # hasn't included the Singleton class, if the class passed in parameter
481
+ # *type* isn't a sub-class of {RLTK::CG::Type Type}, or if the type check
482
+ # fails.
483
+ #
484
+ # @return [Array<Type>] An array containing the objects in *array* with any singleton classes replaced by their instances.
485
+ def check_cg_array_type(array, type = RLTK::CG::Type, blame = 'el_types', strict = false)
486
+ array.map do |o|
487
+ if o.is_a?(Class)
488
+ type_ok = if strict then o == type else o.subclass_of?(type) end
489
+
490
+ if type_ok
491
+ if o.includes_module?(Singleton)
492
+ o.instance
493
+ else
494
+ raise "The #{o.name} class (passed in parameter #{blame}) must be instantiated directly."
495
+ end
496
+ else
497
+ raise "The #{o.name} class (passed in parameter #{blame}) does not inherit from the #{type.name} class."
498
+ end
499
+
500
+ else
501
+ type_ok = if strict then o.instance_of(type) else o.is_a?(type) end
502
+
503
+ if type_ok
504
+ o
505
+ else
506
+ raise "Parameter #{blame} must contain instances of the #{type.name} class."
507
+ end
508
+ end
509
+ end
510
+ end