コンパイラ作成(29) printfのバグ修正
今回の目標
前回のバグの修正をするよ。
int main() { printf("Hello, World!\n"); printf("%s\n","Hello, World!"); printf("%d %d %d\n",1,2,3); printf("%d %d %d %d %d\n",1,2,3,4,5); printf("%d %d %d %d %d\n",1,2,3,4,2*5); }
最期のprintfがバグってちゃんと表示されなかったやつね。
codegen_els
コード生成を修正するよ。
# 式のコード生成(二項演算の右側被演算子) def codegen_els(op, operand) if op.str == "+" then ostr = "add " elsif op.str == "-" then ostr = "sub " elsif op.str == "*" then ostr = "mul " elsif op.str == "/" then ostr = "div " elsif op.str == "==" then ostr = "cmp " else perror "unknown operator \"" + op.str + "\"" end if operand.kind_of?(Array) then if operand[0].size == 2 && operand[0].kind == TK::ID && operand[1].str == "()" then codegen " push rax" codegen " call " + operand[0].str codegen " mov ebx, eax" codegen " pop rax" else codegen " push rax" codegen_el operand codegen " mov ebx, eax" codegen " pop rax" end if op.str == "==" then codegen " " + ostr + " eax, ebx" codegen " sete al" codegen " and eax, 1" elsif op.str == "*" || op.str == "/" then codegen " mov r11, rdx" if op.str == "/" then codegen " xor edx, edx" end codegen " " + ostr + " ebx" codegen " mov rdx, r11" else codegen " " + ostr + " eax, ebx" end elsif operand.kind == TK::NUMBER then if op.str == "==" then codegen " " + ostr + " eax, " + operand.str codegen " sete al" codegen " and eax, 1" elsif op.str == "*" || op.str == "/" then codegen " mov ebx, " + operand.str codegen " mov r11, rdx" if op.str == "/" then codegen " xor edx, edx" end codegen " " + ostr + " ebx" codegen " mov rdx, r11" else codegen " " + ostr + " eax, " + operand.str end end end
乗算除算のところでrdxをr11に退避するようにしたよ。本当はrdxの使用状況に合わせて必要な場合のみ退避すれば良いんだけど、面倒何で無条件に退避するようにしたよ。rdxに値を入れるのは関数呼出の時だけだから、引数をrdxに入れたときにフラグをセットして、printfのコールの後にフラグをリセットすれば良いのかな。やればできるかな。うーん、とりあえずはこのままで良いか。
動作テスト
どうかな。
~/myc$ myc m3.myc ~/myc$ ./m3 Hello, World! Hello, World! 1 2 3 1 2 3 4 5 1 2 3 4 10 ~/myc$
ちゃんと表示されたよ。これで一応printfが使えるようになったよ。まだ引数の数とか制限はあるけどね。これでもう組み込み関数printは必要なくなったのかな。でも動作確認用のソースがprint使いまくってるなあ。あれを全部書き換えるの面倒だから、当面残しておくか。動作確認のためには処理が単純なprintの方が良いような気もするしなあ。
さて次回は何やろうかな。そろそろ変数に手を出してみるかな。ちょっと考えてみたけど難しそうだな。どうするかもうちょっと悩むか。