rltk 2.2.1 → 3.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.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +12 -12
  3. data/README.md +458 -285
  4. data/Rakefile +99 -92
  5. data/lib/rltk/ast.rb +221 -126
  6. data/lib/rltk/cfg.rb +218 -239
  7. data/lib/rltk/cg/basic_block.rb +1 -1
  8. data/lib/rltk/cg/bindings.rb +9 -26
  9. data/lib/rltk/cg/builder.rb +40 -8
  10. data/lib/rltk/cg/context.rb +1 -1
  11. data/lib/rltk/cg/contractor.rb +51 -0
  12. data/lib/rltk/cg/execution_engine.rb +45 -8
  13. data/lib/rltk/cg/function.rb +12 -2
  14. data/lib/rltk/cg/generated_bindings.rb +2541 -575
  15. data/lib/rltk/cg/generic_value.rb +2 -2
  16. data/lib/rltk/cg/instruction.rb +104 -83
  17. data/lib/rltk/cg/llvm.rb +44 -3
  18. data/lib/rltk/cg/memory_buffer.rb +22 -5
  19. data/lib/rltk/cg/module.rb +85 -36
  20. data/lib/rltk/cg/old_generated_bindings.rb +6152 -0
  21. data/lib/rltk/cg/pass_manager.rb +87 -43
  22. data/lib/rltk/cg/support.rb +2 -4
  23. data/lib/rltk/cg/target.rb +158 -28
  24. data/lib/rltk/cg/triple.rb +8 -8
  25. data/lib/rltk/cg/type.rb +69 -25
  26. data/lib/rltk/cg/value.rb +107 -66
  27. data/lib/rltk/cg.rb +16 -17
  28. data/lib/rltk/lexer.rb +21 -11
  29. data/lib/rltk/lexers/calculator.rb +1 -1
  30. data/lib/rltk/lexers/ebnf.rb +8 -7
  31. data/lib/rltk/parser.rb +300 -247
  32. data/lib/rltk/parsers/infix_calc.rb +1 -1
  33. data/lib/rltk/parsers/postfix_calc.rb +2 -2
  34. data/lib/rltk/parsers/prefix_calc.rb +2 -2
  35. data/lib/rltk/token.rb +1 -2
  36. data/lib/rltk/version.rb +3 -3
  37. data/lib/rltk.rb +6 -6
  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 +105 -8
  51. data/test/tc_cfg.rb +63 -48
  52. data/test/tc_lexer.rb +84 -96
  53. data/test/tc_parser.rb +224 -52
  54. data/test/tc_token.rb +6 -6
  55. data/test/ts_rltk.rb +12 -15
  56. metadata +149 -75
  57. data/lib/rltk/cg/generated_extended_bindings.rb +0 -287
  58. data/lib/rltk/util/abstract_class.rb +0 -25
  59. data/lib/rltk/util/monkeys.rb +0 -129
@@ -15,7 +15,7 @@ require 'rltk/cg/context'
15
15
  # Classes and Modules #
16
16
  #######################
17
17
 
18
- module RLTK::CG # :nodoc:
18
+ module RLTK::CG
19
19
 
20
20
  # This class represents a collection of functions, constants, and global
21
21
  # variables.
@@ -31,33 +31,49 @@ module RLTK::CG # :nodoc:
31
31
 
32
32
  # Load a module from LLVM bitcode.
33
33
  #
34
- # @see MemoryBuffer#initialize
35
- #
36
- # @param [MemoryBuffer, FFI::Pointer, String, nil] overloaded Where to read the bitecode from.
34
+ # @param [MemoryBuffer, String] overloaded Where to read the bitecode from
35
+ # @param [Context, nil] context Context in which to parse bitcode
37
36
  #
38
37
  # @return [Module]
39
- def self.read_bitcode(overloaded)
40
- buffer = if overloaded.is_a?(MemoryBuffer) then overloaded else MemoryBuffer.new(overloaded) end
38
+ def self.read_bitcode(overloaded, context = nil)
39
+ buffer = overloaded.is_a?(MemoryBuffer) ? overloaded : MemoryBuffer.new(overloaded)
41
40
 
42
41
  mod_ptr = FFI::MemoryPointer.new(:pointer)
43
42
  msg_ptr = FFI::MemoryPointer.new(:pointer)
44
43
 
45
- status = Bindings.parse_bitcode(buffer, mod_ptr, msg_ptr)
46
-
47
- if status != 0
48
- raise msg_ptr.get_pointer(0).get_string(0)
44
+ status =
45
+ if context
46
+ Bindings.parse_bitcode_in_context(context, buffer, mod_ptr, msg_ptr)
49
47
  else
48
+ Bindings.parse_bitcode(buffer, mod_ptr, msg_ptr)
49
+ end
50
+
51
+ if status.zero?
50
52
  Module.new(mod_ptr.get_pointer(0))
53
+ else
54
+ raise msg_ptr.get_pointer(0).get_string(0)
51
55
  end
52
56
  end
53
57
 
54
- # Load a Module form an LLVM IR file.
58
+ # Load a Module form an LLVM IR.
55
59
  #
56
- # @param [String] file_name Name of file containing LLVM IR module.
60
+ # @param [MemoryBuffer, String] overloaded Where to read the IR from
61
+ # @param [Context] context Context in which to parse IR
57
62
  #
58
63
  # @return [Module]
