C LLI与LLVM

我有一个用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,则按值传递; else在x86上传递值或在x64上传递指针。

这似乎很简单(相对而言),但是sext的LLVM文档明确指出“这表明代码生成器应该将参数或返回值符号扩展到目标的ABI所需的范围(通常为32位) )由调用者(对于参数)或被调用者(对于返回值)。“ x86调用约定的Microsoft页面没有提及任何扩展任何宽度的内容。

我观察到Clang生成的LLVM IR在Windows上生成了byval属性。 我从上面收集到的理解从未要求使用byval

如何将各种平台C ABI降低到LLVM IR?

我不能说我理解你的问题100%,但值得注意的是LLVM IR根本无法代表平台ABI的所有细微之处。 因此,在Clang工具链中,前端负责执行ABI降低,例如通过值将对象正确传递给函数等。

查看Clang源代码树中的lib/Basic/Targets.cpp以获取定义。 血腥细节还在lib/CodeGen/TargetInfo.cpp

我最终攻击Clang的CodeGen内部以执行C ABI呼叫我(C ++ ABI支持已经完成)。 因此,我只需重新使用他们的工作,而不必重新实现(并重新测试)他们的代码。 正式的CodeGen API不是公开的,并不是任何人都可以使用的,但在这种情况下,我设法让它工作。 事实certificate,它比它看起来要糟糕得多 – 像LValue / RValue / ReturnValueSlot这样的类只是llvm :: Value *上的包装器,并附加了一些额外的可选语义。

更有问题的是从C ABI到我自己的ABI创造蹦床。 CodeGenFunction接口似乎不太适合。 但我想我可以让它发挥作用。