首页 > 解决方案 > LLVM 断言“解决此责任集之外的符号”

问题描述

为什么我打电话给

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 日,我正在使用 LLVM 的 SVN 存储库版本,基于 Visual Studio 2017 15.9.6 构建。

标签: llvmllvm-ir

解决方案


这确实是 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 代码的控制流。小心使用。


推荐阅读