// File: /workspace/github_c_makefile_star2_O1/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
cmpq $0x0, 0x10(%rdi)
je 0x42e38
movq 0x55c9a(%rip), %rax     # 0x989d8
movq %rax, (%rsp)
movq %rdi, 0x8(%rsp)
movq 0x28(%rdi), %r14
xorl %r13d, %r13d
testq %r14, %r14
je 0x42ddf
leaq 0xd2e7(%rip), %r15      # 0x50045
movq %r14, %rbp
movq 0x8(%rbp), %rbp
movsbq (%rbp), %rbx
movl %ebx, %ebx
testl %ebx, %ebx
jle 0x42dda
movq 0x10(%rbp,%rbx,8), %r12
decq %rbx
cmpw $0x100, (%rbp)          # imm = 0x100
jb 0x42d85
testq %r12, %r12
je 0x42d6c
movq %r12, %rdi
callq 0x41d4f
movq 0x10(%r12), %rcx
movl 0x50(%rcx), %r12d
cmpl $0x21, %r12d
movl $0x20, %ecx
cmovll %ecx, %r12d
testl %r13d, %r13d
movl $0x0, %ecx
leaq 0xd299(%rip), %rdx      # 0x5004b
cmoveq %rdx, %rcx
movq %r15, %rdi
movq %rax, %rsi
xorl %edx, %edx
callq 0x4259e
leaq 0x275d6(%rip), %rax     # 0x6a3a0
movl (%rax), %ecx
leal (%r12,%rcx), %eax
decl %eax
cltd
idivl %ecx
addl %eax, %r13d
jmp 0x42d6a
cmpq %r14, %rbp
jne 0x42d61
movq 0x8(%rsp), %rax
movq 0x20(%rax), %r14
cmpb $0x9, (%r14)
jne 0x42e0a
movq 0x20(%r14), %rax
cmpb $0x3, (%rax)
jne 0x42e0a
movq 0x20(%rax), %rax
movq 0x60(%rax), %rcx
xorl %ebx, %ebx
cmpb $0x5, (%rcx)
cmoveq %rax, %rbx
jmp 0x42e0c
xorl %ebx, %ebx
testq %rbx, %rbx
je 0x42e51
movl $0x2, %edi
callq 0x42575
orb $0x2, 0x8(%rax)
movq %rbx, 0x20(%rax)
leaq 0xb234(%rip), %rdi      # 0x4e05e
movq %rax, %rsi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x4259e
jmp 0x42e97
movq 0x8(%rdi), %rdi
leaq 0x673d(%rip), %rsi      # 0x49580
xorl %ebx, %ebx
xorl %eax, %eax
callq 0x11a38
jmp 0x42ef2
movq %r14, %rdi
callq 0x41d4f
movq 0x10(%r14), %rdx
leaq 0x2896c(%rip), %rsi     # 0x6b7d0
movq %rax, %rdi
xorl %ecx, %ecx
callq 0x4263e
movabsq $0xa786165252a09, %rax  # imm = 0xA786165252A09
leaq 0x10(%rsp), %rsi
movq %rax, 0x5(%rsi)
movabsq $0x252a096c6c616309, %rax # imm = 0x252A096C6C616309
movq %rax, (%rsi)
movq (%rsp), %rdi
callq 0x42a90
testl %r13d, %r13d
je 0x42ecd
movl $0x4, %edi
callq 0x42575
movslq %r13d, %rcx
movq %rcx, 0x20(%rax)
movq $0x2, 0x8(%rax)
leaq 0xd0a1(%rip), %rdi      # 0x4ff5d
leaq 0x28a5d(%rip), %rdx     # 0x6b920
movq %rax, %rsi
xorl %ecx, %ecx
callq 0x4259e
movl $0x4, %edi
callq 0x427bd
movq %rax, %rbx
leaq 0x288ef(%rip), %rdi     # 0x6b7d0
leaq 0xd177(%rip), %rcx      # 0x5005f
movq %rax, %rsi
xorl %edx, %edx
callq 0x4263e
movq %rbx, %rax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq