// File: /workspace/github_cpp_makefile_star2_O2/rofl0r[P]ascc/cs_parser.cpp
// Function: check_type_mismatch(int, int, int)
int check_type_mismatch(int typeIs, int typeWantsToBe, int orderMatters) {
  int isTypeMismatch = 0;
  int numstrings = 0;

  int typeIsOriginally = typeIs;
  int typeWantsToBeOriginally = typeWantsToBe;

  if (is_string(typeIs))
    numstrings++;
  if (is_string(typeWantsToBe))
    numstrings++;

  // we allow to turn char* or char[] addresses into ints and vice versa
  // if -fpointerhack=1 is passed, to enable some low-level routines
  // to be written.
  if (ccGetOption(SCOPT_POINTERHACK)!=0) {
    if (numstrings == 1 && (is_int(typeIs) || is_int(typeWantsToBe)))
      return 0;
    if (is_int(typeIs) && (typeWantsToBe & STYPE_POINTER) &&
        is_integral_type(typeWantsToBe & ~STYPE_POINTER))
      return 0;
    if (is_int(typeWantsToBe) && (typeIs & STYPE_POINTER) &&
        is_integral_type(typeIs & ~STYPE_POINTER))
      return 0;
  }

  if (numstrings == 1) {
    isTypeMismatch = 1;
  }

  // can convert String* to const string
  if ((typeIs == (STYPE_POINTER | sym.stringStructSym)) &&
      (typeWantsToBe == (STYPE_CONST | sym.normalStringSym)))
    return 0;

  // cannot convert 'void' to anything
  if (typeIs == sym.normalVoidSym)
    isTypeMismatch = 1;

  // cannot convert const to non-const
  if (((typeIs & STYPE_CONST) != 0) && ((typeWantsToBe & STYPE_CONST) == 0))
    isTypeMismatch = 1;

  // cannot convert from/to dynamic array
  if ((typeIs == (STYPE_POINTER | sym.nullSym)) &&
      ((typeWantsToBe & STYPE_DYNARRAY) != 0))
  {
    // null is always allowed
    return 0;
  }
  else if ((typeIs & STYPE_DYNARRAY) != (typeWantsToBe & STYPE_DYNARRAY))
    isTypeMismatch = 1;

  // allow safe comparisons from here on
  typeIs &= ~(STYPE_CONST | STYPE_DYNARRAY);
  typeWantsToBe &= ~(STYPE_CONST | STYPE_DYNARRAY);

  // floats cannot mingle with other types
  if ((typeIs == sym.normalFloatSym) && (typeWantsToBe != sym.normalFloatSym))
    isTypeMismatch = 1;
  if ((typeWantsToBe == sym.normalFloatSym) && (typeIs != sym.normalFloatSym))
    isTypeMismatch = 1;

  // a pointer can only be compared with another pointer (except for
  // the   string/char*  exception)
  if (numstrings == 2) { }
  else if ((typeIs & STYPE_POINTER) || (typeWantsToBe & STYPE_POINTER)) {
    // pointers must point to same type
    int pointerIsOk = 0;
    if (typeIs == (STYPE_POINTER | sym.nullSym)) {
      // null can be cast to any pointer type
      if (typeWantsToBe & STYPE_POINTER)
        pointerIsOk = 1;
    }
    // check against inherited classes
    int tryTypeIs = typeIs & ~STYPE_POINTER;
    while (sym.entries[tryTypeIs].extends > 0) {
      tryTypeIs = sym.entries[tryTypeIs].extends;
      if ((tryTypeIs | STYPE_POINTER) == typeWantsToBe) {
        pointerIsOk = 1;
        break;
      }
    }
    // both sides must be pointers
    if ((typeIs & STYPE_POINTER) != (typeWantsToBe & STYPE_POINTER))
      isTypeMismatch = 1;

    if ((pointerIsOk == 0) && (typeIs != typeWantsToBe)) {
      isTypeMismatch = 1;
    }
  }
  else if ((sym.entries[typeIs].flags & SFLG_STRUCTTYPE) ||
           (sym.entries[typeWantsToBe].flags & SFLG_STRUCTTYPE)) {
    if (typeIs != typeWantsToBe) {
      isTypeMismatch = 1;
    }
  }

  if (isTypeMismatch) {
    if (!orderMatters) {
      // if not an assignment so left and right are interchangable,
      // try the other way round
      if (check_type_mismatch(typeWantsToBeOriginally, typeIsOriginally, 1))
        return -1;
    }
    else {
      cc_error("Type mismatch: cannot convert '%s' to '%s'", sym.get_friendly_name(typeIsOriginally).c_str(), sym.get_friendly_name(typeWantsToBeOriginally).c_str());
      return -1;
    }
  }
  return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movl %edx, %r14d
movl %esi, %ebx
movl %edi, %ebp
callq 0x6dc1
movl %eax, %r15d
movl %ebx, %edi
callq 0x6dc1
movl %eax, %r12d
addl %r15d, %r12d
movl $0x800, %edi            # imm = 0x800
callq 0x127df
testl %eax, %eax
je 0x7046
leaq 0x1e707(%rip), %rax     # 0x256f0
movl (%rax), %r15d
cmpl $0x1, %r12d
jne 0x7002
cmpl %ebp, %r15d
sete %al
cmpl %ebx, %r15d
sete %cl
orb %al, %cl
jne 0x7067
cmpl %ebp, %r15d
setne %al
btl $0x1e, %ebx
setae %cl
orb %al, %cl
jne 0x7024
movl %ebx, %edi
andl $0xbfffffff, %edi       # imm = 0xBFFFFFFF
callq 0x6f87
testl %eax, %eax
jne 0x7067
cmpl %ebx, %r15d
setne %al
btl $0x1e, %ebp
setae %cl
orb %al, %cl
jne 0x7046
movl %ebp, %edi
andl $0xbfffffff, %edi       # imm = 0xBFFFFFFF
callq 0x6f87
testl %eax, %eax
jne 0x7067
leaq 0x1e6a3(%rip), %rax     # 0x256f0
movl $0x40000000, %edx       # imm = 0x40000000
movl 0x20(%rax), %ecx
orl %edx, %ecx
cmpl %ebp, %ecx
jne 0x706f
movl $0x20000000, %ecx       # imm = 0x20000000
orl 0x10(%rax), %ecx
cmpl %ebx, %ecx
jne 0x706f
xorl %r15d, %r15d
jmp 0x7246
orl 0x1c(%rax), %edx
cmpl %ebp, %edx
sete %cl
movl %ebx, %esi
shrl $0x1c, %esi
xorl %r15d, %r15d
testb %cl, %sil
jne 0x7246
movl %r14d, 0x4(%rsp)
cmpl $0x1, %r12d
sete %dil
movl %ebp, %ecx
shrl $0x1d, %ecx
btl $0x1d, %ebx
setae %sil
andb %cl, %sil
movl 0x14(%rax), %r8d
cmpl %ebp, 0x18(%rax)
sete %r9b
movl %ebx, %r10d
xorl %ebp, %r10d
shrl $0x1c, %r10d
andl $0x1, %r10d
orb %sil, %r10b
movl $0xcfffffff, %ecx       # imm = 0xCFFFFFFF
movl %ebp, %esi
andl %ecx, %esi
andl %ebx, %ecx
cmpl %r8d, %esi
sete %r11b
setne %r13b
cmpl %r8d, %ecx
setne %r8b
sete %r14b
andb %r11b, %r8b
orb %r10b, %r8b
andb %r13b, %r14b
orb %r9b, %r14b
orb %r8b, %r14b
orb %dil, %r14b
movzbl %r14b, %edi
andl $0x1, %edi
cmpl $0x2, %r12d
jne 0x7115
movl %edi, %eax
movl 0x4(%rsp), %r14d
testl %eax, %eax
jne 0x71d6
jmp 0x7246
movl %ebx, %r8d
orl %ebp, %r8d
btl $0x1e, %r8d
movl 0x4(%rsp), %r14d
jb 0x7163
movslq %esi, %rdx
movq 0x28(%rax), %rax
imulq $0xb0, %rdx, %rdx
testb $0x4, 0x29(%rax,%rdx)
jne 0x71cc
cmpl %ecx, %esi
je 0x7258
movslq %ecx, %rcx
imulq $0xb0, %rcx, %rcx
movq 0x28(%rax,%rcx), %rcx
movl %edi, %eax
andl $0x400, %ecx            # imm = 0x400
jne 0x71d6
jmp 0x7108
movl $0x40000000, %r8d       # imm = 0x40000000
movl %ebp, %r9d
andl %r8d, %r9d
andl %ebx, %r8d
setne %r10b
cmpl %edx, %esi
sete %dl
andb %r10b, %dl
movl %ebp, %r10d
andl $0x8fffffff, %r10d      # imm = 0x8FFFFFFF
movq 0x28(%rax), %rax
movslq %r10d, %r10
imulq $0xb0, %r10, %r10
movswl 0x50(%rax,%r10), %r10d
testl %r10d, %r10d
jle 0x71b2
movl %r10d, %r11d
orl $0x40000000, %r11d      # imm = 0x40000000
cmpl %ecx, %r11d
jne 0x718c
movb $0x1, %dl
cmpl %r8d, %r9d
pushq $0x1
popq %rax
cmovel %edi, %eax
cmpl %ecx, %esi
je 0x7108
testb %dl, %dl
je 0x71d6
jmp 0x7108
movl %edi, %eax
cmpl %ecx, %esi
je 0x7108
testl %r14d, %r14d
je 0x7232
leaq 0x1e50e(%rip), %r15     # 0x256f0
leaq 0x28(%rsp), %r14
movq %r14, %rdi
movq %r15, %rsi
movl %ebp, %edx
callq 0x10864
movq (%r14), %r14
leaq 0x8(%rsp), %rdi
movq %r15, %rsi
movl %ebx, %edx
callq 0x10864
movq 0x8(%rsp), %rdx
leaq 0x11e0c(%rip), %rdi     # 0x1901e
movq %r14, %rsi
xorl %eax, %eax
callq 0xf258
leaq 0x8(%rsp), %rdi
callq 0x31a0
leaq 0x28(%rsp), %rdi
callq 0x31a0
jmp 0x7242
pushq $0x1
popq %rdx
movl %ebx, %edi
movl %ebp, %esi
callq 0x6faa
testl %eax, %eax
je 0x7246
pushq $-0x1
popq %r15
movl %r15d, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl %edi, %eax
jmp 0x7108
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x31a0
jmp 0x7271
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0x31a0
movq %rbx, %rdi
callq 0x3560