// File: 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
movq %rsp, %rbp
subq $0x90, %rsp
movl %edi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl %edx, -0x10(%rbp)
movl $0x0, -0x14(%rbp)
movl $0x0, -0x18(%rbp)
movl -0x8(%rbp), %eax
movl %eax, -0x1c(%rbp)
movl -0xc(%rbp), %eax
movl %eax, -0x20(%rbp)
movl -0x8(%rbp), %edi
callq 0xa470
cmpl $0x0, %eax
je 0xa804
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
movl -0xc(%rbp), %edi
callq 0xa470
cmpl $0x0, %eax
je 0xa81a
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
movl $0x800, %edi            # imm = 0x800
callq 0x265a0
cmpl $0x0, %eax
je 0xa8cd
cmpl $0x1, -0x18(%rbp)
jne 0xa859
movl -0x8(%rbp), %edi
callq 0xa740
cmpl $0x0, %eax
jne 0xa84d
movl -0xc(%rbp), %edi
callq 0xa740
cmpl $0x0, %eax
je 0xa859
movl $0x0, -0x4(%rbp)
jmp 0xac2f
movl -0x8(%rbp), %edi
callq 0xa740
cmpl $0x0, %eax
je 0xa892
movl -0xc(%rbp), %eax
andl $0x40000000, %eax       # imm = 0x40000000
cmpl $0x0, %eax
je 0xa892
movl -0xc(%rbp), %edi
andl $0xbfffffff, %edi       # imm = 0xBFFFFFFF
callq 0xa760
cmpl $0x0, %eax
je 0xa892
movl $0x0, -0x4(%rbp)
jmp 0xac2f
movl -0xc(%rbp), %edi
callq 0xa740
cmpl $0x0, %eax
je 0xa8cb
movl -0x8(%rbp), %eax
andl $0x40000000, %eax       # imm = 0x40000000
cmpl $0x0, %eax
je 0xa8cb
movl -0x8(%rbp), %edi
andl $0xbfffffff, %edi       # imm = 0xBFFFFFFF
callq 0xa760
cmpl $0x0, %eax
je 0xa8cb
movl $0x0, -0x4(%rbp)
jmp 0xac2f
jmp 0xa8cd
cmpl $0x1, -0x18(%rbp)
jne 0xa8da
movl $0x1, -0x14(%rbp)
movl -0x8(%rbp), %eax
leaq 0x37f8c(%rip), %rcx     # 0x42870
movl 0x20(%rcx), %ecx
orl $0x40000000, %ecx       # imm = 0x40000000
cmpl %ecx, %eax
jne 0xa914
movl -0xc(%rbp), %eax
leaq 0x37f75(%rip), %rcx     # 0x42870
movl 0x10(%rcx), %ecx
orl $0x20000000, %ecx       # imm = 0x20000000
cmpl %ecx, %eax
jne 0xa914
movl $0x0, -0x4(%rbp)
jmp 0xac2f
movl -0x8(%rbp), %eax
leaq 0x37f52(%rip), %rcx     # 0x42870
cmpl 0x18(%rcx), %eax
jne 0xa92a
movl $0x1, -0x14(%rbp)
movl -0x8(%rbp), %eax
andl $0x20000000, %eax       # imm = 0x20000000
cmpl $0x0, %eax
je 0xa94b
movl -0xc(%rbp), %eax
andl $0x20000000, %eax       # imm = 0x20000000
cmpl $0x0, %eax
jne 0xa94b
movl $0x1, -0x14(%rbp)
movl -0x8(%rbp), %eax
leaq 0x37f1b(%rip), %rcx     # 0x42870
movl 0x1c(%rcx), %ecx
orl $0x40000000, %ecx       # imm = 0x40000000
cmpl %ecx, %eax
jne 0xa97b
movl -0xc(%rbp), %eax
andl $0x10000000, %eax       # imm = 0x10000000
cmpl $0x0, %eax
je 0xa97b
movl $0x0, -0x4(%rbp)
jmp 0xac2f
movl -0x8(%rbp), %eax
andl $0x10000000, %eax       # imm = 0x10000000
movl -0xc(%rbp), %ecx
andl $0x10000000, %ecx       # imm = 0x10000000
cmpl %ecx, %eax
je 0xa997
movl $0x1, -0x14(%rbp)
jmp 0xa999
movl -0x8(%rbp), %eax
andl $0xcfffffff, %eax       # imm = 0xCFFFFFFF
movl %eax, -0x8(%rbp)
movl -0xc(%rbp), %eax
andl $0xcfffffff, %eax       # imm = 0xCFFFFFFF
movl %eax, -0xc(%rbp)
movl -0x8(%rbp), %eax
leaq 0x37eb7(%rip), %rcx     # 0x42870
cmpl 0x14(%rcx), %eax
jne 0xa9d4
movl -0xc(%rbp), %eax
leaq 0x37ea8(%rip), %rcx     # 0x42870
cmpl 0x14(%rcx), %eax
je 0xa9d4
movl $0x1, -0x14(%rbp)
movl -0xc(%rbp), %eax
leaq 0x37e92(%rip), %rcx     # 0x42870
cmpl 0x14(%rcx), %eax
jne 0xa9f9
movl -0x8(%rbp), %eax
leaq 0x37e83(%rip), %rcx     # 0x42870
cmpl 0x14(%rcx), %eax
je 0xa9f9
movl $0x1, -0x14(%rbp)
cmpl $0x2, -0x18(%rbp)
jne 0xaa04
jmp 0xab41
movl -0x8(%rbp), %eax
andl $0x40000000, %eax       # imm = 0x40000000
cmpl $0x0, %eax
jne 0xaa22
movl -0xc(%rbp), %eax
andl $0x40000000, %eax       # imm = 0x40000000
cmpl $0x0, %eax
je 0xaae4
movl $0x0, -0x24(%rbp)
movl -0x8(%rbp), %eax
leaq 0x37e3d(%rip), %rcx     # 0x42870
movl 0x1c(%rcx), %ecx
orl $0x40000000, %ecx       # imm = 0x40000000
cmpl %ecx, %eax
jne 0xaa56
movl -0xc(%rbp), %eax
andl $0x40000000, %eax       # imm = 0x40000000
cmpl $0x0, %eax
je 0xaa54
movl $0x1, -0x24(%rbp)
jmp 0xaa56
movl -0x8(%rbp), %eax
andl $0xbfffffff, %eax       # imm = 0xBFFFFFFF
movl %eax, -0x28(%rbp)
movslq -0x28(%rbp), %rsi
leaq 0x37e04(%rip), %rdi     # 0x42870
addq $0x28, %rdi
callq 0x17e60
movswl 0x50(%rax), %eax
cmpl $0x0, %eax
jle 0xaab1
movslq -0x28(%rbp), %rsi
leaq 0x37de7(%rip), %rdi     # 0x42870
addq $0x28, %rdi
callq 0x17e60
movswl 0x50(%rax), %eax
movl %eax, -0x28(%rbp)
movl -0x28(%rbp), %eax
orl $0x40000000, %eax       # imm = 0x40000000
cmpl -0xc(%rbp), %eax
jne 0xaaaf
movl $0x1, -0x24(%rbp)
jmp 0xaab1
jmp 0xaa61
movl -0x8(%rbp), %eax
andl $0x40000000, %eax       # imm = 0x40000000
movl -0xc(%rbp), %ecx
andl $0x40000000, %ecx       # imm = 0x40000000
cmpl %ecx, %eax
je 0xaacd
movl $0x1, -0x14(%rbp)
cmpl $0x0, -0x24(%rbp)
jne 0xaae2
movl -0x8(%rbp), %eax
cmpl -0xc(%rbp), %eax
je 0xaae2
movl $0x1, -0x14(%rbp)
jmp 0xab3f
movslq -0x8(%rbp), %rsi
leaq 0x37d81(%rip), %rdi     # 0x42870
addq $0x28, %rdi
callq 0x17e60
movq 0x28(%rax), %rax
andq $0x400, %rax            # imm = 0x400
cmpq $0x0, %rax
jne 0xab2c
movslq -0xc(%rbp), %rsi
leaq 0x37d5d(%rip), %rdi     # 0x42870
addq $0x28, %rdi
callq 0x17e60
movq 0x28(%rax), %rax
andq $0x400, %rax            # imm = 0x400
cmpq $0x0, %rax
je 0xab3d
movl -0x8(%rbp), %eax
cmpl -0xc(%rbp), %eax
je 0xab3b
movl $0x1, -0x14(%rbp)
jmp 0xab3d
jmp 0xab3f
jmp 0xab41
cmpl $0x0, -0x14(%rbp)
je 0xac28
cmpl $0x0, -0x10(%rbp)
jne 0xab77
movl -0x20(%rbp), %edi
movl -0x1c(%rbp), %esi
movl $0x1, %edx
callq 0xa7c0
cmpl $0x0, %eax
je 0xab72
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xac2f
jmp 0xac26
movl -0x1c(%rbp), %edx
leaq 0x37cef(%rip), %rsi     # 0x42870
movq %rsi, -0x88(%rbp)
leaq -0x48(%rbp), %rdi
movq %rdi, -0x90(%rbp)
callq 0x1f080
movq -0x90(%rbp), %rdi
callq 0x41b0
movq -0x88(%rbp), %rsi
movq %rax, -0x80(%rbp)
movl -0x20(%rbp), %edx
leaq -0x68(%rbp), %rdi
callq 0x1f080
jmp 0xabbd
leaq -0x68(%rbp), %rdi
callq 0x41b0
movq -0x80(%rbp), %rsi
movq %rax, %rdx
leaq 0x273fe(%rip), %rdi     # 0x31fd2
xorl %eax, %eax
callq 0x1bac0
jmp 0xabdd
leaq -0x68(%rbp), %rdi
callq 0x4270
leaq -0x48(%rbp), %rdi
callq 0x4270
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xac2f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0xac1b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x4270
leaq -0x48(%rbp), %rdi
callq 0x4270
jmp 0xac3b
jmp 0xac28
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x90, %rsp
popq %rbp
retq
movq -0x70(%rbp), %rdi
callq 0x4670
nopw %cs:(%rax,%rax)