[LLVMdev] Problem linking and JITing code through C++-API
Andy Jost
Andrew.Jost at synopsys.com
Mon Sep 1 16:41:32 PDT 2014
I have a frontend that generates some LLVM bitcode that needs to be linked with other bitcode (its runtime library), which I generate from C++ source using Clang.
If I write the output of my program to disk, link it with llvm-link, and then run it with lli, everything works perfectly. But if I try to perform the linking and running steps in my main program, I get this error during llvm::ExecutionEngine::getPointerToFunction:
Stack dump:
0. Running pass 'X86 Machine Code Emitter' on function '@.step.myappend'
1. Running pass 'X86 Machine Code Emitter' on function '@.step.myappend'
Segmentation fault (core dumped)
There are no other messages. Any idea what I'm doing wrong? I'll copy the source of my main C++ file and the bitcode for .step.myappend below. I can send the full bitcode file, too, if someone asks for it, but it is around 800 lines.
####################
#include <fstream>
#include <iostream>
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Linker.h"
#include "llvm/PassManager.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "sprite/compiler.hpp"
#include "sprite/config.hpp"
#include "sprite/curryinput.hpp"
#include "sprite/icurry_parser.hpp"
namespace
{
std::string dirname(std::string const & path)
{
size_t const pos = path.find_last_of("/");
return path.substr(0, pos == std::string::npos ? 0 : pos);
}
std::string basename(std::string const & path)
{
size_t const pos = path.find_last_of("/");
return path.substr(pos == std::string::npos ? 0 : pos + 1);
}
std::string remove_extension(std::string const & path)
{
size_t const pos = path.find_last_of(".");
return pos == std::string::npos ? path : path.substr(0, pos);
}
std::string joinpath(std::string const & dirname, std::string const & path)
{
if(!path.empty() && path.front() == '/')
return path;
if(dirname.empty())
return path;
return dirname.back() == '/' ? dirname + path : dirname + "/" + path;
}
}
int main(int argc, char const *argv[])
{
if(argc != 2)
{
std::cerr << "Usage: " << argv[0] << " <file.curry>" << std::endl;
return 1;
}
std::string const curry2read =
std::string(SPRITE_LIBINSTALL) + "/cmc/translator/bin/curry2read";
std::string const curryfile(argv[1]);
std::string const readablefile = joinpath(
dirname(curryfile)
, ".curry/" + remove_extension(basename(curryfile)) + ".read"
);
// Generate the readable Curry file.
int ok = std::system((curry2read + " -q " + curryfile).c_str());
if(ok != 0) return 1;
std::ifstream input(readablefile);
if(!input)
{
std::cerr << "Could not open \"" << readablefile << "\"" << std::endl;
return 1;
}
// Parse the input program.
sprite::curry::Library lib;
input >> lib;
std::string topmodule = lib.modules.front().name;
// sprite::compiler::prettyprint(lib);
// Compile the program.
sprite::compiler::LibrarySTab stab;
sprite::compiler::compile(lib, stab);
// Declare the main function.
namespace tgt = sprite::backend;
auto & module_stab = stab.modules.at(topmodule);
auto & compiler = *module_stab.compiler;
tgt::scope _ = module_stab.module_ir;
tgt::extern_(
tgt::types::int_(32)(), "main", {}
, [&]{
// Construct the root expression (just the "main" symbol).
tgt::value root_p = compiler.node_alloc();
sprite::curry::Qname const main_{topmodule, "main"};
root_p = construct(compiler, root_p, {main_, {}});
// Evaluate and then print the root expression.
compiler.rt.normalize(root_p);
compiler.rt.printexpr(root_p, "\n");
tgt::return_(0);
}
);
// module_stab.module_ir->dump();
// Load the runtime library.
llvm::OwningPtr<llvm::MemoryBuffer> buffer;
llvm::error_code err = llvm::MemoryBuffer::getFile(
SPRITE_LIBINSTALL "/sprite-rt.bc", buffer
);
if(err)
{
std::cerr << err.message() << std::endl;
return EXIT_FAILURE;
}
// Make the runtime library into a module.
std::string errmsg;
llvm::Module *rtlib = llvm::ParseBitcodeFile(
buffer.get(), module_stab.module_ir.context(), &errmsg
);
if(!rtlib)
{
std::cerr << errmsg << std::endl;
return EXIT_FAILURE;
}
// Link the compiled program code into the runtime module.
bool failed = llvm::Linker::LinkModules(
rtlib, module_stab.module_ir.ptr(), llvm::Linker::PreserveSource, &errmsg
);
if(failed)
{
std::cerr << errmsg << std::endl;
return EXIT_FAILURE;
}
std::cout << "Linking done..." << std::endl;
rtlib->dump();
// Run optimization passes.
// std::vector<const char *> exportList;
// llvm::PassManager Passes;
// Passes.add(new llvm::DataLayout(rtlib));
// Passes.add(llvm::createDemoteRegisterToMemoryPass());
// Passes.add(llvm::createInternalizePass(exportList));
// Passes.add(llvm::createScalarReplAggregatesPass());
// Passes.add(llvm::createInstructionCombiningPass());
// Passes.add(llvm::createGlobalOptimizerPass());
// Passes.add(llvm::createFunctionInliningPass());
// Passes.run(*rtlib);
// Create the JIT
llvm::InitializeNativeTarget();
llvm::ExecutionEngine * jit = llvm::EngineBuilder(rtlib)
.setErrorStr(&errmsg)
.setEngineKind(llvm::EngineKind::JIT)
.create();
if(!jit)
{
std::cerr << "Failed to create JIT compiler: " << errmsg << std::endl;
return EXIT_FAILURE;
}
// Execute the program.
std::cout << "Begin Execution..." << std::endl;
// rtlib->dump();
void * main_fp = jit->getPointerToFunction(rtlib->getFunction("main"));
int32_t (*target_program)() = (int32_t(*)())(intptr_t)(main_fp);
std::cout << "Ready..." << std::endl;
return target_program();
#if 0
// Write a bitcode file and interpret it.
{
std::string err;
llvm::raw_fd_ostream fout("sprite-out.bc", err, llvm::raw_fd_ostream::F_Binary);
llvm::WriteBitcodeToFile(module_stab.module_ir.ptr(), fout);
}
std::system("llvm-link-3.3 sprite-out.bc " SPRITE_LIBINSTALL "/sprite-rt.bc > tmp.bc");
std::system("mv tmp.bc sprite-out.bc");
int const status = std::system("lli-3.3 sprite-out.bc");
return WEXITSTATUS(status);
#endif
}
####################
define linkonce void @.step.myappend(%"struct.sprite::compiler::node"* %root_p) {
.entry:
%0 = alloca %"struct.sprite::compiler::node"*
%1 = alloca %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %root_p, %"struct.sprite::compiler::node"** %0
%2 = load %"struct.sprite::compiler::node"** %0
%3 = getelementptr %"struct.sprite::compiler::node"* %2, i32 0, i32 2
%4 = load i8** %3
%5 = bitcast i8* %4 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %5, %"struct.sprite::compiler::node"** %0
br label %11
; <label>:6 ; preds = %11
%7 = load %"struct.sprite::compiler::node"** %0
%8 = getelementptr %"struct.sprite::compiler::node"* %7, i32 0, i32 2
%9 = load i8** %8
%10 = bitcast i8* %9 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %10, %"struct.sprite::compiler::node"** %0
br label %11, !sprite.implied !0
; <label>:11 ; preds = %6, %.entry
%12 = load %"struct.sprite::compiler::node"** %0
%13 = getelementptr %"struct.sprite::compiler::node"* %12, i32 0, i32 1
%14 = load i64* %13
%15 = load i64* %13
%16 = icmp eq i64 %15, -3
br i1 %16, label %6, label %17
; <label>:17 ; preds = %11
%18 = load %"struct.sprite::compiler::node"** %0
store %"struct.sprite::compiler::node"* %18, %"struct.sprite::compiler::node"** %1
%19 = getelementptr %"struct.sprite::compiler::node"* %18, i32 0, i32 1
%20 = load i64* %19
%21 = add i64 %20, 4
%22 = getelementptr [6 x i8*]* @.jtable, i32 0, i64 %21
%23 = load i8** %22
indirectbr i8* %23, [label %24, label %26, label %36, label %38, label %44, label %66]
; <label>:24 ; preds = %26, %17
%25 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([16 x i8]* @.str21, i32 0, i32 0))
ret void, !case...FAIL !1
; <label>:26 ; preds = %26, %17
%27 = load %"struct.sprite::compiler::node"** %1
%28 = getelementptr %"struct.sprite::compiler::node"* %27, i32 0, i32 2
%29 = load i8** %28
%30 = bitcast i8* %29 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %30, %"struct.sprite::compiler::node"** %1
%31 = getelementptr %"struct.sprite::compiler::node"* %30, i32 0, i32 1
%32 = load i64* %31
%33 = add i64 %32, 4
%34 = getelementptr [6 x i8*]* @.jtable, i32 0, i64 %33
%35 = load i8** %34
indirectbr i8* %35, [label %24, label %26, label %36, label %38, label %44, label %66]
; <label>:36 ; preds = %26, %17
%37 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([18 x i8]* @.str22, i32 0, i32 0))
ret void, !case...CHOICE !1
; <label>:38 ; preds = %26, %17
%39 = load %"struct.sprite::compiler::node"** %1
%40 = getelementptr %"struct.sprite::compiler::node"* %39, i32 0, i32 0
%41 = load %"struct.sprite::compiler::vtable"** %40
%42 = getelementptr %"struct.sprite::compiler::vtable"* %41, i32 0, i32 4
%43 = load void (%"struct.sprite::compiler::node"*)** %42
tail call void %43(%"struct.sprite::compiler::node"* %39)
ret void
; <label>:44 ; preds = %26, %17
store %"struct.sprite::compiler::node"* %root_p, %"struct.sprite::compiler::node"** %0
%45 = load %"struct.sprite::compiler::node"** %0
%46 = getelementptr %"struct.sprite::compiler::node"* %45, i32 0, i32 3
%47 = load i8** %46
%48 = bitcast i8* %47 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %48, %"struct.sprite::compiler::node"** %0
br label %54
; <label>:49 ; preds = %54
%50 = load %"struct.sprite::compiler::node"** %0
%51 = getelementptr %"struct.sprite::compiler::node"* %50, i32 0, i32 2
%52 = load i8** %51
%53 = bitcast i8* %52 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %53, %"struct.sprite::compiler::node"** %0
br label %54, !sprite.implied !0
; <label>:54 ; preds = %49, %44
%55 = load %"struct.sprite::compiler::node"** %0
%56 = getelementptr %"struct.sprite::compiler::node"* %55, i32 0, i32 1
%57 = load i64* %56
%58 = load i64* %56
%59 = icmp eq i64 %58, -3
br i1 %59, label %49, label %60
; <label>:60 ; preds = %54
%61 = load %"struct.sprite::compiler::node"** %0
%62 = bitcast %"struct.sprite::compiler::node"* %61 to i8*
%63 = getelementptr %"struct.sprite::compiler::node"* %root_p, i32 0, i32 0
store %"struct.sprite::compiler::vtable"* @.fwd.vt, %"struct.sprite::compiler::vtable"** %63
%64 = getelementptr %"struct.sprite::compiler::node"* %root_p, i32 0, i32 1
store i64 -3, i64* %64
%65 = getelementptr %"struct.sprite::compiler::node"* %root_p, i32 0, i32 2
store i8* %62, i8** %65
ret void
; <label>:66 ; preds = %26, %17
store %"struct.sprite::compiler::node"* %root_p, %"struct.sprite::compiler::node"** %0
%67 = load %"struct.sprite::compiler::node"** %0
%68 = getelementptr %"struct.sprite::compiler::node"* %67, i32 0, i32 2
%69 = load i8** %68
%70 = bitcast i8* %69 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %70, %"struct.sprite::compiler::node"** %0
br label %76
; <label>:71 ; preds = %76
%72 = load %"struct.sprite::compiler::node"** %0
%73 = getelementptr %"struct.sprite::compiler::node"* %72, i32 0, i32 2
%74 = load i8** %73
%75 = bitcast i8* %74 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %75, %"struct.sprite::compiler::node"** %0
br label %76, !sprite.implied !0
; <label>:76 ; preds = %71, %66
%77 = load %"struct.sprite::compiler::node"** %0
%78 = getelementptr %"struct.sprite::compiler::node"* %77, i32 0, i32 1
%79 = load i64* %78
%80 = load i64* %78
%81 = icmp eq i64 %80, -3
br i1 %81, label %71, label %82
; <label>:82 ; preds = %76
%83 = load %"struct.sprite::compiler::node"** %0
%84 = getelementptr %"struct.sprite::compiler::node"* %83, i32 0, i32 2
%85 = load i8** %84
%86 = bitcast i8* %85 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %86, %"struct.sprite::compiler::node"** %0
br label %92
; <label>:87 ; preds = %92
%88 = load %"struct.sprite::compiler::node"** %0
%89 = getelementptr %"struct.sprite::compiler::node"* %88, i32 0, i32 2
%90 = load i8** %89
%91 = bitcast i8* %90 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %91, %"struct.sprite::compiler::node"** %0
br label %92, !sprite.implied !0
; <label>:92 ; preds = %87, %82
%93 = load %"struct.sprite::compiler::node"** %0
%94 = getelementptr %"struct.sprite::compiler::node"* %93, i32 0, i32 1
%95 = load i64* %94
%96 = load i64* %94
%97 = icmp eq i64 %96, -3
br i1 %97, label %87, label %98
; <label>:98 ; preds = %92
%99 = load %"struct.sprite::compiler::node"** %0
%100 = bitcast %"struct.sprite::compiler::node"* %99 to i8*
%101 = call i8* @malloc(i64 32)
%102 = bitcast i8* %101 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %root_p, %"struct.sprite::compiler::node"** %0
%103 = load %"struct.sprite::compiler::node"** %0
%104 = getelementptr %"struct.sprite::compiler::node"* %103, i32 0, i32 2
%105 = load i8** %104
%106 = bitcast i8* %105 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %106, %"struct.sprite::compiler::node"** %0
br label %112
; <label>:107 ; preds = %112
%108 = load %"struct.sprite::compiler::node"** %0
%109 = getelementptr %"struct.sprite::compiler::node"* %108, i32 0, i32 2
%110 = load i8** %109
%111 = bitcast i8* %110 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %111, %"struct.sprite::compiler::node"** %0
br label %112, !sprite.implied !0
; <label>:112 ; preds = %107, %98
%113 = load %"struct.sprite::compiler::node"** %0
%114 = getelementptr %"struct.sprite::compiler::node"* %113, i32 0, i32 1
%115 = load i64* %114
%116 = load i64* %114
%117 = icmp eq i64 %116, -3
br i1 %117, label %107, label %118
; <label>:118 ; preds = %112
%119 = load %"struct.sprite::compiler::node"** %0
%120 = getelementptr %"struct.sprite::compiler::node"* %119, i32 0, i32 3
%121 = load i8** %120
%122 = bitcast i8* %121 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %122, %"struct.sprite::compiler::node"** %0
br label %128
; <label>:123 ; preds = %128
%124 = load %"struct.sprite::compiler::node"** %0
%125 = getelementptr %"struct.sprite::compiler::node"* %124, i32 0, i32 2
%126 = load i8** %125
%127 = bitcast i8* %126 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %127, %"struct.sprite::compiler::node"** %0
br label %128, !sprite.implied !0
; <label>:128 ; preds = %123, %118
%129 = load %"struct.sprite::compiler::node"** %0
%130 = getelementptr %"struct.sprite::compiler::node"* %129, i32 0, i32 1
%131 = load i64* %130
%132 = load i64* %130
%133 = icmp eq i64 %132, -3
br i1 %133, label %123, label %134
; <label>:134 ; preds = %128
%135 = load %"struct.sprite::compiler::node"** %0
%136 = bitcast %"struct.sprite::compiler::node"* %135 to i8*
store %"struct.sprite::compiler::node"* %root_p, %"struct.sprite::compiler::node"** %0
%137 = load %"struct.sprite::compiler::node"** %0
%138 = getelementptr %"struct.sprite::compiler::node"* %137, i32 0, i32 3
%139 = load i8** %138
%140 = bitcast i8* %139 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %140, %"struct.sprite::compiler::node"** %0
br label %146
; <label>:141 ; preds = %146
%142 = load %"struct.sprite::compiler::node"** %0
%143 = getelementptr %"struct.sprite::compiler::node"* %142, i32 0, i32 2
%144 = load i8** %143
%145 = bitcast i8* %144 to %"struct.sprite::compiler::node"*
store %"struct.sprite::compiler::node"* %145, %"struct.sprite::compiler::node"** %0
br label %146, !sprite.implied !0
; <label>:146 ; preds = %141, %134
%147 = load %"struct.sprite::compiler::node"** %0
%148 = getelementptr %"struct.sprite::compiler::node"* %147, i32 0, i32 1
%149 = load i64* %148
%150 = load i64* %148
%151 = icmp eq i64 %150, -3
br i1 %151, label %141, label %152
; <label>:152 ; preds = %146
%153 = load %"struct.sprite::compiler::node"** %0
%154 = bitcast %"struct.sprite::compiler::node"* %153 to i8*
%155 = getelementptr %"struct.sprite::compiler::node"* %102, i32 0, i32 0
store %"struct.sprite::compiler::vtable"* @.vtable.for.myappend, %"struct.sprite::compiler::vtable"** %155
%156 = getelementptr %"struct.sprite::compiler::node"* %102, i32 0, i32 1
store i64 -1, i64* %156
%157 = getelementptr %"struct.sprite::compiler::node"* %102, i32 0, i32 2
store i8* %136, i8** %157
%158 = getelementptr %"struct.sprite::compiler::node"* %102, i32 0, i32 3
store i8* %154, i8** %158
%159 = getelementptr %"struct.sprite::compiler::node"* %root_p, i32 0, i32 0
store %"struct.sprite::compiler::vtable"* @.vt.CTOR.MyCons, %"struct.sprite::compiler::vtable"** %159
%160 = getelementptr %"struct.sprite::compiler::node"* %root_p, i32 0, i32 1
store i64 1, i64* %160
%161 = getelementptr %"struct.sprite::compiler::node"* %root_p, i32 0, i32 2
store i8* %100, i8** %161
%162 = getelementptr %"struct.sprite::compiler::node"* %root_p, i32 0, i32 3
store i8* %101, i8** %162
ret void
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140901/52547f6a/attachment.html>
More information about the llvm-dev
mailing list