先週は、TinyBasicの変数の定義とか代入文のLLVM-IRコード生成部分を説明した。
今週は、行番号とかGOTO文などを説明する。
行番号については、コード生成は簡単だ。
LLVM-IRアセンブラでは、他のアセンブリ言語と同様にラベル定義ができるので、行番号の数字を含んだラベルを生成すればよい。
行番号が10なら「_L10」、
行番号が20なら「_L20」、
とか。
TinyBasicで、
10 A=2
20 B=A*5
などというのがあったら、
_L10: (A=0の処理) _L20: (B=A*5の処理)
とコードを生成すればよいように思える。
しかし、LLVM-IR(llvm-as)ではエラーになる。
LLVM-IRの場合、ラベルは必ず処理のブロックになっていなくてはならず、ブロック終端には必ずジャンプ命令が必要だからだ。
ちょっと面倒なルールだ。
このルールに合わせるため、
br %_L10 _L10: (A=0の処理) br %_L20 _L20: (B=A*5の処理) br 次の行のラベル
などと、br命令を余分に入れる。br命令(branch命令)は、アドレスを指定してジャンプするジャンプ命令だ。
凄く無駄な気がするが、仕方ない。最適化フェーズでこういう余分な部分が削除されるはずなので、自分では特に対策をしない。
GOTO文についても、br命令のコードを出力するだけなので簡単に思えるが、上記と同様の問題が発生する。
例えば、
10 A=2: GOTO 30
20 B=A*5
というのがあったら、
br %_L10 _L10: (A=0の処理) br %_L20 ; (GOTO文のコード生成の分) br %_L20 _L20: (B=A*5の処理) br 次の行のラベル
と書けそうなのだが、2つめのbr %_L20がラベルを持っていないので、
これもダミーのラベルを生成してやる必要がある。
br %_L10 _L10: (A=0の処理) br %_L20 ; (GOTO文のコード生成の分) DUMMY1: ; (GOTO文のせいで生じた余分なダミーのラベル) br %_L20 _L20: (B=A*5の処理) br 次の行のラベル
というようにする。
ダミーのラベルとダミーのジャンプ命令が増えてしまった。
ちなみに、明示的にラベルを生成しないと暗黙のラベルが生成されることになる。
ちょっと分かりにくくなるので、自分で管理して自前のラベルを入れる方が分かりやすくなると思う。
暗黙のラベルのラベル番号は、前回使っていた%1とか%2とかの使い捨てのレジスタ的な変数の番号と共通なので、暗黙に番号が使われてしまうと、急に番号がずれるので分かりにくくなってしまうからだ。
(説明がわかりにくいかも?)