免責事項: MIPS についてはわかりませんが、x86 についてはある程度知っています。原理は同じであると思います。
通常の関数呼び出し規約では、コンパイラは の値をn
スタックにプッシュして function に渡しますfoo
。ただし、fastcall
代わりにレジスタを介して値を渡すように gcc に指示するために使用できる規則があります。(MSVC にもこのオプションがありますが、その構文はわかりません。)
test.cpp:
int foo1 (int n) { return ++n; }
int foo2 (int n) __attribute__((fastcall));
int foo2 (int n) {
return ++n;
}
上記を でコンパイルすると、次のようg++ -O3 -fomit-frame-pointer -c test.cpp
になりますfoo1
。
mov eax,DWORD PTR [esp+0x4]
add eax,0x1
ret
ご覧のとおり、スタックから値を読み込みます。
そして、ここにありますfoo2
:
lea eax,[ecx+0x1]
ret
これで、レジスタから直接値が取得されます。
もちろん、関数をインライン化すると、コンパイラは、指定した呼び出し規則に関係なく、より大きな関数の本体に単純な追加を行います。しかし、インライン化できない場合、これが発生します。
免責事項 2: 私は、コンパイラーを継続的に推測する必要があると言っているわけではありません。ほとんどの場合、これはおそらく実用的ではなく、必要でもありません。しかし、それが完璧なコードを生成するとは思わないでください。
編集 1:単純なローカル変数 (関数の引数ではない) について話している場合、はい、コンパイラはそれらをレジスタまたはスタックに割り当てます。
編集 2:呼び出し規約はアーキテクチャ固有のようで、Richard Pennington が回答で述べているように、MIPS は最初の 4 つの引数をスタックに渡します。したがって、あなたの場合、追加の属性を指定する必要はありません (実際には x86 固有の属性です)。