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