// File: /workspace/github_c_makefile_star2_O2/michaelforney[P]cproc/eval.c
// Function: eval
struct expr *
eval(struct expr *expr)
{
	struct expr *l, *r, *c;
	struct decl *d;
	struct type *t;

	t = expr->type;
	switch (expr->kind) {
	case EXPRIDENT:
		d = expr->u.ident.decl;
		if (d->kind != DECLCONST)
			break;
		expr->kind = EXPRCONST;
		expr->u.constant.u = d->u.enumconst;
		break;
	case EXPRCOMPOUND:
		d = expr->u.compound.decl;
		if (d->u.obj.storage != SDSTATIC)
			break;
		d->value = mkglobal(d);
		emitdata(d, expr->u.compound.init);
		expr->kind = EXPRIDENT;
		expr->u.ident.decl = d;
		break;
	case EXPRUNARY:
		l = eval(expr->base);
		switch (expr->op) {
		case TBAND:
			switch (l->kind) {
			case EXPRUNARY:
				if (l->op == TMUL)
					expr = eval(l->base);
				break;
			case EXPRSTRING:
				l->u.ident.decl = stringdecl(l);
				l->kind = EXPRIDENT;
				expr->base = l;
				break;
			}
			break;
		case TMUL:
			break;
		default:
			if (l->kind != EXPRCONST)
				break;
			unary(expr, expr->op, l);
			break;
		}
		break;
	case EXPRCAST:
		l = eval(expr->base);
		if (l->kind == EXPRCONST) {
			expr->kind = EXPRCONST;
			if (l->type->prop & PROPINT && t->prop & PROPFLOAT) {
				if (l->type->u.basic.issigned)
					expr->u.constant.f = l->u.constant.i;
				else
					expr->u.constant.f = l->u.constant.u;
			} else if (l->type->prop & PROPFLOAT && t->prop & PROPINT) {
				if (t->u.basic.issigned) {
					if (l->u.constant.f < -0x1p63 || l->u.constant.f >= 0x1p63)
						error(&tok.loc, "integer part of floating-point constant %g cannot be represented as signed integer", l->u.constant.f);
					expr->u.constant.i = l->u.constant.f;
				} else {
					if (l->u.constant.f < 0.0 || l->u.constant.f >= 0x1p64)
						error(&tok.loc, "integer part of floating-point constant %g cannot be represented as unsigned integer", l->u.constant.f);
					expr->u.constant.u = l->u.constant.f;
				}
			} else {
				expr->u.constant = l->u.constant;
			}
			cast(expr);
		} else if (l->type->kind == TYPEPOINTER) {
			/*
			A cast from a pointer to integer is not a valid constant
			expression, but C11 allows implementations to recognize
			other forms of constant expressions (6.6p10), and some
			programs expect this functionality.
			*/
			if (t->kind == TYPEPOINTER || t->prop & PROPINT && t->size == typelong.size)
				expr = l;
		}
		break;
	case EXPRBINARY:
		l = eval(expr->u.binary.l);
		r = eval(expr->u.binary.r);
		expr->u.binary.l = l;
		expr->u.binary.r = r;
		switch (expr->op) {
		case TADD:
			if (r->kind == EXPRBINARY)
				c = l, l = r, r = c;
			/* fallthrough */
		case TSUB:
			if (r->kind != EXPRCONST)
				break;
			if (l->kind == EXPRCONST) {
				binary(expr, expr->op, l, r);
			} else if (l->kind == EXPRBINARY && l->type->kind == TYPEPOINTER && l->op == TADD && l->u.binary.r->kind == EXPRCONST) {
				/* (P + C1) ± C2  ->  P + (C1 ± C2) */
				binary(expr->u.binary.r, expr->op, l->u.binary.r, r);
				expr->op = TADD;
				expr->u.binary.l = l->u.binary.l;
			}
			break;
		case TLOR:
			if (l->kind != EXPRCONST)
				break;
			return l->u.constant.u ? l : r;
		case TLAND:
			if (l->kind != EXPRCONST)
				break;
			return l->u.constant.u ? r : l;
		default:
			if (l->kind != EXPRCONST || r->kind != EXPRCONST)
				break;
			binary(expr, expr->op, l, r);
		}
		break;
	}

	return expr;
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rdi, %rbx
leaq 0xc329(%rip), %r15      # 0x12038
movl (%rbx), %eax
cmpq $0x9, %rax
ja 0x60c4
movslq (%r15,%rax,4), %rax
addq %r15, %rax
jmpq *%rax
movq 0x18(%rbx), %rdi
callq 0x5d00
movq %rax, %r14
movl 0x14(%rbx), %eax
cmpl $0x4a, %eax
jne 0x5d51
movl (%r14), %eax
cmpl $0x7, %eax
jne 0x5d99
cmpl $0x4b, 0x14(%r14)
jne 0x60c4
movq 0x18(%r14), %rbx
jmp 0x5d0f
cmpl $0x4b, %eax
je 0x60c4
cmpl $0x1, (%r14)
jne 0x60c4
movl $0x1, (%rbx)
movq 0x8(%r14), %rcx
movl 0x4(%rcx), %ecx
andl $0x20, %ecx
shll $0x3, %ecx
orl %eax, %ecx
cmpl $0x14d, %ecx            # imm = 0x14D
je 0x5f67
cmpl $0x4d, %ecx
jne 0x5f7f
xorl %eax, %eax
subq 0x30(%r14), %rax
jmp 0x5e59
cmpl $0x2, %eax
jne 0x60c4
movq %r14, %rdi
callq 0x5352
movq %rax, 0x30(%r14)
andl $0x0, (%r14)
movq %r14, 0x18(%rbx)
jmp 0x60c4
movq 0x30(%rbx), %rax
cmpl $0x3, 0x8(%rax)
jne 0x60c4
movl $0x1, (%rbx)
movq 0x40(%rax), %rax
movq %rax, 0x30(%rbx)
jmp 0x60c4
movq 0x30(%rbx), %r14
cmpl $0x0, 0x44(%r14)
jne 0x60c4
movq %r14, %rdi
callq 0xd2c0
movq %rax, 0x20(%r14)
movq 0x38(%rbx), %rsi
movq %r14, %rdi
callq 0xf9aa
andl $0x0, (%rbx)
movq %r14, 0x30(%rbx)
jmp 0x60c4
movq 0x8(%rbx), %r15
movq 0x18(%rbx), %rdi
callq 0x5d00
movq %rax, %r14
cmpl $0x1, (%rax)
jne 0x5eae
movl $0x1, (%rbx)
movq 0x8(%r14), %rax
movl 0x4(%rax), %ecx
testb $0x2, %cl
je 0x5e45
testb $0x20, 0x4(%r15)
jne 0x5f92
testb $0x20, %cl
je 0x5e55
testb $0x2, 0x4(%r15)
jne 0x5faf
movq 0x30(%r14), %rax
movq %rax, 0x30(%rbx)
jmp 0x60bc
movq 0x30(%rbx), %rdi
callq 0x5d00
movq %rax, %r14
movq 0x38(%rbx), %rdi
callq 0x5d00
movq %r14, 0x30(%rbx)
movq %rax, 0x38(%rbx)
movl 0x14(%rbx), %esi
cmpl $0x5d, %esi
je 0x5f26
cmpl $0x4d, %esi
je 0x5ee2
cmpl $0x5c, %esi
je 0x5f0b
cmpl $0x4c, %esi
jne 0x5f41
cmpl $0x9, (%rax)
movq %rax, %rcx
cmoveq %r14, %rcx
cmoveq %rax, %r14
jmp 0x5ee5
movq 0x8(%r14), %rax
cmpl $0xc, (%rax)
jne 0x60c4
cmpl $0xc, (%r15)
je 0x5f39
testb $0x2, 0x4(%r15)
je 0x60c4
movq 0x10(%r15), %rax
leaq 0x15dd9(%rip), %rcx     # 0x1bcb0
cmpq 0x10(%rcx), %rax
je 0x5f39
jmp 0x60c4
movq %rax, %rcx
cmpl $0x1, (%rcx)
jne 0x60c4
movl (%r14), %edx
cmpl $0x9, %edx
je 0x6001
cmpl $0x1, %edx
jne 0x60c4
movq %rbx, %rdi
movq %r14, %rdx
jmp 0x5f5d
cmpl $0x1, (%r14)
jne 0x60c4
cmpq $0x0, 0x30(%r14)
cmoveq %r14, %rax
movq %rax, %rbx
jmp 0x60c4
cmpl $0x1, (%r14)
jne 0x60c4
cmpq $0x0, 0x30(%r14)
cmoveq %rax, %r14
movq %r14, %rbx
jmp 0x60c4
cmpl $0x1, (%r14)
jne 0x60c4
cmpl $0x1, (%rax)
jne 0x60c4
movq %rbx, %rdi
movq %r14, %rdx
movq %rax, %rcx
callq 0x6126
jmp 0x60c4
movsd 0x30(%r14), %xmm0
xorpd 0xc09b(%rip), %xmm0     # 0x12010
movlpd %xmm0, 0x30(%rbx)
jmp 0x60bc
leaq 0xc24e(%rip), %rdi      # 0x121d4
xorl %eax, %eax
callq 0xcffb
jmp 0x60bc
movq 0x30(%r14), %rcx
cmpb $0x1, 0x40(%rax)
jne 0x603e
cvtsi2sd %rcx, %xmm0
movsd %xmm0, 0x30(%rbx)
jmp 0x60bc
movsd 0x30(%r14), %xmm0
cmpb $0x1, 0x40(%r15)
jne 0x6066
movsd 0xc068(%rip), %xmm1     # 0x12030
ucomisd %xmm0, %xmm1
ja 0x5fd8
ucomisd 0xc052(%rip), %xmm0     # 0x12028
jb 0x5ff7
leaq 0x16129(%rip), %rdi     # 0x1c108
addq $0x8, %rdi
leaq 0xc142(%rip), %rsi      # 0x1212c
movb $0x1, %al
callq 0xc536
movsd 0x30(%r14), %xmm0
cvttsd2si %xmm0, %rax
jmp 0x5e59
movq 0x8(%r14), %rdx
cmpl $0xc, (%rdx)
jne 0x60c4
cmpl $0x4c, 0x14(%r14)
jne 0x60c4
movq 0x38(%r14), %rdx
cmpl $0x1, (%rdx)
jne 0x60c4
movq %rax, %rdi
callq 0x6126
movl $0x4c, 0x14(%rbx)
movq 0x30(%r14), %rax
jmp 0x5dd3
movq %rcx, %xmm0
punpckldq 0xbfa5(%rip), %xmm0 # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
subpd 0xbfad(%rip), %xmm0     # 0x12000
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
movsd %xmm1, 0x30(%rbx)
jmp 0x60bc
xorpd %xmm1, %xmm1
ucomisd %xmm0, %xmm1
ja 0x607a
ucomisd 0xbfa8(%rip), %xmm0     # 0x12020
jb 0x6099
leaq 0x16087(%rip), %rdi     # 0x1c108
addq $0x8, %rdi
leaq 0xc0f3(%rip), %rsi      # 0x1217f
movb $0x1, %al
callq 0xc536
movsd 0x30(%r14), %xmm0
cvttsd2si %xmm0, %rax
movq %rax, %rcx
subsd 0xbf7f(%rip), %xmm0     # 0x12028
cvttsd2si %xmm0, %rdx
sarq $0x3f, %rcx
andq %rcx, %rdx
orq %rax, %rdx
movq %rdx, 0x30(%rbx)
movq %rbx, %rdi
callq 0x60cd
movq %rbx, %rax
popq %rbx
popq %r14
popq %r15
retq