这个
%1
寄存器是由clang生成的,用于
处理函数中的多个返回语句。想象一下,你正在编写一个计算整数阶乘的函数。不要像这样:
int factorial(int n){
int result;
if(n < 2)
result = 1;
else{
result = n * factorial(n-1);
}
return result;
}
你可能会这样做
int factorial(int n){
if(n < 2)
return 1;
return n * factorial(n-1);
}
为什么?因为Clang将插入包含返回值的变量
result
。太好了。这就是使用
%1
变量的原因。看一下稍微修改过的代码的ir。
修改后的代码,
enum days {MON, TUE, WED, THU};
int main() {
enum days d;
d = WED;
if(d) return 1;
return 0;
}
IR,
define dso_local i32 @main() #0 !dbg !15 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 2, i32* %2, align 4, !dbg !22
%3 = load i32, i32* %2, align 4, !dbg !23
%4 = icmp ne i32 %3, 0, !dbg !23
br i1 %4, label %5, label %6, !dbg !25
5:
store i32 1, i32* %1, align 4, !dbg !26
br label %7, !dbg !26
6:
store i32 0, i32* %1, align 4, !dbg !27
br label %7, !dbg !27
7:
%8 = load i32, i32* %1, align 4, !dbg !28
ret i32 %8, !dbg !28
}
现在你看到了%1
派上用场了吧?大多数只有一个返回语句的函数都会被 LLVM 的这个 Pass 去掉这个变量。
main
函数之前的初始化有关 (https://godbolt.org/z/kEtS-s)。该链接展示了汇编代码如何映射到源代码。 - Pradeep Kumarmain
以外的其他名称,则神秘的额外变量将消失。有趣的是,如果您完全省略return
语句(在C中对于main
是合法的,并且等同于return 0;
),它也会消失。 - Nate Eldredgeenum
看起来完全是一个误导; 如果main
函数只包含return 0;
或return 17;
,你也会看到一个不必要的变量(无论哪种情况下,这个额外的变量都被设置为零)。这个额外的变量最终也会出现在汇编代码中。 - Nate Eldredgemain
声明为int main(int argc, char **argv)
,你会看到argc
和argv
被复制到堆栈上,但神秘的零变量仍然存在于它们之外。 - Nate Eldredge