// File: /workspace/github_c_makefile_star2_O1/lucvoo[P]sparse-dev/builtin.c
// Function: expand_object_size
static int expand_object_size(struct expression *expr, int cost)
{
	struct expression *arg = first_expression(expr->args);
	int type = get_expression_value_silent(ptr_list_nth(expr->args, 1));
	unsigned long val = -1, off = 0;

	while (arg) {
		switch (arg->type) {
		case EXPR_IMPLIED_CAST:
		case EXPR_CAST:
			// ignore those
			arg = arg->cast_expression;
			continue;
		case EXPR_BINOP:
			// a constant add is (maybe) an offset
			if (!arg->right || arg->op != '+' || arg->right->type != EXPR_VALUE)
				break;
			off += arg->right->value;
			arg = arg->left;
			continue;
		case EXPR_PREOP:
			// a deref is just intermediate variable
			// and so the offset needs to be zeroed.
			if (arg->op == '*') {
				struct expression *parent = arg;
				arg = arg->unop;
				off = 0;
				switch (arg->type) {
				case EXPR_SYMBOL:
					arg = arg->symbol->initializer;
					if (arg == parent) {
						// stop at self-initialized vars
						// and do not expand them.
						arg = NULL;
						val = -1;
						break;
					}
					continue;
				default:
					break;
				}
			}
			break;
		case EXPR_SYMBOL:
			// the symbol we're looking after
			val = bits_to_bytes(arg->symbol->bit_size);
			break;
		case EXPR_CALL:
			// use alloc_size() attribute but only after linearization.
			return UNSAFE;
		default:
			break;
		}
		break;
	}

	if (val == -1)
		val = (type & 2) ? 0 : val;
	else if (type & 1)
		return UNSAFE;
	else
		val -= off;

	expr->flags |= CEF_SET_ICE;
	expr->type = EXPR_VALUE;
	expr->value = val;
	expr->taint = 0;
	return 0;
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
movq 0x28(%rdi), %rdi
callq 0x22634
movq %rax, %r14
movq 0x28(%rbx), %rdi
movl $0x1, %esi
callq 0x22680
movq %rax, %rdi
callq 0xf2fb
movq %rax, %rcx
movq $-0x1, %rdx
testq %r14, %r14
je 0x3124e
xorl %esi, %esi
leaq 0x18703(%rip), %rax     # 0x498c4
movq %r14, %rdi
movzbl (%rdi), %r8d
leal -0x3(%r8), %r9d
cmpl $0xa, %r9d
ja 0x31294
movslq (%rax,%r9,4), %r8
addq %rax, %r8
jmpq *%r8
movq 0x28(%rdi), %rdi
testq %rdi, %rdi
jne 0x311c4
jmp 0x31250
cmpl $0x2a, 0x4(%rdi)
jne 0x31250
movq 0x20(%rdi), %r14
movb $0x1, %r8b
cmpb $0x3, (%r14)
jne 0x3121a
movq 0x20(%r14), %rsi
movq 0xb0(%rsi), %rsi
cmpq %rdi, %rsi
sete %r8b
movl $0x0, %r14d
cmovneq %rsi, %r14
movl $0x0, %esi
testb %r8b, %r8b
je 0x31243
jmp 0x3124e
movq 0x28(%rdi), %r8
testq %r8, %r8
je 0x31250
cmpl $0x2b, 0x4(%rdi)
jne 0x31250
cmpb $0x1, (%r8)
jne 0x31250
addq 0x20(%r8), %rsi
movq 0x20(%rdi), %r14
testq %r14, %r14
jne 0x311c1
jmp 0x31250
xorl %esi, %esi
cmpq $-0x1, %rdx
je 0x31265
movl $0x64, %eax
testb $0x1, %cl
jne 0x3128c
subq %rsi, %rdx
jmp 0x31271
xorl %eax, %eax
btl $0x1, %ecx
adcl $-0x1, %eax
movslq %eax, %rdx
movl $0xffffcf00, %eax       # imm = 0xFFFFCF00
andl (%rbx), %eax
orl $0x3001, %eax           # imm = 0x3001
movl %eax, (%rbx)
movq %rdx, 0x20(%rbx)
movl $0x0, 0x28(%rbx)
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
retq
cmpl $0x14, %r8d
jne 0x31250
movl $0x64, %eax
jmp 0x3128c
movq 0x20(%rdi), %rax
movl 0x50(%rax), %eax
testl %eax, %eax
js 0x31250
leaq 0x3444d(%rip), %rdx     # 0x65700
movl (%rdx), %edi
addl %edi, %eax
decl %eax
cltd
idivl %edi
movslq %eax, %rdx
jmp 0x31250