// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x120, %rsp            # imm = 0x120
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
cmpq $0x0, (%rax)
je 0x527d
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movq (%rax), %rax
movq %rax, -0xd0(%rbp)
jmp 0x528d
leaq 0xc2ca(%rip), %rax      # 0x1154e
movq %rax, -0xd0(%rbp)
jmp 0x528d
movq -0xd0(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rdi
callq 0x3500
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
movq 0x28(%rax), %rcx
movq %rcx, -0x40(%rbp)
movq 0x30(%rax), %rax
movq %rax, -0x38(%rbp)
movl $0x0, -0x44(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x50(%rbp)
cmpq $0x0, -0x50(%rbp)
je 0x52e6
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
movq -0x50(%rbp), %rax
movq 0x60(%rax), %rax
movq %rax, -0x50(%rbp)
jmp 0x52c8
movl -0x44(%rbp), %eax
cmpl -0x38(%rbp), %eax
je 0x530b
movq -0x28(%rbp), %rdx
movl -0x38(%rbp), %ecx
movl -0x44(%rbp), %r8d
xorl %eax, %eax
movl %eax, %edi
leaq 0xc254(%rip), %rsi      # 0x11558
movb $0x0, %al
callq 0x3880
movl -0x38(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x54(%rbp)
cmpl $0x0, -0x54(%rbp)
jl 0x54b5
cmpq $0x0, -0x20(%rbp)
jne 0x532a
jmp 0x54b5
movq -0x40(%rbp), %rax
movslq -0x54(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x8(%rax), %rax
movq %rax, -0x60(%rbp)
movq -0x20(%rbp), %rdi
callq 0x3500
movq %rax, -0x68(%rbp)
movq -0x60(%rbp), %rax
movl (%rax), %eax
movq -0x68(%rbp), %rcx
cmpl (%rcx), %eax
je 0x5375
movl -0x54(%rbp), %edx
addl $0x1, %edx
movq -0x28(%rbp), %rcx
xorl %eax, %eax
movl %eax, %edi
leaq 0xc22e(%rip), %rsi      # 0x1159c
movb $0x0, %al
callq 0x3880
movq -0x8(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x4920
cmpl $0x8, -0x54(%rbp)
jl 0x53f1
movq -0x8(%rbp), %rax
movq %rax, -0xd8(%rbp)
leaq -0x88(%rbp), %rdi
xorl %edx, %edx
movl %edx, %esi
callq 0x63c0
movl $0x36, %edi
movl $0x1, %esi
leaq -0x88(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rcx
movq %rcx, 0x10(%rsp)
movq 0x18(%rax), %rax
movq %rax, 0x18(%rsp)
movb $0x0, %al
callq 0x6460
movq -0xd8(%rbp), %rdi
movq %rax, %rsi
callq 0x68f0
jmp 0x549b
movq -0x8(%rbp), %rax
movq %rax, -0xe0(%rbp)
movslq -0x54(%rbp), %rcx
leaq 0x11d39(%rip), %rax     # 0x17140
movl (%rax,%rcx,4), %edx
leaq -0xa8(%rbp), %rdi
xorl %esi, %esi
callq 0x63c0
leaq -0xc8(%rbp), %rdi
xorl %edx, %edx
movl %edx, %esi
callq 0x63c0
movl $0x3e, %edi
movl $0x2, %esi
leaq -0xa8(%rbp), %rcx
leaq -0xc8(%rbp), %rax
movq (%rcx), %rdx
movq %rdx, (%rsp)
movq 0x8(%rcx), %rdx
movq %rdx, 0x8(%rsp)
movq 0x10(%rcx), %rdx
movq %rdx, 0x10(%rsp)
movq 0x18(%rcx), %rcx
movq %rcx, 0x18(%rsp)
movq (%rax), %rcx
movq %rcx, 0x20(%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x28(%rsp)
movq 0x10(%rax), %rcx
movq %rcx, 0x30(%rsp)
movq 0x18(%rax), %rax
movq %rax, 0x38(%rsp)
movb $0x0, %al
callq 0x6460
movq -0xe0(%rbp), %rdi
movq %rax, %rsi
callq 0x68f0
movq -0x20(%rbp), %rax
movq 0x60(%rax), %rax
movq %rax, -0x20(%rbp)
movl -0x54(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x5314
addq $0x120, %rsp            # imm = 0x120
popq %rbp
retq
nop