LLVM 中的 C ABI

13

我有一个使用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?


在 LLVM IR 中,在调用之前,_不需要_显式地将变量放入寄存器或栈中。相反,您可以使用多种调用约定来注释 LLVM IR 调用和函数。请参阅http://www.llvm.org/docs/LangRef.html#calling-conventions - Iwillnotexist Idonotexist
1
是的,但这些还不足以满足目标 C ABI。你必须自己处理。因此才有这个问题。 - Puppy
你试过使用 inreg 参数属性了吗? - Iwillnotexist Idonotexist
我没有看到Clang生成inreg,所以我选择“那不是必要的”。 - Puppy
3
此外,考虑到这里存在大量未定义的行为,“试一试”并不是一个可行的态度。我已经尝试过了,但由于完全错误的理解,它似乎至少有一半的时间可以工作。如果你违反ABI,也不会像得到明确的LLVM错误那样清晰明了。 - Puppy
2个回答

7
我不能百分之百地理解你的问题,但值得注意的是,LLVM IR无法表示平台ABI的所有微妙差别。因此,在Clang工具链中,前端负责执行ABI降级,例如正确地通过值将对象传递给函数等。
请查看Clang源代码树中的lib/Basic/Targets.cpp以获取定义。详细信息在lib/CodeGen/TargetInfo.cpp中。

如果我的问题不够清晰,我向您道歉。我已经明白了我需要作为前端来调用C函数的部分。我想知道的是如何处理它-也就是说,如果我有一个给定的C原型,我该如何将其降低到LLVM IR?我会查看那些文件。 - Puppy
我正在尝试:P 你说得很对,这确实不是一件简单的事情。这里有相当大量的代码,其中很多都是针对Clang的,因此很难将真正与ABI相关的部分分离出来。 - Puppy
我观察到的另一件事是,Clang经常表现出完全不符合我发现的ABI规范的行为,因此遵循Clang感觉就像在黑暗中盲目行动。 - Puppy
1
抱歉。我的真正意思是,我坐在那里盯着代码看了好几个小时,但它对我来说毫无意义。仅仅试图匹配Clang的做法让我感觉自己并不真正理解正在发生的事情或原因,而且我也不知道最终的代码是否正确。 - Puppy
6
那么每种以LLVM为目标的语言都需要重新实现所有这些代码来获得良好的C交互性,是吗? - user519179
显示剩余4条评论

5
我最终通过对Clang的CodeGen内部进行了一些修改来为我执行C ABI调用(C++ ABI支持已经完成)。因此,我不需要重新实现(和重新测试)他们的代码,而是简单地重新使用了他们的工作。官方上来说,CodeGen APIs并没有公开,并且也不应该被任何人使用,但在这种情况下,我成功让它起作用。结果发现,它比看起来要简单得多——像LValue / RValue / ReturnValueSlot等许多类只是在llvm :: Value *上包装了几个额外的可选语义。

更具问题性的是从C ABI到我的ABI创建跳板。 CodeGenFunction接口似乎不太适合这样做。但我认为我可以让它工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接