バックパッチ
Ifブロックや、Forブロックや、Whileブロックをコード生成する時の話 前提知識が必要なので、一旦ここに示す。
しかもelse節のない時の話限定(?)
いや、たぶんだが、elseがあっても必要だなmrsekut.icon
(JVMでは?)ASTから以下のような構成のコードを生成する
code:gen
0: <condition>のオブジェクトコード
// ここに条件比較などの処理を生成する
n: (条件付き分岐命令) goto @next // else節にあたるnextに飛ぶだけ
j: <statement>のオブジェクトコード
// ここにthen節の処理を生成する
k: @next
// ここにこのifブロックの次の処理が生成される
実際のコードとの対応はこんなイメージ
https://gyazo.com/5d46b8a688e0eb3b653dbbd4b09514ce
左が実際のコード、右がIR
@nextは番地。
0,n,j,kは番地
goto Nでオフセットで飛び先を指定する
このとき、上から生成していくわけだが、「(条件付き分岐命令)」のところを生成する時に@nextの番地がわかっていないといけない
が、まだstatementのところを生成していないので、@nextが幾つになるのかが判断できない
じゃあどうするか?
ここでバックパッチです
一旦goto 0;としてstatementのオブジェクトコードの生成に取り掛かる
つまり、offsetが0なので、自分自身を指していることになる
本来はgoto k-nとしたい
取り掛かる前にここの番地nをローカル変数として保持しておく
あとで戻るために
satementの生成が終わり@nextの番地が確定したら、0からk-nに修正する
この一旦進めて、あとで戻って修正する方法をバックパッチという
この@nextの番地が1byteで足りるのか問題も起こり得る
statementのところが長すぎると1byteでは足りない
対処法 ref 『コンパイラとバーチャルマシン』.icon p.83