2

使用 LLVM 8.0.1 库,我尝试使用以下代码为函数创建调试信息:

DIFile *Unit = DebugBuilder->createFile(CompileUnit->getFilename(), CompileUnit->getDirectory());
DIScope *FContext(Unit);

DISubprogram *SP = DebugBuilder->createFunction(
    FContext, def->Name, def->Name, Unit, LineNo,
    CreateFunctionType(ft, CompileUnit->getFile()), 0);

func->setSubprogram(SP);

但是,这会导致 IR 如下所示:

define i32 @main(i32 %y) !dbg !3 {
entry:
  ret i32 2
}
    ; ...
!3 = !DISubprogram(name: "main", linkageName: "main", scope: !2, file: !2, type: !4, spFlags: 0, retainedNodes: !7)
    ; ...
!7 = <temporary!> !{}

哪个,在调用时DebugBuilder->finalize(),抛出Assertion failed: !N->isTemporary() && "Expected all forward declarations to be resolved"

我在官方参考资料和其他教程中都没有找到该retainedNodes字段的描述,并且网络搜索只会导致 LLVM 源代码中未注释的部分。这个领域的意义或目的是什么?临时节点是如何在那里创建的?

4

3 回答 3

3

我发现通过在生成之前添加解决了这个问题DebugBuilder

TheModule->addModuleFlag(llvm::Module::Warning, "CodeView", 1);

...正如官方文档中显然没有解释的那样。

于 2020-08-12T08:11:35.530 回答
1

LLVM C API(inkwell-rs用作包装器)有同样的问题。我通过调用and解决LLVMDIBuilderCreateFunction了这个问题。这保留了元数据节点,但其值为空元数据 ( ) 而不是临时的。IsDefinition = trueIsLocalToUnit = trueretainedNodes!{}

于 2021-04-15T15:14:19.070 回答
1

我通过使用 finalizeSubprogram 明确地完成子程序解决了类似的问题。

DebugBuilder->finalizeSubprogram(SP);

这似乎解决了临时问题,但在编译生成的 IR 时我仍然收到一些警告。

如果通过添加要调用的DISubprogram::SPFlagDefinition标志来定义函数DebugBuilder->createFunction,retainedNodes 将设置为空节点而不是临时节点。

于 2021-04-30T17:19:11.800 回答