// File: /workspace/github_c_makefile_star2_O2/lucvoo[P]sparse-dev/evaluate.c
// Function: type_difference
const char *type_difference(struct ctype *c1, struct ctype *c2,
	unsigned long mod1, unsigned long mod2)
{
	struct ident *as1 = c1->as, *as2 = c2->as;
	struct symbol *t1 = c1->base_type;
	struct symbol *t2 = c2->base_type;
	int move1 = 1, move2 = 1;
	mod1 |= c1->modifiers;
	mod2 |= c2->modifiers;
	for (;;) {
		unsigned long diff;
		int type;
		struct symbol *base1 = t1->ctype.base_type;
		struct symbol *base2 = t2->ctype.base_type;

		/*
		 * FIXME! Collect alignment and context too here!
		 */
		if (move1) {
			if (t1 && t1->type != SYM_PTR) {
				mod1 |= t1->ctype.modifiers;
				combine_address_space(t1->pos, &as1, t1->ctype.as);
			}
			move1 = 0;
		}

		if (move2) {
			if (t2 && t2->type != SYM_PTR) {
				mod2 |= t2->ctype.modifiers;
				combine_address_space(t2->pos, &as2, t2->ctype.as);
			}
			move2 = 0;
		}

		if (t1 == t2)
			break;
		if (!t1 || !t2)
			return "different types";

		if (t1->type == SYM_NODE || t1->type == SYM_ENUM) {
			t1 = base1;
			move1 = 1;
			if (!t1)
				return "bad types";
			continue;
		}

		if (t2->type == SYM_NODE || t2->type == SYM_ENUM) {
			t2 = base2;
			move2 = 1;
			if (!t2)
				return "bad types";
			continue;
		}

		move1 = move2 = 1;
		type = t1->type;
		if (type != t2->type)
			return "different base types";

		switch (type) {
		default:
			sparse_error(t1->pos,
				     "internal error: bad type in derived(%d)",
				     type);
			return "bad types";
		case SYM_RESTRICT:
			return "different base types";
		case SYM_UNION:
		case SYM_STRUCT:
			/* allow definition of incomplete structs and unions */
			if (t1->ident == t2->ident)
			  return NULL;
			return "different base types";
		case SYM_ARRAY:
			/* XXX: we ought to compare sizes */
			break;
		case SYM_PTR:
			if (as1 != as2)
				return "different address spaces";
			/* MOD_SPECIFIER is due to idiocy in parse.c */
			if ((mod1 ^ mod2) & ~MOD_IGNORE & ~MOD_SPECIFIER)
				return "different modifiers";
			/* we could be lazier here */
			base1 = examine_pointer_target(t1);
			base2 = examine_pointer_target(t2);
			mod1 = t1->ctype.modifiers;
			as1 = t1->ctype.as;
			mod2 = t2->ctype.modifiers;
			as2 = t2->ctype.as;
			break;
		case SYM_FN: {
			struct symbol *arg1, *arg2;
			int i;

			if (as1 != as2)
				return "different address spaces";
			if ((mod1 ^ mod2) & ~MOD_IGNORE & ~MOD_SIGNEDNESS)
				return "different modifiers";
			mod1 = t1->ctype.modifiers;
			as1 = t1->ctype.as;
			mod2 = t2->ctype.modifiers;
			as2 = t2->ctype.as;

			if (t1->variadic != t2->variadic)
				return "incompatible variadic arguments";
			examine_fn_arguments(t1);
			examine_fn_arguments(t2);
			PREPARE_PTR_LIST(t1->arguments, arg1);
			PREPARE_PTR_LIST(t2->arguments, arg2);
			i = 1;
			for (;;) {
				const char *diffstr;
				if (!arg1 && !arg2)
					break;
				if (!arg1 || !arg2)
					return "different argument counts";
				diffstr = type_difference(&arg1->ctype,
							  &arg2->ctype,
							  MOD_IGN, MOD_IGN);
				if (diffstr) {
					static char argdiff[80];
					sprintf(argdiff, "incompatible argument %d (%s)", i, diffstr);
					return argdiff;
				}
				NEXT_PTR_LIST(arg1);
				NEXT_PTR_LIST(arg2);
				i++;
			}
			FINISH_PTR_LIST(arg2);
			FINISH_PTR_LIST(arg1);
			break;
		}
		case SYM_BASETYPE:
			if (as1 != as2)
				return "different address spaces";
			if (base1 != base2)
				return "different base types";
			if (t1->rank != t2->rank)
				return "different type sizes";
			diff = (mod1 ^ mod2) & ~MOD_IGNORE;
			if (!diff)
				return NULL;
			else if (diff & ~MOD_SIGNEDNESS)
				return "different modifiers";
			else
				return "different signedness";
		}
		t1 = base1;
		t2 = base2;
	}
	if (as1 != as2)
		return "different address spaces";
	if ((mod1 ^ mod2) & ~MOD_IGNORE & ~MOD_SIGNEDNESS)
		return "different modifiers";
	return NULL;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq 0x20(%rdi), %rax
leaq 0x18(%rsp), %r8
movq %rax, (%r8)
movq 0x20(%rsi), %rax
leaq 0x10(%rsp), %r8
movq %rax, (%r8)
movq (%rdi), %r13
orq 0x8(%rdi), %rdx
movq %rdx, (%rsp)
movq (%rsi), %r12
orq 0x8(%rsi), %rcx
movq %rcx, 0x8(%rsp)
xorl %eax, %eax
leaq 0x16582(%rip), %r15     # 0x42e54
movq %r12, %rbx
xorl %r14d, %r14d
movq %r13, %rbp
movq 0x60(%rbp), %r13
movq 0x60(%rbx), %r12
testq %rbp, %rbp
sete %cl
orb %al, %cl
testb $0x1, %cl
jne 0x2c917
cmpb $0x4, (%rbp)
je 0x2c917
movq (%rsp), %rax
orq 0x68(%rbp), %rax
movq %rax, (%rsp)
movq 0x4(%rbp), %rdi
movq 0x80(%rbp), %rdx
leaq 0x18(%rsp), %rsi
callq 0x2cce9
testb $0x1, %r14b
jne 0x2c945
cmpb $0x4, (%rbx)
je 0x2c945
movq 0x8(%rsp), %rax
orq 0x68(%rbx), %rax
movq %rax, 0x8(%rsp)
movq 0x4(%rbx), %rdi
movq 0x80(%rbx), %rdx
leaq 0x10(%rsp), %rsi
callq 0x2cce9
cmpq %rbx, %rbp
je 0x2cbbe
movl (%rbp), %eax
cmpb $0x9, %al
je 0x2c95d
movzbl %al, %edx
cmpl $0x3, %edx
jne 0x2c973
movb $0x1, %r14b
xorl %eax, %eax
movq %r13, %rbp
testq %r13, %r13
jne 0x2c8db
jmp 0x2cbeb
movl (%rbx), %eax
cmpb $0x9, %al
je 0x2c981
movzbl %al, %eax
cmpl $0x3, %eax
jne 0x2c994
movb $0x1, %al
movq %rbp, %r13
testq %r12, %r12
jne 0x2c8d2
jmp 0x2cbeb
cmpl %eax, %edx
jne 0x2cc26
leal -0x2(%rdx), %ecx
cmpl $0xb, %ecx
ja 0x2cc99
xorl %eax, %eax
leaq 0x1626f(%rip), %rsi     # 0x42c20
movslq (%rsi,%rcx,4), %rcx
addq %rsi, %rcx
jmpq *%rcx
movq 0x18(%rsp), %rax
cmpq 0x10(%rsp), %rax
jne 0x2cc47
movq 0x8(%rsp), %rax
xorq (%rsp), %rax
testq $-0x2043e1e0, %rax      # imm = 0xDFBC1E20
jne 0x2cc50
movq %rbp, %rdi
callq 0x270ef
movq %rax, %r13
movq %rbx, %rdi
callq 0x270ef
movq %rax, %r12
movq 0x68(%rbp), %rax
movq %rax, (%rsp)
movq 0x80(%rbp), %rax
movq %rax, 0x18(%rsp)
movq 0x68(%rbx), %rax
movq %rax, 0x8(%rsp)
movq 0x80(%rbx), %rax
movq %rax, 0x10(%rsp)
xorl %eax, %eax
jmp 0x2c8d2
movq 0x18(%rsp), %rax
cmpq 0x10(%rsp), %rax
jne 0x2cc47
movq 0x8(%rsp), %rax
xorq (%rsp), %rax
testq $-0x2043e1e0, %rax      # imm = 0xDFBC1E20
jne 0x2cc50
movq 0x68(%rbp), %rcx
movq 0x80(%rbp), %rax
movq %rax, 0x18(%rsp)
movq 0x68(%rbx), %rax
movq %rax, 0x8(%rsp)
movq 0x80(%rbx), %rax
movq %rax, 0x10(%rsp)
movl 0x54(%rbx), %eax
xorl 0x54(%rbp), %eax
btl $0x9, %eax
jb 0x2ccb0
movq %rcx, (%rsp)
movq %rbp, %rdi
callq 0x2cd18
movq %rbx, %rdi
callq 0x2cd18
movq 0x88(%rbp), %rcx
xorl %r15d, %r15d
testq %rcx, %rcx
je 0x2cab8
movq %rcx, %rbp
cmpb $0x0, (%rbp)
jg 0x2cac1
movq 0x10(%rbp), %rbp
cmpq %rcx, %rbp
jne 0x2caa5
xorl %edi, %edi
jmp 0x2cabc
xorl %edi, %edi
xorl %ebp, %ebp
xorl %r14d, %r14d
jmp 0x2cacf
movq 0x18(%rbp), %rdi
andq $-0x4, %rdi
pushq $0x1
popq %rax
movl %eax, %r14d
movq 0x88(%rbx), %rdx
testq %rdx, %rdx
je 0x2caf3
movq %rdx, %rbx
cmpb $0x0, (%rbx)
jg 0x2caf9
movq 0x10(%rbx), %rbx
cmpq %rdx, %rbx
jne 0x2cade
xorl %esi, %esi
xorl %r15d, %r15d
jmp 0x2cb07
xorl %esi, %esi
xorl %ebx, %ebx
jmp 0x2cb07
movq 0x18(%rbx), %rsi
andq $-0x4, %rsi
pushq $0x1
popq %rax
movl %eax, %r15d
pushq $0x1
popq %r8
movq %rcx, 0x30(%rsp)
movq %rdx, 0x28(%rsp)
movq %rdi, %rax
orq %rsi, %rax
je 0x2c8c9
testq %rdi, %rdi
je 0x2cbfd
testq %rsi, %rsi
je 0x2cbfd
addq $0x60, %rdi
addq $0x60, %rsi
movl $0x11000e00, %edx       # imm = 0x11000E00
movl $0x11000e00, %ecx       # imm = 0x11000E00
movl %r8d, 0x24(%rsp)
callq 0x2c88c
movl 0x24(%rsp), %r8d
movq 0x28(%rsp), %rdx
movq 0x30(%rsp), %rcx
testq %rax, %rax
jne 0x2cc06
movsbl (%rbp), %eax
cmpl %eax, %r14d
jl 0x2cb80
movq 0x10(%rbp), %rbp
xorl %r14d, %r14d
cmpq %rcx, %rbp
jne 0x2cb67
xorl %edi, %edi
jmp 0x2cb8f
movslq %r14d, %rax
movq 0x18(%rbp,%rax,8), %rdi
andq $-0x4, %rdi
incl %r14d
movsbl (%rbx), %eax
cmpl %eax, %r15d
jl 0x2cba7
movq 0x10(%rbx), %rbx
xorl %r15d, %r15d
cmpq %rdx, %rbx
jne 0x2cb8f
xorl %esi, %esi
jmp 0x2cbb6
movslq %r15d, %rax
movq 0x18(%rbx,%rax,8), %rsi
andq $-0x4, %rsi
incl %r15d
incl %r8d
jmp 0x2cb15
movq 0x18(%rsp), %rax
leaq 0x162d1(%rip), %r15     # 0x42e9b
cmpq 0x10(%rsp), %rax
jne 0x2cbeb
movq 0x8(%rsp), %rax
xorq (%rsp), %rax
andq $-0x2043e1e0, %rax      # imm = 0xDFBC1E20
leaq 0x162cd(%rip), %r15     # 0x42eb4
cmoveq %rax, %r15
movq %r15, %rax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x162e4(%rip), %r15     # 0x42ee8
jmp 0x2cbeb
leaq 0x5d2f3(%rip), %r15     # 0x89f00
leaq 0x162ee(%rip), %rsi     # 0x42f02
movq %r15, %rdi
movl %r8d, %edx
movq %rax, %rcx
xorl %eax, %eax
callq 0xe2d0
jmp 0x2cbeb
leaq 0x16231(%rip), %r15     # 0x42e5e
jmp 0x2cbeb
movq 0x18(%rbp), %rax
xorl %r15d, %r15d
cmpq 0x18(%rbx), %rax
leaq 0x1621d(%rip), %rax     # 0x42e5e
cmovneq %rax, %r15
jmp 0x2cbeb
leaq 0x1624d(%rip), %r15     # 0x42e9b
jmp 0x2cbeb
leaq 0x1625d(%rip), %r15     # 0x42eb4
jmp 0x2cbeb
movq 0x18(%rsp), %rax
leaq 0x16236(%rip), %r15     # 0x42e9b
cmpq 0x10(%rsp), %rax
jne 0x2cbeb
leaq 0x161e7(%rip), %r15     # 0x42e5e
cmpq %r12, %r13
jne 0x2cbeb
movl 0x54(%rbx), %eax
xorl 0x54(%rbp), %eax
testl $0x3800000, %eax        # imm = 0x3800000
je 0x2ccbc
leaq 0x1628c(%rip), %r15     # 0x42f20
jmp 0x2cbeb
movq 0x4(%rbp), %rdi
leaq 0x161cf(%rip), %rsi     # 0x42e73
xorl %eax, %eax
callq 0x1120e
jmp 0x2cbeb
leaq 0x16211(%rip), %r15     # 0x42ec8
jmp 0x2cbeb
movq 0x8(%rsp), %rcx
xorq (%rsp), %rcx
testq $-0x204381e0, %rcx      # imm = 0xDFBC7E20
je 0x2cce1
testq $-0x2043e1e0, %rcx      # imm = 0xDFBC1E20
leaq 0x16259(%rip), %rax     # 0x42f35
jmp 0x2cbe0
xorl %r15d, %r15d
jmp 0x2cbeb