// File: luooofan[P]hblzbd_compiler/src/generate_ir.cpp
// Function: ast::BinaryExpression::GenerateIR(ir::ContextInfo&, std::vector<ir::IR*, std::allocator<ir::IR*>>&)
void BinaryExpression::GenerateIR(ir::ContextInfo &ctx, std::vector<ir::IR *> &gIRList) {
  ir::Opn opn1, opn2;
  IROpKind op;

  auto number = dynamic_cast<Number *>(lhs_.get());
  auto number2 = dynamic_cast<Number *>(&rhs_);
  if ((nullptr != number && number->value_ == 0) || (nullptr != number2 && number2->value_ == 0)) {
    switch (op_) {
      case MUL:
      case DIV:  // 实际上0不能作为div和mod的rhs
      case MOD:
        ctx.opn_ = ir::Opn(OpnType::Imm, 0);
        ctx.shape_.clear();
        return;
    }
  }

  lhs_->GenerateIR(ctx, gIRList);
  opn1 = ctx.opn_;
  CHECK_OPN_INT("lhs exp");

  rhs_.GenerateIR(ctx, gIRList);
  opn2 = ctx.opn_;
  CHECK_OPN_INT("rhs exp");

  if (opn1.type_ == OpnType::Imm && opn2.type_ == OpnType::Imm) {
    int result;
    int num1 = opn1.imm_num_, num2 = opn2.imm_num_;
    switch (op_) {
      case ADD:
        result = num1 + num2;
        break;
      case SUB:
        result = num1 - num2;
        break;
      case MUL:
        result = num1 * num2;
        break;
      case DIV:
        result = num1 / num2;
        break;
      case MOD:
        result = num1 % num2;
        break;
      default:
        // printf("mystery operator code: %d", op_);
        MyAssert(0);
        break;
    }
    ctx.opn_ = ir::Opn(OpnType::Imm, result);
  } else {
    switch (op_) {
      case ADD:
        op = IROpKind::ADD;
        break;
      case SUB:
        op = IROpKind::SUB;
        break;
      case MUL:
        op = IROpKind::MUL;
        break;
      case DIV:
        op = IROpKind::DIV;
        break;
      case MOD:
        op = IROpKind::MOD;
        break;
      default:
        // printf("mystery operator code: %d", op_);
        MyAssert(0);
        break;
    }
    const std::string &res_temp_var = ir::NewTemp();
    // NOTE: 中间变量栈偏移-1 并且不维护scope的dynamic offset
    ir::gScopes[ctx.scope_id_].symbol_table_.insert({res_temp_var, {false, false}});

    ir::Opn temp = ir::Opn(OpnType::Var, res_temp_var, ctx.scope_id_);
    ctx.opn_ = temp;
    gIRList.push_back(new ir::IR(op, opn1, opn2, temp));
  }
}

