LLVM IR 中的调用约定
Calling conventions in LLVM IR
LLVM 允许 call
指令和 define
指定调用约定。 IR 本身是否已经需要遵守指定的约定?例如,当使用 ccc
时,我认为 return 值需要适合我的 OS/architecture 上的 64 位 eax
。我是否可以编写 LLVM IR 代码,其中 return 是 3 i32
的结构? LLVM 是否将其转换为符合 C 调用约定的内容?我可以在不更改任何其他代码的情况下更改调用约定吗?
当我查看使用 -emit-llvm
编译 C 文件的输出时,IR 生成器已经应用了调用约定,并将在调用站点分配,并将 return 值转换为一个指针参数。这在现阶段绝对有必要吗? LLVM 对下一阶段使用哪个调用约定的信息做了什么,-emit-obj
?
不幸的是,这里混杂了很多东西。调用约定通常根据源语言定义。在转换为 LLVM IR 时,许多必要的细节已经丢失。因此,为了保留 ABI 和调用约定前端应该正确布置参数/return 值,以便它们将在 LLVM 级别正确编码。
因此,长话短说:调用约定包含高级(源语言)和低级要求。前者由前端处理,后者由后端处理。您可以更改 LLVM IR,但您需要确保生成的代码确实与您的 C 代码兼容。在某些平台上,这可能很复杂。
LLVM 允许 call
指令和 define
指定调用约定。 IR 本身是否已经需要遵守指定的约定?例如,当使用 ccc
时,我认为 return 值需要适合我的 OS/architecture 上的 64 位 eax
。我是否可以编写 LLVM IR 代码,其中 return 是 3 i32
的结构? LLVM 是否将其转换为符合 C 调用约定的内容?我可以在不更改任何其他代码的情况下更改调用约定吗?
当我查看使用 -emit-llvm
编译 C 文件的输出时,IR 生成器已经应用了调用约定,并将在调用站点分配,并将 return 值转换为一个指针参数。这在现阶段绝对有必要吗? LLVM 对下一阶段使用哪个调用约定的信息做了什么,-emit-obj
?
不幸的是,这里混杂了很多东西。调用约定通常根据源语言定义。在转换为 LLVM IR 时,许多必要的细节已经丢失。因此,为了保留 ABI 和调用约定前端应该正确布置参数/return 值,以便它们将在 LLVM 级别正确编码。
因此,长话短说:调用约定包含高级(源语言)和低级要求。前者由前端处理,后者由后端处理。您可以更改 LLVM IR,但您需要确保生成的代码确实与您的 C 代码兼容。在某些平台上,这可能很复杂。