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,252 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/03/15
4
+ # Description: This file defines the PassManager class.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Ruby Language Toolkit
11
+ require 'rltk/cg/bindings'
12
+
13
+ #######################
14
+ # Classes and Modules #
15
+ #######################
16
+
17
+ module RLTK::CG
18
+
19
+ # A PassManager is responsible for scheduling and running optimization
20
+ # passes on modules.
21
+ class PassManager
22
+ include BindingClass
23
+
24
+ # The Proc object called by the garbage collector to free resources used by LLVM.
25
+ CLASS_FINALIZER = Proc.new { |id| Bindings.dispose_pass_manager(ptr) if ptr = ObjectSpace._id2ref(id).ptr }
26
+
27
+ # A list of passes that are available to be added to the pass
28
+ # manager via the {PassManager#add} method.
29
+ PASSES = {
30
+ :ADCE => :aggressive_dce,
31
+ :AlwaysInline => :always_inliner,
32
+ :ArgPromote => :argument_promotion,
33
+ :BasicAliasAnalysis => :basic_alias_analysis,
34
+ :BBVectorize => :bb_vectorize,
35
+ :CFGSimplify => :cfg_simplification,
36
+ :ConstMerge => :constant_merge,
37
+ :ConstProp => :constant_propagation,
38
+ :CorValProp => :correlated_value_propagation,
39
+ :DAE => :dead_arg_elimination,
40
+ :DSE => :dead_store_elimination,
41
+ :DemoteMemToReg => :demote_memory_to_register,
42
+ :EarlyCSE => :early_cse,
43
+ :FunctionAttrs => :function_attrs,
44
+ :FunctionInline => :function_inlining,
45
+ :GDCE => :global_dce,
46
+ :GlobalOpt => :global_optimizer,
47
+ :GVN => :gvn,
48
+ :Internalize => :internalize,
49
+ :IndVarSimplify => :ind_var_simplify,
50
+ :InstCombine => :instruction_combining,
51
+ :IPConstProp => :ip_constant_propagation,
52
+ :IPSCCP => :ipsccp,
53
+ :JumpThreading => :jump_threading,
54
+ :LICM => :licm,
55
+ :LoopDeletion => :loop_deletion,
56
+ :LoopIdiom => :loop_idiom,
57
+ :LoopReroll => :loop_reroll,
58
+ :LoopRotate => :loop_rotate,
59
+ :LoopUnroll => :loop_unroll,
60
+ :LoopUnswitch => :loop_unswitch,
61
+ :LoopVectorize => :loop_vectorize,
62
+ :LEI => :lower_expect_intrinsics,
63
+ :MemCopyOpt => :mem_cpy_opt,
64
+ :PILC => :partially_inline_lib_calls,
65
+ :PromoteMemToReg => :promote_memory_to_register,
66
+ :PruneEH => :prune_eh,
67
+ :Reassociate => :reassociate,
68
+ :SCCP => :sccp,
69
+ :ScalarRepl => :scalar_repl_aggregates,
70
+ :SimplifyLibCalls => :simplify_lib_calls,
71
+ :SLPVectorize => :slp_vectorize,
72
+ :StripDeadProtos => :strip_dead_prototypes,
73
+ :StripSymbols => :strip_symbols,
74
+ :TailCallElim => :tail_call_elimination,
75
+ :TBAA => :type_based_alias_analysis,
76
+ :Verifier => :verifier
77
+ }
78
+
79
+ # Create a new pass manager. You should never have to do this as
80
+ # {Module Modules} should create PassManagers for you whenever they
81
+ # are requested.
82
+ #
83
+ # @see Module#pass_manager
84
+ #
85
+ # @param [Module] mod Module this pass manager belongs to.
86
+ def initialize(mod)
87
+ # LLVM Initialization
88
+ @ptr = Bindings.create_pass_manager
89
+ @mod = mod
90
+
91
+ # Set the target data if the module is associated with a execution engine.
92
+ self.target_data = mod.engine.target_data if mod.engine
93
+
94
+ # RLTK Initialization
95
+ @enabled = Array.new
96
+
97
+ # Define a finalizer to free the memory used by LLVM for this
98
+ # pass manager.
99
+ ObjectSpace.define_finalizer(self, CLASS_FINALIZER)
100
+ end
101
+
102
+ # Add a pass or passes to this pass manager. Passes may either be
103
+ # specified via the keys for the PASSES hash or any string that will
104
+ # be turned into a string (via the {Bindings.get_bname} method)
105
+ # appearing as a value of the PASSES hash.
106
+ #
107
+ # @see PASSES
108
+ #
109
+ # @param [Array<Symbol>] names Passes to add to the pass manager.
110
+ #
111
+ # @return [PassManager] self
112
+ def add(*names)
113
+ names.each do |name|
114
+ name = name.to_sym
115
+
116
+ if PASSES.has_key?(name)
117
+ next if @enabled.include?(name)
118
+
119
+ Bindings.send("add_#{PASSES[name]}_pass", @ptr)
120
+
121
+ @enabled << name
122
+
123
+ elsif PASSES.has_value?(bname = Bindings.get_bname(name))
124
+ next if @enabled.include?(PASSES.key(bname))
125
+
126
+ Bindings.send("add_#{bname}_pass", @ptr)
127
+
128
+ @enabled << PASSES.key(bname)
129
+
130
+ else
131
+ raise "Unknown pass: #{name}"
132
+ end
133
+ end
134
+
135
+ self
136
+ end
137
+ alias :<< :add
138
+
139
+ # @return [Array<Symbol>] List of passes that have been enabled.
140
+ def enabled
141
+ @enabled.clone
142
+ end
143
+
144
+ # @return [Boolean] Weather the pass has been enabled or not.
145
+ def enabled?(name)
146
+ @enabled.include?(name) or @enabled.include?(PASSES.key(Bindings.get_bname(name)))
147
+ end
148
+
149
+ # Run the enabled passes on the execution engine's module.
150
+ #
151
+ # @return [void]
152
+ def run
153
+ Bindings.run_pass_manager(@ptr, @mod).to_bool
154
+ end
155
+
156
+ # Set the target data for this pass manager.
157
+ #
158
+ # @param [TargetData] data
159
+ #
160
+ # @return [void]
161
+ def target_data=(data)
162
+ Bindings.add_target_data(check_type(data, TargetData, 'data'), @ptr)
163
+ end
164
+
165
+ protected
166
+ # Empty method used by {FunctionPassManager} to clean up resources.
167
+ def finalize
168
+ end
169
+ end
170
+
171
+ # A FunctionPassManager is responsible for scheduling and running optimization
172
+ # passes on individual functions inside the context of a module.
173
+ class FunctionPassManager < PassManager
174
+ # Create a new function pass manager. You should never have to do
175
+ # this as {Module Modules} should create FunctionPassManagers for you
176
+ # whenever they are requested.
177
+ #
178
+ # @see Module#function_pass_manager
179
+ #
180
+ # @param [Module] mod Module this pass manager belongs to.
181
+ def initialize(mod)
182
+ # LLVM Initialization
183
+ @ptr = Bindings.create_function_pass_manager_for_module(mod)
184
+
185
+ # Set the target data if the module is associated with a execution engine.
186
+ self.target_data = mod.engine.target_data if mod.engine
187
+
188
+ Bindings.initialize_function_pass_manager(@ptr)
189
+
190
+ # RLTK Initialization
191
+ @enabled = Array.new
192
+ end
193
+
194
+ # Run the enabled passes on the given function inside the execution
195
+ # engine's module.
196
+ #
197
+ # @param [Function] fun Function to optimize.
198
+ #
199
+ # @return [void]
200
+ def run(fun)
201
+ Bindings.run_function_pass_manager(@ptr, fun).to_bool
202
+ end
203
+
204
+ protected
205
+ # Called by {#dispose} to finalize any operations of the function
206
+ # pass manager.
207
+ #
208
+ # @return [void]
209
+ def finalize
210
+ Bindings.finalize_function_pass_manager(@ptr).to_bool
211
+ end
212
+ end
213
+
214
+ PASS_GROUPS = [
215
+ :analysis,
216
+ :core,
217
+ :inst_combine,
218
+ :instrumentation,
219
+ :ipa,
220
+ :ipo,
221
+ :objc_arc_opts,
222
+ :scalar_opts,
223
+ :target,
224
+ :transform_utils,
225
+ :vectorization
226
+ ]
227
+
228
+ class PassRegistry
229
+ include BindingClass
230
+
231
+ def self.global
232
+ PassRegistry.allocate.tap { |pr| pr.ptr = Bindings.get_global_pass_registry }
233
+ end
234
+
235
+ def initialize
236
+ @ptr = Bindings::OpaquePassRegistry.new
237
+ end
238
+
239
+ def init(pass_group = :all)
240
+ if pass_group == :all
241
+ PASS_GROUPS.each { |pg| Bindings.send("initialize_#{pg}", @ptr) }
242
+
243
+ elsif PASS_GROUPS.include?(pass_group)
244
+ Bindings.send("initialize_#{pass_group}", @ptr)
245
+ end
246
+ end
247
+
248
+ def init(pass_group)
249
+
250
+ end
251
+ end
252
+ end
@@ -0,0 +1,29 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/03/15
4
+ # Description: This file defines the Support module.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Ruby Language Toolkit
11
+ require 'rltk/cg/bindings'
12
+
13
+ #######################
14
+ # Classes and Modules #
15
+ #######################
16
+
17
+ module RLTK::CG
18
+
19
+ # Support functionality for LLVM code generation.
20
+ module Support
21
+ # Load a shared library into memory and make its exported symbols
22
+ # available to execution engines.
23
+ #
24
+ # @param [String] lib Path to the shared library to load
25
+ def self.load_library(lib)
26
+ Bindings.load_library_permanently(lib).to_bool
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,230 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/06/13
4
+ # Description: This file defines the Target class.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Ruby Language Toolkit
11
+ require 'rltk/cg/bindings'
12
+ require 'rltk/cg/triple'
13
+
14
+ #######################
15
+ # Classes and Modules #
16
+ #######################
17
+
18
+ module RLTK::CG
19
+
20
+ # Class binding for the LLVM Triple class.
21
+ class Target
22
+ include BindingClass
23
+
24
+ #################
25
+ # Class Methods #
26
+ #################
27
+
28
+ # @return [Target] First target in the target list
29
+ def self.first
30
+ @first ||= self.new(Bindings.get_first_target)
31
+ end
32
+
33
+ # @return [Target] Target object for the host architecture.
34
+ def self.host
35
+ @host ||= self.new(Triple.host)
36
+ end
37
+
38
+ # @return [Target] Next target in the target list
39
+ def self.next_target(target)
40
+ self.new(Bindings.get_next_target(target))
41
+ end
42
+
43
+ ####################
44
+ # Instance Methods #
45
+ ####################
46
+
47
+ # Create an object representing a particular code generation target.
48
+ # You can create a target either from a string or a Triple.
49
+ #
50
+ # @param [Triple, String] overloaded Object describing the target.
51
+ def initialize(overloaded)
52
+ @ptr, @triple =
53
+ case overloaded
54
+ when String
55
+ [Bindings.get_target_from_name(overloaded), Triple.new(overloaded)]
56
+
57
+ when RLTK::CG::Triple
58
+ ptr = FFI::MemoryPointer.new(:pointer)
59
+ error = FFI::MemoryPointer.new(:pointer)
60
+ status = Bindings.get_target_from_triple(overloaded.to_s, ptr, error)
61
+
62
+ if status.zero?
63
+ [ptr, overloaded]
64
+
65
+ else
66
+ errorp = error.read_pointer
67
+ message = errorp.null? ? 'Unknown' : errorp.read_string
68
+
69
+ error.autorelease = false
70
+
71
+ Bindings.dispose_message(error)
72
+
73
+ raise "Error creating target: #{message}"
74
+ end
75
+
76
+ when RLTK::CG::Bindings::Triple
77
+ [overloaded, nil]
78
+ end
79
+ end
80
+
81
+ # @return [Boolean] Whether or not the target has an ASM backend
82
+ def asm_backend?
83
+ Bindings.target_has_asm_backend(@ptr).to_bool
84
+ end
85
+
86
+ # @return [Boolean] Whether or not the target has a JIT
87
+ def jit?
88
+ Bindings.target_has_jit(@ptr).to_bool
89
+ end
90
+
91
+ # @return [Boolean] Whether or not the target has a TargetMachine
92
+ def target_machine?
93
+ Bindings.target_has_target_machine(@ptr).to_bool
94
+ end
95
+
96
+ # @return [String] Description of the target
97
+ def describe
98
+ Bindings.get_target_description(@ptr)
99
+ end
100
+
101
+ # @return [Triple] Triple object for this target
102
+ def triple
103
+ @triple ||= Triple.new(Bindings.get_target_name(@ptr))
104
+ end
105
+ end
106
+
107
+ # This class represents data about a specific architecture. Currently it
108
+ # is for internal use only and should not be instantiated by users.
109
+ class TargetData
110
+ include BindingClass
111
+
112
+ # @param [FFI::Pointer] ptr
113
+ def initialize(ptr)
114
+ @ptr = ptr
115
+ end
116
+
117
+ # Gets the pointer size for this target machine and address space
118
+ # combination.
119
+ #
120
+ # @param [Integer] as Address space
121
+ #
122
+ # @return [Integer] Size of pointer
123
+ def pointer_size(as)
124
+ Bindings.pointer_size_for_as(@ptr, as)
125
+ end
126
+ end
127
+
128
+ # This class represents a specific architecture that wil be targeted by
129
+ # LLVM's compilation process.
130
+ class TargetMachine
131
+ include BindingClass
132
+
133
+ # The Proc object called by the garbage collector to free resources used by LLVM.
134
+ CLASS_FINALIZER = Proc.new { |id| Bindings.dispose_target_machine(ptr) if ptr = ObjectSpace._id2ref(id).ptr }
135
+
136
+ # @return [TargetMachine] TargetMachine representation of the host machine.
137
+ def self.host
138
+ @host ||= self.new(Target.host)
139
+ end
140
+
141
+ # Create a new object describing a target machine.
142
+ #
143
+ # @see Bindings._enum_reloc_model_
144
+ # @see Bindings._enum_code_model_
145
+ #
146
+ # @param [Target] target Target description
147
+ # @param [String] mcpu Specific CPU type to target
148
+ # @param [Array<String>, String] features Features present for this target machine
149
+ # @param [Symbol from _enum_code_gen_opt_level_] opt_level Optimization level
150
+ # @param [Symbol from _enum_reloc_mode_] reloc_mode Code relocation model
151
+ # @param [Symbol from _enum_code_model_] code_model Code generation model
152
+ def initialize(target, mcpu = '', features = '', opt_level = :none, reloc_mode = :default, code_model = :default)
153
+ # Convert the features parameter if necessary.
154
+ features = TargetMachine.build_feature_string(features) if features.is_a?(Array)
155
+
156
+ @ptr = Bindings.create_target_machine(target, target.triple.to_s, mcpu, features, opt_level, reloc_mode, code_model)
157
+
158
+ # Define a finalizer to free the memory used by LLVM for
159
+ # this target machine.
160
+ ObjectSpace.define_finalizer(self, CLASS_FINALIZER)
161
+ end
162
+
163
+ # @return [String] Name of the target machine's CPU
164
+ def cpu
165
+ Bindings.get_target_machine_cpu(@ptr)
166
+ end
167
+
168
+ # @return [TargetData]
169
+ def data
170
+ TargetData.new(Bindings.get_target_machine_data(@pt))
171
+ end
172
+
173
+ # Emit assembly or object code for the given module to the file
174
+ # specified.
175
+ #
176
+ # @param [Module] mod Module to emit code for
177
+ # @param [String] file_name File to emit code to
178
+ # @param [:assembly, :object] emit_type Type of code to emit
179
+ #
180
+ # @return [void]
181
+ #
182
+ # @raise LLVM error message if unable to emite code for module
183
+ def emit_module(mod, file_name, emit_type)
184
+ error = FFI::MemoryPointer.new(:pointer)
185
+ status = Bindings.target_machine_emit_to_file(@ptr, mod, file_name, emit_type, error)
186
+
187
+ if not status.zero?
188
+ errorp = error.read_pointer
189
+ message = errorp.null? ? 'Unknown' : errorp.read_string
190
+
191
+ error.autorelease = false
192
+
193
+ Bindings.dispose_message(error)
194
+
195
+ raise "Error emiting code for module: #{message}"
196
+ end
197
+ end
198
+
199
+ # @return [String] Feature string for this target machine
200
+ def feature_string
201
+ Bindings.get_target_machine_feature_string(@ptr)
202
+ end
203
+
204
+ # @return [Target]
205
+ def target
206
+ Target.new(Bindings.get_target_machine_target(@ptr))
207
+ end
208
+
209
+ # @return [Triple]
210
+ def triple
211
+ Triple.new(Bindings.get_target_machine_triple(@ptr))
212
+ end
213
+
214
+ # Set verbose ASM property.
215
+ #
216
+ # @param [Boolean] bool Verbose ASM or not
217
+ #
218
+ # @return [void]
219
+ def verbose_asm=(bool)
220
+ @verbose_asm = bool
221
+
222
+ Bindings.set_target_machine_asm_verbosity(@ptr, bool.to_i)
223
+ end
224
+
225
+ # @return [Boolean] If this target machine should print verbose ASM
226
+ def verbose_asm?
227
+ @verbose_asm ||= false
228
+ end
229
+ end
230
+ end
@@ -0,0 +1,58 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/06/13
4
+ # Description: This file defines the Triple class.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Ruby Language Toolkit
11
+ require 'rltk/cg/bindings'
12
+
13
+ #######################
14
+ # Classes and Modules #
15
+ #######################
16
+
17
+ module RLTK::CG
18
+
19
+ # Class binding for the LLVM Triple class.
20
+ class Triple
21
+ include BindingClass
22
+
23
+ #################
24
+ # Class Methods #
25
+ #################
26
+
27
+ # @return [Triple] Object representing the host architecture, vendor, OS, and environment.
28
+ def self.host
29
+ @host ||= Triple.new(host_string)
30
+ end
31
+
32
+ # @return [String] String representation of the host architecture, vendor, OS, and environment.
33
+ def self.host_string
34
+ @host_string ||= Bindings.get_default_target_triple
35
+ end
36
+
37
+ ####################
38
+ # Instance Methods #
39
+ ####################
40
+
41
+ # Create a new triple describing the host architecture, vendor, OS,
42
+ # and (optionally) environment.
43
+ #
44
+ # @param [FFI::Pointer, String] overloaded
45
+ def initialize(overloaded)
46
+ @ptr, @str =
47
+ case overloaded
48
+ when FFI::Pointer then [overloaded, nil]
49
+ when String then [Bindings.triple_create(overloaded), overloaded]
50
+ end
51
+ end
52
+
53
+ # @return [String] String representation of this triple.
54
+ def to_s
55
+ @str ||= Bindings.get_triple_string(@ptr)
56
+ end
57
+ end
58
+ end