rltk 2.2.1 → 3.0.0

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