我有一个使用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
清楚地说明:“这表示代码生成器应该按照目标ABI(通常为32位)的要求,由调用者(对于参数)或被调用者(对于返回值)将参数或返回值符号扩展到所需的程度。”。 Microsoft页面中的x86调用约定没有提到任何内容需要扩展到任何宽度。
我观察了Clang生成的LLVM IR,在Windows上生成了byval
属性。从上面获得的理解从未要求使用byval
。
我如何将各种平台的C ABI降低到LLVM IR?
inreg
参数属性了吗? - Iwillnotexist Idonotexistinreg
,所以我选择“那不是必要的”。 - Puppy