// File: /workspace/github_c_makefile_star2_O2/sisshiki1969[P]monocc/src/type.c
// Function: type
Type *type(Node *node) {
  if (!node) return NULL;
  if (node->type) return node->type;
  Type *l_ty;
  Type *r_ty;
  switch (node->kind) {
    case ND_INIT:
      return node->type;
    // statement
    case ND_IF:
    case ND_WHILE:
    case ND_BLOCK:
    case ND_BREAK:
    case ND_CONTINUE:
      error("Can not determine a type of statement.");
    case ND_RETURN:
      return NULL;
    // declaration
    case ND_FDECL:
      error("Can not determine a type of declaration.");

    // expression
    case ND_NUM:
      // return new_type_int();
    case ND_LVAR:
      // return node->lvar->type;
      error_at_node(node, "Internal error: type of node is missing.");
    case ND_ASSIGN:
      node->type = type(node->lhs);
      return node->type;
    case ND_CALL:
      return node->type;
    case ND_CAST:
      return node->type;
    case ND_ADDR:
      l_ty = type(node->lhs);
      if (is_array(l_ty))
        node->type = new_type_ptr_to(l_ty->ptr_to);
      else
        node->type = new_type_ptr_to(l_ty);
      return node->type;
    case ND_DEREF:
      l_ty = type(node->lhs);
      if (is_ptr(l_ty)) {
        node->type = l_ty->ptr_to;
        return node->type;
      } else
        error_at_node(node,
                      "Operand of dereference operator must be a pointer.\n");
  }

  l_ty = type(node->lhs);
  r_ty = type(node->rhs);
  switch (node->kind) {
    case ND_AND:
    case ND_OR:
    case ND_XOR:
    case ND_SHR:
    case ND_SHL:
      if (is_arith(l_ty) && is_arith(r_ty)) {
        node->type = get_common_type(l_ty, r_ty);
      } else
        error_at_node(node, "Illegal operation. (Type mismatch)");
      return node->type;
    case ND_ADD:
      if (is_arith(l_ty) && is_arith(r_ty)) {
        node->type = get_common_type(l_ty, r_ty);
      } else if (is_ptr(l_ty) && is_arith(r_ty)) {
        node->type = l_ty;
      } else if (is_arith(l_ty) && is_ptr(r_ty)) {
        node->type = r_ty;
      } else
        error_at_node(node, "Illegal operation. (Type mismatch)");
      return node->type;
    case ND_SUB:
      if (is_arith(l_ty) && is_arith(r_ty))
        node->type = get_common_type(l_ty, r_ty);
      else if (is_ptr(l_ty) && is_arith(r_ty))
        node->type = l_ty;
      else if (is_ptr(l_ty) && is_ptr(r_ty))
        node->type = new_type_int();
      else {
        error_types(l_ty, r_ty);
        error_at_node(node, "Illegal operation. (Type mismatch)");
      }
      return node->type;
    case ND_MUL:
    case ND_DIV:
      if (is_arith(l_ty) && is_arith(r_ty))
        node->type = get_common_type(l_ty, r_ty);
      else
        error_at_node(node, "Illegal operation. (Type mismatch)");
      return node->type;
    case ND_EQ:
    case ND_NEQ:
    case ND_GE:
    case ND_GT:
    case ND_LAND:
    case ND_LOR:
    case ND_NOT:
      if (!is_comparable_type(l_ty, r_ty)) {
        error_types(l_ty, r_ty);
        error_at_node(node, "Illegal operation. (Type mismatch)");
      }
      node->type = new_type_int();
      return node->type;
  }
  error_at_node(node, "type(): Unimplemented NodeKind.");
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
testq %rdi, %rdi
je 0x9655
movq %rdi, %rbx
movq 0x58(%rdi), %r14
testq %r14, %r14
jne 0x9658
movl (%rbx), %eax
xorl %r14d, %r14d
leal -0x15(%rax), %ecx
cmpl $0x12, %ecx
ja 0x9663
leaq 0x24d7(%rip), %rax      # 0xbb10
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
leaq 0x2656(%rip), %rdi      # 0xbc9f
xorl %r14d, %r14d
xorl %eax, %eax
callq 0x462f
jmp 0x9658
xorl %r14d, %r14d
movq %r14, %rax
addq $0x8, %rsp
popq %rbx
popq %r14
retq
cmpl $0x1, %eax
je 0x9694
cmpl $0x3, %eax
je 0x9658
jmp 0x96e3
movq 0x8(%rbx), %rdi
callq 0x9610
cmpl $0x9, (%rax)
jne 0x96d2
movq 0x8(%rax), %r14
jmp 0x9786
leaq 0x2639(%rip), %rdi      # 0xbcc6
xorl %eax, %eax
callq 0x462f
leaq 0x2654(%rip), %rsi      # 0xbcef
movq %rbx, %rdi
xorl %eax, %eax
callq 0x4a9e
movq 0x8(%rbx), %rdi
callq 0x9610
movq %rax, %r14
movq %rax, 0x58(%rbx)
jmp 0x9658
movq 0x8(%rbx), %rdi
callq 0x9610
cmpl $0xa, (%rax)
jne 0x977b
movq 0x8(%rax), %rdi
jmp 0x977e
leaq 0x263f(%rip), %rsi      # 0xbd18
movq %rbx, %rdi
xorl %eax, %eax
callq 0x4a9e
movq 0x8(%rbx), %rdi
callq 0x9610
movq %rax, %r14
movq 0x10(%rbx), %rdi
callq 0x9610
movl (%rbx), %ecx
addl $-0x4, %ecx
cmpl $0xf, %ecx
ja 0x980e
leaq 0x244f(%rip), %rdx      # 0xbb5c
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movl (%r14), %ecx
cmpl $0xd, %ecx
ja 0x978f
movl $0x23fe, %edx           # imm = 0x23FE
btl %ecx, %edx
jae 0x978f
movl (%rax), %ecx
cmpl $0xd, %ecx
ja 0x978f
btl %ecx, %edx
jae 0x978f
leaq 0x7b4d(%rip), %r14      # 0x11288
jmp 0x9786
movl (%r14), %ecx
cmpl $0xd, %ecx
ja 0x987a
movl $0x21fe, %edx           # imm = 0x21FE
btl %ecx, %edx
jae 0x987a
movl (%rax), %ecx
cmpl $0xd, %ecx
ja 0x987a
btl %ecx, %edx
jae 0x987a
movq %r14, %rdi
movq %rax, %rsi
callq 0x9207
jmp 0x96ae
movq %rax, %rdi
callq 0x90cc
movq %rax, %r14
movq %r14, 0x58(%rbx)
jmp 0x9658
movq %r14, %rdi
movq %rax, %rsi
callq 0x98a4
leaq 0xfe2(%rip), %rsi       # 0xa783
movq %rbx, %rdi
xorl %eax, %eax
callq 0x4a9e
jmp 0x9734
movl (%r14), %edx
leal -0x1(%rdx), %esi
cmpl $0x8, %esi
jae 0x9824
movl (%rax), %ecx
cmpl $0xd, %ecx
ja 0x97c9
movl $0x21fe, %edi           # imm = 0x21FE
btl %ecx, %edi
jb 0x976b
cmpl $0x8, %esi
jae 0x9894
cmpl $0x9, %ecx
jne 0x987a
movq %rax, 0x58(%rbx)
movq %rax, %r14
jmp 0x9658
movl (%r14), %edx
leal -0x1(%rdx), %ecx
cmpl $0x8, %ecx
jae 0x9845
movl (%rax), %ecx
cmpl $0xd, %ecx
ja 0x9807
movl $0x21fe, %esi           # imm = 0x21FE
btl %ecx, %esi
jb 0x976b
cmpl $0x9, %edx
je 0x9851
jmp 0x986f
leaq 0x2537(%rip), %rsi      # 0xbd4c
movq %rbx, %rdi
xorl %eax, %eax
callq 0x4a9e
jmp 0x9658
cmpl $0xd, %edx
je 0x97b8
cmpl $0x9, %edx
jne 0x987a
movl (%rax), %ecx
cmpl $0xd, %ecx
ja 0x987a
movl $0x21fe, %eax           # imm = 0x21FE
btl %ecx, %eax
jb 0x9786
jmp 0x987a
cmpl $0xd, %edx
je 0x97f2
cmpl $0x9, %edx
jne 0x986f
movl (%rax), %ecx
leal -0x1(%rcx), %edx
cmpl $0x8, %edx
jb 0x9786
cmpl $0x9, %ecx
je 0x9734
cmpl $0xd, %ecx
je 0x9786
movq %r14, %rdi
movq %rax, %rsi
callq 0x98a4
leaq 0xf02(%rip), %rsi       # 0xa783
movq %rbx, %rdi
xorl %eax, %eax
callq 0x4a9e
movq 0x58(%rbx), %r14
jmp 0x9658
cmpl $0xd, %edx
je 0x97d2
cmpl $0x9, %edx
je 0x9830
jmp 0x987a