Created
May 29, 2014 23:25
-
-
Save ishikawa/5d43dae2d42ad86b700b to your computer and use it in GitHub Desktop.
ruby-llvm factorial example using MCJIT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'ffi' | |
require 'llvm/core' | |
require 'llvm/execution_engine' | |
require 'llvm/target' | |
# Start the "engine" before driving | |
# call InitializeNativeTargetAsmPrinter and InitializeNativeTargetAsmParser | |
LLVM::Target.init_native(true) | |
LLVM::C.link_in_mcjit | |
# modules hold functions and variables | |
mod = LLVM::Module.new('Factorial.mcjit') | |
fun = | |
mod.functions.add("fac", [LLVM::Int], LLVM::Int) do |fac, n| | |
n.name = "n" | |
entry = fac.basic_blocks.append("entry") | |
recur = fac.basic_blocks.append("recur") | |
result = fac.basic_blocks.append("result") | |
n_fac_n_1 = nil # predeclare within function's scope | |
entry.build do |b| | |
test = b.icmp(:eq, n, LLVM::Int(1), "test") | |
b.cond(test, result, recur) | |
end | |
recur.build do |b| | |
n_1 = b.sub(n, LLVM::Int(1), "n-1") | |
fac_n_1 = b.call(fac, n_1, "fac(n-1)") | |
n_fac_n_1 = b.mul(n, fac_n_1, "n*fac(n-1)") | |
b.br(result) | |
end | |
result.build do |b| | |
fac = b.phi(LLVM::Int, | |
{ entry => LLVM::Int(1), | |
recur => n_fac_n_1 }, | |
"fac") | |
b.ret(fac) | |
end | |
end | |
mod.verify | |
mod.dump | |
# MCJIT | |
execution_engine = | |
FFI::MemoryPointer.new(:pointer) do |ptr| | |
error = FFI::MemoryPointer.new(:pointer) | |
status = LLVM::C.create_mcjit_compiler_for_module(ptr, mod, nil, 0, error) | |
unless status.zero? | |
errorp = error.read_pointer | |
message = errorp.read_string unless errorp.null? | |
LLVM::C.dispose_message(error) | |
error.autorelease=false | |
raise RuntimeError, "Error creating JIT compiler: #{message}" | |
end | |
end | |
execution_engine = execution_engine.read_pointer | |
# Run function | |
fac_n = ARGV[0] || 15 | |
LLVM::C.get_pointer_to_global(execution_engine, fun).tap do |ptr| | |
fn = FFI::Function.new(:int, [:int], ptr) | |
fac = fn.call(fac_n) | |
puts "fac(#{fac_n}) = #{fac}" | |
end | |
LLVM::C.dispose_execution_engine(execution_engine) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment