// File: /workspace/github_c_makefile_star2_O0/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 %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x10(%rbp)
cmpq $0x0, -0x10(%rbp)
jne 0xddc0
movq $0x0, -0x8(%rbp)
jmp 0xe232
movq -0x10(%rbp), %rax
cmpq $0x0, 0x58(%rax)
je 0xdddc
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0xe232
movq -0x10(%rbp), %rax
movl (%rax), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0x28(%rbp)
subl $0x26, %eax
ja 0xdf52
movq -0x28(%rbp), %rax
leaq 0x2f72(%rip), %rcx      # 0x10d70
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0xe232
leaq 0x3130(%rip), %rdi      # 0x10f4f
movb $0x0, %al
callq 0x5970
movq $0x0, -0x8(%rbp)
jmp 0xe232
leaq 0x313c(%rip), %rdi      # 0x10f76
movb $0x0, %al
callq 0x5970
movq -0x10(%rbp), %rdi
leaq 0x3153(%rip), %rsi      # 0x10f9f
movb $0x0, %al
callq 0x6040
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xdda0
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0xe232
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0xe232
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0xe232
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xdda0
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
callq 0xd370
testb $0x1, %al
jne 0xdebe
jmp 0xded8
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xd140
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
jmp 0xdeec
movq -0x18(%rbp), %rdi
callq 0xd140
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0xe232
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xdda0
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
callq 0xd350
testb $0x1, %al
jne 0xdf1d
jmp 0xdf3e
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0xe232
movq -0x10(%rbp), %rdi
leaq 0x307f(%rip), %rsi      # 0x10fc8
movb $0x0, %al
callq 0x6040
jmp 0xdf52
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xdda0
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0xdda0
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movl (%rax), %eax
addl $-0x4, %eax
movl %eax, %ecx
movq %rcx, -0x30(%rbp)
subl $0xf, %eax
ja 0xe220
movq -0x30(%rbp), %rax
leaq 0x2e75(%rip), %rcx      # 0x10e0c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x18(%rbp), %rdi
callq 0xd490
testb $0x1, %al
jne 0xdfaf
jmp 0xdfd8
movq -0x20(%rbp), %rdi
callq 0xd490
testb $0x1, %al
jne 0xdfbe
jmp 0xdfd8
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0xd520
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
jmp 0xdfea
movq -0x10(%rbp), %rdi
leaq 0x1790(%rip), %rsi      # 0xf773
movb $0x0, %al
callq 0x6040
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0xe232
movq -0x18(%rbp), %rdi
callq 0xd490
testb $0x1, %al
jne 0xe00a
jmp 0xe033
movq -0x20(%rbp), %rdi
callq 0xd490
testb $0x1, %al
jne 0xe019
jmp 0xe033
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0xd520
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
jmp 0xe0a1
movq -0x18(%rbp), %rdi
callq 0xd350
testb $0x1, %al
jne 0xe042
jmp 0xe05f
movq -0x20(%rbp), %rdi
callq 0xd490
testb $0x1, %al
jne 0xe051
jmp 0xe05f
movq -0x18(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
jmp 0xe09f
movq -0x18(%rbp), %rdi
callq 0xd490
testb $0x1, %al
jne 0xe06e
jmp 0xe08b
movq -0x20(%rbp), %rdi
callq 0xd350
testb $0x1, %al
jne 0xe07d
jmp 0xe08b
movq -0x20(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
jmp 0xe09d
movq -0x10(%rbp), %rdi
leaq 0x16dd(%rip), %rsi      # 0xf773
movb $0x0, %al
callq 0x6040
jmp 0xe09f
jmp 0xe0a1
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0xe232
movq -0x18(%rbp), %rdi
callq 0xd490
testb $0x1, %al
jne 0xe0c1
jmp 0xe0ea
movq -0x20(%rbp), %rdi
callq 0xd490
testb $0x1, %al
jne 0xe0d0
jmp 0xe0ea
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0xd520
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
jmp 0xe169
movq -0x18(%rbp), %rdi
callq 0xd350
testb $0x1, %al
jne 0xe0f9
jmp 0xe116
movq -0x20(%rbp), %rdi
callq 0xd490
testb $0x1, %al
jne 0xe108
jmp 0xe116
movq -0x18(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
jmp 0xe167
movq -0x18(%rbp), %rdi
callq 0xd350
testb $0x1, %al
jne 0xe125
jmp 0xe146
movq -0x20(%rbp), %rdi
callq 0xd350
testb $0x1, %al
jne 0xe134
jmp 0xe146
callq 0xd0b0
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
jmp 0xe165
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0xe240
movq -0x10(%rbp), %rdi
leaq 0x1615(%rip), %rsi      # 0xf773
movb $0x0, %al
callq 0x6040
jmp 0xe167
jmp 0xe169
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0xe232
movq -0x18(%rbp), %rdi
callq 0xd490
testb $0x1, %al
jne 0xe189
jmp 0xe1b2
movq -0x20(%rbp), %rdi
callq 0xd490
testb $0x1, %al
jne 0xe198
jmp 0xe1b2
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0xd520
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
jmp 0xe1c4
movq -0x10(%rbp), %rdi
leaq 0x15b6(%rip), %rsi      # 0xf773
movb $0x0, %al
callq 0x6040
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0xe232
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0xdd00
testb $0x1, %al
jne 0xe202
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0xe240
movq -0x10(%rbp), %rdi
leaq 0x1578(%rip), %rsi      # 0xf773
movb $0x0, %al
callq 0x6040
callq 0xd0b0
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0xe232
movq -0x10(%rbp), %rdi
leaq 0x2dd1(%rip), %rsi      # 0x10ffc
movb $0x0, %al
callq 0x6040
movq -0x8(%rbp), %rax
addq $0x30, %rsp
popq %rbp
retq
nopl (%rax)