在 LLVM 中,如何在程序集文件中反映元数据?

Ner*_*ate 2 metadata llvm inline-assembly llvm-ir

这是设置:我正在使用 LLVM,并且我有一个分析过程,需要使分析的一些结果可供以后使用。这些结果需要在我生成的最终 .s 文件(ARM 架构)中可见。然后我在 .s 文件上运行一些脚本,这些脚本使用这些结果做进一步分析,但也依赖于生成的 ASM 的实际结构(否则我只会使用更多的 LLVM 传递)。

最初我认为元数据就是我想要的,我创建了一些简单的测试函数来为我关心的每条指令插入一些元数据。但我不知道如何使这个元数据反映在最终的 .s 文件中。更糟糕的是,我无法弄清楚如何使元数据字符串成为我真正想要的。您将在下面看到的“5”永远不会输出。相反,我在输出中看到 46 或 47。

void addMetadata(Instruction& I) {
    LLVMContext& C = I.getContext();
    MDNode* N = MDNode::get(C, MDString::get(C, "5"));
    I.setMetadata("alias_set", N);

    std::cerr << "Instruction" << std::endl;
    I.dump();
}
Run Code Online (Sandbox Code Playgroud)

示例输出:

Instruction
  %30 = load i32* %29, align 4, !dbg !67, !alias_set !46
Run Code Online (Sandbox Code Playgroud)

我也听说内联汇编可能会起作用,但我不知道这是否允许我在特定的 IR 指令之前插入注释或标签。如果 IR 被重新排序,那么无论它走到哪里,该标签或评论都需要跟随它。基本上,我只想在 .s 文件中看到一个标签或评论,其中包含一些我想要的少量信息。有谁知道这是怎么做到的吗?谢谢!

Ner*_*ate 6

在进一步的研究中,我发现您无法轻松完成我试图对元数据进行的操作。调试信息是输出到程序集文件的元数据的一种特殊情况。事实证明,对我有用的是内联 ASM。作为 LLVM 元数据类的一部分,这可能会很有帮助;转储元数据的能力。我最终做的是提取我关心的任何元数据,并将其作为内联汇编插入指令前。此函数将在指令前插入汇编注释,您可以将@info_you_want_to_output 替换为您关心的任何数据的字符串表示形式。注意:@ 通常是 ARM 汇编注释的开始。此函数使用 ATT 汇编语法,但如果您需要 Intel 语法,您可以将 AD_ATT 替换为 AD_Intel。

void insertInfo(Instruction& I)
{
    std::vector<llvm::Type *> AsmArgTypes = {};

    FunctionType *AsmFTy = FunctionType::get(Type::getVoidTy(I.getContext()), AsmArgTypes, false);
    InlineAsm *IA = InlineAsm::get(AsmFTy, std::string("@info_you_want_to_output"), "",
                            /*hasSideEffects*/ true, /*isAlignStack*/ false, InlineAsm::AD_ATT);
    Instruction *newInst = CallInst::Create(IA, "", &I);
}
Run Code Online (Sandbox Code Playgroud)

这是我的 ARM 程序集 (.s) 文件中的一些示例输出:

ldr r2, .LCPI0_2
mov r1, r4
@APP
@@info_you_want_to_output
@NO_APP
bl  __cxa_atexit
pop {r4, lr}
mov pc, lr
Run Code Online (Sandbox Code Playgroud)

注意内联汇编前后插入@APP和@NO_APP。我不确定这意味着什么,但很容易被忽略。希望这对未来的任何人都有帮助。