Lonnie Chrisman
Lonnie Chrisman

Reputation: 63

LLVM asserts "Resolving symbol outside this responsibility set"

Why does my call to

jit->lookup("test");

hit a failed assert: "Resolving symbol outside this responsibility set"?

It does this when I create my function as:

define double @test() {
begin:
  ret double 1.343000e+01
}

But it works fine (i.e., finds it without an assert) when I create the function as

define void @test() {
begin:
  ret void
}

It is not a case of not finding the function "test", it has different behavior if I lookup a name that doesn't exist.

Here's the code that hits the assert:

ThreadSafeModule Create_M()
{
    auto pCtx = make_unique<LLVMContext>();
    LLVMContext& ctx = *pCtx;
    auto pM = make_unique<Module>("myModule", ctx);
    Module& M = *pM;

    IRBuilder<> builder(ctx);

    FunctionType* FT = FunctionType::get(Type::getDoubleTy(ctx),false);
    Function* testFn = Function::Create(FT, 
                GlobalValue::LinkageTypes::ExternalLinkage, "test", M);
    auto BB = BasicBlock::Create(ctx,"begin",testFn);
    builder.SetInsertPoint(BB);
    builder.CreateRet(ConstantFP::get(ctx,APFloat(13.43)));

    outs() << M;        // For debugging

    return ThreadSafeModule(std::move(pM), std::move(pCtx));
}


int main()
{
    InitializeNativeTarget();
    InitializeNativeTargetAsmPrinter();

    // Create an LLJIT instance.
    auto jit = ExitOnErr(LLJITBuilder().create());
    auto M1 = Create_M();
    ExitOnErr(jit->addIRModule(std::move(M1)));
    auto testSym = ExitOnErr(jit->lookup("test"));
}

Replace the function creation with these lines and it doesn't have the problem:

FunctionType* FT = FunctionType::get(Type::getVoidTy(ctx),false);
Function* testFn = Function::Create(FT, 
            GlobalValue::LinkageTypes::ExternalLinkage, "test", M);
auto BB = BasicBlock::Create(ctx,"begin",testFn);
builder.SetInsertPoint(BB);
builder.CreateRetVoid();

I'd like to understand what the assert means, why it asserts in the one case and not the other, and what I need to do for the (*double)() case to get it to work. I did a lot of searching for documentation on LLVM responsibility sets, and found almost nothing. Some mention at https://llvm.org/docs/ORCv2.html, but not enough for me to interpret what it is telling me with this assert.

I'm using the SVN repository version of LLVM as of 20-Aug-2019, building on Visual Studio 2017 15.9.6.

Upvotes: 1

Views: 287

Answers (2)

Lanistor
Lanistor

Reputation: 303

To fix this error, add ObjectLinkingLayer.setAutoClaimResponsibilityForObjectSymbols(true);

Such as:


auto jit = ExitOnErr(LLJITBuilder()
  .setJITTargetMachineBuilder(std::move(JTMB))
  .setObjectLinkingLayerCreator([&](ExecutionSession &ES, const Triple &TT) {
    auto ll = make_unique<ObjectLinkingLayer>(ES, 
        make_unique<jitlink::InProcessMemoryManager>());
    ll->setAutoClaimResponsibilityForObjectSymbols(true);
    return move(ll);
  })
  .create());

Upvotes: 2

InflexCZE
InflexCZE

Reputation: 732

This was indeed bug in ORC LLJIT on Windows platform.

See bug record here:
https://bugs.llvm.org/show_bug.cgi?id=44337

Fix commit reference:
https://github.com/llvm/llvm-project/commit/84217ad66115cc31b184374a03c8333e4578996f

For anyone building custom JIT / compiler-layer stack by hand (not using LLJIT), all you need to do is force weak symbol autoclaim when emitting ELF images.

if (JTMB.getTargetTriple().isOSBinFormatCOFF())
{
    ObjectLayer.setAutoClaimResponsibilityForObjectSymbols(true);
}

http://llvm.org/doxygen/classllvm_1_1orc_1_1ObjectLinkingLayer.html#aa30bc825696d7254aef0fe76015d10ff

If set, this ObjectLinkingLayer instance will claim responsibility for any symbols provided by a given object file that were not already in the MaterializationResponsibility instance.

Setting this flag allows higher-level program representations (e.g. LLVM IR) to be added based on only a subset of the symbols they provide, without having to write intervening layers to scan and add the additional symbols. This trades diagnostic quality for convenience however: If all symbols are enumerated up-front then clashes can be detected and reported early (and usually deterministically). If this option is set, clashes for the additional symbols may not be detected until late, and detection may depend on the flow of control through JIT'd code. Use with care.

Upvotes: 0

Related Questions