2013-12-20 (Fri) [長年日記]
_ x86-64での可変長引数の扱い
x86-64では整数・ポインタ・浮動小数点数の引数が一部レジスタで渡されるが、ふと可変長引数の場合はどうなるんだろうと思った。
調べてみると、va_listが
typedef struct { unsigned int gp_offset; /* 汎用レジスタで渡された次の引数を指すreg_save_area上のオフセット */ unsigned int fp_offset; /* 浮動小数点数レジスタで渡された次の引数を指すreg_save_area上のオフセット */ void *overflow_arg_area; /* スタックで渡された引数の領域を指すポインタ */ void *reg_save_area; /* レジスタで渡された引数の値をダンプした領域を指すポインタ */ } va_list[1];
のような構造になっていて、va_start()で上記のメンバの値を適切にセットして、va_arg()で求められる型によってva_listを操作して値を取り出すようだ。
せっかくレジスタで引数を渡しているのに、メモリ上にレジスタの値をダンプした上でこんな効率悪そうな処理をしないといけないのはもったいない…とつい思ってしまったが、Ruby動かすコストに比べたら全然たいしたことないよなあ。
参考: System V Application Binary Interface AMD64 Architecture Processor Supplement