0

I have generated the following llvm ir at runtime and I am looking to execute the function immediately

;other declarations/functions

define %gen__struct__81ty_struct.catch_val @gen__fun__115(void**) {
entry:
  %1 = getelementptr void*, void** %0, i32 0
  %2 = load void*, void** %1, align 8
  %3 = bitcast void* %2 to i64*
  store i64 1, i64* %3, align 8
  %4 = load i64, i64* %3, align 8
  %5 = getelementptr void*, void** %0, i32 1
  %6 = load void*, void** %5, align 8
  %7 = bitcast void* %6 to i64*
  store i64 1, i64* %7, align 8
  %8 = load i64, i64* %7, align 8
  %9 = getelementptr void*, void** %0, i32 2
  %10 = load void*, void** %9, align 8
  %11 = bitcast void* %10 to i64*
  store i64 1, i64* %11, align 8
  ret %gen__struct__81ty_struct.catch_val zeroinitializer
}

I then use the kaleidoscope jit and the following C++ code to compile and executed the above function but I keep getting segfault.

    Function* out = 0;
    //code that generates the function ...

    runFunc fptr = 0;
    jit->addModule(std::move(gblDevice->lmod));
    fptr = (runFunc)jit->getPointerToFunction(out);

    vector<void*> params;
    uint64_t a = 0;
    uint64_t b = 0;
    uint64_t c = 0;
    params.push_back(&a);
    params.push_back(&b);
    params.push_back(&c);

    catch_val_pt cval = fptr(&params[0]);

I have tried for hours to work out what is wrong with the above code but everything seems to check out.

The getPointerToFunction function is.

class OrcJIT {
// ...
JITSymbol findSymbol(const std::string Name) {
    std::string MangledName;
    raw_string_ostream MangledNameStream(MangledName);
    Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
    return CODLayer.findSymbol(MangledNameStream.str(), true);
}

inline void* getPointerToFunction(Function* F) {
    return (void*)findSymbol(F->getName().data()).getAddress();
}
//...
}
ceorron
  • 1,230
  • 1
  • 17
  • 28
  • This could be a duplicate of https://stackoverflow.com/q/46884340. Basically you ran into the reason why `getPointerToFunction` is deprecated for MCJIT. Use `getFunctionAddress(functionName)` instead, this should do the necessary finalization automatically. – PaulR Oct 25 '17 at 08:36
  • I may have been too quick there, what version of LLVM are you using and where exactly do you get the segfault? Try running the program in a debugger like gdb. If you cannot get a backtrace you are probably in the generated code. Compare the address with the function pointer. If the segfault occurs on the very first instruction this may indeed be the problem I described in the previous question. You could narrow this down by generating a function that does not use pointers to exclude that your code is accessing something it should not. – PaulR Oct 25 '17 at 08:53
  • 1
    I'm using llvm-4.0.0, windows 64-bit, MinGW, g++ See my answer for what it done in the getPointerToFunction function. – ceorron Oct 25 '17 at 09:01
  • If you replace your generated function with one that does nothing except return a constant number, does it still segfault? – PaulR Oct 25 '17 at 09:05
  • 1
    It doesn't segfault if I do not modify the variables passed in, however could this could simply be optimizing the function to a jump/return? – ceorron Oct 25 '17 at 09:10
  • Looks like you are using the ORC JIT which is not affected by the problem in the other post. – PaulR Oct 25 '17 at 09:11
  • So it definitely isn't getPointerToFunction – ceorron Oct 25 '17 at 09:14
  • I guess it is time to start your debugger, it will at least tell you where it crashes. – PaulR Oct 25 '17 at 09:17

1 Answers1

0

The answer turned out to be very simple in the end.

There must be binary incompatibility between the way llvm does return values and gcc does return values. The short answer being that gen__struct__81ty_struct.catch_val return value causes the segfault.

Put simply in the generated function you will need to return this through copy to structure through a pointer passed to the generated function. You can't rely on return values from the generated function matching in anything but the simplest of cases (aka int).

ceorron
  • 1,230
  • 1
  • 17
  • 28