[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

17.7.6 引数のレジスタ渡し

この節では、色々な型の引数をレジスタで渡す方法、あるいはスタックで 渡す方法を制御するマクロについて説明する。

FUNCTION_ARG (cum, mode, type, named)

関数の引数がレジスタで渡されるかどうか、そしてどのレジスタで渡されるのかを 制御する C の式を定義する。

引数の cum は、以前の引数を全て要約する。 mode は、引数のマシンモードである。 type は、ツリーノードとしての引数のデータ型か、 未知であれば 0 である(C サポートライブラリ関数の場合)。 named は、通常の引数では 1 になり、呼び出される関数のプロトタイプの ‘’ に対応する引数では 0 になる。

この式の値は、引数を渡すハードレジスタについては reg RTX であり、 引数をスタックで渡す場合は 0 である。

Vax や 68000 のような、通常全ての引数がプッシュされる機種では、 ゼロという定義で充分である。

この式の値は parallel RTX とすることもできる。 これは、一個の引数が複数の位置に置かれて渡される場合に使われる。 この parallel のモードは引数全体のモードにすべきである。 parallel は、任意の個数の expr_list 対を保持する。 そのそれぞれが、引数の一部がどこに渡されるかを記述する。 各 expr_list では、第一オペランドは、引数のこの部分を渡す ハードレジスタを表す reg RTX でなければならない。 そして レジスタ RTX のモードが引数のこの部分の大きさを表す。 expr_list の第二オペランドは、const_int であり、 引数全体のうち、この部分が始まる位置のオフセットを与える。 特別な例外として、parallel RTX の先頭の expr_list の 第一オペランドはゼロであっても良い。 これは、expr_list の第二オペランドから始まるバイト列が スタックに格納され、レジスタには保持されないことを表す。

ANSI ライブラリ ‘stdarg.h’ を、引数の幾つかが通常はレジスタで 渡されるような機種で動作させるようにする普通の方法は、 名前のない引数を代わりにスタックで渡すようにすることである。 これは、named が 0 の場合には常に FUNCTION_ARG が 0 を 返すようにすれば良い。

このマクロを定義するのに MUST_PASS_IN_STACK (mode, type) というマクロを使って、この引数がスタックで渡さなければならない型か どうかを決めることができる。REG_PARM_STACK_SPACE が 定義されていない場合に、このような引数に対して FUNCTION_ARG が ゼロでない値を返すと、コンパイラは異常終了する。 REG_PARM_STACK_SPACE が定義されていると、この引数は スタックで計算された後、レジスタにロードされる。

MUST_PASS_IN_STACK (mode, type)

C の式である。これを評価すると、type 単独でレジスタで渡す方法が わからないときは、ゼロでない値になる。ファイル ‘expr.h’ で 通常適切な定義を定義している。詳細については ‘expr.h’ を参照のこと。

FUNCTION_INCOMING_ARG (cum, mode, type, named)

ターゲットマシンに「レジスタウィンドウ」がある場合にはこのマクロを 定義し、関数から見て引数が入っているレジスタと、呼び出し側が引数を 渡したレジスタが必ずしも同じである必要はないということを指示する。

そういう機種では、FUNCTION_ARG が、 呼び出し側が値を渡すレジスタを計算する。 そして、FUNCTION_INCOMING_ARG を同様の形で定義して、 呼び出される関数にどこに引数が到着するかを知らせるようにする。

FUNCTION_INCOMING_ARG が定義されていなければ、 FUNCTION_ARG が両方の役割を果たす。

FUNCTION_ARG_PARTIAL_NREGS (cum, mode, type, named)

一個の C の式。ある引数の先頭で、レジスタに置かなければならないワード数を 表す。この値は、全体がレジスタで渡されるか、全体がスタックにプッシュされる 引数についてはゼロにならなければならない。

機種によっては、ある種の引数は部分的にレジスタとメモリに分かれて 渡さなければならないことがある。そういう機種では、典型的には、 先頭の n ワードの引数がレジスタで渡され、残りはスタックで 渡される。ある一個の複数語の引数(double や構造体)がその 境界をまたがるなら、その先頭の数ワードをレジスタで渡し、残りは スタックにプッシュしなければならない。このマクロはコンパイラに、 これが何時発生するかとレジスタに行くべき語数を知らせる。

これらの引数に対して FUNCTION_ARG は、この引数に対して 呼び出し側により使われる先頭のレジスタを返すべきである。 同様に、FUNCTION_INCOMING_ARG は、呼び出された側により使われる 先頭のレジスタを返すべきである。

FUNCTION_ARG_PASS_BY_REFERENCE (cum, mode, type, named)

引数が参照で渡されなければならない事を示す C の式。 引数一個につき、その引数のコピーがメモリに作られ、そこへのポインタが、 引数自体の代わりに渡される場合は、ゼロでない値となる。 ポインタは、その型へのポインタを渡すのに適切な方法で渡される。

REG_PARM_STACK_SPACE が定義されない機種では、適切な定義は 以下のようになる。

 
#define FUNCTION_ARG_PASS_BY_REFERENCE\
(CUM, MODE, TYPE, NAMED)  \
  MUST_PASS_IN_STACK (MODE, TYPE)
FUNCTION_ARG_CALLEE_COPIES (cum, mode, type, named)

一個の C の式。定義されていると、不可視の参照で渡された引数のコピーを 作るのが呼び出された関数の責任であるのはいつかを示す。 普通、呼び出し側がコピーを作り、そのコピーのアドレスを呼び出されるルーチンに 渡す。FUNCTION_ARG_CALLEE_COPIES が定義されていて、それが ゼロでなければ、呼び出し側はコピーを作らない。代わりに、 「生の」値へのポインタを渡す。呼び出された関数はこの値を変更しては ならない。この値が変更されないことに決められるなら、コピーを作る必要は ない。それ以外の場合はコピーを作らなければならない。

CUMULATIVE_ARGS

ある C の型。この型は、FUNCTION_ARG の先頭の引数とその他の関連する値 として使われる変数を宣言する。 幾つかのターゲット機種用には、int 型で充分であり、これまでのところ、 その引数のバイト数を保持可能である。

スタックで渡された引数については、CUMULATIVE_ARGS には 一切記録する必要がない。コンパイラは、他の変数群でそれらを記録する。 全ての引数がスタックで渡されるターゲット機種では、 CUMULATIVE_ARGS には何も格納する必要がない。 だが、このデータ構造は存在しなくてはならず、空であってはいけないので、 その場合は int を使うこと。

INIT_CUMULATIVE_ARGS (cum, fntype, libname, indirect)

一個の C の文(セミコロンなし)。この文は、引数リストの先頭の状態を表す 変数 cum を初期化する。変数の型は CUMULATIVE_ARGS である。 fntype の値は、引数を受け取る関数のデータ型を表すツリーノードか、 その引数がコンパイラがサポートしているライブラリ関数に対するものなら 0 である。indirect の値は、間接呼びだし、例えば、関数ポインタを 通しての呼び出しの場合はゼロでない値である。 indirect の値は明示的に指定された関数の呼び出しか、 ライブラリ関数への呼びだし、あるいはコンパイル中の関数の引数を 見つけるのに INIT_CUMULATIVE_ARGSが使われるときは、ゼロである。

コンパイラサポートライブラリ関数への呼び出しを処理する際には、 libname がどれであるかを特定する。libname は、 関数名を文字列として含む symbol_ref RTX である。 libname は、普通の C の関数呼び出しが処理される場合は 0 である。 つまり、このマクロが呼び出されると必ず、libnamefntype の どちらかはゼロでない。だが、両方同時にゼロでない値になることはない。

INIT_CUMULATIVE_INCOMING_ARGS (cum, fntype, libname)

INIT_CUMULATIVE_ARGS とほぼ同じだが、コンパイル中の関数の 引数を見つける目的のために、それを上書きする。 このマクロが定義されていないと、INIT_CUMULATIVE_ARGS が代わりに 使われる。

libname に渡される値は常に 0 である。なぜなら、特別な 呼びだし規約を使うライブラリルーチンは GNU CC でコンパイルされることは 決してないからである。引数 libnameINIT_CUMULATIVE_ARGS との対称性のために存在する。

FUNCTION_ARG_ADVANCE (cum, mode, type, named)

一個の C の文(セミコロンなし)。要約変数 cum を更新して、 引数リストの中のある引数を越えたところまで進める。 modetypenamed の値がその引数を記述する。 一旦これが行なわれると、変数 cum は、FUNCTION_ARG 等を 使って 後続の引数の解析を行なうに適したものになる。

このマクロは、問題の引数がスタックで渡されたものなら何もする必要がない。 コンパイラは、引数に使われるスタック領域の量を特別な助けがなくとも 追跡する方法を知っている。

FUNCTION_ARG_PADDING (mode, type)

一個の C の式。定義されていれば、引数を余分なスペースで詰め込むかどうか、 詰め込むならどちら向きにするかを決める。この式の値は、 enum direction 型でなければならない。upward は引数の 上側に詰め込み、downward は下側を詰め込む。none は 詰め込みをしない。

詰め込みは、いつでも次の FUNCTION_ARG_BOUNDARY の倍数に ちょうど達するだけの量である。このマクロはそれを制御しない。

このマクロには、ほとんどのシステムに対して正しくなる、デフォルトの 定義がある。リトルエンディアンの機種では、デフォルトは上向きに 詰め込みをする。ビッグエンディアンの機種では、int よりも 小さい固定サイズの引数に対しては下向きに、その他の引数については 上向きに詰め込みをする。

FUNCTION_ARG_BOUNDARY (mode, type)

一個の C の式。定義されていれば、指定されたモードとタイプの引数の アラインメント境界をビット単位で与える。これが定義されていないと、 全ての引数について PARM_BOUNDARY が使われる。

FUNCTION_ARG_REGNO_P (regno)

regno が関数の引数が渡されることもあるハードレジスタ番号なら、 ゼロでない値となる C の式である。 この場合の引数には、静的チェーンと構造体値アドレスのような暗黙の引数は 含まない。 多くの機種では、この目的ではレジスタは使えない。関数の引数が 全てスタックで渡されるからである。

LOAD_ARGS_REVERSED

定義されていると、引数がそれぞれ対応する引数レジスタにロードされる 順番が反転され、最後の引数が最初にロードされる。このマクロが 影響するのは、レジスタで渡す引数だけである。


This document was generated using texi2html 1.78.