// File: /workspace/github_c_makefile_star2_O2/takoeight0821[P]hoc_nyan/src/gen_ir.c
// Function: emit_stmt
static void emit_stmt(Node* node) {
  switch (node->tag) {
  case NDEFVAR: {
    emit_ir(alloc(size_of(type_of(node))));
    /* assign_var(node->name, new); */
    break;
  }
  case NEXPR_STMT: {
    emit_expr(node->expr);
    break;
  }
  case NRETURN: {
    if (node->expr) {
      IReg* val = emit_expr(node->expr);
      IR* new = calloc(1, sizeof(IR));
      new->op = IRET;
      new->r1 = val;
      emit_ir(new);
    } else {
      IR* new = calloc(1, sizeof(IR));
      new->op = IRET;
      emit_ir(new);
    }
    break;
  }
  case NBLOCK: {
    // FIXME: スコープを正しく切る
    // VarEnv* prev = var_env; 
    for (int i = 0; i < node->stmts->length; i++) {
      emit_stmt(node->stmts->ptr[i]);
    }
    // var_env = prev;
    break;
  }
  case NIF: {
    IReg* cond = emit_expr(node->cond);

    char* then_label = new_label("then");
    char* end_label = new_label("endif");

    emit_ir(branch(cond, then_label, end_label));

    in_new_block(then_label);
    emit_stmt(node->then);

    in_new_block(end_label);
    break;
  }
  case NIFELSE: {
    IReg* cond = emit_expr(node->cond);

    char* then_label = new_label("then");
    char* else_label = new_label("else");
    char* end_label = new_label("endif");

    emit_ir(branch(cond, then_label, else_label));

    in_new_block(then_label);
    emit_stmt(node->then);
    emit_ir(jmp(end_label));

    in_new_block(else_label);
    emit_stmt(node->els);

    in_new_block(end_label);
    break;
  }
  case NCOMMA: {
    // for initializer
    warn_token(node->token, "warning(expr_stmt): NCOMMA");
    emit_expr(node->lhs);
    emit_expr(node->rhs);
    break;
  }
  case NWHILE: {
    char* begin = new_label("begin");
    char* end = new_label("end");
    char* prev_break = break_label;
    break_label = end;

    in_new_block(begin);
    IReg* cond = emit_expr(node->cond);
    IReg* zero = new_reg(size_of(type_of(node->cond)));
    emit_ir(imm(zero, 0));
    IReg* cond1 = new_reg(size_of(type_of(node->cond)));
    emit_ir(new_binop_ir(IEQ, cond1, cond, zero));
    char* body = new_label("body");
    emit_ir(branch(cond1, end, body));

    in_new_block(body);
    emit_stmt(node->body);
    emit_ir(jmp(begin));

    in_new_block(end);
    break_label = prev_break;
    break;
  }
  case NFOR: {
    char* begin = new_label("begin");
    char* end = new_label("end");
    char* prev_break = break_label;
    break_label = end;

    if (node->init) {
      emit_expr(node->init);
    }

    in_new_block(begin);

    assert(node->cond);
    char* body = new_label("body");
    if (node->cond) {
      IReg* cond = emit_expr(node->cond);
      IReg* cond1 = new_reg(size_of(type_of(node->cond)));
      IReg* zero = new_reg(size_of(type_of(node->cond)));
      emit_ir(imm(zero, 0));
      emit_ir(new_binop_ir(IEQ, cond1, cond, zero));

      emit_ir(branch(cond1, end, body));
    } else {
      emit_ir(jmp(body));
    }

    in_new_block(body);
    emit_stmt(node->body);
    if (node->step) {
      emit_expr(node->step);
    }
    emit_ir(jmp(begin));

    in_new_block(end);
    break_label = prev_break;

    break;
  }
  case NSWITCH: {
    IReg* val = emit_expr(node->expr);

    for (size_t i = 0; i < node->cases->length; i++) {
      Node* clause = node->cases->ptr[i];

      if (clause->tag == NDEFAULT) {
        emit_ir(jmp(clause->name));
      } else {
        IReg* c_val = emit_expr(clause->expr);
        IReg* cond = new_reg(4);
        emit_ir(new_binop_ir(IEQ, cond, val, c_val));
        char* next = new_label("next");
        emit_ir(branch(cond, clause->name, next));
        in_new_block(next);
      }
    }
    char* prev_break = break_label;
    break_label = new_label("break");
    emit_stmt(node->body);

    in_new_block(break_label);
    break_label = prev_break;
    
    break;
  }
  case NCASE: {
    in_new_block(node->name);
    emit_stmt(node->body);
    break;
  }
  case NDEFAULT: {
    in_new_block(node->name);
    emit_stmt(node->body);
    break;
  }
  case NBREAK: {
    assert(break_label);
    emit_ir(jmp(break_label));
    break;
  }
  case NINT: case NVAR: case NGVAR:
  case NADD: case NSUB: case NMUL: case NDIV: case NMOD:
  case NLT: case NLE: case NGT: case NGE: case NEQ: case NNE:
  case NLOGNOT: case NNOT: case NAND: case NOR: case NXOR:
  case NLOGAND: case NLOGOR: case NASSIGN: case NCALL:
  case NADDR: case NDEREF: case NMEMBER: case NSIZEOF: case NCAST:
    bad_token(node->token, "error: expression cannot appear on here");
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
leaq 0x7dc3(%rip), %r14      # 0xca8c
movl (%rbx), %eax
cmpq $0x28, %rax
ja 0x520d
movslq (%r14,%rax,4), %rax
addq %r14, %rax
jmpq *%rax
movq 0x40(%rbx), %rdi
callq 0x4c06
movq 0x80(%rbx), %rbx
jmp 0x4cc9
leaq 0x7b0e(%rip), %rdi      # 0xc805
callq 0x4be6
movq %rax, %r15
leaq 0x7509(%rip), %rdi      # 0xc20f
callq 0x4be6
movq %rax, %r14
movq 0xd42b(%rip), %r13      # 0x12140
movq %rax, 0xd424(%rip)      # 0x12140
movq 0x70(%rbx), %rdi
testq %rdi, %rdi
je 0x4d2a
callq 0x526a
movq %r15, %rdi
callq 0x4c06
cmpq $0x0, 0x58(%rbx)
je 0x522c
leaq 0x7ef0(%rip), %rdi      # 0xcc34
callq 0x4be6
movq %rax, %r12
movq 0x58(%rbx), %rdi
testq %rdi, %rdi
je 0x51bc
callq 0x526a
movq %rax, 0x8(%rsp)
movq 0x58(%rbx), %rdi
callq 0x76db
movq %rax, %rdi
callq 0x75fe
movq %rax, %rdi
callq 0x4c6a
movq %rax, %rbp
movq 0x58(%rbx), %rdi
callq 0x76db
movq %rax, %rdi
callq 0x75fe
movq %rax, %rdi
callq 0x4c6a
movq %r12, 0x10(%rsp)
movq %r14, %r12
movq %r15, %r14
movq %r13, %r15
movq %rax, %r13
movq %rax, %rdi
xorl %esi, %esi
callq 0x5bb9
movq %rax, %rdi
callq 0x4c47
pushq $0xb
popq %rdi
movq %rbp, %rsi
movq 0x8(%rsp), %rdx
movq %r13, %rcx
movq %r15, %r13
movq %r14, %r15
movq %r12, %r14
movq 0x10(%rsp), %r12
callq 0x6c56
movq %rax, %rdi
callq 0x4c47
movq %rbp, %rdi
movq %r14, %rsi
movq %r12, %rdx
callq 0x5b7f
jmp 0x51c4
xorl %r14d, %r14d
movq 0x30(%rbx), %rax
cmpq %r14, 0x10(%rax)
jbe 0x520d
movq (%rax), %rax
movq (%rax,%r14,8), %rdi
callq 0x4cb1
incq %r14
jmp 0x4dfa
movq 0xd320(%rip), %rdi      # 0x12140
testq %rdi, %rdi
je 0x524b
callq 0x5ba7
jmp 0x51a6
movq %rbx, %rdi
callq 0x76db
movq %rax, %rdi
callq 0x75fe
movl %eax, %edi
callq 0x4c5a
jmp 0x51a6
leaq 0x79af(%rip), %rdi      # 0xc805
callq 0x4be6
movq %rax, %r15
leaq 0x73aa(%rip), %rdi      # 0xc20f
callq 0x4be6
movq %rax, %r14
movq 0xd2cc(%rip), %rax      # 0x12140
movq %rax, 0x8(%rsp)
movq %r14, 0xd2c0(%rip)      # 0x12140
movq %r15, %rdi
callq 0x4c06
movq 0x58(%rbx), %rdi
callq 0x526a
movq %rax, %r12
movq 0x58(%rbx), %rdi
callq 0x76db
movq %rax, %rdi
callq 0x75fe
movq %rax, %rdi
callq 0x4c6a
movq %rax, %r13
movq %rax, %rdi
xorl %esi, %esi
callq 0x5bb9
movq %rax, %rdi
callq 0x4c47
movq 0x58(%rbx), %rdi
callq 0x76db
movq %rax, %rdi
callq 0x75fe
movq %rax, %rdi
callq 0x4c6a
movq %rax, %rbp
pushq $0xb
popq %rdi
movq %rax, %rsi
movq %r12, %rdx
movq %r13, %rcx
callq 0x6c56
movq %rax, %rdi
callq 0x4c47
leaq 0x7d36(%rip), %rdi      # 0xcc34
callq 0x4be6
movq %rax, %r12
movq %rbp, %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x5b7f
movq %rax, %rdi
callq 0x4c47
movq %r12, %rdi
callq 0x4c06
movq 0x80(%rbx), %rdi
callq 0x4cb1
movq %r15, %rdi
callq 0x5ba7
movq %rax, %rdi
callq 0x4c47
movq %r14, %rdi
callq 0x4c06
movq 0x8(%rsp), %rax
movq %rax, 0xd1ec(%rip)      # 0x12140
jmp 0x520d
movq 0x8(%rbx), %rdi
leaq 0x7cb5(%rip), %rsi      # 0xcc19
callq 0xa048
movq 0x18(%rbx), %rdi
callq 0x526a
movq 0x20(%rbx), %rdi
jmp 0x5037
movq 0x58(%rbx), %rdi
callq 0x526a
movq %rax, %r12
leaq 0x7c86(%rip), %rdi      # 0xcc14
callq 0x4be6
movq %rax, %r13
leaq 0x784a(%rip), %rdi      # 0xc7e7
callq 0x4be6
movq %rax, %r15
leaq 0x7087(%rip), %rdi      # 0xc033
callq 0x4be6
movq %rax, %r14
movq %r12, %rdi
movq %r13, %rsi
movq %r15, %rdx
callq 0x5b7f
movq %rax, %rdi
callq 0x4c47
movq %r13, %rdi
callq 0x4c06
movq 0x60(%rbx), %rdi
callq 0x4cb1
movq %r14, %rdi
callq 0x5ba7
movq %rax, %rdi
callq 0x4c47
movq %r15, %rdi
callq 0x4c06
movq 0x68(%rbx), %rdi
callq 0x4cb1
movq %r14, %rdi
jmp 0x509e
movq 0x38(%rbx), %rdi
testq %rdi, %rdi
je 0x5195
callq 0x526a
movq %rax, %rbx
pushq $0x1
popq %rdi
pushq $0x58
popq %rsi
callq 0x20f0
movl $0x1a, (%rax)
movq %rbx, 0x18(%rax)
jmp 0x51a6
movq 0x38(%rbx), %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x526a
movq 0x58(%rbx), %rdi
callq 0x526a
movq %rax, %r14
leaq 0x7bb7(%rip), %rdi      # 0xcc14
callq 0x4be6
movq %rax, %r15
leaq 0x6fc7(%rip), %rdi      # 0xc033
callq 0x4be6
movq %rax, %r12
movq %r14, %rdi
movq %r15, %rsi
movq %rax, %rdx
callq 0x5b7f
movq %rax, %rdi
callq 0x4c47
movq %r15, %rdi
callq 0x4c06
movq 0x60(%rbx), %rdi
callq 0x4cb1
movq %r12, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x4c06
movq 0x38(%rbx), %rdi
callq 0x526a
movq %rax, %r14
xorl %ebp, %ebp
movq 0x88(%rbx), %rax
cmpq 0x10(%rax), %rbp
jae 0x515a
movq (%rax), %rax
movq (%rax,%rbp,8), %r12
cmpl $0x26, (%r12)
jne 0x50f2
movq 0x40(%r12), %rdi
callq 0x5ba7
movq %rax, %rdi
callq 0x4c47
jmp 0x5152
movq 0x38(%r12), %rdi
callq 0x526a
movq %rax, %r13
pushq $0x4
popq %rdi
callq 0x4c6a
movq %rax, %r15
pushq $0xb
popq %rdi
movq %rax, %rsi
movq %r14, %rdx
movq %r13, %rcx
callq 0x6c56
movq %rax, %rdi
callq 0x4c47
leaq 0x757c(%rip), %rdi      # 0xc6a6
callq 0x4be6
movq %rax, %r13
movq 0x40(%r12), %rsi
movq %r15, %rdi
movq %rax, %rdx
callq 0x5b7f
movq %rax, %rdi
callq 0x4c47
movq %r13, %rdi
callq 0x4c06
incq %rbp
jmp 0x50bf
movq 0xcfdf(%rip), %r14      # 0x12140
leaq 0x7702(%rip), %rdi      # 0xc86a
callq 0x4be6
movq %rax, 0xcfcc(%rip)      # 0x12140
movq 0x80(%rbx), %rdi
callq 0x4cb1
movq 0xcfb9(%rip), %rdi      # 0x12140
callq 0x4c06
movq %r14, 0xcfad(%rip)      # 0x12140
jmp 0x520d
pushq $0x1
popq %rdi
pushq $0x58
popq %rsi
callq 0x20f0
movl $0x1a, (%rax)
movq %rax, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x4c47
movq %r12, %rdi
callq 0x5ba7
movq %rax, %rdi
callq 0x4c47
movq %r12, %rdi
callq 0x4c06
movq 0x80(%rbx), %rdi
callq 0x4cb1
movq 0x78(%rbx), %rdi
testq %rdi, %rdi
je 0x51ee
callq 0x526a
movq %r15, %rdi
callq 0x5ba7
movq %rax, %rdi
callq 0x4c47
movq %r14, %rdi
callq 0x4c06
movq %r13, 0xcf33(%rip)      # 0x12140
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%rbx), %rdi
leaq 0x7a40(%rip), %rsi      # 0xcc67
callq 0xa124
leaq 0x7a06(%rip), %rdi      # 0xcc39
leaq 0x79ab(%rip), %rsi      # 0xcbe5
leaq 0x7a03(%rip), %rcx      # 0xcc44
movl $0x220, %edx            # imm = 0x220
callq 0x20c0
leaq 0x7a09(%rip), %rdi      # 0xcc5b
leaq 0x798c(%rip), %rsi      # 0xcbe5
leaq 0x79e4(%rip), %rcx      # 0xcc44
movl $0x25f, %edx            # imm = 0x25F
callq 0x20c0