Pup*_*ppy 11 c abi llvm llvm-codegen
我有一个用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*)的聚合.对于其他聚合,如果它们是HVAs,则按值传递; else在x86上传递值或在x64上传递指针.
这似乎很简单(相对而言),但是LLVM文档sext清楚地表明"这表明代码生成器应该将参数或返回值符号扩展到目标的ABI所需的范围(通常是32位)由调用者(对于参数)或被调用者(对于返回值)." x86调用约定的Microsoft页面没有提及任何扩展到任何宽度的内容.
我观察到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
我最终破解了 Clang 的 CodeGen 内部结构来为我执行 C ABI 调用(C++ ABI 支持已经完成)。因此,我不必重新实现(并重新测试)他们的代码,而只需重新使用他们的工作。正式来说,CodeGen API 不是公开的,也不适合任何人使用,但在本例中,我设法让它发挥作用。事实证明,它并没有看起来那么可怕 - 许多像 LValue/RValue/ReturnValueSlot 这样的类只是 llvm::Value* 上的包装器,并附加了一些额外的可选语义。
更大的问题是创建从 C ABI 到我自己的 ABI 的蹦床。CodeGenFunction 接口似乎不太适合这一点。但我想我可以让它发挥作用。