[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