[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
GNU CC には、‘varargs.h’ と ‘stdarg.h’ のある実装が付属しており、 引数をスタック上で渡す機種では変更なしで動作する。 そうでない機種ではそれ自身の varargs の実装が必要になり、 その場合、機種独立の二つのヘッダファイルから条件付きで実装ファイルを インクルードしなければならない。
ANSI の ‘stdarg.h’ は、旧来の ‘varargs.h’ とは、
va_start
の呼び出し規約の点で主に異なっている。
旧来の実装では、va_start
は引数をただ一つだけ取り、
それが引数ポインタを格納する変数になっている。
ANSI の va_start
の実装では、引数が一つ追加されている。
プログラマは、関数の引数で名前が付いている最後のものを va_start
の
二番目の引数に書くことを要求される。
しかし、va_start
はこの二番目の引数を使うべきではない。
名前付き引数の最後を見つける方法は、以下に記述する組み込み関数で
行なう。
__builtin_saveregs ()
この組み込み関数を使って、引数レジスタをメモリにセーブすることで、
varargs の機構がそれらをアクセス可能になる。
va_start
の ANSI 版も旧来版もどちらも、
代わりに SETUP_INCOMING_VARARGS
(以下を参照)を使うのでない限り、
__builtin_saveregs
を使わなければならない。
機種によっては、__builtin_saveregs
はマクロ
EXPAND_BUILTIN_SAVEREGS
の制御の元で C 言語で書かれている。
その他の機種では、アセンブラ言語で書かれたルーチンを呼び出す。
これは、‘libgcc2.c’ にある。
__builtin_saveregs
呼び出し用に生成されたコードは、
__builtin_saveregs
の呼び出しが書かれている場所とは
対照的に、そのコードが何をするかには関係なく、
関数の先頭に現れる。
これは、レジスタは、関数がそれ自身の目的でそのレジスタを使い始める前に
セーブされなければならないものだからである。
__builtin_args_info (category)
この組み込み関数を使って、レジスタにある最初の無名引数を見つける。
一般に、一つの機種には、引数として使われるレジスタには色々なカテゴリが
あり、それぞれ特定のデータ型のカテゴリに対して使われる。
(例えば、ある機種では、浮動小数点レジスタは浮動小数点引数に
使われる一方で、それ以外の引数は汎用レジスタで渡される。)
非 varargs 関数が正しい呼び出し規約を使用するようにするには、
データ型 CUMULATIVE_ARGS
を定義して、各カテゴリで
何個のレジスタがこれまで使われたかを記録する必要がある。
__builtin_args_info
は CUMULATIVE_ARGS
型と同じデータ構造
を、それを使った通常の引数のレイアウトが終わった後で参照する。
このとき、category がどのワードを参照すべきかを指定する。
つまり、この値は与えられたカテゴリのレジスタで未使用のものの先頭を指す。
普通は、va_start
の実装で __builtin_args_info
を
使い、各カテゴリを一度だけアクセスし、値を va_list
オブジェクトに
格納する。これは va_list
がその値を更新しなければならないためであり、
__builtin_args_info
によりアクセスされる値を変える方法が
ないためである。
__builtin_next_arg (lastarg)
これは、スタック上の引数については、__builtin_args_info
に
等価である。先頭の無名スタック引数のアドレスを、void *
型で
返す。ARGS_GROW_DOWNWARD
が定義されていれば、
先頭の無名スタック引数の上の位置のアドレスを返す。
それを va_start
で使って、スタックから引数を取り出すための
ポインタを初期化する。また、va_start
で、
第二引数 lastarg が現在の関数の名前のある引数の最後で
あることを検証するのにも使われる。
__builtin_classify_type (object)
それぞれの機種には固有の規約があって、どの型のデータをどの種類の
レジスタで渡すかを決めている。読者はその規約を具体化するように
va_arg
を実装しなければならない。指定されたデータ型を
分類する一番手っ取り早い方法は、__builtin_classify_type
を
sizeof
や __alignof__
を組み合わせて使うことである。
__builtin_classify_type
は object の値は無視し、
そのデータ型だけを見る。
どんな型であるか—整数、浮動小数点、ポインタ、構造体などを
記述する整数を返す。
ファイル ‘typeclass.h’ である列挙型を定義していて、
__builtin_classify_type
の値を解釈するのに使うことができる。
以下のマシン記述マクロは varargs の実装を助ける。
EXPAND_BUILTIN_SAVEREGS (args)
定義されているなら、一個の C の式であり、__builtin_saveregs
を
呼び出すための機種固有のコードを生成する。
このコードは関数の一番先頭の、仮引数のアクセスが行なわれる前に移動される。
この関数の戻り値は、__builtin_saveregs
の戻り値として
使う値を含む RTX とすべきである。
引数 args は、__builtin_saveregs
に渡された引数を
含む、ある tree_list
である。
このマクロが定義されていない場合は、コンパイラは 通常の、ライブラリ関数 ‘__builtin_saveregs’ の呼び出しを 出力する。
SETUP_INCOMING_VARARGS (args_so_far, mode, type, pretend_args_size, second_time)
このマクロは、__builtin_saveregs
の使い方とマクロ
EXPAND_BUILTIN_SAVEREGS
の定義の仕方に別の選択肢を提供する。
このマクロを使って、無名のレジスタ引数をスタックに格納し、
全ての引数がスタック上に連続して渡されたように見せることができる。
一旦これをやっておくと、varargs の標準の実装を使うことができる。
varargs の標準の実装は、全ての引数をスタックで渡す機種に対して
使うことができる。
引数 args_so_far はデータ構造 CUMULATIVE_ARGS
である。
このデータ構造は、名前つき引数を処理した後の値を含む。
引数 mode と type は最後の名前つき引数を、
そのマシンモードとデータ型をツリーノードとして記述する。
このマクロの実装では次の二つを行なう必要がある。
まず第一に、名前つき引数用に使われていない全ての引数レジスタを
スタックにプッシュする。次に、このようにしてプッシュされたデータの
大きさを int
型の値の変数に格納する。この変数の名前は、
引数 pretend_args_size で提供される。ここで格納した値は、
スタックフレームの設定で使われる追加のオフセットとして機能する。
無名引数をプッシュするコードを、コンパイル時にそのデータ型を知ることなし
に生成しなければならないので、SETUP_INCOMING_VARARGS
は、
引数レジスタのカテゴリが一個しかなく、全データ型にたいして等しくそれを
使う機種でのみ、意味がある。
引数 second_time がゼロでないと、この関数の引数が二回目に
解析されることを意味する。これはインライン展開関数の場合に起こり、
ソースファイルの終りに達するまで実際にコンパイルされない。
マクロ SETUP_INCOMING_VARARGS
は、この場合何も命令を生成すべきでない。
STRICT_ARGUMENT_NAMING
関数の引数が渡される位置が、その引数が名前付きの引数かどうかに 依存するなら、このマクロをゼロでない値に定義する。
このマクロは、FUNCTION_ARG
への引数 named が
varargs と stdarg 関数に対してどのようにして設定されるかを制御する。
このマクロがゼロでない値を返すなら、引数 named は名前つき引数に
対しては常に真になり、名無し引数では偽になる。
このマクロが値ゼロを返すが、SETUP_INCOMING_VARARGS
が
定義されている場合は、全ての引数が名前つきとして扱われる。
それ以外の場合は、全ての名前つき引数は、最後の引数を除いて、
名前付きとして扱われる。
常にゼロを返すなら、このマクロを定義する必要はない。
PRETEND_OUTGOING_VARARGS_NAMED
ABI を条件により変更して、一方は SETUP_INCOMING_VARARGS
が
定義されている場合に動作するようにし、もう一方は、
SETUP_INCOMING_VARARGS
も STRICT_ARGUMENT_NAMING
も
定義されていないかのように動作させる必要がある場合には、
このマクロを、SETUP_INCOMING_VARARGS
が使われている場合には
ゼロでない値を返すように定義し、使われていない場合にはゼロを
返すようにする。該当しな場合は、このマクロを定義すべきではない。
This document was generated
using texi2html 1.78.