diff --git a/lib/llvm/core.rb b/lib/llvm/core.rb index 5056d308..426aacd2 100644 --- a/lib/llvm/core.rb +++ b/lib/llvm/core.rb @@ -134,6 +134,20 @@ module C # @return [Bool] # @scope class attach_function :is_literal_struct, :LLVMIsLiteralStruct, [:pointer], :bool + + # /** + # * Read LLVM IR from a memory buffer and convert it into an in-memory Module + # * object. Returns 0 on success. + # * Optionally returns a human-readable description of any errors that + # * occurred during parsing IR. OutMessage must be disposed with + # * LLVMDisposeMessage. + # * + # * @see llvm::ParseIR() + # */ + # LLVMBool LLVMParseIRInContext(LLVMContextRef ContextRef, + # LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM, + # char **OutMessage); + attach_function :parse_ir_in_context, :LLVMParseIRInContext, [:pointer, :pointer, :pointer, :pointer], :bool end # Yields a pointer suitable for storing an LLVM output message. diff --git a/lib/llvm/core/bitcode.rb b/lib/llvm/core/bitcode.rb index 9425ea66..23451269 100644 --- a/lib/llvm/core/bitcode.rb +++ b/lib/llvm/core/bitcode.rb @@ -36,6 +36,28 @@ def write_bitcode(path_or_io) end status == 0 end + + def self.parse_ir(path_or_memory_buffer, context = Context.global) + memory_buffer = case path_or_memory_buffer + when MemoryBuffer then path_or_memory_buffer + else MemoryBuffer.from_file(path_or_memory_buffer) + end + FFI::MemoryPointer.new(:pointer) do |mod_ref| + FFI::MemoryPointer.new(:pointer) do |msg_ref| + status = C.parse_ir_in_context(context, memory_buffer, mod_ref, msg_ref) + raise msg_ref.get_pointer(0).get_string(0) if status + return from_ptr(mod_ref.get_pointer(0)) + end + end + end + + def write_ir!(filename) + FFI::MemoryPointer.new(:pointer) do |msg_ref| + status = C.print_module_to_file(self, filename, msg_ref) + raise msg_ref.get_pointer(0).get_string(0) if status != 0 + end + self + end end # @private diff --git a/test/bitcode_test.rb b/test/bitcode_test.rb index 01ccebdb..44b08457 100644 --- a/test/bitcode_test.rb +++ b/test/bitcode_test.rb @@ -22,5 +22,11 @@ def test_bitcode result = run_function_on_module(new_module, "test_function").to_i assert_equal 1, result end + Tempfile.open("ir") do |tmp| + assert test_module.write_ir!(tmp.path) + new_module = LLVM::Module.parse_ir(tmp.path) + result = run_function_on_module(new_module, "test_function").to_i + assert_equal 1, result + end end end