// File: /workspace/github_c_makefile_star2_O1/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 0x8880(%rip), %r14      # 0xea8c
movl (%rbx), %eax
cmpq $0x28, %rax
ja 0x6a3c
movslq (%r14,%rax,4), %rax
addq %r14, %rax
jmpq *%rax
movq 0x40(%rbx), %rdi
callq 0x61af
movq 0x80(%rbx), %rbx
jmp 0x620c
movl 0xceef(%rip), %edx      # 0x13128
leaq 0x899a(%rip), %r15      # 0xebda
leaq 0x85be(%rip), %rsi      # 0xe805
movq %r15, %rdi
xorl %eax, %eax
callq 0xd7f2
movq %rax, %r14
movl 0xcece(%rip), %edx      # 0x13128
incl %edx
movl %edx, 0xcec6(%rip)      # 0x13128
leaq 0x7fa6(%rip), %rsi      # 0xe20f
movq %r15, %rdi
xorl %eax, %eax
callq 0xd7f2
movq %rax, %r15
incl 0xceac(%rip)            # 0x13128
movq 0xcebd(%rip), %rax      # 0x13140
movq %rax, 0x8(%rsp)
movq %r15, 0xceb1(%rip)      # 0x13140
movq 0x70(%rbx), %rdi
testq %rdi, %rdi
je 0x629d
callq 0x6a99
movq %r14, %rdi
callq 0x61af
cmpq $0x0, 0x58(%rbx)
je 0x6a5b
movl 0xce72(%rip), %edx      # 0x13128
leaq 0x891d(%rip), %rdi      # 0xebda
leaq 0x8970(%rip), %rsi      # 0xec34
xorl %eax, %eax
callq 0xd7f2
incl 0xce57(%rip)            # 0x13128
movq %rax, %r12
movq 0x58(%rbx), %rdi
testq %rdi, %rdi
je 0x69be
callq 0x6a99
movq %rax, 0x10(%rsp)
movq 0x58(%rbx), %rdi
callq 0x9e0f
movq %rax, %rdi
callq 0x9c8c
movq %r14, (%rsp)
movq %rax, %r14
movl $0x1, %edi
movl $0x20, %esi
callq 0x20f0
movq %rax, %rbp
movl 0xce1d(%rip), %eax      # 0x13138
leal 0x1(%rax), %ecx
movl %ecx, 0xce14(%rip)      # 0x13138
movl %eax, 0x4(%rbp)
movq %r14, 0x8(%rbp)
movq 0x58(%rbx), %rdi
callq 0x9e0f
movq %rax, %rdi
callq 0x9c8c
movq %rax, %r14
movl $0x1, %edi
movl $0x20, %esi
callq 0x20f0
movq %rax, %r13
movl 0xcde1(%rip), %eax      # 0x13138
leal 0x1(%rax), %ecx
movl %ecx, 0xcdd8(%rip)      # 0x13138
movl %eax, 0x4(%r13)
movq %r14, 0x8(%r13)
movq (%rsp), %r14
movl $0x1, %edi
movl $0x58, %esi
callq 0x20f0
movq $0x0, (%rax)
movq %r13, 0x10(%rax)
movq 0xcda3(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30b6
movl $0xb, %edi
movq %rbp, %rsi
movq 0x10(%rsp), %rdx
movq %r13, %rcx
callq 0x8cc6
movq 0xcd7b(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30b6
movl $0x18, %edi
callq 0x8cb0
movq %rbp, 0x18(%rax)
movq %r15, 0x38(%rax)
movq %rax, %rcx
addq $0x40, %rcx
jmp 0x69cf
movq 0x30(%rbx), %rax
cmpq $0x0, 0x10(%rax)
je 0x6a3c
xorl %r14d, %r14d
movq (%rax), %rax
movq (%rax,%r14,8), %rdi
callq 0x61f4
incq %r14
movq 0x30(%rbx), %rax
cmpq %r14, 0x10(%rax)
ja 0x63f1
jmp 0x6a3c
movq 0xcd2a(%rip), %rbx      # 0x13140
testq %rbx, %rbx
je 0x6a7a
movl $0x19, %edi
callq 0x8cb0
movq %rbx, 0x30(%rax)
jmp 0x699d
movq %rbx, %rdi
callq 0x9e0f
movq %rax, %rdi
callq 0x9c8c
movq %rax, %rbx
movl $0x12, %edi
callq 0x8cb0
movl %ebx, 0x4(%rax)
jmp 0x699d
movl 0xcccb(%rip), %edx      # 0x13128
leaq 0x8776(%rip), %r15      # 0xebda
leaq 0x839a(%rip), %rsi      # 0xe805
movq %r15, %rdi
xorl %eax, %eax
callq 0xd7f2
movq %rax, %r14
movq %rax, (%rsp)
movl 0xcca6(%rip), %edx      # 0x13128
incl %edx
movl %edx, 0xcc9e(%rip)      # 0x13128
leaq 0x7d7e(%rip), %rsi      # 0xe20f
movq %r15, %rdi
xorl %eax, %eax
callq 0xd7f2
incl 0xcc87(%rip)            # 0x13128
movq %rax, %r15
movq 0xcc95(%rip), %rax      # 0x13140
movq %rax, 0x8(%rsp)
movq %r15, 0xcc89(%rip)      # 0x13140
movq %r14, %rdi
callq 0x61af
movq 0x58(%rbx), %rdi
callq 0x6a99
movq %rax, %r13
movq 0x58(%rbx), %rdi
callq 0x9e0f
movq %rax, %rdi
callq 0x9c8c
movq %rax, %r12
movl $0x1, %edi
movl $0x20, %esi
callq 0x20f0
movq %rax, %rbp
movl 0xcc41(%rip), %eax      # 0x13138
leal 0x1(%rax), %ecx
movl %ecx, 0xcc38(%rip)      # 0x13138
movl %eax, 0x4(%rbp)
movq %r12, 0x8(%rbp)
movl $0x1, %edi
movl $0x58, %esi
callq 0x20f0
movq $0x0, (%rax)
movq %rbp, 0x10(%rax)
movq 0xcc08(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30b6
movq 0x58(%rbx), %rdi
callq 0x9e0f
movq %rax, %rdi
callq 0x9c8c
movq %rax, %r14
movl $0x1, %edi
movl $0x20, %esi
callq 0x20f0
movq %rax, %r12
movl 0xcbd8(%rip), %eax      # 0x13138
leal 0x1(%rax), %ecx
movl %ecx, 0xcbcf(%rip)      # 0x13138
movl %eax, 0x4(%r12)
movq %r14, 0x8(%r12)
movl $0xb, %edi
movq %r12, %rsi
movq %r13, %rdx
movq %rbp, %rcx
callq 0x8cc6
movq 0xcba3(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30b6
movl 0xcb89(%rip), %edx      # 0x13128
leaq 0x868e(%rip), %rsi      # 0xec34
leaq 0x862d(%rip), %rdi      # 0xebda
xorl %eax, %eax
callq 0xd7f2
movq %rax, %r14
incl 0xcb6b(%rip)            # 0x13128
movl $0x18, %edi
callq 0x8cb0
movq %r12, 0x18(%rax)
movq %r15, 0x38(%rax)
movq %r14, 0x40(%rax)
movq 0xcb56(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30b6
movq %r14, %rdi
callq 0x61af
movq 0x80(%rbx), %rdi
callq 0x61f4
movl $0x19, %edi
callq 0x8cb0
movq (%rsp), %rcx
movq %rcx, 0x30(%rax)
jmp 0x6a15
movq 0x8(%rbx), %rdi
leaq 0x85fd(%rip), %rsi      # 0xec19
callq 0xcd5c
movq 0x18(%rbx), %rdi
callq 0x6a99
movq 0x20(%rbx), %rdi
jmp 0x6755
movq 0x58(%rbx), %rdi
callq 0x6a99
movq %rax, %r12
movl 0xcae3(%rip), %edx      # 0x13128
leaq 0x858e(%rip), %r15      # 0xebda
leaq 0x85c1(%rip), %rsi      # 0xec14
movq %r15, %rdi
xorl %eax, %eax
callq 0xd7f2
movq %rax, %r13
movl 0xcac2(%rip), %edx      # 0x13128
incl %edx
movl %edx, 0xcaba(%rip)      # 0x13128
leaq 0x8172(%rip), %rsi      # 0xe7e7
movq %r15, %rdi
xorl %eax, %eax
callq 0xd7f2
movq %rax, %r14
movl 0xcaa0(%rip), %edx      # 0x13128
incl %edx
movl %edx, 0xca98(%rip)      # 0x13128
leaq 0x799c(%rip), %rsi      # 0xe033
movq %r15, %rdi
xorl %eax, %eax
callq 0xd7f2
movq %rax, %r15
incl 0xca7e(%rip)            # 0x13128
movl $0x18, %edi
callq 0x8cb0
movq %r12, 0x18(%rax)
movq %r13, 0x38(%rax)
movq %r14, 0x40(%rax)
movq 0xca69(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30b6
movq %r13, %rdi
callq 0x61af
movq 0x60(%rbx), %rdi
callq 0x61f4
movl $0x19, %edi
callq 0x8cb0
movq %r15, 0x30(%rax)
movq 0xca37(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30b6
movq %r14, %rdi
callq 0x61af
movq 0x68(%rbx), %rdi
callq 0x61f4
movq %r15, %rdi
jmp 0x67fa
movq 0x38(%rbx), %rdi
testq %rdi, %rdi
je 0x6988
callq 0x6a99
movq %rax, %rbx
movl $0x1, %edi
movl $0x58, %esi
callq 0x20f0
movl $0x1a, (%rax)
movq %rbx, 0x18(%rax)
jmp 0x699d
movq 0x38(%rbx), %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x6a99
movq 0x58(%rbx), %rdi
callq 0x6a99
movq %rax, %r14
movl 0xc9ae(%rip), %edx      # 0x13128
leaq 0x8459(%rip), %r12      # 0xebda
leaq 0x848c(%rip), %rsi      # 0xec14
movq %r12, %rdi
xorl %eax, %eax
callq 0xd7f2
movq %rax, %r15
movl 0xc98d(%rip), %edx      # 0x13128
incl %edx
movl %edx, 0xc985(%rip)      # 0x13128
leaq 0x7889(%rip), %rsi      # 0xe033
movq %r12, %rdi
xorl %eax, %eax
callq 0xd7f2
movq %rax, %r12
incl 0xc96b(%rip)            # 0x13128
movl $0x18, %edi
callq 0x8cb0
movq %r14, 0x18(%rax)
movq %r15, 0x38(%rax)
movq %r12, 0x40(%rax)
movq 0xc956(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30b6
movq %r15, %rdi
callq 0x61af
movq 0x60(%rbx), %rdi
callq 0x61f4
movq %r12, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x61af
movq 0x38(%rbx), %rdi
callq 0x6a99
movq %rax, %r14
movq 0x88(%rbx), %rax
cmpq $0x0, 0x10(%rax)
je 0x6935
xorl %r15d, %r15d
movq (%rax), %rax
movq (%rax,%r15,8), %r12
cmpl $0x26, (%r12)
jne 0x6867
movq 0x40(%r12), %r12
movl $0x19, %edi
callq 0x8cb0
movq %r12, 0x30(%rax)
movq 0xc8da(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30b6
jmp 0x6921
movq 0x38(%r12), %rdi
callq 0x6a99
movq %rax, %rbp
movl $0x1, %edi
movl $0x20, %esi
callq 0x20f0
movq %rax, %r13
movl 0xc8ac(%rip), %eax      # 0x13138
leal 0x1(%rax), %ecx
movl %ecx, 0xc8a3(%rip)      # 0x13138
movl %eax, 0x4(%r13)
movq $0x4, 0x8(%r13)
movl $0xb, %edi
movq %r13, %rsi
movq %r14, %rdx
movq %rbp, %rcx
callq 0x8cc6
movq 0xc875(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30b6
movl 0xc85b(%rip), %edx      # 0x13128
leaq 0x8306(%rip), %rdi      # 0xebda
leaq 0x7dcb(%rip), %rsi      # 0xe6a6
xorl %eax, %eax
callq 0xd7f2
movq %rax, %rbp
incl 0xc83d(%rip)            # 0x13128
movq 0x40(%r12), %r12
movl $0x18, %edi
callq 0x8cb0
movq %r13, 0x18(%rax)
movq %r12, 0x38(%rax)
movq %rbp, 0x40(%rax)
movq 0xc823(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30b6
movq %rbp, %rdi
callq 0x61af
incq %r15
movq 0x88(%rbx), %rax
cmpq 0x10(%rax), %r15
jb 0x682e
movq 0xc804(%rip), %r14      # 0x13140
movl 0xc7e6(%rip), %edx      # 0x13128
leaq 0x8291(%rip), %rdi      # 0xebda
leaq 0x7f1a(%rip), %rsi      # 0xe86a
xorl %eax, %eax
callq 0xd7f2
incl 0xc7cb(%rip)            # 0x13128
movq %rax, 0xc7dc(%rip)      # 0x13140
movq 0x80(%rbx), %rdi
callq 0x61f4
movq 0xc7c9(%rip), %rdi      # 0x13140
callq 0x61af
movq %r14, 0xc7bd(%rip)      # 0x13140
jmp 0x6a3c
movl $0x1, %edi
movl $0x58, %esi
callq 0x20f0
movl $0x1a, (%rax)
movq 0xc78c(%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 0x30b6
movl $0x19, %edi
callq 0x8cb0
movq %rax, %rcx
addq $0x30, %rcx
movq %r12, (%rcx)
movq 0xc757(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30b6
movq %r12, %rdi
callq 0x61af
movq 0x80(%rbx), %rdi
callq 0x61f4
movq 0x78(%rbx), %rdi
testq %rdi, %rdi
je 0x6a07
callq 0x6a99
movl $0x19, %edi
callq 0x8cb0
movq %r14, 0x30(%rax)
movq 0xc714(%rip), %rcx      # 0x13130
movq 0x8(%rcx), %rdi
movq %rax, %rsi
callq 0x30b6
movq %r15, %rdi
callq 0x61af
movq 0x8(%rsp), %rax
movq %rax, 0xc704(%rip)      # 0x13140
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%rbx), %rdi
leaq 0x8211(%rip), %rsi      # 0xec67
callq 0xce4d
leaq 0x81d7(%rip), %rdi      # 0xec39
leaq 0x817c(%rip), %rsi      # 0xebe5
leaq 0x81d4(%rip), %rcx      # 0xec44
movl $0x220, %edx            # imm = 0x220
callq 0x20c0
leaq 0x81da(%rip), %rdi      # 0xec5b
leaq 0x815d(%rip), %rsi      # 0xebe5
leaq 0x81b5(%rip), %rcx      # 0xec44
movl $0x25f, %edx            # imm = 0x25F
callq 0x20c0