[llvm-dev] Undefined symbols with inline functions using the ORC JIT on Linux

Martin Andersson via llvm-dev
2019-01-04T17:49:12Z

Hi,

I am developing an application that uses the ORC api to JIT compile C++
code using Clang. So far I have done most of the work on Windows, where it
now mostly works as expected. However, when I tried to run my application
on Linux I ran into some problems.

The problem I ran into is that symbols for jitted inline functions cannot
be resolved. Both LLVM and Clang are checked out with latest master branch.

It is probably me that is doing something wrong but I cannot figure out
what it is. Here is what I found so far. In the file RuntimeDyld.cpp in
function loadObjectImpl, a check is made whether a particular function is
weak or not. Since inline functions are weak (as I understood it) an
attempt is made to promote this symbol to a strong definition. But only if
it is present in the "ResponsibilitySet", that check is made on line
273.
However, the inline functions are not in that set so they are not promoted
to strong definitions. Shouldn't functions defined in the jitted code be
our responsibility?

Looking closer what happens with the ResponsibiltySet. When it is created
it tries to to find symbols for all the names it knows about. Eventually
the look up request ends up in my application where I use a
LegacyIRCompileLayer to search for the symbol in the jitted module. That
function call eventually ends up in getSymbol in RTDyldObjectLinkingLayer.h
where the symbol is found but it does not have and address (Address is zero
and Flags is 50). So an instance of JITSymbol is returned to the
LegacyRTDyldObjectLinkingLayer and the findSymbol function which checks if
an valid symbol was found (on line 406 in RTDyldObjectLinkingLayer.h).
Since the address is zero the JITSymbol is deemed to be not valid, via the
bool operator in JITSymbol.h and that is why that particular symbol name
does not end up in the ResponsibilitySet. That is as far as I got, I don't
know enough about LLVM to understand what the problem is (if any).

This issue can be replicated with the clang-interpreter application.

This program does not work, clang-interpreter crashes because it cannot
find the symbol for the Test constructor function.

class Test {
    public: Test() {}
};

int main()
{
    Test test;
    return 0;
}

This program works:

class Test {
    public: Test();
};

Test::Test() { }

int main()
{
    Test test;
    return 0;
}

The first version works on Windows since the inline constructor is not
marked as weak. Can anyone enlighten me on what is happening here? Is this
the expected behavior, and if it is, what am I doing wrong?

Btw, I also tried various compiler flags (fno-inline and
fno-inline-functions) but those do not help in this case.

//Martin
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20190104/1739ed0e/attachment.html>