// File: /workspace/github_c_makefile_star2_O2/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), %rbp
callq 0x33ed
movq 0x28(%rax), %r13
movl 0x30(%rax), %r15d
xorl %r8d, %r8d
movq %r14, %rax
testq %rax, %rax
je 0x46c4
incl %r8d
movq 0x60(%rax), %rax
jmp 0x46b6
testq %rbp, %rbp
leaq 0x7e4c(%rip), %r12      # 0xc51a
cmovneq %rbp, %r12
cmpl %r8d, %r15d
je 0x47db
leaq 0x7e42(%rip), %rsi      # 0xc524
xorl %edi, %edi
movq %r12, %rdx
movl %r15d, %ecx
xorl %eax, %eax
callq 0x35e4
jmp 0x47db
testq %r14, %r14
je 0x47e4
movq -0x8(%r13,%r15,8), %rax
movq 0x8(%rax), %rbp
movq %r14, %rdi
callq 0x33ed
movl (%rbp), %ecx
cmpl (%rax), %ecx
je 0x472d
xorl %edi, %edi
leaq 0x7e48(%rip), %rsi      # 0xc568
movl %r15d, %edx
movq %r12, %rcx
xorl %eax, %eax
callq 0x35e4
movq %rbx, %rdi
movq %r14, %rsi
callq 0x40b5
cmpq $0x9, %r15
jb 0x476f
leaq 0x88(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x50d0
movups 0x88(%rsp), %xmm0
movups 0x98(%rsp), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
pushq $0x36
popq %rdi
pushq $0x1
jmp 0x47c1
leaq 0x7eea(%rip), %rax      # 0xc660
movl -0x4(%rax,%r15,4), %edx
leaq 0x68(%rsp), %rdi
xorl %esi, %esi
callq 0x50d0
leaq 0x48(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x50d0
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)
pushq $0x3e
popq %rdi
pushq $0x2
popq %rsi
xorl %eax, %eax
callq 0x50ff
movq %rbx, %rdi
movq %rax, %rsi
callq 0x53ce
movq 0x60(%r14), %r14
decq %r15
testl %r15d, %r15d
jg 0x46f6
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq