LLVM:变量来自哪里?
LLVM使用SSA(静态单一分配)形式作为其IR。这导致在IR级别向代码中引入新变量。然而,有什么方法,API。。。要确定某个变量最初是属于程序还是由编译器插入?没有将新变量插入LLVM IR的概念。源语言和LLVM IR只是两种不同的语言,您更应该将编译视为一个翻译步骤 从概念上讲,当变量是否属于原始程序时,很难给出精确的定义 例如,考虑这个小C函数:LLVM:变量来自哪里?,llvm,llvm-ir,Llvm,Llvm Ir,LLVM使用SSA(静态单一分配)形式作为其IR。这导致在IR级别向代码中引入新变量。然而,有什么方法,API。。。要确定某个变量最初是属于程序还是由编译器插入?没有将新变量插入LLVM IR的概念。源语言和LLVM IR只是两种不同的语言,您更应该将编译视为一个翻译步骤 从概念上讲,当变量是否属于原始程序时,很难给出精确的定义 例如,考虑这个小C函数: void test() { int i; i = 2; i = 3; } 将此函数编译为LLVM IR将导致至少两个
void test() {
int i;
i = 2;
i = 3;
}
将此函数编译为LLVM IR将导致至少两个变量(如果未应用常数折叠),因为SSA形式是。哪一个是原始的,哪一个是插入的
当涉及控制流和phi功能时,这也变得复杂:
int a = 1;
int b = 2;
int c = 3;
int func() {
int result;
if (a) {
result = b;
} else {
result = c;
}
return result;
}
将此C函数转换为LLVM IR并应用-mem2reg过程时,我们得到以下结果:
define i32 @func() #0 {
%1 = load i32* @a, align 4
%2 = icmp ne i32 %1, 0
br i1 %2, label %3, label %5
; <label>:3 ; preds = %0
%4 = load i32* @b, align 4
br label %7
; <label>:5 ; preds = %0
%6 = load i32* @c, align 4
br label %7
; <label>:7 ; preds = %5, %3
%result.0 = phi i32 [ %4, %3 ], [ %6, %5 ]
ret i32 %result.0
}
define i32@func()#0{
%1=负载i32*@a,对齐4
%2=icmp ne i32%1,0
br i1%2,标签%3,标签%5
;:3;preds=%0
%4=负载i32*@b,对齐4
br标签%7
;:5;preds=%0
%6=负载i32*@c,对齐4
br标签%7
;:7;preds=%5,%3
%结果0=φi32[%4,%3],%6,%5]
ret i32%结果。0
}
如您所见,result的虚拟寄存器名不会显示在赋值阶段。它仅在合并点处可见。在这里,变量赋值的原始位置被移到函数的末尾。同样,插入了哪些变量,哪些没有,这是个问题
您可以使用调试元数据编译原始程序,然后处理调试信息以查找变量声明等。在Clang中,您可以使用
-g
标志输出调试信息。没有将新变量插入LLVM IR的概念。源语言和LLVM IR只是两种不同的语言,您更应该将编译视为一个翻译步骤
从概念上讲,当变量是否属于原始程序时,很难给出精确的定义
例如,考虑这个小C函数:
void test() {
int i;
i = 2;
i = 3;
}
将此函数编译为LLVM IR将导致至少两个变量(如果未应用常数折叠),因为SSA形式是。哪一个是原始的,哪一个是插入的
当涉及控制流和phi功能时,这也变得复杂:
int a = 1;
int b = 2;
int c = 3;
int func() {
int result;
if (a) {
result = b;
} else {
result = c;
}
return result;
}
将此C函数转换为LLVM IR并应用-mem2reg过程时,我们得到以下结果:
define i32 @func() #0 {
%1 = load i32* @a, align 4
%2 = icmp ne i32 %1, 0
br i1 %2, label %3, label %5
; <label>:3 ; preds = %0
%4 = load i32* @b, align 4
br label %7
; <label>:5 ; preds = %0
%6 = load i32* @c, align 4
br label %7
; <label>:7 ; preds = %5, %3
%result.0 = phi i32 [ %4, %3 ], [ %6, %5 ]
ret i32 %result.0
}
define i32@func()#0{
%1=负载i32*@a,对齐4
%2=icmp ne i32%1,0
br i1%2,标签%3,标签%5
;:3;preds=%0
%4=负载i32*@b,对齐4
br标签%7
;:5;preds=%0
%6=负载i32*@c,对齐4
br标签%7
;:7;preds=%5,%3
%结果0=φi32[%4,%3],%6,%5]
ret i32%结果。0
}
如您所见,result的虚拟寄存器名不会显示在赋值阶段。它仅在合并点处可见。在这里,变量赋值的原始位置被移到函数的末尾。同样,插入了哪些变量,哪些没有,这是个问题
您可以使用调试元数据编译原始程序,然后处理调试信息以查找变量声明等。在Clang中,您可以使用
-g
标志输出调试信息。考虑为解析AST实现Clang过程,并执行与原始程序更相关的分析codeConsider实现了一个用于解析AST的铿锵过程,并执行与原始代码稍微相关的分析