我有一个用 LLVM 编写的编译器,我希望提高 ABI 合规性。例如,我发现很难在 Windows x86 或 Linux 上实际找到 C ABI 的规范文档。我发现的那些用 RAX/EAX/等术语解释它,而不是我可以使用的 IR 术语。
到目前为止,我认为 LLVM 不可见地对待聚合 - 也就是说,它将它们的成员视为每个不同的参数。例如,在 Windows x64 上,如果我想像文档中所述那样处理聚合,我需要强制转换为该大小的单个整数(如果是 8、16、32 或 64 位)。否则,通过指针传递。
对于 Windows x86,似乎 __cdecl 和 __stdcall 不需要我执行任何操作,因为所有参数都在堆栈上传递。 __fastcall 表示前两个 32 位或更小的参数是寄存器传递的,因此我需要强制该大小或更小的聚合。 __thiscall 将其传递到寄存器中,其余部分传递到堆栈中,所以看起来我不需要在这里执行任何调整。
对于 __vectorcall,通过整数强制传递不超过 sizeof(void*) 的聚合。对于其他聚合,如果它们是 HVA,则按值传递;否则在 x86 上按值传递或在 x64 上按指针传递。
这看起来很简单(嗯,相对来说),但是 LLVM 文档sext
明确指出“这向代码生成器表明参数或返回值应该由调用者(对于参数)或被调用者(对于返回值)”。 Microsoft 的 x86 调用约定页面没有提及将任何内容扩展到任何宽度。
我观察到 Clang 生成的 LLVM IR 生成了byval
Windows 上的属性。我从上面收集到的理解从来不需要byval
的用法。
如何将各种平台 C ABI 降低到 LLVM IR?
我不能说我 100% 理解你的问题,但值得注意的是 LLVM IR 根本无法代表平台 ABI 的所有微妙之处。因此,在 Clang 工具链中,前端负责执行 ABI 降低,例如正确地将对象按值传递给函数等。
看一眼lib/Basic/Targets.cpp
在 Clang 源代码树中获取定义。血淋淋的细节进一步在lib/CodeGen/TargetInfo.cpp
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)