// Assembly:
subq $0x4f8, %rsp            # imm = 0x4F8
movq %rdi, 0x4f0(%rsp)
movq %rsi, 0x4e8(%rsp)
movq %rdx, 0x4e0(%rsp)
movq 0x4f0(%rsp), %rax
movq %rax, 0xb8(%rsp)
leaq 0x4a0(%rsp), %rdi
callq 0x36950
leaq 0x460(%rsp), %rdi
callq 0x36950
jmp 0x2320b
movq 0xb8(%rsp), %rdi
addq $0x10, %rdi
callq 0x15e00
movq %rax, 0xb0(%rsp)
cmpq $0x0, %rax
je 0x2326c
movq 0xb0(%rsp), %rdi
leaq 0x127baf(%rip), %rsi    # 0x14ade8
leaq 0x1278a0(%rip), %rdx    # 0x14aae0
xorl %eax, %eax
movl %eax, %ecx
callq 0x8410
movq %rax, 0xa8(%rsp)
jmp 0x23278
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
jmp 0x23da0
xorl %eax, %eax
movq %rax, 0xa8(%rsp)
jmp 0x23278
movq 0xb8(%rsp), %rax
movq 0xa8(%rsp), %rcx
movq %rcx, 0x448(%rsp)
movq 0x20(%rax), %rax
movq %rax, 0xa0(%rsp)
cmpq $0x0, %rax
je 0x232cb
movq 0xa0(%rsp), %rdi
leaq 0x127b37(%rip), %rsi    # 0x14ade8
leaq 0x127828(%rip), %rdx    # 0x14aae0
xorl %eax, %eax
movl %eax, %ecx
callq 0x8410
movq %rax, 0x98(%rsp)
jmp 0x232d7
xorl %eax, %eax
movq %rax, 0x98(%rsp)
jmp 0x232d7
movq 0x98(%rsp), %rax
movq %rax, 0x440(%rsp)
xorl %eax, %eax
cmpq 0x448(%rsp), %rax
je 0x23301
movq 0x448(%rsp), %rax
cmpl $0x0, 0xc(%rax)
je 0x23323
xorl %eax, %eax
cmpq 0x440(%rsp), %rax
je 0x233de
movq 0x440(%rsp), %rax
cmpl $0x0, 0xc(%rax)
jne 0x233de
movq 0xb8(%rsp), %rax
movl 0xc(%rax), %eax
addl $0xfffffefb, %eax       # imm = 0xFFFFFEFB
subl $0x2, %eax
ja 0x233dc
jmp 0x2333e
leaq 0x400(%rsp), %rdi
movl $0x1, %esi
xorl %edx, %edx
callq 0x1f160
jmp 0x23354
movq 0x4e8(%rsp), %rdi
addq $0x8, %rdi
leaq 0x400(%rsp), %rsi
callq 0x433c0
jmp 0x2336f
leaq 0x400(%rsp), %rdi
callq 0x1f210
movq 0x4e8(%rsp), %rdi
addq $0x50, %rdi
callq 0x361a0
movl $0x1, 0x3fc(%rsp)
jmp 0x23d71
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
jmp 0x23d93
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
leaq 0x400(%rsp), %rdi
callq 0x1f210
jmp 0x23d93
jmp 0x233de
movq 0xb8(%rsp), %rdi
addq $0x10, %rdi
callq 0x14c70
movq %rax, %rdi
movq 0x4e8(%rsp), %rsi
movq 0x4e0(%rsp), %rdx
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
jmp 0x2340d
movq 0x4e8(%rsp), %rsi
addq $0x8, %rsi
leaq 0x4a0(%rsp), %rdi
callq 0x43230
jmp 0x23428
movq 0x4e8(%rsp), %rdi
addq $0x50, %rdi
callq 0x10a80
testb $0x1, %al
jne 0x2356e
movq 0x4e8(%rsp), %rax
cmpl $0x4, 0x8(%rax)
jne 0x2356e
movq 0xb8(%rsp), %rax
movl 0x8(%rax), %eax
movl %eax, 0x94(%rsp)
movq 0x4e8(%rsp), %rsi
addq $0x10, %rsi
leaq 0xd7e08(%rip), %rdx     # 0xfb280
leaq 0x398(%rsp), %rdi
callq 0xc720
jmp 0x23487
leaq 0xd79bd(%rip), %rdx     # 0xfae4b
leaq 0x3b8(%rsp), %rdi
leaq 0x398(%rsp), %rsi
callq 0xcbd0
jmp 0x234a5
leaq 0xd7650(%rip), %rdx     # 0xfaafc
leaq 0x3d8(%rsp), %rdi
leaq 0x3b8(%rsp), %rsi
callq 0xcbd0
jmp 0x234c3
movl 0x94(%rsp), %edi
leaq 0x3d8(%rsp), %rsi
callq 0x47ce0
jmp 0x234d9
leaq 0x3d8(%rsp), %rdi
callq 0x8728
leaq 0x3b8(%rsp), %rdi
callq 0x8728
leaq 0x398(%rsp), %rdi
callq 0x8728
jmp 0x2356e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
jmp 0x2355c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
jmp 0x2354f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
leaq 0x3d8(%rsp), %rdi
callq 0x8728
leaq 0x3b8(%rsp), %rdi
callq 0x8728
leaq 0x398(%rsp), %rdi
callq 0x8728
jmp 0x23d93
movq 0xb8(%rsp), %rax
movq 0x20(%rax), %rdi
movq 0x4e8(%rsp), %rsi
movq 0x4e0(%rsp), %rdx
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
jmp 0x23595
movq 0x4e8(%rsp), %rsi
addq $0x8, %rsi
leaq 0x460(%rsp), %rdi
callq 0x43230
jmp 0x235b0
movq 0x4e8(%rsp), %rdi
addq $0x50, %rdi
callq 0x10a80
testb $0x1, %al
jne 0x236f6
movq 0x4e8(%rsp), %rax
cmpl $0x4, 0x8(%rax)
jne 0x236f6
movq 0xb8(%rsp), %rax
movl 0x8(%rax), %eax
movl %eax, 0x90(%rsp)
movq 0x4e8(%rsp), %rsi
addq $0x10, %rsi
leaq 0xd7c80(%rip), %rdx     # 0xfb280
leaq 0x338(%rsp), %rdi
callq 0xc720
jmp 0x2360f
leaq 0xd777a(%rip), %rdx     # 0xfad90
leaq 0x358(%rsp), %rdi
leaq 0x338(%rsp), %rsi
callq 0xcbd0
jmp 0x2362d
leaq 0xd74c8(%rip), %rdx     # 0xfaafc
leaq 0x378(%rsp), %rdi
leaq 0x358(%rsp), %rsi
callq 0xcbd0
jmp 0x2364b
movl 0x90(%rsp), %edi
leaq 0x378(%rsp), %rsi
callq 0x47ce0
jmp 0x23661
leaq 0x378(%rsp), %rdi
callq 0x8728
leaq 0x358(%rsp), %rdi
callq 0x8728
leaq 0x338(%rsp), %rdi
callq 0x8728
jmp 0x236f6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
jmp 0x236e4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
jmp 0x236d7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
leaq 0x378(%rsp), %rdi
callq 0x8728
leaq 0x358(%rsp), %rdi
callq 0x8728
leaq 0x338(%rsp), %rdi
callq 0x8728
jmp 0x23d93
cmpl $0x1, 0x4a0(%rsp)
jne 0x238df
cmpl $0x1, 0x460(%rsp)
jne 0x238df
movq 0xb8(%rsp), %rax
movl 0x4a4(%rsp), %ecx
movl %ecx, 0x330(%rsp)
movl 0x464(%rsp), %ecx
movl %ecx, 0x32c(%rsp)
movl 0xc(%rax), %eax
addl $0xfffffefe, %eax       # imm = 0xFFFFFEFE
movl %eax, %ecx
movq %rcx, 0x88(%rsp)
subl $0x5, %eax
ja 0x237ee
movq 0x88(%rsp), %rax
leaq 0xd7300(%rip), %rcx     # 0xfaa60
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl 0x330(%rsp), %eax
addl 0x32c(%rsp), %eax
movl %eax, 0x334(%rsp)
jmp 0x23871
movl 0x330(%rsp), %eax
subl 0x32c(%rsp), %eax
movl %eax, 0x334(%rsp)
jmp 0x23871
movl 0x330(%rsp), %eax
imull 0x32c(%rsp), %eax
movl %eax, 0x334(%rsp)
jmp 0x23871
movl 0x330(%rsp), %eax
cltd
idivl 0x32c(%rsp)
movl %eax, 0x334(%rsp)
jmp 0x23871
movl 0x330(%rsp), %eax
cltd
idivl 0x32c(%rsp)
movl %edx, 0x334(%rsp)
jmp 0x23871
movq 0x1287f3(%rip), %rdi    # 0x14bfe8
leaq 0xd68fc(%rip), %rsi     # 0xfa0f8
callq 0x8330
movq %rax, 0x80(%rsp)
jmp 0x2380b
movq 0x80(%rsp), %rdi
leaq 0xd72f0(%rip), %rsi     # 0xfab0a
callq 0x8330
movq %rax, 0x78(%rsp)
jmp 0x23826
movq 0x78(%rsp), %rdi
leaq 0xd7bb8(%rip), %rsi     # 0xfb3ea
callq 0x8330
movq %rax, 0x70(%rsp)
jmp 0x2383e
movq 0x70(%rsp), %rdi
movl $0x103, %esi            # imm = 0x103
callq 0x8650
movq %rax, 0x68(%rsp)
jmp 0x23854
movq 0x68(%rsp), %rdi
movq 0x128720(%rip), %rsi    # 0x14bf80
callq 0x8380
jmp 0x23867
movl $0xff, %edi
callq 0x8460
movl 0x334(%rsp), %edx
leaq 0x2e8(%rsp), %rdi
movl $0x1, %esi
callq 0x1f160
jmp 0x2388c
movq 0x4e8(%rsp), %rdi
addq $0x8, %rdi
leaq 0x2e8(%rsp), %rsi
callq 0x433c0
jmp 0x238a7
leaq 0x2e8(%rsp), %rdi
callq 0x1f210
jmp 0x23d66
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
leaq 0x2e8(%rsp), %rdi
callq 0x1f210
jmp 0x23d93
movq 0xb8(%rsp), %rax
movl 0xc(%rax), %eax
addl $0xfffffefe, %eax       # imm = 0xFFFFFEFE
movl %eax, %ecx
movq %rcx, 0x60(%rsp)
subl $0x5, %eax
ja 0x2395d
movq 0x60(%rsp), %rax
leaq 0xd7141(%rip), %rcx     # 0xfaa48
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x0, 0x450(%rsp)
jmp 0x239da
movl $0x1, 0x450(%rsp)
jmp 0x239da
movl $0x2, 0x450(%rsp)
jmp 0x239da
movl $0x3, 0x450(%rsp)
jmp 0x239da
movl $0x4, 0x450(%rsp)
jmp 0x239da
movq 0x128684(%rip), %rdi    # 0x14bfe8
leaq 0xd678d(%rip), %rsi     # 0xfa0f8
callq 0x8330
movq %rax, 0x58(%rsp)
jmp 0x23977
movq 0x58(%rsp), %rdi
leaq 0xd7187(%rip), %rsi     # 0xfab0a
callq 0x8330
movq %rax, 0x50(%rsp)
jmp 0x2398f
movq 0x50(%rsp), %rdi
leaq 0xd7a4f(%rip), %rsi     # 0xfb3ea
callq 0x8330
movq %rax, 0x48(%rsp)
jmp 0x239a7
movq 0x48(%rsp), %rdi
movl $0x11a, %esi            # imm = 0x11A
callq 0x8650
movq %rax, 0x40(%rsp)
jmp 0x239bd
movq 0x40(%rsp), %rdi
movq 0x1285b7(%rip), %rsi    # 0x14bf80
callq 0x8380
jmp 0x239d0
movl $0xff, %edi
callq 0x8460
leaq 0x2c0(%rsp), %rdi
callq 0x43010
jmp 0x239e9
leaq 0x2c0(%rsp), %rax
movq %rax, 0x2e0(%rsp)
movq 0x4e8(%rsp), %rax
movslq (%rax), %rsi
leaq 0x128c1d(%rip), %rdi    # 0x14c628
callq 0x183c0
movq %rax, 0x30(%rsp)
movq 0x2e0(%rsp), %rax
movq %rax, 0x38(%rsp)
leaq 0x200(%rsp), %rdi
xorl %edx, %edx
movl %edx, %esi
callq 0x366c0
jmp 0x23a35
movq 0x38(%rsp), %rsi
leaq 0x250(%rsp), %rdi
leaq 0x200(%rsp), %rdx
callq 0x369f0
jmp 0x23a51
movq 0x30(%rsp), %rdi
leaq 0x250(%rsp), %rsi
callq 0x36670
movb %dl, 0x27(%rsp)
movq %rax, 0x28(%rsp)
jmp 0x23a6e
movb 0x27(%rsp), %al
movq 0x28(%rsp), %rcx
movq %rcx, 0x1f0(%rsp)
movb %al, 0x1f8(%rsp)
leaq 0x250(%rsp), %rdi
callq 0x36810
leaq 0x200(%rsp), %rdi
callq 0x36840
movq 0x2e0(%rsp), %rsi
leaq 0x190(%rsp), %rdi
callq 0x81a0
jmp 0x23ab7
movq 0x4e8(%rsp), %rax
movl (%rax), %ecx
leaq 0x1b0(%rsp), %rdi
xorl %esi, %esi
leaq 0x190(%rsp), %rdx
callq 0x36480
jmp 0x23ada
leaq 0x190(%rsp), %rdi
callq 0x8728
movq 0x4e8(%rsp), %rdi
addq $0x8, %rdi
leaq 0x1b0(%rsp), %rsi
callq 0x43230
jmp 0x23b02
movq 0x4e0(%rsp), %rax
movq %rax, 0x10(%rsp)
movl $0xe0, %edi
callq 0x8340
movq %rax, 0x18(%rsp)
jmp 0x23b20
movb $0x1, 0xc7(%rsp)
movl 0x450(%rsp), %eax
movl %eax, 0xc(%rsp)
leaq 0x148(%rsp), %rdi
leaq 0x4a0(%rsp), %rsi
callq 0x43130
jmp 0x23b4a
leaq 0x108(%rsp), %rdi
leaq 0x460(%rsp), %rsi
callq 0x43130
jmp 0x23b61
leaq 0xc8(%rsp), %rdi
leaq 0x1b0(%rsp), %rsi
callq 0x43130
jmp 0x23b78
movl 0xc(%rsp), %esi
movq 0x18(%rsp), %rdi
leaq 0x148(%rsp), %rdx
leaq 0x108(%rsp), %rcx
leaq 0xc8(%rsp), %r8
callq 0x36a60
jmp 0x23ba0
movq 0x10(%rsp), %rdi
movq 0x18(%rsp), %rax
movb $0x0, 0xc7(%rsp)
movq %rax, 0x188(%rsp)
leaq 0x188(%rsp), %rsi
callq 0x185b0
jmp 0x23bc9
leaq 0xc8(%rsp), %rdi
callq 0x1f210
leaq 0x108(%rsp), %rdi
callq 0x1f210
leaq 0x148(%rsp), %rdi
callq 0x1f210
leaq 0x1b0(%rsp), %rdi
callq 0x1f210
leaq 0x2c0(%rsp), %rdi
callq 0x8728
jmp 0x23d66
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
jmp 0x23d57
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
jmp 0x23c5f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
leaq 0x250(%rsp), %rdi
callq 0x36810
leaq 0x200(%rsp), %rdi
callq 0x36840
jmp 0x23d57
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
leaq 0x190(%rsp), %rdi
callq 0x8728
jmp 0x23d57
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
jmp 0x23d4a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
jmp 0x23d2d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
jmp 0x23d20
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
jmp 0x23d13
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x458(%rsp)
movl %eax, 0x454(%rsp)
leaq 0xc8(%rsp), %rdi
callq 0x1f210
leaq 0x108(%rsp), %rdi
callq 0x1f210
leaq 0x148(%rsp), %rdi
callq 0x1f210
testb $0x1, 0xc7(%rsp)
jne 0x23d39
jmp 0x23d48
movq 0x18(%rsp), %rdi
movl $0xe0, %esi
callq 0x8350
jmp 0x23d4a
leaq 0x1b0(%rsp), %rdi
callq 0x1f210
leaq 0x2c0(%rsp), %rdi
callq 0x8728
jmp 0x23d93
movl $0x0, 0x3fc(%rsp)
leaq 0x460(%rsp), %rdi
callq 0x1f210
leaq 0x4a0(%rsp), %rdi
callq 0x1f210
addq $0x4f8, %rsp            # imm = 0x4F8
retq
leaq 0x460(%rsp), %rdi
callq 0x1f210
leaq 0x4a0(%rsp), %rdi
callq 0x1f210
movq 0x458(%rsp), %rdi
callq 0x8670
nopw (%rax,%rax)