[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
以下のマクロは、プロファイル用コードの生成を助ける。
FUNCTION_PROFILER (file, labelno)
一個の C の文か複文で、file に、プロファイルサブルーチン mcount
を呼び出すアセンブラコードを出力する。
呼び出しの前に、このアセンブラコードはカウンタ変数のアドレスを、
mcount
がそのアドレスを見つけると想定しているレジスタに
ロードしなければならい。このカウンタ変数の名前は ‘LP’ の後に、
番号 labelno が付いたものなので、fprintf
で ‘LP%d’ と
することでこの名前を生成できる。
アドレスが mcount
にどのように渡されるかの詳細は、
GNU CC ではなく、ユーザのオペレーティングシステム環境により
決まる。それがどういうものであるか調べるには、小さいプログラムを
システムにインストール済みの C コンパイラを使ってプロファイリング用に
コンパイルし、その結果生成されるアセンブラコードを見れば良い。
PROFILE_BEFORE_PROLOGUE
関数のプロファイリング用コードを関数のプロローグコードの前に置くべきなら このマクロを定義する。普通は、プロファイリング用コードはプロローグコードの 後に来る。
FUNCTION_BLOCK_PROFILER (file, labelno)
一個の C の文か複文で、file に、現在のオブジェクトモジュールの
基本ブロックのプロファイリングを初期化するアセンブラコードを出力する。
グローバルなコンパイルフラグ profile_block_flag
で
二つのプロファイリングのモードを区別する。
profile_block_flag != 2
オブジェクトモジュール毎にサブルーチン __bb_init_func
を一度だけ
呼び出すコードを出力する。このサブルーチンにはただ一つの引数として、
そのオブジェクトモジュール内に割り当てられたあるブロックのアドレスを
渡す。
ブロック名はローカルシンボルであり、次の文で作られる。
ASM_GENERATE_INTERNAL_LABEL (buffer, "LPBX", 0); |
もちろん、このマクロの定義だけではなくて、
ASM_GENERATE_INTERNAL_LABEL
の定義も書くわけだから、
このマクロの定義をショートカットして、生成されるとわかっている名前を
使っても良い。
このブロックの先頭のワードは、そのオブジェクトモジュールが既に初期化済み
であればゼロでない値となるフラグである。そのため、まずこのワードを
調べ、フラグがゼロでなければ __bb_init_func
を呼ばないようにする。
labelno には、__bb_init_func
が呼ばれないときの
分岐先ラベルを生成するのに使われる一意的な番号が入る。
アセンブラ言語で書くと、出力すべきコードは以下のようになる。
cmp (LPBX0),0 bne local_label parameter1 <- LPBX0 call __bb_init_func local_label: |
profile_block_flag == 2
サブルーチン __bb_init_trace_func
を呼び出し、二つのパラメータを
渡すコードを出力する。
第一のパラメータは __bb_init_func
と同じである。
二番目のパラメータは、labelno により与えられる関数の先頭の
基本ブロックの番号である。
__bb_init_trace_func
は、オブジェクトモジュールが既に初期化済み
の場合でも、必ず呼び出されなければならないことに注意して欲しい。
アセンブラ言語で書くと、出力すべきコードは以下のようになる。
parameter1 <- LPBX0 parameter2 <- BLOCK_OR_LABEL call __bb_init_trace_func |
BLOCK_PROFILER (file, blockno)
一個の C の文か、複文。この文は file に、
基本ブロック番号 blockno に付随するカウンタをインクリメント
するアセンブラコードを出力する。
グローバルなコンパイルフラグ profile_block_flag
で、
以下の二つのプロファイルモードを区別する。
profile_block_flag != 2
カウンタを直接インクリメントするコードを出力する。基本ブロックは 各コンパイル毎に別々にゼロから始まる番号が付けられる。 基本ブロック番号 blockno に付随するカウンタは、ワードの ベクトルの添え字 blockno の要素にある。 この配列の名前は、以下の文で作られるローカルシンボルである。
ASM_GENERATE_INTERNAL_LABEL (buffer, "LPBX", 2); |
もちろん、このマクロの定義だけではなくて、
ASM_GENERATE_INTERNAL_LABEL
の定義も書くわけだから、
このマクロの定義をショートカットして、生成されるとわかっている名前を
使っても良い。
アセンブラ言語で書くと、出力すべきコードは以下のようになる。
inc (LPBX2+4*BLOCKNO) |
profile_block_flag == 2
グローバルな構造体 __bb
を初期化し、関数 __bb_trace_func
を呼び出すコードを出力する。__bb_trace_func
は、カウンタを
インクリメントする。
__bb
は二つのワードからなる。最初のワードには、blockno
で与えられる、現在の基本ブロックの番号が格納されなければならない。
二番目のワードには、オブジェクトモジュール中に割り当てられたブロックの
アドレスが格納されなければならない。このアドレスは、以下の文で作られる
ラベルで与えられる。
ASM_GENERATE_INTERNAL_LABEL (buffer, "LPBX", 0); |
アセンブラ言語で書くと、出力すべきコードは以下のようになる。
move BLOCKNO -> (__bb) move LPBX0 -> (__bb+4) call __bb_trace_func |
FUNCTION_BLOCK_PROFILER_EXIT (file)
一個の C の文か、複文。この文は、file に関数 __bb_trace_ret
を呼び出すアセンブラコードを出力する。
このアセンブラコードは、グローバルなコンパイルフラグ
profile_block_flag
== 2 の場合だけ出力すべきである。
このマクロは、関数から戻るためのコードが生成される全ての場所で
(例えば、FUNCTION_EPILOGUE
)使う必要がある。
FUNCTION_EPILOGUE
の定義も同様に書かなければならないが、
このマクロを定義することでコンパイラに対し、__bb_trace_ret
の
正しい呼び出しが生成されるよう指示しなければならない。
MACHINE_STATE_SAVE (id)
一個の C の文か、一個の複文。この文は、全レジスタをセーブする。
レジスタは関数呼び出しにより破壊されるものであっても良く、条件コードを含む。
この作業を扱うのに一番必要そうなのは、asm
文だろう。
アセンブラコード中の局所ラベルを文字列 id と連結して、
一意的なラベル名を得ることもできる。
FUNCTION_PROLOGUE
か FUNCTION_EPILOGUE
により
破壊されるレジスタや条件コードは、マクロ FUNCTION_BLOCK_PROFILER
、
FUNCTION_BLOCK_PROFILER_EXIT
、BLOCK_PROFILER
により、
それぞれ __bb_init_trace_func
、__bb_trace_ret
、
__bb_trace_func
の呼び出しに先だって、セーブしなければならない。
MACHINE_STATE_RESTORE (id)
MACHINE_STATE_SAVE
によりセーブされた、条件コードを含む、
全レジスタをリストアする C の文か複文。
FUNCTION_PROLOGUE
か FUNCTION_EPILOGUE
により
破壊されるレジスタや条件コードは、マクロ FUNCTION_BLOCK_PROFILER
、
FUNCTION_BLOCK_PROFILER_EXIT
、BLOCK_PROFILER
により、
それぞれ __bb_init_trace_func
、__bb_trace_ret
、
__bb_trace_func
の呼び出しの後で、リストアしなければならない。
BLOCK_PROFILER_CODE
ブロックプロファイリングをサポートするライブラリで必要な一つの、 あるいは複数の関数。
This document was generated
using texi2html 1.78.