LLVM断言“正在解决此职责范围之外的符号”

时间:2019-08-30 22:48:11

标签: llvm llvm-ir

为什么打给

jit->lookup("test");

命中失败的断言:“正在解决此职责范围之外的符号”?

当我以以下方式创建函数时会执行此操作:

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

但是当我将函数创建为

时,它可以正常工作(即,在没有断言的情况下找到它)
define void @test() {
begin:
  ret void
}

这不是找不到函数“ test”的情况,如果我查找不存在的名称,它的行为会有所不同。

这是命中断言的代码:

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"));
}

用这些行替换函数创建,没有问题:

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();

我想了解断言的含义,为什么它在一种情况下而不在另一种情况下断言,以及我需要为(* double)()情况做些什么才能使其生效。我做了很多搜索有关LLVM责任集的文档的工作,但几乎没有发现。在https://llvm.org/docs/ORCv2.html处有人提及,但不足以让我解释该断言告诉我的内容。

我正在使用截至2019年8月20日的SVN存储库版本的LLVM,该版本基于Visual Studio 2017 15.9.6。

2 个答案:

答案 0 :(得分:0)

这确实是Windows平台上ORC LLJIT中的错误。

在此处查看错误记录:
https://bugs.llvm.org/show_bug.cgi?id=44337

修正提交参考:
https://github.com/llvm/llvm-project/commit/84217ad66115cc31b184374a03c8333e4578996f

对于任何手动构建自定义JIT /编译器层堆栈的人(不使用LLJIT),您需要做的就是在发射ELF图像时强制弱符号自动声明。

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

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

如果设置,此ObjectLinkingLayer实例将声明对 由给定目标文件提供的任何符号,这些符号尚未存在 MaterializationResponsibility实例。

设置此标志将允许更高级别的程序表示(例如 LLVM IR)仅根据它们的一部分符号添加 提供,而无需编写中间层即可进行扫描和添加 附加符号。为了方便起见,这以诊断质量为代价 但是:如果所有符号都是预先枚举的,则冲突可能是 尽早发现并报告(通常是确定性的)。如果这 设置了此选项,可能无法检测到其他符号的冲突 直到很晚,检测可能取决于控制流程 JIT代码。小心使用。

答案 1 :(得分:0)

要解决此错误,请添加ObjectLinkingLayer.setAutoClaimResponsibilityForObjectSymbols(true);

例如:


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());