// File: /workspace/github_c_makefile_star2_O0/lucvoo[P]sparse-dev/compile-i386.c
// Function: x86_call_expression
static struct storage *x86_call_expression(struct expression *expr)
{
	struct function *f = current_func;
	struct symbol *direct;
	struct expression *arg, *fn;
	struct storage *retval, *fncall;
	int framesize;
	char s[64];

	if (!expr->ctype) {
		warning(expr->pos, "\tcall with no type!");
		return NULL;
	}

	framesize = 0;
	FOR_EACH_PTR_REVERSE(expr->args, arg) {
		struct storage *new = x86_expression(arg);
		int size = arg->ctype->bit_size;

		/*
		 * FIXME: i386 SysV ABI dictates that values
		 * smaller than 32 bits should be placed onto
		 * the stack as 32-bit objects.  We should not
		 * blindly do a 32-bit push on objects smaller
		 * than 32 bits.
		 */
		if (size < 32)
			size = 32;
		insn("pushl", new, NULL,
		     !framesize ? "begin function call" : NULL);

		framesize += bits_to_bytes(size);
	} END_FOR_EACH_PTR_REVERSE(arg);

	fn = expr->fn;

	/* Remove dereference, if any */
	direct = NULL;
	if (fn->type == EXPR_PREOP) {
		if (fn->unop->type == EXPR_SYMBOL) {
			struct symbol *sym = fn->unop->symbol;
			if (sym->ctype.base_type->type == SYM_FN)
				direct = sym;
		}
	}
	if (direct) {
		struct storage *direct_stor = new_storage(STOR_SYM);
		direct_stor->flags |= STOR_WANTS_FREE;
		direct_stor->sym = direct;
		insn("call", direct_stor, NULL, NULL);
	} else {
		fncall = x86_expression(fn);
		emit_move(fncall, REG_EAX, fn->ctype, NULL);

		strcpy(s, "\tcall\t*%eax\n");
		push_text_atom(f, s);
	}

	/* FIXME: pay attention to BITS_IN_POINTER */
	if (framesize) {
		struct storage *val = new_storage(STOR_VALUE);
		val->value = (long long) framesize;
		val->flags = STOR_WANTS_FREE;
		insn("addl", val, REG_ESP, NULL);
	}

	retval = stack_alloc(4);
	emit_move(REG_EAX, retval, NULL, "end function call");

	return retval;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movq %rdi, -0x10(%rbp)
movq 0x5b112(%rip), %rax     # 0xbfdb8
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x64cd8
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
leaq 0x72e9(%rip), %rsi      # 0x6bfad
movb $0x0, %al
callq 0x16df0
movq $0x0, -0x8(%rbp)
jmp 0x64fd2
movl $0x0, -0x44(%rbp)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x98(%rbp)
movq -0x98(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0x98(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0x10(%rbp), %rax
cmpq $0x0, 0x28(%rax)
jne 0x64d1a
jmp 0x64e26
jmp 0x64d1c
movq -0xa0(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0xa0(%rbp)
movq -0xa0(%rbp), %rax
movw (%rax), %ax
shlw $0x8, %ax
sarw $0x8, %ax
cwtl
movl %eax, -0xac(%rbp)
movl -0xac(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, %eax
jl 0x64e10
movq -0xa0(%rbp), %rax
movslq -0xac(%rbp), %rcx
movq 0x18(%rax,%rcx,8), %rax
movq %rax, -0x28(%rbp)
movq -0xa0(%rbp), %rax
movw (%rax), %ax
sarw $0x8, %ax
cwtl
cmpl $0x0, %eax
je 0x64d93
cmpq $0x0, -0x28(%rbp)
jne 0x64d93
jmp 0x64d47
movq -0x28(%rbp), %rdi
callq 0x62220
movq %rax, -0xb8(%rbp)
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rax
movl 0x50(%rax), %eax
movl %eax, -0xbc(%rbp)
cmpl $0x20, -0xbc(%rbp)
jge 0x64dc7
movl $0x20, -0xbc(%rbp)
movq -0xb8(%rbp), %rsi
cmpl $0x0, -0x44(%rbp)
setne %dl
xorb $-0x1, %dl
xorl %eax, %eax
movl %eax, %ecx
leaq 0xdff1(%rip), %rax      # 0x72dd4
testb $0x1, %dl
cmovneq %rax, %rcx
leaq 0xdfdd(%rip), %rdi      # 0x72dce
xorl %eax, %eax
movl %eax, %edx
callq 0x63500
movl -0xbc(%rbp), %edi
callq 0x65d40
addl -0x44(%rbp), %eax
movl %eax, -0x44(%rbp)
jmp 0x64d47
jmp 0x64e12
movq -0xa0(%rbp), %rax
cmpq -0x98(%rbp), %rax
jne 0x64d1c
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x30(%rbp)
movq $0x0, -0x20(%rbp)
movq -0x30(%rbp), %rax
movl (%rax), %eax
andl $0xff, %eax
cmpl $0x9, %eax
jne 0x64e97
movq -0x30(%rbp), %rax
movq 0x20(%rax), %rax
movl (%rax), %eax
andl $0xff, %eax
cmpl $0x3, %eax
jne 0x64e95
movq -0x30(%rbp), %rax
movq 0x20(%rax), %rax
movq 0x20(%rax), %rax
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rax
movq 0x60(%rax), %rax
movl (%rax), %eax
andl $0xff, %eax
cmpl $0x5, %eax
jne 0x64e93
movq -0xc8(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x64e95
jmp 0x64e97
cmpq $0x0, -0x20(%rbp)
je 0x64eed
movl $0x2, %edi
callq 0x63490
movq %rax, -0xd0(%rbp)
movq -0xd0(%rbp), %rax
movq 0x8(%rax), %rcx
orq $0x2, %rcx
movq %rcx, 0x8(%rax)
movq -0x20(%rbp), %rcx
movq -0xd0(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0xd0(%rbp), %rsi
leaq 0xba19(%rip), %rdi      # 0x708f8
xorl %eax, %eax
movl %eax, %ecx
movq %rcx, %rdx
callq 0x63500
jmp 0x64f40
movq -0x30(%rbp), %rdi
callq 0x62220
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rdi
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rdx
leaq 0x2d983(%rip), %rsi     # 0x92890
addq $0x330, %rsi            # imm = 0x330
xorl %eax, %eax
movl %eax, %ecx
callq 0x63640
leaq -0x90(%rbp), %rdi
leaq 0xdebd(%rip), %rsi      # 0x72de8
callq 0x110a0
movq -0x18(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x63e60
cmpl $0x0, -0x44(%rbp)
je 0x64f9a
movl $0x4, %edi
callq 0x63490
movq %rax, -0xd8(%rbp)
movslq -0x44(%rbp), %rcx
movq -0xd8(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0xd8(%rbp), %rax
movq $0x2, 0x8(%rax)
movq -0xd8(%rbp), %rsi
leaq 0xdd63(%rip), %rdi      # 0x72ce6
leaq 0x2d906(%rip), %rdx     # 0x92890
addq $0x480, %rdx            # imm = 0x480
xorl %eax, %eax
movl %eax, %ecx
callq 0x63500
movl $0x4, %edi
callq 0x63a00
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rsi
leaq 0x2d8dd(%rip), %rdi     # 0x92890
addq $0x330, %rdi            # imm = 0x330
xorl %eax, %eax
movl %eax, %edx
leaq 0xde30(%rip), %rcx      # 0x72df5
callq 0x63640
movq -0x38(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0xe0, %rsp
popq %rbp
retq
nop