[llvm-dev] Including a global variable lookup in a JIT compiler

Sanket Diwale via llvm-dev llvm-dev at lists.llvm.org
Wed Dec 9 06:54:27 PST 2020


Hi,

I was getting started with writing my own JIT compiler, starting with the
KaleidoscopeJIT example available from the LLVM git repository (
https://github.com/llvm-mirror/llvm/blob/master/examples/Kaleidoscope/include/KaleidoscopeJIT.h
).

However, even without any modifications to the example, I noticed that
global variables are not being found by the lookup function
in KaleidoscopeJIT.h

Is the way to lookup global variables somewhat different from that of the
lookup for local variables and functions that works in the KaleidoscopeJIT
example?

I have an IR code generated that looks like this

```

ModuleID = 'my jit module'
source_filename = "my jit module"
target datalayout =
"e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"

%g = type { double, double }

@r = common global %g

define double @b() {
entry_b:
  %p = alloca %g, align 8
  %0 = getelementptr %g, %g* %p, i32 0, i32 1
  store double 1.170000e+02, double* %0, align 8
  %1 = load %g, %g* %p, align 8
  store %g %1, %g* @r, align 8
  %2 = load double, double* %0, align 8
  ret double %2
}

```

However, when the JIT compiler tries to compile the function "b", I get an
error saying

```

Failure value returned from cantFail wrapped call
Symbols not found: [ _r ]

```

The error occurs when trying to compile the IR code line

```

store %g %1, %g* @r, align 8

```

as the JIT is not able to find the symbol corresponding to the global
variable "r" in the symbol table of the JIT.

The relevant lines from the Kaleidoscope JIT seem to be

```

  JITSymbol findSymbol(const std::string Name) {
    return findMangledSymbol(mangle(Name));
  }
private:
  std::string mangle(const std::string &Name) {
    std::string MangledName;
    {
      raw_string_ostream MangledNameStream(MangledName);
      Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
    }
    return MangledName;
  }

  JITSymbol findMangledSymbol(const std::string &Name) {

    // ...
    // Search modules in reverse order: from last added to first added.
    // This is the opposite of the usual search order for dlsym, but makes more
    // sense in a REPL where we want to bind to the newest available definition.
    for (auto H : make_range(ModuleKeys.rbegin(), ModuleKeys.rend()))
      if (auto Sym = CompileLayer.findSymbolIn(H, Name, ExportedSymbolsOnly))
        return Sym;

    // ...

    return nullptr;
  }

```

The symbol name for "r", gets mangled to "_r" and is looked up in the
module. When not found, nullptr is returned by the findMangledSymbol
function. When debugging with breakpoints, I can see that nullptr is indeed
being returned.

Is there some modification that needs to be done to the above JIT lookup in
order to find global variables, is there a separate symbol table or
different mangling that is required?

Could you point me to the right document sources or the right modifications
that might be required?

The way I call the JIT compiler on the module is:

    TheJIT->addModule(std::move(TheModule));
    // evaluate things from the module
    auto ExprSymbol = TheJIT->findSymbol("b");
    assert(ExprSymbol && "Function not found");

    // Get the symbol's address and cast it to the right type
    // call the function b
    double (*FP)() = (double
(*)())(intptr_t)llvm::cantFail(ExprSymbol.getAddress()); // (THIS IS
WHERE THE ERROR IS ENCOUNTERED)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20201209/b7f3476a/attachment.html>


More information about the llvm-dev mailing list