// File: /workspace/github_c_makefile_star2_O3/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 %r15
pushq %r14
pushq %rbx
testq %rdi, %rdi
je 0xb26b
movq %rdi, %rbx
movq 0x58(%rdi), %r14
testq %r14, %r14
jne 0xb26e
movl (%rbx), %eax
xorl %r14d, %r14d
leal -0x15(%rax), %ecx
cmpl $0x12, %ecx
ja 0xb277
leaq 0x28a5(%rip), %rax      # 0xdaf4
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
leaq 0x2a24(%rip), %rdi      # 0xdc83
xorl %r14d, %r14d
xorl %eax, %eax
callq 0x508c
jmp 0xb26e
xorl %r14d, %r14d
movq %r14, %rax
popq %rbx
popq %r14
popq %r15
retq
cmpl $0x1, %eax
je 0xb2ab
cmpl $0x3, %eax
je 0xb26e
jmp 0xb312
movq 0x8(%rbx), %rdi
callq 0xb225
cmpl $0x9, (%rax)
jne 0xb301
movq 0x8(%rax), %r14
jmp 0xb369
leaq 0x2a06(%rip), %rdi      # 0xdcaa
xorl %eax, %eax
callq 0x508c
leaq 0x2a21(%rip), %rsi      # 0xdcd3
movq %rbx, %rdi
xorl %eax, %eax
callq 0x5502
movq 0x8(%rbx), %rdi
callq 0xb225
movq %rax, %r14
movq %rax, 0x58(%rbx)
jmp 0xb26e
movq 0x8(%rbx), %rdi
callq 0xb225
movq %rax, %r15
cmpl $0xa, (%rax)
jne 0xb2e3
movq 0x8(%r15), %r15
movl $0x1, %edi
movl $0x40, %esi
callq 0x10d0
movq %rax, %r14
movl $0x9, (%rax)
movq %r15, 0x8(%rax)
jmp 0xb2c8
leaq 0x29f4(%rip), %rsi      # 0xdcfc
movq %rbx, %rdi
xorl %eax, %eax
callq 0x5502
movq 0x8(%rbx), %rdi
callq 0xb225
movq %rax, %r14
movq 0x10(%rbx), %rdi
callq 0xb225
movl (%rbx), %ecx
addl $-0x4, %ecx
cmpl $0xf, %ecx
ja 0xb429
leaq 0x2804(%rip), %rdx      # 0xdb40
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movl (%r14), %ecx
leal -0x1(%rcx), %edx
cmpl $0x9, %edx
jae 0xb43f
movl (%rax), %ecx
leal -0x1(%rcx), %edx
cmpl $0x9, %edx
jae 0xb44a
leaq 0x7f1f(%rip), %r14      # 0x13288
movq %r14, 0x58(%rbx)
jmp 0xb26e
movl (%r14), %ecx
leal -0x1(%rcx), %edx
cmpl $0x8, %edx
jae 0xb397
movl (%rax), %ecx
leal -0x1(%rcx), %edx
cmpl $0x8, %edx
jae 0xb39e
movq %r14, %rdi
movq %rax, %rsi
callq 0xade3
jmp 0xb2c5
cmpl $0xd, %ecx
je 0xb37d
jmp 0xb3a3
cmpl $0xd, %ecx
je 0xb387
leaq 0x13d9(%rip), %rsi      # 0xc783
movq %rbx, %rdi
xorl %eax, %eax
callq 0x5502
movq 0x58(%rbx), %r14
jmp 0xb26e
movl (%r14), %edx
leal -0x1(%rdx), %esi
cmpl $0x8, %esi
jae 0xb474
movl (%rax), %ecx
leal -0x1(%rcx), %edi
cmpl $0x8, %edi
jb 0xb387
cmpl $0xd, %ecx
je 0xb387
cmpl $0x8, %esi
jae 0xb4e0
cmpl $0x9, %ecx
jne 0xb3a3
movq %rax, 0x58(%rbx)
movq %rax, %r14
jmp 0xb26e
movl (%r14), %edx
leal -0x1(%rdx), %ecx
cmpl $0x8, %ecx
jae 0xb4a2
movl (%rax), %ecx
leal -0x1(%rcx), %esi
cmpl $0x8, %esi
jb 0xb387
cmpl $0xd, %ecx
je 0xb387
cmpl $0x9, %edx
je 0xb4b2
jmp 0xb4d0
leaq 0x2900(%rip), %rsi      # 0xdd30
movq %rbx, %rdi
xorl %eax, %eax
callq 0x5502
jmp 0xb26e
cmpl $0xd, %ecx
je 0xb354
jmp 0xb453
cmpl $0xd, %ecx
je 0xb362
movq %r14, %rdi
movq %rax, %rsi
callq 0x17d5
leaq 0x131e(%rip), %rsi      # 0xc783
movq %rbx, %rdi
xorl %eax, %eax
callq 0x5502
jmp 0xb362
cmpl $0xd, %edx
je 0xb3cc
cmpl $0x9, %edx
jne 0xb3a3
movl (%rax), %ecx
leal -0x1(%rcx), %eax
cmpl $0x8, %eax
jb 0xb369
cmpl $0xd, %ecx
je 0xb369
jmp 0xb3a3
cmpl $0xd, %edx
je 0xb404
cmpl $0x9, %edx
jne 0xb4d0
movl (%rax), %ecx
leal -0x1(%rcx), %edx
cmpl $0x8, %edx
jb 0xb369
cmpl $0x9, %ecx
je 0xb362
cmpl $0xd, %ecx
je 0xb369
movq %r14, %rdi
movq %rax, %rsi
callq 0x17d5
jmp 0xb3a3
cmpl $0xd, %edx
je 0xb3e4
cmpl $0x9, %edx
jne 0xb3a3
jmp 0xb488