获取 LLVM IR 解析器的块名称
getting block names for LLVM IR parser
我正在编写一个 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
我需要的是将这些 "labels" 放入列表中。我还看到一些 .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()
来获取块的名称:即:'if.then'、'if.else' 等
但是对于第一种格式,这是不可能的,因为它没有名称。但是我用 printAsOperand(errs(), true)
进行了测试,我可以从中打印出如下地址:'%4, %7 %10'。我的问题是,如何将这些地址(或操作数)添加到 stings 列表中?或获取这些值并赋值给某个变量。
指令/基本块名称是一种调试功能,可简化 IR-level 通道的开发,但不对它们做出任何保证。例如。它们可能被简单地剥离,它们可能会产生误导,等等。您不应该依赖它们来获得任何有意义的东西(通常它们可能与原始源代码没有任何联系)。通常,名称不会在 LLVM 的发布版本中生成。您需要在调试(或发布+断言)模式下构建所有内容。
方法如下;
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();
}
我正在编写一个 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
我需要的是将这些 "labels" 放入列表中。我还看到一些 .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()
来获取块的名称:即:'if.then'、'if.else' 等
但是对于第一种格式,这是不可能的,因为它没有名称。但是我用 printAsOperand(errs(), true)
进行了测试,我可以从中打印出如下地址:'%4, %7 %10'。我的问题是,如何将这些地址(或操作数)添加到 stings 列表中?或获取这些值并赋值给某个变量。
指令/基本块名称是一种调试功能,可简化 IR-level 通道的开发,但不对它们做出任何保证。例如。它们可能被简单地剥离,它们可能会产生误导,等等。您不应该依赖它们来获得任何有意义的东西(通常它们可能与原始源代码没有任何联系)。通常,名称不会在 LLVM 的发布版本中生成。您需要在调试(或发布+断言)模式下构建所有内容。
方法如下;
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();
}