コンパイラ作成(85) double型の比較演算子
今回の目標
前回の残りの比較演算をサポートするよ。
// double型の比較 int main() { double x; x = 1.5; if( x != 1.5 ) printf("true\n"); else printf("false\n"); x = 1.0; if( x != 1.5 ) printf("true\n"); else printf("false\n"); }
コード生成部
修正箇所は前回と同じ。
# ニーモニック def mnemonic(op, type) if type == "double" then if op.str == "+" then return "addsd " elsif op.str == "-" then return "subsd " elsif op.str == "*" then return "mulsd " elsif op.str == "/" then return "divsd " elsif op.str == "%" then return "divsd " elsif op.str == "==" then return "ucomisd" elsif op.str == "!=" then return "ucomisd" elsif op.str == "<" || op.str == "<" || op.str == ">" || op.str == "<=" || op.str == ">=" then return "ucomisd" else perror "unknown operator \"" + op.str + "\"" end else if op.str == "+" then return "add " elsif op.str == "-" then return "sub " elsif op.str == "*" then return "imul" elsif op.str == "/" then return "idiv" elsif op.str == "%" then return "idiv" elsif op.str == "==" then return "cmp " elsif op.str == "!=" then return "cmp " elsif op.str == "<" || op.str == "<" || op.str == ">" || op.str == "<=" || op.str == ">=" then return "cmp " else perror "unknown operator \"" + op.str + "\"" end end end
# 左被演算子と右被演算子とで計算 if op.str == "==" then codegen " " + ostr + " #{reg}, " + str if type_l == "double" then codegen " sete al" codegen " setnp r10b" codegen " and al, r10b" codegen " and eax, 1" type_l = "int" else codegen " sete al" codegen " and eax, 1" end elsif op.str == "!=" then codegen " " + ostr + " #{reg}, " + str if type_l == "double" then codegen " setne al" codegen " setp r10b" codegen " or al, r10b" codegen " and eax, 1" type_l = "int" else codegen " setne al" codegen " and eax, 1" end elsif op.str == "<" then codegen " " + ostr + " #{reg}, " + str if type_l == "double" then codegen " setb al" codegen " and eax, 1" type_l = "int" else codegen " setl al" codegen " and eax, 1" end elsif op.str == ">" then codegen " " + ostr + " #{reg}, " + str if type_l == "double" then codegen " seta al" codegen " and eax, 1" type_l = "int" else codegen " setg al" codegen " and eax, 1" end elsif op.str == "<=" then codegen " " + ostr + " #{reg}, " + str if type_l == "double" then codegen " setbe al" codegen " and eax, 1" type_l = "int" else codegen " setle al" codegen " and eax, 1" end elsif op.str == ">=" then codegen " " + ostr + " #{reg}, " + str if type_l == "double" then codegen " setae al" codegen " and eax, 1" type_l = "int" else codegen " setge al" codegen " and eax, 1" end
前回同様、clang先輩の出力結果を参考に。
動作テスト
~/myc$ myc p16.myc ~/myc$ ./p16 false true ~/myc$
大丈夫だね。残りの演算子についても同様にチェック。地味で面倒な作業だけどサボらずやったよ。これだけじゃ面白くないんでもういっちょやってみるよ。
// モンテカルロ法による円周率の計算 extern double sqrt(double x); extern size_t time(size_t *t); extern void srand48(size_t seed); extern double drand48(); int main() { size_t t; srand48(time(&t)); double count = 0.0; for(int i = 0; i < 1000000; i = i + 1) { double x = drand48(); double y = drand48(); if( x*x + y*y <= 1.0 ) count = count + 1.0; } printf("pi = %10.8f\n",count / 1000000.0 * 4.0); }
どうかな。
~/myc$ myc p21.myc ~/myc$ ./p21 pi = 3.14105600 ~/myc$
できたできた。countがdouble型になってるのは型変換がまだできないから。これも宿題だなあ。あとtime(0)とかtime(NULL)とか書けるようにしたいなあ。さて次は単項演算子かな。