59
- def self.read_ir_file(file_name, context = Context.global)
60
- self.new(Bindings.load_module_from_ir_file(file_name, context))
64
+ def self.read_ir(overloaded, context = Context.global)
65
+ buffer = overloaded.is_a?(MemoryBuffer) ? overloaded : MemoryBuffer.new(overloaded)
66
+
67
+ mod_ptr = FFI::MemoryPointer.new(:pointer)
68
+ msg_ptr = FFI::MemoryPointer.new(:pointer)
69
+
70
+ status = Bindings.parse_ir_in_context(context, buffer, mod_ptr, msg_ptr)
71
+
72
+ if status.zero?
73
+ Module.new(mod_ptr.get_pointer(0))
74
+ else
75
+ raise msg_ptr.get_pointer(0).get_string(0)
76
+ end
61
77
  end
62
78
 
63
79
  # Create a new LLVM module.
@@ -77,6 +93,9 @@ module RLTK::CG # :nodoc:
77
93
  else
78
94
  Bindings.module_create_with_name(overloaded)
79
95
  end
96
+
97
+ else
98
+ raise 'Argument `overloaded` must be a FFI::Pointer of String.'
80
99
  end
81
100
 
82
101
  # Define a finalizer to free the memory used by LLVM for this
@@ -88,15 +107,15 @@ module RLTK::CG # :nodoc:
88
107
 
89
108
  # Compile this module to an assembly or object file.
90
109
  #
91
- # @param [String] file_name Name of output file.
92
- # @param [:asm, :object] mode Generate assembly or object file?
93
- # @param [TargetMachine] machine Machine type to target.
94
- # @param [0, 1, 2, 3] opt_level Optimization level to use during compilation.
95
- # @param [Boolean] verify Verify the module before compilation or not.
110
+ # @param [String] file_name File to emit code to
111
+ # @param [:assembly, :object] emit_type Type of code to emit
112
+ # @param [TargetMachine] machine TargetMachine used to generate code
96
113
  #
97
114
  # @return [void]
98
- def compile(file_name, mode = :object, machine = TargetMachine.host, opt_level = 2, verify = true)
99
- Bindings.compile_module_to_file(@ptr, machine, self.pm, file_name, mode, opt_level, (!verify).to_i)
115
+ #
116
+ # @raise LLVM error message if unable to emit code for module
117
+ def compile(file_name, emit_type = :object, machine = TargetMachine.host)
118
+ machine.emite_module(self, file_name, emit_type)
100
119
  end
101
120
 
102
121
  # @return [Context] Context in which this module exists.
@@ -121,29 +140,52 @@ module RLTK::CG # :nodoc:
121
140
  end
122
141
  alias :fpm :function_pass_manager
123
142
 
143
+ # Link another module into this one, taking ownership of it. You may
144
+ # not access the other module again once linking it.
145
+ #
146
+ # @param [Module] other Module to be linked
147
+ #
148
+ # @raise Errors encountered during linking
149
+ def link(other)
150
+ error = FFI::MemoryPointer.new(:pointer)
151
+ status = Bindings.link_modules(@ptr, other, :linker_destroy_source, error)
152
+
153
+ if not status.zero?
154
+ errorp = error.read_pointer
155
+ message = errorp.null? ? 'Unknown' : errorp.read_string
156
+
157
+ error.autorelease = false
158
+
159
+ Bindings.dispose_message(error)
160
+
161
+ raise "Error linking modules: #{message}"
162
+ end
163
+ end
164
+
124
165
  # @return [PassManager] Pass manager for this module.
125
166
  def pass_manager
126
167
  @pass_manager ||= PassManager.new(self)
127
168
  end
128
169
  alias :pm :pass_manager
129
170
 
130
- # Print the LLVM IR representation of this module to a file. The
131
- # file may be specified via a file name (which will be created or
132
- # truncated) or an object that responds to #fileno.
171
+ # Print the LLVM IR representation of this module to a file.
133
172
  #
134
- # @LLVMECB
135
- #
136
- # @param [String, #fileno] io File name or object with a file descriptor to print to.
173
+ # @param [String] file_name Name of file to print to
137
174
  #
138
175
  # @return [void]
139
- def print(io = $stdout)
140
- case io
141
- when String
142
- File.open(io, 'w') do |f|
143
- Bindings.print_module(@ptr, f.fileno)
144
- end
145
- else
146
- Bindings.print_module(@ptr, io.fileno)
176
+ def print(file_name)
177
+ error = FFI::MemoryPointer.new(:pointer)
178
+ status = Bindings.print_module_to_file(@ptr, file_name, error)
179
+
180
+ if not status.zero?
181
+ errorp = error.read_pointer
182
+ message = errorp.null? ? 'Unknown' : errorp.read_string
183
+
184
+ error.autorelease = false
185
+
186
+ Bindings.dispose_message(error)
187
+
188
+ raise "Error printing module: #{message}"
147
189
  end
148
190
  end
149
191
 
@@ -174,6 +216,13 @@ module RLTK::CG # :nodoc:
174
216
  Bindings.get_target(@ptr)
175
217
  end
176
218
 
219
+ # Return a LLVM IR representation of this file as a string.
220
+ #
221
+ # @return [String]
222
+ def to_s
223
+ Bindings.print_module_to_string(@ptr)
224
+ end
225
+
177
226
  # Write the module as LLVM bitcode to a file.
178
227
  #
179
228
  # @param [#path, #fileno, Integer, String] overloaded Where to write the bitcode.
@@ -214,7 +263,7 @@ module RLTK::CG # :nodoc:
214
263
  str_ptr = FFI::MemoryPointer.new(:pointer)
215
264
  status = Bindings.verify_module(@ptr, action, str_ptr)
216
265
 
217
- returning(status == 1 ? str_ptr.read_string : nil) { Bindings.dispose_message(str_ptr.read_pointer) }
266
+ status == 1 ? str_ptr.read_string : nil
218
267
  end
219
268
  private :do_verification
220
269