Presentation is loading. Please wait.

Presentation is loading. Please wait.

コンパイラ資料 実行時環境.

Similar presentations


Presentation on theme: "コンパイラ資料 実行時環境."— Presentation transcript:

1 コンパイラ資料 実行時環境

2 本日のメニュー: 関数の翻訳 関数によるスタック利用の詳細 関数定義・呼び出しの翻訳(AST→IR) x86 MASM assembler
本日のメニュー: 関数の翻訳 関数によるスタック利用の詳細 x86 MASM assembler スタック領域(フレーム)の管理・利用のコード 関数定義・呼び出しの翻訳(AST→IR) FUN, ARGS, CALL, RTNノード

3 実行時環境 activation record
関数呼び出しを持つ言語の場合  関数の呼び出しごとに割り当てられるメモリ領域のこと、またその領域に格納される情報 通常はスタックを用いるのでactivation recordのことをスタックフレームまたは単にフレームとよぶ。

4 関数定義と関数呼び出し int foo(int x) //関数定義、呼び出し元(親) { int y; if(x=0)y:=1;
else y=x+ bar(x-1);//関数呼び出し(子) return y; //リターン文 }

5 今のフレーム(自分) 自分を呼び出した親のフレーム フレームのレイアウト 上: 低アドレス 下: 高アドレス 引数0
←esp  スタックポインタ 上: 低アドレス 引数m-1 spills 今のフレーム(自分) 局所変数 退避callee-save 退避ebp ←ebp フレームポインタ 戻りアドレス 引数0 自分を呼び出した親のフレーム 下: 高アドレス 引数n-1 フレームのレイアウト

6 呼び出し動作 call push ebp mov ebp, esp sub esp, (SIZE-2)*WRD,
mov [ebp – WRD ], ebx mov [ebp- 2*WRD ], esi mov [ebp - 3*WRD ], edi body ←esp  mov esp, ebp pop ebp ←ebp  ret

7 呼び出し規約 calling convention
cdecl レジスタesi, edi, ebp, ebxは呼び出し前後で値が変化してはいけない。呼び出された側で使うときは退避してから使い、おわったらもどす。(callee-save) そのほかの(汎用)レジスタは呼び出し側で退避する。(caller-save) 引数の積み込み順序は最後の引数が最初

8 フレームサイズの決定 フレームサイズSIZE未定のまま、次を翻訳時・レジスタ割り当て時にカウントし、IR生成完了後にSIZEを埋める
使用するcallee-save registerの個数 ローカル変数の同時使用個数の最大値 レジスタからあふれた(spill)数の最大数 caller-save退避用含む 呼び出す関数の引数の最大値(関数ごと/一律)

9 関数定義コードの構成 prologue epilogue 関数名のラベル(第1子から取得) (第2子から引数リスト取得)
呼び出し元ベースポインタの退避 ベースポインタ更新 スタックフレームの作成 callee-saveレジスタ退避 関数本体 エピローグラベル callee-saveレジスタ復帰 スタックフレーム解放 呼び出し元ベースポインタ復帰 リターン prologue epilogue

10 prologue/epilogue prologue: push ebp mov ebp, esp
sub esp, (SIZE-2)*WRD mov [ebp-4], ebx, mov [ebp-8], esi mov [ebp-12], edi epilogue : mov edi, [ebp-12] mov esi, [ebp-8] mov ebx, [ebp-4] mov esp, ebp pop ebp ret 使うものだけ 使ったものだけ

11 関数本体からの参照(IDノードで) 自分 親 仮引数 局所変数 引数kはベースポインタのk+2個下 [ebp+(k+2)*WRD]
引数0 ←esp   仮引数 引数kはベースポインタのk+2個下  [ebp+(k+2)*WRD] (k = 0,1,…) 局所変数 出現順(i=0,…)に記号表に場所を登録  [ebp-(i+S+1)*WRD] S=使用するcallee-save reg.の数 引数m-1 spills 自分 局所変数 退避callee-save 退避ebp ←ebp 戻りアドレス 引数0 引数n-1

12 リターン文(RTNノードで) 戻り値(リターン文引数の値)をeaxに置く エピローグラベルにjmp

13 関数呼び出し(Call) 呼び出し側利用レジスタ退避(caller-save) 実引数をespから下(高位)に向かって順に積む
引数jは[esp+j*WRD]  (j=0,…) call XXX 戻り値取り出し, 値置き用レジスタ t にコピー movl t, eax 呼び出し側利用レジスタ復帰

14 呼び出し時の実引数格納場所 自分 親 引数jは [esp+j*WRD ] に格納する。 引数0 ←esp … 引数m-1 spills
局所変数 退避callee-save 退避ebp ←ebp 戻りアドレス 引数0 引数n-1

15 Accessの印字まとめ reg(n) : eax, ebx, ecx, edx, esi, edi (n=0,1,2,3,4,5)
reg(n): [ebp-(WRD*(n-REG_SIZE+L+S+1)] (n>= REG_SIZE=6) formal(n) : [ebp+WRD*(n+2)] //退避ebpのn+2個下(n=0,1,...) local (n) : [ebp -(WRD*(n+S+1)) ] //退避ebpのn+S+1個上(n=0,1,...) arg (n) : [esp+WRD*n]   //esp以下に積む (n=0,1,...) label(n) : L_n  L=関数内の局所変数の数 S=使用したcallee-saveレジスタ数(=退避数) 上下は図の上/下(アドレスの低/高の方向)

16 課題:Print printf(“%d\n”, 5); print文は外部関数(Cの標準ライブラリ)を呼び出す命令列に翻訳する。
Cでつぎの関数呼び出しに対応するアセンブリコードを調べてAST/Printノードの翻訳処理を追加せよ。 printf(“%d\n”, 5); ヒント:第1引数の定数文字列を表す専用Accessを導入せよ。

17 課題:IR_visitor(完全版) 6章のIR_visitorに関数定義、リターン文、関数呼び出しのケースを加筆してIRへの翻訳を完成させよ。 (prologue, epilogueは定型なのでそれぞれ1つのInstrとしてよい。)


Download ppt "コンパイラ資料 実行時環境."

Similar presentations


Ads by Google