<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    Hi Marcus<br>
    <br>
    If I understand correctly, you are creating a module with a
    declaration for an external function. Then you compile and load the
    module with the ExecutionEngine JIT interface. The loader is
    supposed to resolve your declaration to an existing definition in
    the host program, right? Do you get the error message "Program used
    external function '...' which could not be resolved!"?<br>
    <br>
    There is a variety of potential reasons here. The mystery that it
    works for sqrt, but not for cos or sin, may be that something in
    your host program exposes a definition with its unmangled name only
    for sqrt, while the others are mangled or not exposed at all. After
    all, your host program links to the C++ stdlib, which provides
    multiple versions of all these functions with different signatures!<br>
    <br>
    In general, using host-process symbols directly can be dangerous and
    hard to debug. Basically, you are relying on details of your host
    compiler and linker. The correct way may be adding another module
    with the stdlib implementation that your JITed code should use. The
    simplest way may be keeping the host-process calls, but
    expose your own wrappers explicitly by address. Using the Orc JIT
    interface directly, a QND implementation with LLVM 5.0 looked like
    this:<br>
<a class="moz-txt-link-freetext" href="https://github.com/weliveindetail/JitFromScratch/commit/e9988a834dd6c35c93268da6ece73a7cc472100a">https://github.com/weliveindetail/JitFromScratch/commit/e9988a834dd6c35c93268da6ece73a7cc472100a</a><br>
    <br>
    Note that on Windows you want to declare the wrappers as: <span
      class="blob-code-inner"><span class="pl-k">extern</span> <span
        class="pl-s"><span class="pl-pds">"</span>C<span class="pl-pds">"</span></span>
      __declspec(dllexport)</span><br>
    <div class="moz-cite-prefix"><br>
      <blockquote type="cite">After many trials and errors we found out
        that no LLVM example works (“4. Kaleidoscope: Adding JIT and
        Optimizer Support”, “The Fibonacci project“). [...] It seems
        that the LLVM JIT compiler cannot find external functions like
        “sin” and “cos” nor intrinsic functions under Windows. Every
        (tutorial) example crashes using them.</blockquote>
      I can imagine this doesn't get tested so much on Windows.<br>
      <br>
      Best</div>
    <div class="moz-cite-prefix">Stefan<br>
    </div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">Am 02.01.19 um 19:05 schrieb Dr. Marcus
      Hoffmann:<br>
    </div>
    <blockquote type="cite"
      cite="mid:572f890b-d4ec-1ae8-f355-b2daee541019@artsystems.de">Hello
      Stefan, <br>
      <br>
      our software FluidSIM (<a class="moz-txt-link-abbreviated" href="http://www.fluidsim.de">www.fluidsim.de</a>) simulates pneumatic,
      hydraulic and electric circuits. For the mathematical models we
      use the language Modelica (<a class="moz-txt-link-abbreviated" href="http://www.modelica.org">www.modelica.org</a>). We developed our own
      Modelica simulator which solves the dynamical created algebraic
      differential equation systems. One tool is our small JIT compiler,
      which compiles mathematical expressions like “2*x0 + sin(x1)” at
      runtime. <br>
      <br>
      In the future we want to compile more complex expressions,
      especially entire blocks, like <br>
      X1 = 2*x0 +4 <br>
      X2 = 3*sin(x1) <br>
      X3 = x1 + x2 <br>
      <br>
      At the moment, we are evaluating the LLVM suite to replace our JIT
      compiler. Our software runs under the Windows platform (32 and 64
      Bit). We are using the Microsoft Visual Studio 2017 Version
      15.9.4. <br>
      For our evaluation we use LLVM 7.0.1. We created the LLVM suite
      for 32 Bit with the cmake tools. We wrote a small parser and took
      the LLVM tutorials as starting point to implement our LLVM JIT
      compiler. All arithmetic expressions work fine. But we failed to
      integrate external functions like “cos” and “sin”. Only “sqrt”
      worked. After many trials and errors we found out that no LLVM
      example works (“4. Kaleidoscope: Adding JIT and Optimizer
      Support”, “The Fibonacci project“). <br>
      <br>
      It seems that the LLVM JIT compiler cannot find external functions
      like “sin” and “cos” nor intrinsic functions under Windows. Every
      (tutorial) example crashes using them. Is there any solution for
      this problem (compiler switches, libraries to include, a simple
      Visual Studio project)? <br>
      <br>
      The following code works for “sqrt” but not for “cos”. It just
      encapsulates an external call. We use <br>
      Microsoft Visual Studio 2017 Version 15.9.4. <br>
      LLVM 7.0.1 <br>
      Solution Configuration: Debug, 32 Bit, Switch: /MTd <br>
      <br>
      using namespace llvm; <br>
      <br>
      typedef double(__cdecl *JitCompiledFn)(double); <br>
      <br>
      int main() <br>
      { <br>
      // "sqrt" works. <br>
      //const char externalFnName[] = "sqrt"; <br>
      <br>
      // "cos", "sin", etc. fails. <br>
      const char externalFnName[] = "cos"; <br>
      <br>
      InitializeNativeTarget(); <br>
      InitializeNativeTargetAsmPrinter(); <br>
      InitializeNativeTargetAsmParser(); <br>
      <br>
      LLVMContext context; <br>
      <br>
      IRBuilder<> builder(context); <br>
      <br>
      std::unique_ptr<llvm::Module> module(new
      Module("TestModule", context)); <br>
      Module* pModule = module.get(); <br>
      <br>
      auto externalFn_IR =
      cast<Function>(pModule->getOrInsertFunction("externalFn",
      Type::getDoubleTy(context), Type::getDoubleTy(context))); <br>
      Value* x = externalFn_IR->arg_begin(); <br>
      x->setName("x"); <br>
      <br>
      BasicBlock *entryBlock = BasicBlock::Create(context, "EntryBlock",
      externalFn_IR); <br>
      builder.SetInsertPoint(entryBlock); <br>
      <br>
      std::vector<Type *> args(1, Type::getDoubleTy(context)); <br>
      FunctionType *FT = FunctionType::get(Type::getDoubleTy(context),
      args, false); <br>
      auto externalFn_llvm = Function::Create(FT,
      Function::ExternalLinkage, externalFnName, pModule); <br>
      auto ret = builder.CreateCall(externalFn_llvm, x); <br>
      <br>
      builder.CreateRet(ret); <br>
      <br>
      errs() << "Created Module:\n\n" << *pModule; <br>
      <br>
      auto jitCompiler =
EngineBuilder(std::move(module)).setOptLevel(CodeGenOpt::Level::Default).create();
      <br>
      <br>
      JitCompiledFn externalFn =
(JitCompiledFn)jitCompiler->getFunctionAddress(externalFn_IR->getName());
      <br>
      <br>
      errs() << "\n\nexternalFn(9.0) = "; <br>
      <br>
      double y = externalFn(9.0); <br>
      <br>
      errs() << y << "\n\n"; <br>
      <br>
      return 0; <br>
      } <br>
      <br>
      <br>
      <br>
      Kind regards <br>
      Marcus Hoffmann <br>
      <br>
    </blockquote>
  </body>
</html>