代码之家  ›  专栏  ›  技术社区  ›  Puppy

C ABI与LLVM

  •  13
  • Puppy  · 技术社区  · 10 年前

    我有一个用LLVM编写的编译器,我希望提高我的ABI合规性。例如,我发现很难在Windows x86或Linux上找到C ABI的规范文档。而我找到的那些解释它的术语是RAX/EAX/等,而不是我可以使用的IR术语。

    到目前为止,我想我已经发现LLVM在无形中对待聚合——也就是说,它将它们的成员视为各自不同的参数。因此,例如,在Windows x64上,如果我想处理文档中所述的聚合,我需要强制为该大小的单个整数,如果是8、16、32或64位。否则,通过指针传递。

    对于Windows x86,似乎__cdecl和__stdcall不需要我执行任何操作,因为所有参数都在堆栈上传递__fastcall表示,前两个32位或更小的参数是寄存器传递的,因此我需要强制使用该大小或更小的聚合__此调用将其传递到寄存器中,其余的传递到堆栈中,因此我似乎不需要在这里执行任何调整。

    对于__vectorcall,通过整数强制传递不超过sizeof(void*)的聚合。对于其他骨料,如果它们是HVA,则按值传递;否则在x86上通过值传递或在x64上通过指针传递。

    这看起来很简单(相对而言),但LLVM文档 sext 明确说明“这向代码生成器表明,调用者(对于参数)或被调用者(对于返回值)应将参数或返回值符号扩展到目标ABI(通常为32位)所需的范围”。

    我观察到Clang生成的LLVM IR byval 属性。我从上面所获得的理解是不需要的 拜瓦尔语 的用法。

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

    2 回复  |  直到 5 年前
        1
  •  6
  •   Eli Bendersky    10 年前

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

    看看 lib/Basic/Targets.cpp 在Clang源树中查找定义。血腥的细节在 lib/CodeGen/TargetInfo.cpp

        2
  •  4
  •   Puppy    10 年前

    我最终侵入了Clang的CodeGen内部,为我调用了C ABI(C++ABI支持已经完成)。因此,我不必重新实现(和重新测试)他们的代码,只需重新使用他们的工作。官方的CodeGen API是不公开的,也不会被任何人使用,但在这种情况下,我设法使它发挥了作用。事实证明,这并不像看起来那么可怕——像LValue/RValue/ReturnValueSlot这样的许多类只是llvm::Value*上的包装器,附加了一些额外的可选语义。

    更多的问题将是从C ABI到我自己的ABI创建蹦床。CodeGenFunction接口似乎不太适合这样做。但我想我能做到。