私は LLVM で書かれたコンパイラを持っており、ABI 準拠を目指しています。たとえば、Windows x86 または Linux での C ABI の仕様ドキュメントを実際に見つけるのは難しいと感じました。そして、私が見つけたものは、私が使用できる IR 用語ではなく、RAX/EAX/etc の観点から説明しています。
これまでのところ、LLVM は集合体を目に見えないように扱っている、つまり、集合体のメンバーをそれぞれ別個のパラメーターと見なしていると考えてきたと思います。たとえば、Windows x64 では、ドキュメントにあるように集計を処理したい場合、8、16、32、または 64 ビットの場合、そのサイズの単一の整数に強制する必要があります。それ以外の場合は、ポインターで渡します。
Windows x86 の場合、すべてのパラメーターがスタックに渡されるため、__cdecl と __stdcall は私からのアクションを必要としないようです。__fastcall によると、最初の 2 つの 32 ビット以下の引数はレジスターで渡されるため、そのサイズ以下の集約を強制する必要があります。__thiscall はこれをレジスタに渡し、残りはスタックに渡すので、ここで調整を行う必要はないようです。
__vectorcall の場合、整数型強制により sizeof(void*) 以下の集合体を渡します。その他の集計については、それらが HVA の場合は値で渡します。それ以外の場合は、x86 では値渡し、x64 ではポインター渡しです。
これは (まあ、比較的) 単純に思えますが、LLVM のドキュメントにはsext
明確に記載されています。呼び出し元 (パラメーターの場合) または呼び出し先 (戻り値の場合) によって。". x86 呼び出し規則に関する Microsoft のページでは、任意の幅に何かを拡張することについては何も言及されていません。
byval
また、Windows で属性を生成する Clang によって生成された LLVM IR を観察しました。上記から得た理解では、byval
の使用は必要ありません。
さまざまなプラットフォーム C ABI を LLVM IR に下げるにはどうすればよいですか?