// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x110, %rsp            # imm = 0x110
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movl (%rax), %eax
movq %rax, -0x110(%rbp)
subq $0x28, %rax
ja 0x6310
movq -0x110(%rbp), %rax
leaq 0xcedc(%rip), %rcx      # 0x12a60
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x8(%rbp), %rdi
callq 0x9f70
movq %rax, %rdi
callq 0x9d60
movl %eax, %edi
callq 0x5a10
movq %rax, %rdi
callq 0x59e0
jmp 0x6310
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rdi
callq 0x6370
jmp 0x6310
movq -0x8(%rbp), %rax
cmpq $0x0, 0x38(%rax)
je 0x5c14
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rdi
callq 0x6370
movq %rax, -0x10(%rbp)
movl $0x1, %edi
movl $0x58, %esi
callq 0x20d0
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movl $0x1a, (%rax)
movq -0x10(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x18(%rbp), %rdi
callq 0x59e0
jmp 0x5c3a
movl $0x1, %edi
movl $0x58, %esi
callq 0x20d0
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movl $0x1a, (%rax)
movq -0x20(%rbp), %rdi
callq 0x59e0
jmp 0x6310
movl $0x0, -0x24(%rbp)
movslq -0x24(%rbp), %rax
movq -0x8(%rbp), %rcx
movq 0x30(%rcx), %rcx
cmpq 0x10(%rcx), %rax
jae 0x5c7b
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movq (%rax), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x5b50
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0x5c46
jmp 0x6310
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x6370
movq %rax, -0x30(%rbp)
leaq 0xcfbc(%rip), %rdi      # 0x12c54
callq 0x5950
movq %rax, -0x38(%rbp)
leaq 0xc38b(%rip), %rdi      # 0x12033
callq 0x5950
movq %rax, -0x40(%rbp)
movq -0x30(%rbp), %rdi
movq -0x38(%rbp), %rsi
movq -0x40(%rbp), %rdx
callq 0x7370
movq %rax, %rdi
callq 0x59e0
movq -0x38(%rbp), %rdi
callq 0x59a0
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rdi
callq 0x5b50
movq -0x40(%rbp), %rdi
callq 0x59a0
jmp 0x6310
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x6370
movq %rax, -0x48(%rbp)
leaq 0xcf4e(%rip), %rdi      # 0x12c54
callq 0x5950
movq %rax, -0x50(%rbp)
leaq 0xcaa7(%rip), %rdi      # 0x127bd
callq 0x5950
movq %rax, -0x58(%rbp)
leaq 0xc30d(%rip), %rdi      # 0x12033
callq 0x5950
movq %rax, -0x60(%rbp)
movq -0x48(%rbp), %rdi
movq -0x50(%rbp), %rsi
movq -0x58(%rbp), %rdx
callq 0x7370
movq %rax, %rdi
callq 0x59e0
movq -0x50(%rbp), %rdi
callq 0x59a0
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rdi
callq 0x5b50
movq -0x60(%rbp), %rdi
callq 0x73c0
movq %rax, %rdi
callq 0x59e0
movq -0x58(%rbp), %rdi
callq 0x59a0
movq -0x8(%rbp), %rax
movq 0x68(%rax), %rdi
callq 0x5b50
movq -0x60(%rbp), %rdi
callq 0x59a0
jmp 0x6310
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
leaq 0xceb7(%rip), %rsi      # 0x12c59
callq 0xec00
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x6370
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x6370
jmp 0x6310
leaq 0xca0e(%rip), %rdi      # 0x127db
callq 0x5950
movq %rax, -0x68(%rbp)
leaq 0xc408(%rip), %rdi      # 0x121e5
callq 0x5950
movq %rax, -0x70(%rbp)
movq 0x1187b(%rip), %rax     # 0x17668
movq %rax, -0x78(%rbp)
movq -0x70(%rbp), %rax
movq %rax, 0x1186c(%rip)     # 0x17668
movq -0x68(%rbp), %rdi
callq 0x59a0
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x6370
movq %rax, -0x80(%rbp)
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x9f70
movq %rax, %rdi
callq 0x9d60
movq %rax, %rdi
callq 0x5a40
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rdi
xorl %esi, %esi
callq 0x73f0
movq %rax, %rdi
callq 0x59e0
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x9f70
movq %rax, %rdi
callq 0x9d60
movq %rax, %rdi
callq 0x5a40
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rsi
movq -0x80(%rbp), %rdx
movq -0x88(%rbp), %rcx
movl $0xb, %edi
callq 0x8db0
movq %rax, %rdi
callq 0x59e0
leaq 0xcdd5(%rip), %rdi      # 0x12c74
callq 0x5950
movq %rax, -0x98(%rbp)
movq -0x90(%rbp), %rdi
movq -0x70(%rbp), %rsi
movq -0x98(%rbp), %rdx
callq 0x7370
movq %rax, %rdi
callq 0x59e0
movq -0x98(%rbp), %rdi
callq 0x59a0
movq -0x8(%rbp), %rax
movq 0x80(%rax), %rdi
callq 0x5b50
movq -0x68(%rbp), %rdi
callq 0x73c0
movq %rax, %rdi
callq 0x59e0
movq -0x70(%rbp), %rdi
callq 0x59a0
movq -0x78(%rbp), %rax
movq %rax, 0x1175d(%rip)     # 0x17668
jmp 0x6310
leaq 0xc8c4(%rip), %rdi      # 0x127db
callq 0x5950
movq %rax, -0xa0(%rbp)
leaq 0xc2bb(%rip), %rdi      # 0x121e5
callq 0x5950
movq %rax, -0xa8(%rbp)
movq 0x1172b(%rip), %rax     # 0x17668
movq %rax, -0xb0(%rbp)
movq -0xa8(%rbp), %rax
movq %rax, 0x11716(%rip)     # 0x17668
movq -0x8(%rbp), %rax
cmpq $0x0, 0x70(%rax)
je 0x5f6a
movq -0x8(%rbp), %rax
movq 0x70(%rax), %rdi
callq 0x6370
movq -0xa0(%rbp), %rdi
callq 0x59a0
movq -0x8(%rbp), %rax
cmpq $0x0, 0x58(%rax)
je 0x5f83
jmp 0x5fa2
leaq 0xccef(%rip), %rdi      # 0x12c79
leaq 0xcc94(%rip), %rsi      # 0x12c25
movl $0x220, %edx            # imm = 0x220
leaq 0xcce7(%rip), %rcx      # 0x12c84
callq 0x20b0
leaq 0xcccb(%rip), %rdi      # 0x12c74
callq 0x5950
movq %rax, -0xb8(%rbp)
movq -0x8(%rbp), %rax
cmpq $0x0, 0x58(%rax)
je 0x6081
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x6370
movq %rax, -0xc0(%rbp)
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x9f70
movq %rax, %rdi
callq 0x9d60
movq %rax, %rdi
callq 0x5a40
movq %rax, -0xc8(%rbp)
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x9f70
movq %rax, %rdi
callq 0x9d60
movq %rax, %rdi
callq 0x5a40
movq %rax, -0xd0(%rbp)
movq -0xd0(%rbp), %rdi
xorl %esi, %esi
callq 0x73f0
movq %rax, %rdi
callq 0x59e0
movq -0xc8(%rbp), %rsi
movq -0xc0(%rbp), %rdx
movq -0xd0(%rbp), %rcx
movl $0xb, %edi
callq 0x8db0
movq %rax, %rdi
callq 0x59e0
movq -0xc8(%rbp), %rdi
movq -0xa8(%rbp), %rsi
movq -0xb8(%rbp), %rdx
callq 0x7370
movq %rax, %rdi
callq 0x59e0
jmp 0x6095
movq -0xb8(%rbp), %rdi
callq 0x73c0
movq %rax, %rdi
callq 0x59e0
movq -0xb8(%rbp), %rdi
callq 0x59a0
movq -0x8(%rbp), %rax
movq 0x80(%rax), %rdi
callq 0x5b50
movq -0x8(%rbp), %rax
cmpq $0x0, 0x78(%rax)
je 0x60c9
movq -0x8(%rbp), %rax
movq 0x78(%rax), %rdi
callq 0x6370
movq -0xa0(%rbp), %rdi
callq 0x73c0
movq %rax, %rdi
callq 0x59e0
movq -0xa8(%rbp), %rdi
callq 0x59a0
movq -0xb0(%rbp), %rax
movq %rax, 0x11571(%rip)     # 0x17668
jmp 0x6310
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rdi
callq 0x6370
movq %rax, -0xd8(%rbp)
movq $0x0, -0xe0(%rbp)
movq -0xe0(%rbp), %rax
movq -0x8(%rbp), %rcx
movq 0x88(%rcx), %rcx
cmpq 0x10(%rcx), %rax
jae 0x622d
movq -0x8(%rbp), %rax
movq 0x88(%rax), %rax
movq (%rax), %rax
movq -0xe0(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xe8(%rbp)
movq -0xe8(%rbp), %rax
cmpl $0x26, (%rax)
jne 0x6180
movq -0xe8(%rbp), %rax
movq 0x40(%rax), %rdi
callq 0x73c0
movq %rax, %rdi
callq 0x59e0
jmp 0x6214
movq -0xe8(%rbp), %rax
movq 0x38(%rax), %rdi
callq 0x6370
movq %rax, -0xf0(%rbp)
movl $0x4, %edi
callq 0x5a40
movq %rax, -0xf8(%rbp)
movq -0xf8(%rbp), %rsi
movq -0xd8(%rbp), %rdx
movq -0xf0(%rbp), %rcx
movl $0xb, %edi
callq 0x8db0
movq %rax, %rdi
callq 0x59e0
leaq 0xc4a6(%rip), %rdi      # 0x1267c
callq 0x5950
movq %rax, -0x100(%rbp)
movq -0xf8(%rbp), %rdi
movq -0xe8(%rbp), %rax
movq 0x40(%rax), %rsi
movq -0x100(%rbp), %rdx
callq 0x7370
movq %rax, %rdi
callq 0x59e0
movq -0x100(%rbp), %rdi
callq 0x59a0
jmp 0x6216
movq -0xe0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xe0(%rbp)
jmp 0x611b
movq 0x11434(%rip), %rax     # 0x17668
movq %rax, -0x108(%rbp)
leaq 0xc5fe(%rip), %rdi      # 0x12840
callq 0x5950
movq %rax, 0x1141a(%rip)     # 0x17668
movq -0x8(%rbp), %rax
movq 0x80(%rax), %rdi
callq 0x5b50
movq 0x11403(%rip), %rdi     # 0x17668
callq 0x59a0
movq -0x108(%rbp), %rax
movq %rax, 0x113f0(%rip)     # 0x17668
jmp 0x6310
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rdi
callq 0x59a0
movq -0x8(%rbp), %rax
movq 0x80(%rax), %rdi
callq 0x5b50
jmp 0x6310
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rdi
callq 0x59a0
movq -0x8(%rbp), %rax
movq 0x80(%rax), %rdi
callq 0x5b50
jmp 0x6310
cmpq $0x0, 0x113a5(%rip)     # 0x17668
je 0x62c7
jmp 0x62e6
leaq 0xc9cd(%rip), %rdi      # 0x12c9b
leaq 0xc950(%rip), %rsi      # 0x12c25
movl $0x25f, %edx            # imm = 0x25F
leaq 0xc9a3(%rip), %rcx      # 0x12c84
callq 0x20b0
movq 0x1137b(%rip), %rdi     # 0x17668
callq 0x73c0
movq %rax, %rdi
callq 0x59e0
jmp 0x6310
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
leaq 0xc99c(%rip), %rsi      # 0x12ca7
callq 0xed90
addq $0x110, %rsp            # imm = 0x110
popq %rbp
retq
nopl (%rax)