我转换最简单的C代码
#include <stdio.h>
int main()
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
到它的LLVM IR,使用
clang -emit-llvm -S hello.c
Run Code Online (Sandbox Code Playgroud)
生成的IR是:
define i32 @main() #0 {
%1 = alloca i32, align 4
store i32 0, i32* %1
ret i32 0
}
Run Code Online (Sandbox Code Playgroud)
但是,我不明白这个IR.(LLVM doc对初学者有帮助但不是那么多)
%1 = alloca i32, align 4?它在原始代码中对应什么?store i32 0, i32* %1Sea*_*ean 37
define i32 @main() #0
Run Code Online (Sandbox Code Playgroud)
这定义了一个main返回32位整数的函数.该#0方法使用命名的属性#0的功能.例如,attributes #0 = { alwaysinline alignstack=4 }IR中可能存在类似的属性,这些属性将应用于main.
%1 = alloca i32, align 4
Run Code Online (Sandbox Code Playgroud)
这会在堆栈上分配32位整数.%1是指向堆栈上此位置的指针的名称.的align 4保证了地址将是4的倍数
store i32 0, i32* %1
Run Code Online (Sandbox Code Playgroud)
这将指向的32位整数设置为32位%1值0.这就像*x = 1在C++中说的那样
ret i32 0
Run Code Online (Sandbox Code Playgroud)
这将从函数返回32位返回值0
考虑到你没有局部变量,赋值是奇数main.LLVM用于BasicBlock表示指令组,基本块具有退出点和指令列表.我的猜测是编译器决定使用returnas作为基本块的退出并选择将至少一条指令放入块中.作业基本上是无操作.
DrY*_*Yap 14
的%n是虚拟寄存器为目标机器生成代码时,将被解析为实际的寄存器.
这i32是类型信息.在原始代码中int,您的编译器将其作为32位整数.
alloca用于在堆栈上分配空间.在此示例中,它是i32(32位整数),因此您可以在0中加载返回值.align 4给出这个分配4字节对齐,即堆栈指针将在4字节对齐的地址上.
它不是最有效的表示,但如果是IR则不是目标.IR应该可以移植到不同的架构.然后到后端生成有效的机器代码.
为什么alloca和store这是有关的main功能.如果您已将此函数调用为其他内容,则IR将按ret预期包含.从检查为main生成的程序集,它似乎与堆栈基指针有关,但我不完全理解它为什么存在.是时候推出C标准了.
更新:我在C标准中找不到任何东西,但似乎clang为每个主要功能都做了这个.我不知道clang代码库是否能够很好地跟踪它.
更新:请参阅Bill Lynch的评论.这些指令在那里:
对于
return 0主要功能可能隐含的