// File: /workspace/github_c_makefile_star2_O3/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
movl (%rbx), %eax
leal -0x25(%rax), %ecx
cmpl $0x2, %ecx
jae 0x61df
movq 0x40(%rbx), %rdi
callq 0x616d
movq 0x80(%rbx), %rbx
jmp 0x61c3
cmpl $0x28, %eax
ja 0x69f2
movl %eax, %eax
leaq 0x889b(%rip), %rcx      # 0xea8c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x8(%rbx), %rdi
leaq 0x89f2(%rip), %rsi      # 0xebf7
callq 0xcc10
movq 0x18(%rbx), %rdi
callq 0x6a4f
movq 0x20(%rbx), %rdi
jmp 0x668e
movl 0xcf06(%rip), %edx      # 0x13128
leaq 0x89b1(%rip), %r15      # 0xebda
leaq 0x85d5(%rip), %rsi      # 0xe805
movq %r15, %rdi
xorl %eax, %eax
callq 0xd86a
movq %rax, %r14
movl 0xcee5(%rip), %edx      # 0x13128
incl %edx
movl %edx, 0xcedd(%rip)      # 0x13128
leaq 0x7fbd(%rip), %rsi      # 0xe20f
movq %r15, %rdi
xorl %eax, %eax
callq 0xd86a
movq %rax, %r15
incl 0xcec3(%rip)            # 0x13128
movq 0xced4(%rip), %rax      # 0x13140
movq %rax, 0x8(%rsp)
movq %r15, 0xcec8(%rip)      # 0x13140
movq 0x70(%rbx), %rdi
testq %rdi, %rdi
je 0x6286
callq 0x6a4f
movq %r14, %rdi
callq 0x616d
cmpq $0x0, 0x58(%rbx)
je 0x6a11
movl 0xce89(%rip), %edx      # 0x13128
leaq 0x8934(%rip), %rdi      # 0xebda
leaq 0x8965(%rip), %rsi      # 0xec12
xorl %eax, %eax
callq 0xd86a
incl 0xce6e(%rip)            # 0x13128
movq %rax, %r12
movq 0x58(%rbx), %rdi
testq %rdi, %rdi
je 0x6974
callq 0x6a4f
movq %rax, 0x10(%rsp)
movq 0x58(%rbx), %rdi
callq 0x9d62
movq %rax, %rdi
callq 0x9bf4
movq %r14, (%rsp)
movq %rax, %r14
movl $0x1, %edi
movl $0x20, %esi
callq 0x20f0
movq %rax, %rbp
movl 0xce34(%rip), %eax      # 0x13138
leal 0x1(%rax), %ecx
movl %ecx, 0xce2b(%rip)      # 0x13138
movl %eax, 0x4(%rbp)
movq %r14, 0x8(%rbp)
movq 0x58(%rbx), %rdi
callq 0x9d62
movq %rax, %rdi
callq 0x9bf4
movq %rax, %r14
movl $0x1, %edi
movl $0x20, %esi
callq 0x20f0
movq %rax, %r13
movl 0xcdf8(%rip), %eax      # 0x13138
leal 0x1(%rax), %ecx
movl %ecx, 0xcdef(%rip)      # 0x13138
movl %eax, 0x4(%r13)
movq %r14, 0x8(%r13)
movq (%rsp), %r14
movl $0x1, %edi
movl $0x58, %esi
callq 0x20f0
movq %r13, 0x10(%rax)
movq 0xcdc1(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30ae
movl $0xb, %edi
movq %rbp, %rsi
movq 0x10(%rsp), %rdx
movq %r13, %rcx
callq 0x8c2a
movq 0xcd99(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30ae
movl $0x18, %edi
callq 0x8c14
movq %rbp, 0x18(%rax)
movq %r15, 0x38(%rax)
movq %rax, %rcx
addq $0x40, %rcx
jmp 0x6985
movq 0x30(%rbx), %rax
cmpq $0x0, 0x10(%rax)
je 0x69f2
xorl %r14d, %r14d
movq (%rax), %rax
movq (%rax,%r14,8), %rdi
callq 0x61b2
incq %r14
movq 0x30(%rbx), %rax
cmpq %r14, 0x10(%rax)
ja 0x63d3
jmp 0x69f2
movq 0x38(%rbx), %rdi
callq 0x6a4f
movq %rax, %r14
movq 0x88(%rbx), %rax
cmpq $0x0, 0x10(%rax)
je 0x6519
xorl %r15d, %r15d
movq (%rax), %rax
movq (%rax,%r15,8), %r12
cmpl $0x26, (%r12)
jne 0x644b
movq 0x40(%r12), %r12
movl $0x19, %edi
callq 0x8c14
movq %r12, 0x30(%rax)
movq 0xccf6(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30ae
jmp 0x6505
movq 0x38(%r12), %rdi
callq 0x6a4f
movq %rax, %rbp
movl $0x1, %edi
movl $0x20, %esi
callq 0x20f0
movq %rax, %r13
movl 0xccc8(%rip), %eax      # 0x13138
leal 0x1(%rax), %ecx
movl %ecx, 0xccbf(%rip)      # 0x13138
movl %eax, 0x4(%r13)
movq $0x4, 0x8(%r13)
movl $0xb, %edi
movq %r13, %rsi
movq %r14, %rdx
movq %rbp, %rcx
callq 0x8c2a
movq 0xcc91(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30ae
movl 0xcc77(%rip), %edx      # 0x13128
leaq 0x8722(%rip), %rdi      # 0xebda
leaq 0x81e7(%rip), %rsi      # 0xe6a6
xorl %eax, %eax
callq 0xd86a
movq %rax, %rbp
incl 0xcc59(%rip)            # 0x13128
movq 0x40(%r12), %r12
movl $0x18, %edi
callq 0x8c14
movq %r13, 0x18(%rax)
movq %r12, 0x38(%rax)
movq %rbp, 0x40(%rax)
movq 0xcc3f(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30ae
movq %rbp, %rdi
callq 0x616d
incq %r15
movq 0x88(%rbx), %rax
cmpq 0x10(%rax), %r15
jb 0x6412
movq 0xcc20(%rip), %r14      # 0x13140
movl 0xcc02(%rip), %edx      # 0x13128
leaq 0x86ad(%rip), %rdi      # 0xebda
leaq 0x8336(%rip), %rsi      # 0xe86a
xorl %eax, %eax
callq 0xd86a
incl 0xcbe7(%rip)            # 0x13128
movq %rax, 0xcbf8(%rip)      # 0x13140
movq 0x80(%rbx), %rdi
callq 0x61b2
movq 0xcbe5(%rip), %rdi      # 0x13140
callq 0x616d
movq %r14, 0xcbd9(%rip)      # 0x13140
jmp 0x69f2
movq 0x58(%rbx), %rdi
callq 0x6a4f
movq %rax, %r12
movl 0xcbaa(%rip), %edx      # 0x13128
leaq 0x8655(%rip), %r15      # 0xebda
leaq 0x8666(%rip), %rsi      # 0xebf2
movq %r15, %rdi
xorl %eax, %eax
callq 0xd86a
movq %rax, %r13
movl 0xcb89(%rip), %edx      # 0x13128
incl %edx
movl %edx, 0xcb81(%rip)      # 0x13128
leaq 0x8239(%rip), %rsi      # 0xe7e7
movq %r15, %rdi
xorl %eax, %eax
callq 0xd86a
movq %rax, %r14
movl 0xcb67(%rip), %edx      # 0x13128
incl %edx
movl %edx, 0xcb5f(%rip)      # 0x13128
leaq 0x7a63(%rip), %rsi      # 0xe033
movq %r15, %rdi
xorl %eax, %eax
callq 0xd86a
movq %rax, %r15
incl 0xcb45(%rip)            # 0x13128
movl $0x18, %edi
callq 0x8c14
movq %r12, 0x18(%rax)
movq %r13, 0x38(%rax)
movq %r14, 0x40(%rax)
movq 0xcb30(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30ae
movq %r13, %rdi
callq 0x616d
movq 0x60(%rbx), %rdi
callq 0x61b2
movl $0x19, %edi
callq 0x8c14
movq %r15, 0x30(%rax)
movq 0xcafe(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30ae
movq %r14, %rdi
callq 0x616d
movq 0x68(%rbx), %rdi
callq 0x61b2
movq %r15, %rdi
jmp 0x690b
movq 0x38(%rbx), %rdi
testq %rdi, %rdi
je 0x693e
callq 0x6a4f
movq %rax, %rbx
movl $0x1, %edi
movl $0x58, %esi
callq 0x20f0
movl $0x1a, (%rax)
movq %rbx, 0x18(%rax)
jmp 0x6953
movq 0x38(%rbx), %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x6a4f
movq %rbx, %rdi
callq 0x9d62
movq %rax, %rdi
callq 0x9bf4
movq %rax, %rbx
movl $0x12, %edi
callq 0x8c14
movl %ebx, 0x4(%rax)
jmp 0x6953
movl 0xca5c(%rip), %edx      # 0x13128
leaq 0x8507(%rip), %r15      # 0xebda
leaq 0x812b(%rip), %rsi      # 0xe805
movq %r15, %rdi
xorl %eax, %eax
callq 0xd86a
movq %rax, %r14
movq %rax, (%rsp)
movl 0xca37(%rip), %edx      # 0x13128
incl %edx
movl %edx, 0xca2f(%rip)      # 0x13128
leaq 0x7b0f(%rip), %rsi      # 0xe20f
movq %r15, %rdi
xorl %eax, %eax
callq 0xd86a
incl 0xca18(%rip)            # 0x13128
movq %rax, %r15
movq 0xca26(%rip), %rax      # 0x13140
movq %rax, 0x8(%rsp)
movq %r15, 0xca1a(%rip)      # 0x13140
movq %r14, %rdi
callq 0x616d
movq 0x58(%rbx), %rdi
callq 0x6a4f
movq %rax, %r13
movq 0x58(%rbx), %rdi
callq 0x9d62
movq %rax, %rdi
callq 0x9bf4
movq %rax, %r12
movl $0x1, %edi
movl $0x20, %esi
callq 0x20f0
movq %rax, %rbp
movl 0xc9d2(%rip), %eax      # 0x13138
leal 0x1(%rax), %ecx
movl %ecx, 0xc9c9(%rip)      # 0x13138
movl %eax, 0x4(%rbp)
movq %r12, 0x8(%rbp)
movl $0x1, %edi
movl $0x58, %esi
callq 0x20f0
movq %rbp, 0x10(%rax)
movq 0xc9a0(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30ae
movq 0x58(%rbx), %rdi
callq 0x9d62
movq %rax, %rdi
callq 0x9bf4
movq %rax, %r14
movl $0x1, %edi
movl $0x20, %esi
callq 0x20f0
movq %rax, %r12
movl 0xc970(%rip), %eax      # 0x13138
leal 0x1(%rax), %ecx
movl %ecx, 0xc967(%rip)      # 0x13138
movl %eax, 0x4(%r12)
movq %r14, 0x8(%r12)
movl $0xb, %edi
movq %r12, %rsi
movq %r13, %rdx
movq %rbp, %rcx
callq 0x8c2a
movq 0xc93b(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30ae
movl 0xc921(%rip), %edx      # 0x13128
leaq 0x8404(%rip), %rsi      # 0xec12
leaq 0x83c5(%rip), %rdi      # 0xebda
xorl %eax, %eax
callq 0xd86a
movq %rax, %r14
incl 0xc903(%rip)            # 0x13128
movl $0x18, %edi
callq 0x8c14
movq %r12, 0x18(%rax)
movq %r15, 0x38(%rax)
movq %r14, 0x40(%rax)
movq 0xc8ee(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30ae
movq %r14, %rdi
callq 0x616d
movq 0x80(%rbx), %rdi
callq 0x61b2
movl $0x19, %edi
callq 0x8c14
movq (%rsp), %rcx
movq %rcx, 0x30(%rax)
jmp 0x69cb
movq 0x58(%rbx), %rdi
callq 0x6a4f
movq %rax, %r14
movl 0xc89d(%rip), %edx      # 0x13128
leaq 0x8348(%rip), %r12      # 0xebda
leaq 0x8359(%rip), %rsi      # 0xebf2
movq %r12, %rdi
xorl %eax, %eax
callq 0xd86a
movq %rax, %r15
movl 0xc87c(%rip), %edx      # 0x13128
incl %edx
movl %edx, 0xc874(%rip)      # 0x13128
leaq 0x7778(%rip), %rsi      # 0xe033
movq %r12, %rdi
xorl %eax, %eax
callq 0xd86a
movq %rax, %r12
incl 0xc85a(%rip)            # 0x13128
movl $0x18, %edi
callq 0x8c14
movq %r14, 0x18(%rax)
movq %r15, 0x38(%rax)
movq %r12, 0x40(%rax)
movq 0xc845(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30ae
movq %r15, %rdi
callq 0x616d
movq 0x60(%rbx), %rdi
callq 0x61b2
movq %r12, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x616d
movq 0xc81b(%rip), %rbx      # 0x13140
testq %rbx, %rbx
je 0x6a30
movl $0x19, %edi
callq 0x8c14
movq %rbx, 0x30(%rax)
jmp 0x6953
movl $0x1, %edi
movl $0x58, %esi
callq 0x20f0
movl $0x1a, (%rax)
movq 0xc7d6(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x30ae
movl $0x19, %edi
callq 0x8c14
movq %rax, %rcx
addq $0x30, %rcx
movq %r12, (%rcx)
movq 0xc7a1(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30ae
movq %r12, %rdi
callq 0x616d
movq 0x80(%rbx), %rdi
callq 0x61b2
movq 0x78(%rbx), %rdi
testq %rdi, %rdi
je 0x69bd
callq 0x6a4f
movl $0x19, %edi
callq 0x8c14
movq %r14, 0x30(%rax)
movq 0xc75e(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30ae
movq %r15, %rdi
callq 0x616d
movq 0x8(%rsp), %rax
movq %rax, 0xc74e(%rip)      # 0x13140
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%rbx), %rdi
leaq 0x8239(%rip), %rsi      # 0xec45
callq 0xcd01
leaq 0x81ff(%rip), %rdi      # 0xec17
leaq 0x81c6(%rip), %rsi      # 0xebe5
leaq 0x81fc(%rip), %rcx      # 0xec22
movl $0x220, %edx            # imm = 0x220
callq 0x20c0
leaq 0x8202(%rip), %rdi      # 0xec39
leaq 0x81a7(%rip), %rsi      # 0xebe5
leaq 0x81dd(%rip), %rcx      # 0xec22
movl $0x25f, %edx            # imm = 0x25F
callq 0x20c0