rltk3 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
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