// File: /workspace/github_c_makefile_star2_O2/lucvoo[P]sparse-dev/evaluate.c
// Function: check_assignment_types
static int check_assignment_types(struct symbol *target, struct expression **rp,
	const char **typediff)
{
	struct symbol *source = degenerate(*rp);
	struct symbol *t, *s;
	int tclass = classify_type(target, &t);
	int sclass = classify_type(source, &s);

	if (tclass & sclass & TYPE_NUM) {
		if (tclass & TYPE_RESTRICT) {
			/* allowed assignments unfoul */
			if (sclass & TYPE_FOULED && unfoul(s) == t)
				goto Cast;
			if (!restricted_value(*rp, target))
				goto Cast;
			if (s == t)
				return 1;
		} else if (!(sclass & TYPE_RESTRICT))
			goto Cast;
                if (t == &bool_ctype) {
                        if (is_fouled_type(s))
                                warning((*rp)->pos, "%s degrades to integer",
                                        show_typename(s->ctype.base_type));
                        goto Cast;
                }
		*typediff = "different base types";
		return 0;
	}

	if (tclass == TYPE_PTR) {
		unsigned long mod1, mod2;
		unsigned long modl, modr;
		struct symbol *b1, *b2;
		// NULL pointer is always OK
		int is_null = is_null_pointer_constant(*rp);
		if (is_null) {
			if (is_null == NULL_ZERO)
				bad_null(*rp);
			goto Cast;
		}
		if (!(sclass & TYPE_PTR)) {
			*typediff = "different base types";
			return 0;
		}
		b1 = examine_pointer_target(t);
		b2 = examine_pointer_target(s);
		mod1 = t->ctype.modifiers & MOD_IGN;
		mod2 = s->ctype.modifiers & MOD_IGN;
		if (whitelist_pointers(b1, b2)) {
			/*
			 * assignments to/from void * are OK, provided that
			 * we do not remove qualifiers from pointed to [C]
			 * or mix address spaces [sparse].
			 */
			if (t->ctype.as != s->ctype.as) {
				*typediff = "different address spaces";
				return 0;
			}
			/*
			 * If this is a function pointer assignment, it is
			 * actually fine to assign a pointer to const data to
			 * it, as a function pointer points to const data
			 * implicitly, i.e., dereferencing it does not produce
			 * an lvalue.
			 */
			if (b1->type == SYM_FN)
				mod1 |= MOD_CONST;
			if (mod2 & ~mod1 & ~MOD_FUN_ATTR) {
				*typediff = "different modifiers";
				return 0;
			}
			goto Cast;
		}
		/* It's OK if the target is more volatile or const than the source */
		/* It's OK if the source is more pure/noreturn than the target */
		modr = mod1 & ~MOD_REV_QUAL;
		modl = mod2 &  MOD_REV_QUAL;
		*typediff = type_difference(&t->ctype, &s->ctype, modl, modr);
		if (*typediff)
			return 0;
		return 1;
	}

	if ((tclass & TYPE_COMPOUND) && s == t)
		return 1;

	if (tclass & TYPE_NUM) {
		/* XXX: need to turn into comparison with NULL */
		if (t == &bool_ctype && (sclass & TYPE_PTR))
			goto Cast;
		*typediff = "different base types";
		return 0;
	}
	*typediff = "invalid types";
	return 0;

Cast:
	*rp = cast_to(*rp, target);
	return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rdx, %r12
movq %rsi, %r14
movq %rdi, %r15
movq (%rsi), %rdi
callq 0x2f6c0
movq %rax, %rbx
leaq 0x8(%rsp), %rsi
movq %r15, %rdi
callq 0x2f4dd
movl %eax, %r13d
leaq 0x10(%rsp), %rsi
movq %rbx, %rdi
callq 0x2f4dd
movl %eax, %ebp
movl %r13d, %eax
andl $0x1, %eax
pushq $0x1
popq %rbx
testl %ebp, %eax
je 0x30da8
testb $0x4, %r13b
jne 0x30dd4
testb $0x4, %bpl
je 0x30e92
movq 0x8(%rsp), %rax
jmp 0x30e11
cmpl $0x10, %r13d
jne 0x30e23
movq (%r14), %rdi
callq 0x3106a
testl %eax, %eax
je 0x30eb1
cmpl $0x2, %eax
jne 0x30e92
movq (%r14), %rdi
callq 0x31099
jmp 0x30e92
testb $0x40, %bpl
je 0x30dee
movq 0x10(%rsp), %rax
movq 0x60(%rax), %rax
cmpq 0x8(%rsp), %rax
je 0x30e92
movq (%r14), %rax
cmpb $0x1, (%rax)
jne 0x30e01
cmpq $0x0, 0x20(%rax)
je 0x30e92
movq 0x8(%rsp), %rax
cmpq %rax, 0x10(%rsp)
je 0x30ea0
cmpq 0x291c8(%rip), %rax     # 0x59fe0
je 0x30e48
leaq 0x1203d(%rip), %rax     # 0x42e5e
jmp 0x30e40
testb $0x20, %r13b
je 0x30e35
movq 0x10(%rsp), %rcx
cmpq 0x8(%rsp), %rcx
je 0x30ea0
testl %eax, %eax
jne 0x30e7e
leaq 0x12336(%rip), %rax     # 0x43176
movq %rax, (%r12)
xorl %ebx, %ebx
jmp 0x30ea0
movq 0x10(%rsp), %r12
movq %r12, %rdi
callq 0x3104e
cmpl $0xe, %eax
jne 0x30e92
movq (%r14), %r13
movq 0x60(%r12), %rdi
callq 0x20b5a
movq 0x8(%r13), %rdi
leaq 0x12271(%rip), %rsi     # 0x430e3
movq %rax, %rdx
xorl %eax, %eax
callq 0x1108a
jmp 0x30e92
testb $0x10, %bpl
je 0x30e1a
movq 0x8(%rsp), %rax
cmpq 0x29150(%rip), %rax     # 0x59fe0
jne 0x30e1a
movq (%r14), %rdi
movq %r15, %rsi
callq 0x2f54c
movq %rax, (%r14)
movl %ebx, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testb $0x10, %bpl
je 0x30e1a
movq 0x8(%rsp), %rbp
movq %rbp, %rdi
callq 0x270ef
movq %rax, 0x30(%rsp)
movq 0x10(%rsp), %r13
movq %r13, %rdi
callq 0x270ef
movq %r13, %r11
movq 0x30(%rsp), %rdi
movq %rbp, %r9
movq 0x68(%rbp), %rcx
movq 0x68(%r13), %rdx
movq %rdi, 0x40(%rsp)
movq %rax, 0x38(%rsp)
cmpq %rax, %rdi
je 0x30ff5
movq %rax, %rbp
leaq 0x3420e(%rip), %rax     # 0x65118
cmpq %rax, %rdi
sete %sil
cmpq %rax, %rbp
sete %al
orb %sil, %al
je 0x30f3c
movq 0x80(%r9), %rax
cmpq 0x80(%r11), %rax
je 0x31025
leaq 0x11f64(%rip), %rax     # 0x42e9b
jmp 0x30e40
leaq 0x40(%rsp), %rsi
movq %rdx, 0x28(%rsp)
movq %rcx, 0x20(%rsp)
movq %r9, 0x18(%rsp)
movq %r11, %r13
callq 0x2f4dd
movq %r13, %r11
movq 0x18(%rsp), %r9
movq 0x20(%rsp), %rcx
movq 0x28(%rsp), %rdx
cmpl $0x1, %eax
jne 0x30ff5
leaq 0x38(%rsp), %rsi
movq %rbp, %rdi
callq 0x2f4dd
movq %r13, %r11
movq 0x30(%rsp), %rdi
movq 0x18(%rsp), %r9
movq 0x20(%rsp), %rcx
movq 0x28(%rsp), %rdx
cmpl $0x1, %eax
jne 0x30ff5
movq 0x40(%rsp), %rax
movq 0x38(%rsp), %r8
cmpq %r8, %rax
je 0x30f1c
movl 0x54(%rax), %eax
movl $0x3800000, %r10d       # imm = 0x3800000
movl %eax, %esi
andl %r10d, %esi
movl 0x54(%r8), %r8d
cmpl $0x3000000, %esi        # imm = 0x3000000
jne 0x30fd9
andl %r8d, %r10d
cmpl $0x3000000, %r10d       # imm = 0x3000000
je 0x30f1c
xorl %eax, %r8d
testl $0x3800000, %r8d        # imm = 0x3800000
jne 0x30ff5
leaq 0x2fe54(%rip), %rax     # 0x60e40
cmpl $0x0, (%rax)
je 0x30f1c
andl $0xe00, %ecx            # imm = 0xE00
andl $0x11000000, %edx       # imm = 0x11000000
addq $0x60, %r9
addq $0x60, %r11
movq %r9, %rdi
movq %r11, %rsi
callq 0x2c88c
movq %rax, (%r12)
xorl %ebx, %ebx
testq %rax, %rax
sete %bl
jmp 0x30ea0
andl $0xe00, %edx            # imm = 0xE00
movl %ecx, %eax
orl $0x200, %eax            # imm = 0x200
cmpb $0x5, (%rdi)
cmovnel %ecx, %eax
notl %eax
testl %eax, %edx
je 0x30e92
leaq 0x11e6b(%rip), %rax     # 0x42eb4
jmp 0x30e40