// File: /workspace/github_cpp_makefile_star2_O3/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 0x73db
movl %eax, %r12d
movl %ebx, %edi
callq 0x73db
movl %eax, %r15d
addl %r12d, %r15d
movl $0x800, %edi            # imm = 0x800
callq 0x13f2c
testl %eax, %eax
je 0x768e
leaq 0x1e0ea(%rip), %rcx     # 0x256e0
movl (%rcx), %edx
cmpl $0x1, %r15d
jne 0x7612
cmpl %ebp, %edx
sete %al
cmpl %ebx, %edx
sete %sil
orb %al, %sil
jne 0x7839
cmpl %ebp, %edx
setne %al
btl $0x1e, %ebx
setae %sil
orb %al, %sil
jne 0x7651
movl %ebx, %esi
andl $0xbfffffff, %esi       # imm = 0xBFFFFFFF
xorl %eax, %eax
cmpl %ebp, %esi
je 0x783b
cmpl %esi, 0x8(%rcx)
je 0x783b
cmpl %esi, 0x4(%rcx)
je 0x783b
cmpl %esi, 0xc(%rcx)
je 0x783b
cmpl %ebx, %edx
setne %al
btl $0x1e, %ebp
setae %dl
orb %al, %dl
jne 0x768e
movl %ebp, %edx
andl $0xbfffffff, %edx       # imm = 0xBFFFFFFF
xorl %eax, %eax
cmpl %ebx, %edx
je 0x783b
cmpl %edx, 0x8(%rcx)
je 0x783b
cmpl %edx, 0x4(%rcx)
je 0x783b
cmpl %edx, 0xc(%rcx)
je 0x783b
leaq 0x1e04b(%rip), %rcx     # 0x256e0
movl $0x40000000, %edx       # imm = 0x40000000
movl 0x20(%rcx), %eax
orl %edx, %eax
cmpl %ebp, %eax
jne 0x76b3
movl $0x20000000, %eax       # imm = 0x20000000
orl 0x10(%rcx), %eax
cmpl %ebx, %eax
je 0x7839
orl 0x1c(%rcx), %edx
cmpl %ebp, %edx
sete %sil
movl %ebx, %edi
shrl $0x1c, %edi
xorl %eax, %eax
testb %sil, %dil
jne 0x783b
cmpl $0x1, %r15d
sete %al
movl %ebp, %esi
shrl $0x1d, %esi
btl $0x1d, %ebx
setae %dil
andb %sil, %dil
movl 0x14(%rcx), %r8d
cmpl %ebp, 0x18(%rcx)
sete %r9b
movl %ebx, %r10d
xorl %ebp, %r10d
shrl $0x1c, %r10d
andl $0x1, %r10d
orb %dil, %r10b
movl $0xcfffffff, %esi       # imm = 0xCFFFFFFF
movl %ebp, %edi
andl %esi, %edi
andl %ebx, %esi
cmpl %r8d, %edi
sete %r11b
setne %r12b
cmpl %r8d, %esi
setne %r8b
sete %r13b
andb %r11b, %r8b
orb %r10b, %r8b
andb %r12b, %r13b
orb %r9b, %r13b
orb %r8b, %r13b
orb %al, %r13b
movzbl %r13b, %eax
andl $0x1, %eax
cmpl $0x2, %r15d
jne 0x77d2
testl %eax, %eax
je 0x7839
testl %r14d, %r14d
je 0x7820
leaq 0x1df85(%rip), %r15     # 0x256e0
leaq 0x28(%rsp), %r14
movq %r14, %rdi
movq %r15, %rsi
movl %ebp, %edx
callq 0x11e2c
movq (%r14), %r14
leaq 0x8(%rsp), %rdi
movq %r15, %rsi
movl %ebx, %edx
callq 0x11e2c
movq 0x8(%rsp), %rdx
leaq 0x138b3(%rip), %rdi     # 0x1b03e
movq %r14, %rsi
xorl %eax, %eax
callq 0x102f4
leaq 0x18(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x77b0
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x3320
leaq 0x38(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x77cb
movq 0x38(%rsp), %rsi
incq %rsi
callq 0x3320
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
jmp 0x783b
movl %ebx, %r8d
orl %ebp, %r8d
btl $0x1e, %r8d
jb 0x784a
movslq %edi, %rdx
movq 0x28(%rcx), %rcx
imulq $0xb0, %rdx, %rdx
testb $0x4, 0x29(%rcx,%rdx)
jne 0x78c2
cmpl %esi, %edi
je 0x7743
movslq %esi, %rdx
imulq $0xb0, %rdx, %rdx
movq 0x28(%rcx,%rdx), %rcx
andl $0x400, %ecx            # imm = 0x400
jne 0x774b
jmp 0x7743
movl %ebx, %edi
movl %ebp, %esi
movl $0x1, %edx
callq 0x75b3
movl %eax, %ecx
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
testl %ecx, %ecx
jne 0x783b
xorl %eax, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x40000000, %r8d       # imm = 0x40000000
movl %ebp, %r9d
andl %r8d, %r9d
andl %ebx, %r8d
setne %r10b
cmpl %edx, %edi
sete %dl
andb %r10b, %dl
movl %ebp, %r10d
andl $0x8fffffff, %r10d      # imm = 0x8FFFFFFF
movq 0x28(%rcx), %rcx
movslq %r10d, %r10
imulq $0xb0, %r10, %r10
movswl 0x50(%rcx,%r10), %r10d
testl %r10d, %r10d
jle 0x78a5
movl %r10d, %r11d
orl $0x40000000, %r11d      # imm = 0x40000000
cmpl %esi, %r11d
jne 0x7873
cmpl %r8d, %r9d
je 0x7743
jmp 0x774b
cmpl %r8d, %r9d
movl $0x1, %ecx
cmovnel %ecx, %eax
cmpl %esi, %edi
sete %cl
orb %dl, %cl
jne 0x7743
jmp 0x774b
cmpl %esi, %edi
je 0x7743
jmp 0x774b
movq %rax, %rbx
leaq 0x18(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x78f2
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x3320
jmp 0x78f2
movq %rax, %rbx
leaq 0x38(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x790d
movq 0x38(%rsp), %rsi
incq %rsi
callq 0x3320
movq %rbx, %rdi
callq 0x3560