extern "C"を理解する
ことの起こり
RustでOS書く時、extern "C"とか、#[repr(C)]とかが登場するが、なぜこの部分につけるかなどがわからなかったので、調べる
extern "C"するとなにが起きる? => CのABIを使うようになる
code:code.rs
pub extern "C" fn rust_function() {
}
no_mangleつけると、関数名がそのままになる(コンパイラが生成した値にならない)
extern "C"をつけると、C言語のABIを使用するようになる(デフォルトはRustのABI)
C ABIで呼び出しできるRustのAPIを作成します。
とあるが、個人的にこれがわかりやすいと思った
C環境から呼び出せるRustの関数(API)を作る、と読み替えた!!
CのABIを使うとなにがいい? => マシン語の方式やメモリの配置などを固定できる
(指定されていないRust の呼び出し規約の代わりに)この関数に C の呼び出し規約を使用するようコンパイラに伝えるために、関数を extern "C" として定義する必要があります。
とある。指定されていないとどうなるのか考えるのがよさそう。
素晴らしい記事にいろいろ書いてあった
「RustにABIがないというのはどういうことか」のセクションに、
関数の呼び出し規約や構造体のデータの表現方法などに代表される、マシン語の生成に関する仕様が明確に定まっていない.
と著者が解釈しているとある。これは上でわかった、ABIによってアセンブル結果が違うことからわかる。
構造体の配置(要素の順)も、最適化で不定だとも書いてあった。
つまり、マシン語の方式やメモリ配置を固定にできるようになる!
では、固定できるとどうなる?
構造体の要素の順番が重要な場合に対応できる
みかん本でそんなのがあった。なんの機能のためだったか忘れてしまった。。。
repr(C)つけると、それが実現できる
インラインアセンブリを入れた関数が、その書いた順にしたがってアセンブリを実行できる(推測)
アセンブリを実行する順だ重要だったりすることが多い?
結論!!
インラインアセンブリが書かれてて、アセンブリに落ちたときにその順番が重要そうなら、extern "C"
構造体の要素の順番が重要そうならrepr(C)
ほんとか!?!?!?
追記!!!
RISC-V原典よんでいたら、3章RISC-Vのアセンブリ言語の最初の方、図3.2(p36)に、zero,sp,t0などのレジスタは「ABI名」だと書いてあった
上に書いた固定をすることで、ABI名のようなわかりやすい名前でインラインアセンブリを書くことができる
ということだと思った