在LLVM IR中给指令添加元数据

24

首先,我是LLVM passes的新手。

我正在尝试在一个转换pass(使用C++ API)之后向LLVM指令添加元数据。我打算将这些信息存储,以供工具链中的另一个工具使用。我有两个关于此的问题。

  1. 我希望存储为元数据的信息可以输入到另一个基于LLVM IR的工具中。所以,使用元数据是一个好主意吗?我打算将字符串作为元数据与一些指令一起存储。

  2. 如果元数据是正确的选择,在创建元数据节点时需要一些帮助。我计划使用setMedata()函数将其附加到指令上。哪个setMetadata()变体是正确的。我不确定我的数据应该是哪种MDKind。我想创建一个MDString,将其附加到我的MDNode上,然后使用指令调用setMetadata()。如果我想将元数据附加到函数内部的指令上,应该使用什么Context?文境与元数据有什么相关性?

我尝试在论坛和llvm doxygen文档中阅读了很多讨论,但没有得到关于所有问题的清晰而完整的答案。感谢您的帮助或一些可以帮助我理解这个问题的资料。

1个回答

29

在我看来:

1. 元数据是否是正确的机制?

如果你的“其他工具”本身不是一个步骤,那么是的,我认为元数据是最好的方法 - 它可以将所有内容保存在IR中,易于肉眼识别,手动添加用于测试也很容易,而且 - 可能最重要的是 - 只要您不重用现有的元数据类型,就不会与任何其他内容冲突。

然而,如果您的“其他工具”本身就是一个步骤,那么还有一种选择:您可以使一个步骤依赖于另一个步骤,然后直接在后面的步骤中使用早期步骤中的信息。优点在于您不必修改IR。

2. 如何使用自定义元数据节点?

使用setMetadatachar*变体,像这样:

LLVMContext& C = Inst->getContext();
MDNode* N = MDNode::get(C, MDString::get(C, "my md string content"));
Inst->setMetadata("my.md.name", N);

如果这是第一次在 setMetadata 中使用该字符串,它将自动在模块中注册 my.md.name 作为一种新类型(我相信这在整个上下文中都是一致的)。您随后可以通过以下方式检索该字符串:

而如果这是第一次在 setMetadata 中使用该字符串,则会自动将 my.md.name 注册到模块中作为一个新的对象(我相信它与整个上下文是一致的)。 您稍后可以使用以下方法检索该字符串:

cast<MDString>(Inst->getMetadata("my.md.name")->getOperand(0))->getString();

如果你想在同一个作用域中重复调用 getMetadatasetMetadata,你可以使用 Module::getMDKindID 来获取实际使用的种类,并使用使用该种类值的这些方法的变化。

最后,请注意,你可以将元数据节点范围限制在函数内部 - 使用 MDNode::get(..., ..., true) 变体即可 - 尽管我自己从未使用过。


如何在LLVM中向元数据添加多个操作数? 我想生成这种形式的元数据: !0 = 元数据!{void(i32)* @kernel,元数据!“kernel”,i32 1} - Johns Paul
@JohnsPaul 如果您有新的问题,即使与此相关,请单独提出。 - Oak
@Oak,当我运行我的程序时,出现了以下错误opt-7: test3.ll:68:209: error: invalid field 'nameTableKind'。你能帮我解决一下吗?我想要获取我的函数调用的行号,我正在使用以下命令clang -O0 -g -S -emit-llvm test3.c -o test3.ll。 - sunil
@sunil 我无法帮助你解决这个问题,你最好创建一个新的问题来描述你的问题。 - Oak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接