ruby-llvm 3.4.1 → 3.4.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.
- checksums.yaml +4 -4
- data/ext/ruby-llvm-support/Rakefile +7 -4
- data/ext/ruby-llvm-support/support.cpp +0 -8
- data/lib/llvm/execution_engine.rb +163 -4
- data/lib/llvm/support.rb +5 -5
- data/lib/llvm/support_ffi.rb +23 -0
- data/lib/llvm/target.rb +2 -2
- data/lib/llvm/version.rb +1 -1
- data/test/mcjit_test.rb +87 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4c3ca01e2020b5ce26bdf7db68f78f33d4fefbe
|
4
|
+
data.tar.gz: 4580027aed01abdc1c9055dfd4d3736f1fae4606
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b111187af62e59fd09acd472f241f0e64913832f956f99cf2fb3faf16806f7b61957840f4fe0246181a41521c9180d0b18420356915077635fa5a9690853b81e
|
7
|
+
data.tar.gz: 108a673c529d5b7621c7206f169b8704473cc518fafed2e10880f2f96fbe58537e8b2f47cab56b5ac0dabf3c2ef7affa9a0166c0e2cf1511a1ba98b5f6ed824e
|
@@ -32,8 +32,11 @@ def find_llvm_config
|
|
32
32
|
|
33
33
|
begin
|
34
34
|
actual_version = `#{llvm_config} --version`.strip
|
35
|
+
actual_maj, actual_min, _ = actual_version.split('.')
|
35
36
|
|
36
|
-
|
37
|
+
required_maj, required_min = LLVM_VERSION.split('.')
|
38
|
+
|
39
|
+
actual_maj == required_maj && actual_min == required_min
|
37
40
|
rescue Errno::ENOENT
|
38
41
|
false
|
39
42
|
end
|
@@ -41,8 +44,8 @@ def find_llvm_config
|
|
41
44
|
end
|
42
45
|
|
43
46
|
def find_cxx
|
44
|
-
check_for('C++ compiler', %W(
|
45
|
-
system(cxx, "--version")
|
47
|
+
check_for('C++ compiler', %W(g++ clang++), 'CXX') do |cxx|
|
48
|
+
system(cxx, "--version", out: File::NULL, err: File::NULL)
|
46
49
|
$?.success?
|
47
50
|
end
|
48
51
|
end
|
@@ -63,7 +66,7 @@ desc "Build the shared library and config module"
|
|
63
66
|
task :default => [SUPPORT_LIB, CONFIG_MOD]
|
64
67
|
|
65
68
|
file SUPPORT_LIB => %w(support.cpp) do |task|
|
66
|
-
sh "#{CXX} -shared
|
69
|
+
sh "#{CXX} -shared #{task.prerequisites.join(' ')} -lLLVM-#{LLVM_VERSION} " \
|
67
70
|
"#{invoke_llvm_config('--cxxflags --ldflags')} -o #{SUPPORT_LIB}"
|
68
71
|
end
|
69
72
|
|
@@ -3,20 +3,12 @@
|
|
3
3
|
*/
|
4
4
|
|
5
5
|
#include <llvm-c/Core.h>
|
6
|
-
#include <llvm/IR/Type.h>
|
7
|
-
#include <llvm/IR/Module.h>
|
8
6
|
#include <llvm/IR/GlobalValue.h>
|
9
|
-
#include <llvm/Support/DynamicLibrary.h>
|
10
7
|
#include <llvm/Support/TargetSelect.h>
|
11
|
-
#include <llvm/Support/raw_ostream.h>
|
12
8
|
|
13
9
|
extern "C" {
|
14
10
|
using namespace llvm;
|
15
11
|
|
16
|
-
int LLVMLoadLibraryPermanently(const char* filename) {
|
17
|
-
return llvm::sys::DynamicLibrary::LoadLibraryPermanently(filename);
|
18
|
-
}
|
19
|
-
|
20
12
|
LLVMBool LLVMHasUnnamedAddr(LLVMValueRef global) {
|
21
13
|
return unwrap<GlobalValue>(global)->hasUnnamedAddr();
|
22
14
|
}
|
@@ -5,12 +5,19 @@ require 'llvm/analysis'
|
|
5
5
|
require 'llvm/execution_engine_ffi'
|
6
6
|
|
7
7
|
module LLVM
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
# @abstract Subclass and override {#create_execution_engine_for_module}.
|
9
|
+
class ExecutionEngine
|
10
|
+
# Create a JIT execution engine for module with the given options.
|
11
|
+
#
|
12
|
+
# @note Important: Call #dispose to free backend memory after use. Do not call #dispose on mod any more.
|
13
|
+
#
|
14
|
+
# @param [LLVM::Module] mod module
|
15
|
+
# @param [Hash{Symbol => Object}] options options
|
16
|
+
# @return [ExecutionEngine] JIT execution engine
|
17
|
+
def initialize(mod, options)
|
11
18
|
FFI::MemoryPointer.new(FFI.type_size(:pointer)) do |ptr|
|
12
19
|
error = FFI::MemoryPointer.new(FFI.type_size(:pointer))
|
13
|
-
status =
|
20
|
+
status = create_execution_engine_for_module(ptr, mod, error, options)
|
14
21
|
errorp = error.read_pointer
|
15
22
|
message = errorp.read_string unless errorp.null?
|
16
23
|
|
@@ -69,6 +76,158 @@ module LLVM
|
|
69
76
|
def pointer_to_global(global)
|
70
77
|
C.get_pointer_to_global(self, global)
|
71
78
|
end
|
79
|
+
|
80
|
+
# Returns a ModuleCollection of all the Modules in the engine.
|
81
|
+
# @return [ModuleCollection]
|
82
|
+
def modules
|
83
|
+
@modules ||= ModuleCollection.new(self)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns a FunctionCollection of all the Functions in the engine.
|
87
|
+
# @return [FunctionCollection]
|
88
|
+
def functions
|
89
|
+
@functions ||= FunctionCollection.new(self)
|
90
|
+
end
|
91
|
+
|
92
|
+
class ModuleCollection
|
93
|
+
# @param [ExecutionEngine] engine
|
94
|
+
def initialize(engine)
|
95
|
+
@engine = engine
|
96
|
+
end
|
97
|
+
|
98
|
+
# @param [LLVM::Module] mod
|
99
|
+
# @return [ModuleCollection]
|
100
|
+
def add(mod)
|
101
|
+
tap { C.add_module(@engine, mod) }
|
102
|
+
end
|
103
|
+
|
104
|
+
# @param [LLVM::Module] mod
|
105
|
+
# @return [LLVM::Module] deleted module
|
106
|
+
def delete(mod)
|
107
|
+
error = FFI::MemoryPointer.new(:pointer)
|
108
|
+
out_mod = FFI::MemoryPointer.new(:pointer)
|
109
|
+
|
110
|
+
status = C.remove_module(@engine, mod, out_mod, error)
|
111
|
+
|
112
|
+
if status.zero?
|
113
|
+
LLVM::Module.from_ptr(out_mod.read_pointer)
|
114
|
+
else
|
115
|
+
errorp = error.read_pointer
|
116
|
+
message = errorp.read_string unless errorp.null?
|
117
|
+
|
118
|
+
C.dispose_message(error)
|
119
|
+
error.autorelease=false
|
120
|
+
|
121
|
+
raise "Error removing module: #{message}"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
alias_method :<<, :add
|
126
|
+
end
|
127
|
+
|
128
|
+
class FunctionCollection
|
129
|
+
# @param [ExecutionEngine] engine
|
130
|
+
def initialize(engine)
|
131
|
+
@engine = engine
|
132
|
+
end
|
133
|
+
|
134
|
+
# @param [String, Symbol] name function name
|
135
|
+
# @return [Function]
|
136
|
+
def named(name)
|
137
|
+
out_fun = FFI::MemoryPointer.new(:pointer)
|
138
|
+
|
139
|
+
status = C.find_function(@engine, name.to_s, out_fun)
|
140
|
+
return unless status.zero?
|
141
|
+
|
142
|
+
Function.from_ptr(out_fun.read_pointer)
|
143
|
+
end
|
144
|
+
|
145
|
+
alias_method :[], :named
|
146
|
+
end
|
147
|
+
|
148
|
+
protected
|
149
|
+
|
150
|
+
# Create a JIT execution engine for module with the given options.
|
151
|
+
#
|
152
|
+
# @param [FFI::Pointer(*ExecutionEngineRef)] out_ee execution engine
|
153
|
+
# @param [LLVM::Module] mod module
|
154
|
+
# @param [FFI::Pointer(**CharS)] out_error error message
|
155
|
+
# @param [Hash{Symbol => Object}] options options. `:opt_level => 3` for example.
|
156
|
+
# @return [Integer] 0 for success, non- zero to indicate an error
|
157
|
+
def create_execution_engine_for_module(out_ee, mod, out_error, options)
|
158
|
+
raise NotImplementedError, "override in subclass"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
class JITCompiler < ExecutionEngine
|
163
|
+
# Create a JIT execution engine.
|
164
|
+
#
|
165
|
+
# @note You should call `LLVM.init_jit` before creating an execution engine.
|
166
|
+
#
|
167
|
+
# @param [LLVM::Module] mod module
|
168
|
+
# @param [Hash{Symbol => Object}] options options
|
169
|
+
# @option options [Integer] :opt_level (3) Optimization level
|
170
|
+
# @return [ExecutionEngine] Execution engine
|
171
|
+
def initialize(mod, options = {})
|
172
|
+
# Prior to ruby-llvm 3.4.0, signature is initialize(mod, opt_level = 3)
|
173
|
+
if options.kind_of?(Integer)
|
174
|
+
options = { :opt_level => options }
|
175
|
+
end
|
176
|
+
|
177
|
+
options = {
|
178
|
+
:opt_level => 3,
|
179
|
+
}.merge(options)
|
180
|
+
|
181
|
+
super
|
182
|
+
end
|
183
|
+
|
184
|
+
protected
|
185
|
+
|
186
|
+
def create_execution_engine_for_module(out_ee, mod, out_error, options)
|
187
|
+
C.create_jit_compiler_for_module(out_ee, mod, options[:opt_level], out_error)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
class MCJITCompiler < ExecutionEngine
|
192
|
+
# Create a MCJIT execution engine.
|
193
|
+
#
|
194
|
+
# @note You should call `LLVM.init_jit(true)` before creating an execution engine.
|
195
|
+
# @todo Add :mcjmm option (MCJIT memory manager)
|
196
|
+
#
|
197
|
+
# @param [LLVM::Module] mod module
|
198
|
+
# @param [Hash{Symbol => Object}] options options
|
199
|
+
# @option options [Integer] :opt_level (2) Optimization level
|
200
|
+
# @option options [Integer] :code_model (0) Code model types
|
201
|
+
# @option options [Boolean] :no_frame_pointer_elim (false) Disable frame pointer elimination optimization
|
202
|
+
# @option options [Boolean] :enable_fast_i_sel (false) Enables fast-path instruction selection
|
203
|
+
# @return [ExecutionEngine] Execution engine
|
204
|
+
def initialize(mod, options = {})
|
205
|
+
options = {
|
206
|
+
:opt_level => 2, # LLVMCodeGenLevelDefault
|
207
|
+
:code_model => 0, # LLVMCodeModelDefault
|
208
|
+
:no_frame_pointer_elim => false,
|
209
|
+
:enable_fast_i_sel => false,
|
210
|
+
# TODO
|
211
|
+
#:mcjmm => nil,
|
212
|
+
}.merge(options)
|
213
|
+
|
214
|
+
super
|
215
|
+
end
|
216
|
+
|
217
|
+
protected
|
218
|
+
|
219
|
+
def create_execution_engine_for_module(out_ee, mod, out_error, options)
|
220
|
+
mcopts = LLVM::C::MCJITCompilerOptions.new
|
221
|
+
|
222
|
+
LLVM::C.initialize_mcjit_compiler_options(mcopts, mcopts.size)
|
223
|
+
|
224
|
+
mcopts[:opt_level] = options[:opt_level]
|
225
|
+
mcopts[:code_model] = options[:code_model]
|
226
|
+
mcopts[:no_frame_pointer_elim] = options[:no_frame_pointer_elim] ? 1 : 0
|
227
|
+
mcopts[:enable_fast_i_sel] = options[:enable_fast_i_sel] ? 1 : 0
|
228
|
+
|
229
|
+
C.create_mcjit_compiler_for_module(out_ee, mod, mcopts, mcopts.size, out_error)
|
230
|
+
end
|
72
231
|
end
|
73
232
|
|
74
233
|
class GenericValue
|
data/lib/llvm/support.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'llvm/core_ffi'
|
2
|
+
require 'llvm/support_ffi'
|
2
3
|
|
3
4
|
module LLVM
|
4
5
|
|
@@ -16,7 +17,6 @@ module LLVM
|
|
16
17
|
lib_path = File.expand_path("../../ext/ruby-llvm-support/#{lib_name}", File.dirname(__FILE__))
|
17
18
|
ffi_lib [lib_path]
|
18
19
|
|
19
|
-
attach_function :load_library_permanently, :LLVMLoadLibraryPermanently, [:string], :int
|
20
20
|
attach_function :has_unnamed_addr, :LLVMHasUnnamedAddr, [OpaqueValue], :int
|
21
21
|
attach_function :set_unnamed_addr, :LLVMSetUnnamedAddr, [OpaqueValue, :int], :void
|
22
22
|
|
@@ -36,11 +36,11 @@ module LLVM
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
def load_library(libname)
|
40
|
-
|
39
|
+
def self.load_library(libname)
|
40
|
+
if C.load_library_permanently(libname) != 0
|
41
|
+
raise "LLVM::Support.load_library failed"
|
42
|
+
end
|
41
43
|
|
42
44
|
nil
|
43
45
|
end
|
44
|
-
|
45
|
-
module_function :load_library
|
46
46
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Generated by ffi_gen. Please do not change this file by hand.
|
2
|
+
|
3
|
+
require 'ffi'
|
4
|
+
|
5
|
+
module LLVM::C
|
6
|
+
extend FFI::Library
|
7
|
+
ffi_lib 'LLVM-3.4'
|
8
|
+
|
9
|
+
def self.attach_function(name, *_)
|
10
|
+
begin; super; rescue FFI::NotFoundError => e
|
11
|
+
(class << self; self; end).class_eval { define_method(name) { |*_| raise e } }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# (Not documented)
|
16
|
+
#
|
17
|
+
# @method load_library_permanently(filename)
|
18
|
+
# @param [String] filename
|
19
|
+
# @return [Integer]
|
20
|
+
# @scope class
|
21
|
+
attach_function :load_library_permanently, :LLVMLoadLibraryPermanently, [:string], :int
|
22
|
+
|
23
|
+
end
|
data/lib/llvm/target.rb
CHANGED
@@ -4,8 +4,8 @@ require 'llvm/target_ffi'
|
|
4
4
|
|
5
5
|
module LLVM
|
6
6
|
# A shorthand for {LLVM::Target.init_native}
|
7
|
-
def self.init_jit
|
8
|
-
LLVM::Target.init_native
|
7
|
+
def self.init_jit(*args)
|
8
|
+
LLVM::Target.init_native(*args)
|
9
9
|
end
|
10
10
|
|
11
11
|
# @deprecated Use LLVM.init_jit or LLVM::Target.init('X86').
|
data/lib/llvm/version.rb
CHANGED
data/test/mcjit_test.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class MCJITTestCase < Minitest::Test
|
4
|
+
def setup
|
5
|
+
LLVM.init_jit(true)
|
6
|
+
end
|
7
|
+
|
8
|
+
def create_square_function_module
|
9
|
+
LLVM::Module.new('square').tap do |mod|
|
10
|
+
mod.functions.add(:square, [LLVM::Int], LLVM::Int) do |fun, x|
|
11
|
+
fun.basic_blocks.append.build do |builder|
|
12
|
+
n = builder.mul(x, x)
|
13
|
+
builder.ret(n)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
mod.verify!
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_simple_function
|
22
|
+
mod = create_square_function_module
|
23
|
+
|
24
|
+
engine = LLVM::MCJITCompiler.new(mod, :opt_level => 0)
|
25
|
+
|
26
|
+
result = engine.run_function(mod.functions['square'], 5)
|
27
|
+
assert_equal 25, result.to_i
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_functions_named
|
31
|
+
mod = LLVM::Module.new('foo').tap do |mod|
|
32
|
+
mod.functions.add(:foo, [], LLVM::Int)
|
33
|
+
mod.verify!
|
34
|
+
end
|
35
|
+
|
36
|
+
engine = LLVM::MCJITCompiler.new(mod, :opt_level => 0)
|
37
|
+
|
38
|
+
['foo', :foo].each do |name|
|
39
|
+
engine.functions[name].tap do |fun|
|
40
|
+
assert fun, "function named #{name.inspect}"
|
41
|
+
assert_equal 'foo', fun.name
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_add_module
|
47
|
+
main_mod = LLVM::Module.new('main')
|
48
|
+
|
49
|
+
main_mod.functions.add(:square, [LLVM::Int], LLVM::Int) do |square|
|
50
|
+
main_mod.functions.add(:call_square, [], LLVM::Int) do |call_square|
|
51
|
+
call_square.basic_blocks.append.build do |builder|
|
52
|
+
n = builder.call(square, LLVM::Int(5))
|
53
|
+
builder.ret(n)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
main_mod.verify!
|
59
|
+
|
60
|
+
engine = LLVM::MCJITCompiler.new(main_mod, :opt_level => 0)
|
61
|
+
engine.modules << create_square_function_module
|
62
|
+
|
63
|
+
result = engine.run_function(main_mod.functions['call_square'])
|
64
|
+
assert_equal 25, result.to_i
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_remove_module
|
68
|
+
mod1 = LLVM::Module.new('foo')
|
69
|
+
mod2 = LLVM::Module.new('bar')
|
70
|
+
|
71
|
+
foo = mod1.functions.add(:foo, [], LLVM::Int)
|
72
|
+
bar = mod2.functions.add(:bar, [], LLVM::Int)
|
73
|
+
|
74
|
+
engine = LLVM::MCJITCompiler.new(mod1, :opt_level => 0)
|
75
|
+
|
76
|
+
(engine.modules << mod2).tap do |ret|
|
77
|
+
assert_equal engine.modules, ret, '#<< returns self'
|
78
|
+
end
|
79
|
+
|
80
|
+
assert engine.functions[:bar]
|
81
|
+
engine.modules.delete(mod2).tap do |ret|
|
82
|
+
assert_instance_of LLVM::Module, ret, '#delete returns module'
|
83
|
+
assert_equal mod2, ret
|
84
|
+
end
|
85
|
+
assert_nil engine.functions[:bar]
|
86
|
+
end
|
87
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-llvm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.4.
|
4
|
+
version: 3.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Voorhis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -127,6 +127,7 @@ files:
|
|
127
127
|
- lib/llvm/linker.rb
|
128
128
|
- lib/llvm/linker_ffi.rb
|
129
129
|
- lib/llvm/support.rb
|
130
|
+
- lib/llvm/support_ffi.rb
|
130
131
|
- lib/llvm/target.rb
|
131
132
|
- lib/llvm/target_ffi.rb
|
132
133
|
- lib/llvm/transforms/builder.rb
|
@@ -153,6 +154,7 @@ files:
|
|
153
154
|
- test/instruction_test.rb
|
154
155
|
- test/ipo_test.rb
|
155
156
|
- test/linker_test.rb
|
157
|
+
- test/mcjit_test.rb
|
156
158
|
- test/memory_access_test.rb
|
157
159
|
- test/module_test.rb
|
158
160
|
- test/parameter_collection_test.rb
|
@@ -183,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
185
|
version: '0'
|
184
186
|
requirements: []
|
185
187
|
rubyforge_project:
|
186
|
-
rubygems_version: 2.
|
188
|
+
rubygems_version: 2.4.1
|
187
189
|
signing_key:
|
188
190
|
specification_version: 4
|
189
191
|
summary: LLVM bindings for Ruby
|
@@ -209,6 +211,7 @@ test_files:
|
|
209
211
|
- test/struct_test.rb
|
210
212
|
- test/parameter_collection_test.rb
|
211
213
|
- test/call_test.rb
|
214
|
+
- test/mcjit_test.rb
|
212
215
|
- test/vector_test.rb
|
213
216
|
- test/target_test.rb
|
214
217
|
- test/array_test.rb
|