コンパイラ作成(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

codegen_elsの比較演算子の処理部。

    # 左被演算子と右被演算子とで計算
    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)とか書けるようにしたいなあ。さて次は単項演算子かな。