获取LLVM IR解析器的块名称

时间:2018-03-17 12:39:01

标签: llvm llvm-clang llvm-ir

我正在编写LLVM解析器来分析程序是否遵循某种编程范例。为此我需要分析IR的每个块并检查某些指令。当我创建.ll文件时,我看不到标签名称,而是地址:

; <label>:4                                       ; preds = %0
  %5 = load i32* %c, align 4
  %6 = add nsw i32 %5, 10
  store i32 %6, i32* %c, align 4
  br label %10

; <label>:7                                       ; preds = %0
  %8 = load i32* %c, align 4
  %9 = add nsw i32 %8, 15
  store i32 %9, i32* %c, align 4
  br label %10

; <label>:10                                      ; preds = %7, %4
  %11 = load i32* %1
  ret i32 %11 

我需要的是获得这些&#34;标签&#34;进入清单。我还看到一些.ll文件具有以下格式:

if.then:                                          ; preds = %entry
      %5 = load i32* %c, align 4
      %6 = add nsw i32 %5, 10
      store i32 %6, i32* %c, align 4
      br label %10

if.else:                                          ; preds = %entry
      %8 = load i32* %c, align 4
      %9 = add nsw i32 %8, 15
      store i32 %9, i32* %c, align 4
      br label %10

if.end:                                           ; preds = %if.else,       
      %11 = load i32* %1
      ret i32 %11 

使用第二种格式,我可以使用getName()来获取块的名称:即:&#39; if.then&#39;,&#39; if.else&#39;等

但是对于第一种格式,它是不可能的,因为它没有名字。但我测试了printAsOperand(errs(), true),我可以打印地址,如:&#39;%4,%7%10&#39;。我的问题是,如何将这些地址(或操作数)添加到stings列表中?或者获取这些值并分配给某个变量。

2 个答案:

答案 0 :(得分:1)

指令/基本块名称是一种调试功能,可简化IR级别传递的开发,但不保证对它们有所保证。例如。它们可能被简单地剥离,它们可能会误导等等。你不应该依赖它们来做任何有意义的事情(通常它们可能与原始源代码没有任何联系)。通常,LLVM的发布版本中不会生成名称。您需要在Debug(或Release + Assertions)模式下构建所有内容。

答案 1 :(得分:1)

这是做到这一点的方法;

应该在raw_ostream方法中使用

printAsOperand()来获取变量所需的地址:

以下是我用于此目的的方法:

#include "llvm/Support/raw_ostream.h"

std::string get_block_reference(BasicBlock *BB){
    std::string block_address;
    raw_string_ostream string_stream(block_address);
    BB->printAsOperand(string_stream, false);

    return string_stream.str();
}