ほとんどのプラットフォームでは、alloca
は、スタックポインタのインライン調整(たとえば、x64上のrsp
から、スタックアライメントを維持するための少しのロジックを足したもの)まで低下します。gccのallocaの扱いはどうですか?
私はgcc
がallocaのために生成するコードを見ていて、かなり変です。これは、次のアセンブリにコンパイル
#include <alloca.h>
#include <stddef.h>
volatile void *psink;
void func(size_t x) {
psink = alloca(x);
}
-O2
で:いくつかの混乱のものがここにあります
func(unsigned long):
push rbp
add rdi, 30
and rdi, -16
mov rbp, rsp
sub rsp, rdi
lea rax, [rsp+15]
and rax, -16
mov QWORD PTR psink[rip], rax
leave
ret
次の簡単な例してください。私はgcc
が(スタックの整列を維持するために)割り当てられたサイズを16の倍数に丸める必要があることを理解しています。通常の方法は(size + 15) & ~0xF
ですが、代わりにadd rdi, 30
に30を追加しますか?どうしたの?
第2に、私はちょうどalloca
の結果が新しいrsp
の値であることを期待しています。これは既によく整列されています。代わりに、gccがこれを行います:
alloca
の結果として使用する
rsp
の値を「再編成」しているように見える
lea rax, [rsp+15]
and rax, -16
- しかし、我々はすでに最初の16バイト境界にrsp
を揃えるために仕事をしました場所。
何がありますか?
コードon godboltでプレーすることができます。 clang
とicc
は、少なくともx86では「期待していること」を実行することに注意する価値があります。 VLAでは、gcc
とclang
は問題ありませんが、icc
は偽物を生成します。
1ここで、psink
への割り当ては、そうでない場合、コンパイラはそれを完全に省略するのでalloca
の結果を消費するだけです。
コメントは議論の対象外です。この会話は[チャットに移動]されています(http://chat.stackoverflow.com/rooms/136822/discussion-on-question-by-beeonrope-whats-up-with-gccs-handling-of-alloca)。 –