コンパイラ作成(82) double型の複雑な四則演算

今回の目標

前回に続き四則演算。

// double型

int main()
{
    printf("%f\n", 2.0 + 5.0 / 2.0);
}

前回対応できなかった複雑な式。

コード生成部

codegen_elsの括弧の処理部と関数呼出の処理部を修正。

  def codegen_els(op, operand, type_l)
    ostr = mnemonic op, type_l

    # 右被演算子を評価
    type_r = "int"
    if operand.kind_of?(Array) then
      if operand[0].size == 2 && operand[0].kind == TK::ID && operand[1].str == "()" then
        if type_l == "double" then
          codegen "  sub    rsp, 16"
          codegen "  movsd  [rsp], xmm8"
          type_r = codegen_func operand
          codegen "  movsd  xmm9, xmm8"
          codegen "  movsd  xmm8, [rsp]"
          codegen "  add    rsp, 16"
          str = "xmm9"
        else
          codegen "  sub  rsp, 8"
          codegen "  push rax"
          type_r = codegen_func operand
          codegen "  mov  r10d, eax"
          codegen "  pop  rax"
          codegen "  add  rsp, 8"
          str = "r10d"
        end
      else
        if type_l == "double" then
          codegen "  sub    rsp, 16"
          codegen "  movsd  [rsp], xmm8"
          type_r = codegen_el operand
          codegen "  movsd  xmm9, xmm8"
          codegen "  movsd  xmm8, [rsp]"
          codegen "  add    rsp, 16"
          str = "xmm9"
        else
          codegen "  sub  rsp, 8"
          codegen "  push rax"
          type_r = codegen_el operand
          codegen "  mov  r10d, eax"
          codegen "  pop  rax"
          codegen "  add  rsp, 8"
          str = "r10d"
        end
      end

レジスタの退避処理だけど、xmmレジスタはpush/popできないんだね。仕方ないんでrsp弄った後にmovsdするようにしたよ。

動作テスト
~/myc$ myc p10.myc
~/myc$ ./p10
4.500000
~/myc$

お、ちゃんと計算できるようになったよ。今回ので式の途中での関数呼出もできるようになったはずだよなあ。ああ、でももう一回処理を見直した方が良いかな。現状でどこまで実装できたのか分からなくなってきたよ。拙い状況だよ。うーむ。