// File: /workspace/github_c_makefile_star2_O3/Yamsman[P]scc/src/gen.c
// Function: gen_expr_call
void gen_expr_call(asm_f *f, ast_n *n) {
	ast_n *func = n->dat.expr.left;
	ast_n *arg = n->dat.expr.right;
	char *fname = (func->dat.expr.sym->name != NULL) ? func->dat.expr.sym->name : "(unknown)";

	//Get type of function
	s_type *ftype = astn_type(func);
	vector params = ftype->param;

	//Count arguments passed to function
	int arg_count = 0;
	ast_n *cur = arg;
	while (cur != NULL) {
		arg_count++;
		cur = cur->next;
	}
	if (arg_count != params.len)
		c_error(NULL, "Invalid number of arguments to function '%s' (expected %i, got %i)\n",
			fname, params.len, arg_count);

	//Generate arguments
	//Place values in registers first, then push the remaining args
	static int arg_reg[8] = {RDI, RSI, RDX, RCX, R8, R9, R10, R11};
	for (int i=params.len-1; i>=0; i--) {
		//Only check types within the bounds of parameter table/argument list
		if (arg == NULL) break;

		//Get types for each argument
		s_type *ptype = ((symbol*)params.table[i])->type; //Type of defined parameter
		s_type *atype = astn_type(arg);			  //Type of call arg

		//Check types
		if (ptype->kind != atype->kind)
			c_error(NULL, "Mismatching type for argument %i of function call '%s'\n",
				i+1, fname);

		//Generate the expression
		gen_expr(f, arg);

		//If the argument's number is greater than 8, push it
		//Otherwise, place it in a register
		if (i >= 8) {
			asmf_add_inst(f, mk_inst(INST_PUSH, 1,
				mk_oprd(OPRD_REG, RAX)
			));
		} else {
			asmf_add_inst(f, mk_inst(INST_MOV, 2,
				mk_oprd(OPRD_REG, arg_reg[i]),
				mk_oprd(OPRD_REG, RAX)
			));
		}
		
		arg = arg->next;
	}

	//Generate the call
	return;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movq %rdi, %rbx
movq 0x20(%rsi), %rdi
movq 0x28(%rsi), %r14
movq 0x18(%rdi), %rax
movq (%rax), %rax
testq %rax, %rax
leaq 0x8d2f(%rip), %r15      # 0xd51a
cmovneq %rax, %r15
callq 0x3626
movl 0x30(%rax), %r12d
xorl %r8d, %r8d
testq %r14, %r14
je 0x480f
movq %r14, %rcx
incl %r8d
movq 0x60(%rcx), %rcx
testq %rcx, %rcx
jne 0x4803
movq 0x28(%rax), %r13
cmpl %r12d, %r8d
je 0x482e
leaq 0x8d05(%rip), %rsi      # 0xd524
xorl %edi, %edi
movq %r15, %rdx
movl %r12d, %ecx
xorl %eax, %eax
callq 0x3250
testq %r14, %r14
sete %al
testl %r12d, %r12d
setle %cl
orb %al, %cl
jne 0x4936
movq -0x8(%r13,%r12,8), %rax
movq 0x8(%rax), %rbp
movq %r14, %rdi
callq 0x3626
movl (%rbp), %ecx
cmpl (%rax), %ecx
je 0x4870
xorl %edi, %edi
leaq 0x8d05(%rip), %rsi      # 0xd568
movl %r12d, %edx
movq %r15, %rcx
xorl %eax, %eax
callq 0x3250
movq %rbx, %rdi
movq %r14, %rsi
callq 0x41eb
cmpq $0x9, %r12
jb 0x48b7
leaq 0x88(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x52a0
movups 0x88(%rsp), %xmm0
movups 0x98(%rsp), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
movl $0x36, %edi
movl $0x1, %esi
jmp 0x490e
leaq 0x8da2(%rip), %rax      # 0xd660
movl -0x4(%rax,%r12,4), %edx
leaq 0x68(%rsp), %rdi
xorl %esi, %esi
callq 0x52a0
leaq 0x48(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x52a0
movups 0x48(%rsp), %xmm0
movups 0x58(%rsp), %xmm1
movups %xmm1, 0x30(%rsp)
movups %xmm0, 0x20(%rsp)
movups 0x68(%rsp), %xmm0
movups 0x78(%rsp), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
movl $0x3e, %edi
movl $0x2, %esi
xorl %eax, %eax
callq 0x52d5
movq %rbx, %rdi
movq %rax, %rsi
callq 0x55c6
cmpq $0x2, %r12
jb 0x4936
movq 0x60(%r14), %r14
decq %r12
testq %r14, %r14
jne 0x4842
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq