为了确认一下:LLVM位码是否跨平台?也就是说,生成的IR(".bc")文件是否可以在各种平台上进行分发和解释/JIT编译?
如果是这样的话,Clang如何将C++转换为平台无关的代码?在C++语言本身中,在实际编译之前使用预处理器来确定其目标平台。
为了确认一下:LLVM位码是否跨平台?也就是说,生成的IR(".bc")文件是否可以在各种平台上进行分发和解释/JIT编译?
如果是这样的话,Clang如何将C++转换为平台无关的代码?在C++语言本身中,在实际编译之前使用预处理器来确定其目标平台。
LLVM IR可以跨平台,除了其他人已经列出的明显例外。然而,这并不意味着Clang生成跨平台代码。正如您所指出的,预处理器几乎普遍用于仅将代码的部分传递给C/C++编译器,具体取决于平台。即使在用户代码中没有这样做,许多系统头文件也包括一些特定于平台的位或两个,例如typedef
。例如,如果您在使用size_t
编译C代码时将其转换为LLVM IR,并且在size_t
为32位的平台上进行编译,则LLVM IR现在使用i32
,您无法通过逆向工程来修复它。
谷歌的可移植本地客户端项目(感谢@willglynn提供的链接),如果我理解正确,通过为所有目标平台固定ABI来实现可移植性。因此,在这个意义上,它并没有解决前面提到的问题:LLVM IR在具有不同ABI的平台上不可移植。之所以更具可移植性,仅仅是因为客户端提供了一个层,将PNaCl ABI与实际ABI匹配。换句话说,PNaCl代码对许多平台都不可移植,“PNaCl VM”才是。
因此,底线是:如果你非常小心,可以在多个平台上使用LLVM IR,但是需要进行重要的额外工作(Clang不会做)来抽象出ABI差异。
给定一个IR文件,我能确定它能编译到我的目标吗?
您不能假设任意的IR文件都是跨平台的,因为在给定的文件中可能存在一些不是平台无关的内容。最显著的例子是IR可以包含实际的汇编序列(通过module-level或inline汇编段),但还有其他例子 - 例如使用仅在某些目标上支持的特定于目标的内部函数或调用约定。
我能生成一个保证在所有目标上编译的IR文件吗?
我不知道,但我相信你可以,特别是如果你避免指定像内联汇编、调用约定、类型所需/首选ABI等这样的东西。不过这可能会影响编译器执行的优化。