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