Skip to content

Instantly share code, notes, and snippets.

@ishikawa
Created May 29, 2014 23:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ishikawa/5d43dae2d42ad86b700b to your computer and use it in GitHub Desktop.
Save ishikawa/5d43dae2d42ad86b700b to your computer and use it in GitHub Desktop.
ruby-llvm factorial example using MCJIT
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