// File: /workspace/github_c_makefile_star2_O1/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 0xb39a
movq %rdi, %rbx
movq 0x58(%rdi), %r14
testq %r14, %r14
jne 0xb39d
movl (%rbx), %eax
xorl %r14d, %r14d
leal -0x15(%rax), %ecx
cmpl $0x12, %ecx
ja 0xb3a6
leaq 0x2776(%rip), %rax      # 0xdaf4
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
leaq 0x28f5(%rip), %rdi      # 0xdc83
xorl %r14d, %r14d
xorl %eax, %eax
callq 0x50b0
jmp 0xb39d
xorl %r14d, %r14d
movq %r14, %rax
popq %rbx
popq %r14
popq %r15
retq
cmpl $0x1, %eax
je 0xb3da
cmpl $0x3, %eax
je 0xb39d
jmp 0xb444
movq 0x8(%rbx), %rdi
callq 0xb354
cmpl $0x9, (%rax)
jne 0xb433
movq 0x8(%rax), %r14
jmp 0xb49b
leaq 0x28d7(%rip), %rdi      # 0xdcaa
xorl %eax, %eax
callq 0x50b0
leaq 0x28f2(%rip), %rsi      # 0xdcd3
movq %rbx, %rdi
xorl %eax, %eax
callq 0x552e
movq 0x8(%rbx), %rdi
callq 0xb354
movq %rax, %r14
jmp 0xb42a
movq 0x8(%rbx), %rdi
callq 0xb354
movq %rax, %r15
cmpl $0xa, (%rax)
jne 0xb40e
movq 0x8(%r15), %r15
movl $0x1, %edi
movl $0x40, %esi
callq 0x10d0
movq %rax, %r14
movl $0x9, (%rax)
movq %r15, 0x8(%rax)
movq %rax, 0x58(%rbx)
jmp 0xb39d
leaq 0x28c2(%rip), %rsi      # 0xdcfc
movq %rbx, %rdi
xorl %eax, %eax
callq 0x552e
movq 0x8(%rbx), %rdi
callq 0xb354
movq %rax, %r14
movq 0x10(%rbx), %rdi
callq 0xb354
movl (%rbx), %ecx
addl $-0x4, %ecx
cmpl $0xf, %ecx
ja 0xb53a
leaq 0x26d2(%rip), %rdx      # 0xdb40
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movl (%r14), %ecx
leal -0x1(%rcx), %edx
cmpl $0x9, %edx
jae 0xb550
movl (%rax), %ecx
leal -0x1(%rcx), %edx
cmpl $0x9, %edx
jae 0xb55b
leaq 0x7ded(%rip), %r14      # 0x13288
movq %r14, 0x58(%rbx)
jmp 0xb39d
movl (%r14), %ecx
leal -0x1(%rcx), %edx
cmpl $0x8, %edx
jae 0xb4d1
movl (%rax), %ecx
leal -0x1(%rcx), %edx
cmpl $0x8, %edx
jae 0xb4d8
movq %r14, %rdi
movq %rax, %rsi
callq 0xaf0f
movq %rax, 0x58(%rbx)
movq 0x58(%rbx), %r14
jmp 0xb39d
cmpl $0xd, %ecx
je 0xb4af
jmp 0xb4dd
cmpl $0xd, %ecx
je 0xb4b9
leaq 0x129f(%rip), %rsi      # 0xc783
movq %rbx, %rdi
xorl %eax, %eax
callq 0x552e
jmp 0xb4c8
movl (%r14), %ecx
leal -0x1(%rcx), %edx
cmpl $0x8, %edx
jae 0xb585
movl (%rax), %esi
leal -0x1(%rsi), %edi
cmpl $0x8, %edi
jb 0xb4b9
cmpl $0xd, %esi
je 0xb4b9
cmpl $0x8, %edx
jae 0xb5c7
cmpl $0x9, (%rax)
je 0xb4c4
jmp 0xb4dd
movl (%r14), %ecx
leal -0x1(%rcx), %edx
cmpl $0x8, %edx
jae 0xb598
movl (%rax), %edx
leal -0x1(%rdx), %esi
cmpl $0x8, %esi
jb 0xb4b9
cmpl $0xd, %edx
je 0xb4b9
jmp 0xb59d
leaq 0x27ef(%rip), %rsi      # 0xdd30
movq %rbx, %rdi
xorl %eax, %eax
callq 0x552e
jmp 0xb39d
cmpl $0xd, %ecx
je 0xb486
jmp 0xb564
cmpl $0xd, %ecx
je 0xb494
movq %r14, %rdi
movq %rax, %rsi
callq 0x17d8
leaq 0x120d(%rip), %rsi      # 0xc783
movq %rbx, %rdi
xorl %eax, %eax
callq 0x552e
jmp 0xb494
cmpl $0x9, %ecx
je 0xb5d9
cmpl $0xd, %ecx
jne 0xb4dd
jmp 0xb4ff
cmpl $0xd, %ecx
je 0xb529
cmpl $0x9, %ecx
jne 0xb608
movl (%rax), %edx
leal -0x1(%rdx), %esi
cmpl $0x8, %esi
jb 0xb5e3
cmpl $0xd, %edx
je 0xb5e3
cmpl $0x9, %ecx
jne 0xb608
cmpl $0x9, (%rax)
jne 0xb608
leaq 0x7cc6(%rip), %rax      # 0x13288
jmp 0xb4c4
cmpl $0xd, %ecx
je 0xb517
cmpl $0x9, %ecx
jne 0xb4dd
movl (%rax), %esi
leal -0x1(%rsi), %edi
cmpl $0x8, %edi
jae 0xb5ec
movq %r14, 0x58(%rbx)
jmp 0xb4c8
cmpl $0xd, %esi
je 0xb5e3
cmpl $0x8, %edx
jb 0xb517
cmpl $0xd, %ecx
je 0xb517
jmp 0xb4dd
movq %r14, %rdi
movq %rax, %rsi
callq 0x17d8
jmp 0xb4dd