// File: /workspace/github_c_makefile_star2_O0/markdryan[P]subtilis/frontend/parser_call.c
// Function: prv_check_call
static void prv_check_call(subtilis_parser_t *p, subtilis_parser_call_t *call,
			   subtilis_error_t *err)
{
	size_t index;
	size_t call_index;
	size_t param_call_index;
	size_t i;
	subtilis_type_section_t *st;
	size_t new_reg;
	subtilis_op_instr_type_t itype;
	subtilis_ir_reg_type_t reg_type;
	subtilis_ir_call_t *call_site;
	subtilis_ir_inst_t *param_call_site;
	subtilis_check_call_ud_t call_ud;
	subtilis_type_fn_t *fn_st;
	subtilis_type_fn_t *fn_ct;
	subtilis_type_section_t *ct = call->call_type;

	if (!subtilis_string_pool_find(p->prog->string_pool, call->name,
				       &index)) {
		if (!ct)
			subtilis_error_set_assertion_failed(err);
		else if (ct->type.params.fn.ret_val->type == SUBTILIS_TYPE_VOID)
			subtilis_error_set_unknown_procedure(
			    err, call->name, p->l->stream->name, call->line);
		else
			subtilis_error_set_unknown_function(
			    err, call->name, p->l->stream->name, call->line);
		return;
	}

	/* We need to fix up the call site of procedures call in an
	 * error handler.
	 */

	call_index = call->index;
	if (call->in_error_handler)
		call_index += call->s->handler_offset;

	/*
	 * If the call has no type section that it is not a real
	 * function. It's an operator that is being implemented as a
	 * function call as the underlying CPU doesn't have an
	 * instruction that maps nicely onto the operator, e.g., DIV on
	 * ARM.  In these cases there's no need to perform the type
	 * checks as the parser has already done them.
	 */

	/*
	 * This assumes that builtins don't require any type promotions.
	 */

	if (!ct) {
		call->s->ops[call_index]->op.call.proc_id = index;
		return;
	}

	st = p->prog->sections[index]->type;
	fn_ct = &ct->type.params.fn;
	fn_st = &st->type.params.fn;

	if ((fn_st->ret_val->type == SUBTILIS_TYPE_VOID) &&
	    (ct->type.params.fn.ret_val->type != SUBTILIS_TYPE_VOID)) {
		subtilis_error_set_procedure_expected(
		    err, call->name, p->l->stream->name, call->line);
		return;
	} else if ((st->type.params.fn.ret_val->type != SUBTILIS_TYPE_VOID) &&
		   (ct->type.params.fn.ret_val->type == SUBTILIS_TYPE_VOID)) {
		subtilis_error_set_function_expected(
		    err, call->name, p->l->stream->name, call->line);
		return;
	}

	if (st->type.params.fn.num_params != ct->type.params.fn.num_params) {
		subtilis_error_set_bad_arg_count(
		    err, ct->type.params.fn.num_params,
		    st->type.params.fn.num_params, p->l->stream->name,
		    call->line);
		return;
	}

	call_site = &call->s->ops[call_index]->op.call;
	switch (call->s->ops[call_index]->type) {
	case SUBTILIS_OP_CALL:
	case SUBTILIS_OP_CALLI32:
	case SUBTILIS_OP_CALLREAL:
		break;
	default:
		subtilis_error_set_assertion_failed(err);
		return;
	}

	for (i = 0; i < fn_st->num_params; i++) {
		if (ct->check_args && ct->check_args[i].arg_name) {
			/*
			 * Someone has passed a pointer to an existing function
			 * as an argument.  We can't do the parameter type
			 * checking or getprocaddr resolution at the call site
			 * so we need to do it here.  The type of the parameter
			 * in fn_ct->params[i] is incomplete at this stage so we
			 * need to look up the actual function whose address was
			 * taken, now it's been seen and patch up the
			 * getprocaddr instruction.
			 */

			if (!subtilis_string_pool_find(
				p->prog->string_pool,
				ct->check_args[i].arg_name,
				&param_call_index)) {
				subtilis_error_set_unknown_procedure(
				    err, ct->check_args[i].arg_name,
				    p->l->stream->name, call->line);
				return;
			}
			subtilis_type_copy(
			    fn_ct->params[i],
			    &p->prog->sections[param_call_index]->type->type,
			    err);
			if (err->type != SUBTILIS_ERROR_OK)
				return;

			param_call_site =
			    &call->s->ops[ct->check_args[i].call_site]
				 ->op.instr;
			param_call_site->operands[1].label = param_call_index;
		}
		if (subtilis_type_eq(fn_st->params[i], fn_ct->params[i]))
			continue;

		/*
		 * TODO.  Haven't bothered to make this code generic as
		 * it will probably all dissapear when we have multi
		 * file subtilis programs.  We'll need to do two passes
		 * of the source and so there will be no need to promote
		 * anything as we'll always know the parameter types in
		 * advance.
		 */

		if ((fn_st->params[i]->type == SUBTILIS_TYPE_REAL) &&
		    (fn_ct->params[i]->type == SUBTILIS_TYPE_INTEGER)) {
			itype = SUBTILIS_OP_INSTR_MOV_I32_FP;
			reg_type = SUBTILIS_IR_REG_TYPE_REAL;
		} else if ((fn_st->params[i]->type == SUBTILIS_TYPE_REAL) &&
			   (fn_ct->params[i]->type == SUBTILIS_TYPE_BYTE)) {
			itype = SUBTILIS_OP_INSTR_MOV_I8_FP;
			reg_type = SUBTILIS_IR_REG_TYPE_REAL;
		} else if (((fn_st->params[i]->type == SUBTILIS_TYPE_INTEGER) ||
			    (fn_st->params[i]->type == SUBTILIS_TYPE_BYTE)) &&
			   (fn_ct->params[i]->type == SUBTILIS_TYPE_REAL)) {
			itype = SUBTILIS_OP_INSTR_MOV_FP_I32;
			reg_type = SUBTILIS_IR_REG_TYPE_INTEGER;
		} else if ((fn_st->params[i]->type == SUBTILIS_TYPE_BYTE) &&
			   (fn_ct->params[i]->type == SUBTILIS_TYPE_INTEGER)) {
			continue;
		} else if ((fn_st->params[i]->type == SUBTILIS_TYPE_INTEGER) &&
			   (fn_ct->params[i]->type == SUBTILIS_TYPE_BYTE)) {
			itype = SUBTILIS_OP_INSTR_SIGNX_8_TO_32;
			reg_type = SUBTILIS_IR_REG_TYPE_INTEGER;
		} else {
			call_ud.i = i;
			call_ud.line = call->line;
			subtilis_type_compare_diag_custom(
			    p, fn_st->params[i], fn_ct->params[i], &call_ud,
			    prv_arg_check_failed, err);
			return;
		}

		new_reg = subtilis_ir_section_promote_nop(
		    call->s, call_site->args[i].nop, itype,
		    call_site->args[i].reg, err);
		if (err->type != SUBTILIS_ERROR_OK)
			return;
		call_site->args[i].reg = new_reg;
		call_site->args[i].type = reg_type;
	}

	call_site->proc_id = index;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x88(%rbp)
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq 0x18(%rax), %rdi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rsi
leaq -0x20(%rbp), %rdx
callq 0x3d5a0
testb $0x1, %al
jne 0x20fe9
cmpq $0x0, -0x88(%rbp)
jne 0x20f44
movq -0x18(%rbp), %rdi
movl $0xf, %esi
leaq 0x896fb(%rip), %rdx     # 0xaa630
movl $0x727, %ecx            # imm = 0x727
callq 0x158e0
jmp 0x20fe4
movq -0x88(%rbp), %rax
movq 0x8(%rax), %rax
cmpl $0x8, (%rax)
jne 0x20f9c
movq -0x18(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x30(%rax), %r8
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movl %eax, %r9d
movl $0x24, %esi
leaq 0x8a2f4(%rip), %rcx     # 0xab276
leaq 0x896a7(%rip), %rax     # 0xaa630
movq %rax, (%rsp)
movl $0x72a, 0x8(%rsp)       # imm = 0x72A
callq 0x156d0
jmp 0x20fe2
movq -0x18(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x30(%rax), %r8
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movl %eax, %r9d
movl $0x25, %esi
leaq 0x8a2ac(%rip), %rcx     # 0xab276
leaq 0x8965f(%rip), %rax     # 0xaa630
movq %rax, (%rsp)
movl $0x72d, 0x8(%rsp)       # imm = 0x72D
callq 0x156d0
jmp 0x20fe4
jmp 0x2158e
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
testb $0x1, 0x10(%rax)
je 0x21015
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq 0x80(%rax), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x88(%rbp)
jne 0x2103f
movq -0x20(%rbp), %rcx
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq 0x48(%rax), %rax
movq -0x28(%rbp), %rdx
movq (%rax,%rdx,8), %rax
movq %rcx, 0x8(%rax)
jmp 0x2158e
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq (%rax), %rax
movq -0x20(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x8(%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x88(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x80(%rbp)
movq -0x40(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movq (%rax), %rax
cmpl $0x8, (%rax)
jne 0x210dc
movq -0x88(%rbp), %rax
movq 0x8(%rax), %rax
cmpl $0x8, (%rax)
je 0x210dc
movq -0x18(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x30(%rax), %r8
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movl %eax, %r9d
movl $0x22, %esi
leaq 0x8a1b7(%rip), %rcx     # 0xab276
leaq 0x8956a(%rip), %rax     # 0xaa630
movq %rax, (%rsp)
movl $0x752, 0x8(%rsp)       # imm = 0x752
callq 0x156d0
jmp 0x2158e
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
cmpl $0x8, (%rax)
je 0x21144
movq -0x88(%rbp), %rax
movq 0x8(%rax), %rax
cmpl $0x8, (%rax)
jne 0x21144
movq -0x18(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x30(%rax), %r8
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movl %eax, %r9d
movl $0x23, %esi
leaq 0x8a14f(%rip), %rcx     # 0xab276
leaq 0x89502(%rip), %rax     # 0xaa630
movq %rax, (%rsp)
movl $0x757, 0x8(%rsp)       # imm = 0x757
callq 0x156d0
jmp 0x2158e
jmp 0x21146
movq -0x40(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x88(%rbp), %rcx
cmpq 0x10(%rcx), %rax
je 0x211ae
movq -0x18(%rbp), %rdi
movq -0x88(%rbp), %rax
movq 0x10(%rax), %rax
movl %eax, %edx
movq -0x40(%rbp), %rax
movq 0x10(%rax), %rax
movl %eax, %ecx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x30(%rax), %r8
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movl %eax, %r9d
movl $0x28, %esi
leaq 0x89498(%rip), %rax     # 0xaa630
movq %rax, (%rsp)
movl $0x75f, 0x8(%rsp)       # imm = 0x75F
callq 0x157b0
jmp 0x2158e
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq 0x48(%rax), %rax
movq -0x28(%rbp), %rcx
movq (%rax,%rcx,8), %rax
addq $0x8, %rax
movq %rax, -0x58(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq 0x48(%rax), %rax
movq -0x28(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movl (%rax), %eax
addl $-0x2, %eax
subl $0x2, %eax
ja 0x211ea
jmp 0x211e8
jmp 0x21209
movq -0x18(%rbp), %rdi
movl $0xf, %esi
leaq 0x89436(%rip), %rdx     # 0xaa630
movl $0x76a, %ecx            # imm = 0x76A
callq 0x158e0
jmp 0x2158e
movq $0x0, -0x38(%rbp)
movq -0x38(%rbp), %rax
movq -0x78(%rbp), %rcx
cmpq 0x8(%rcx), %rax
jae 0x21583
movq -0x88(%rbp), %rax
cmpq $0x0, 0x148(%rax)
je 0x2136a
movq -0x88(%rbp), %rax
movq 0x148(%rax), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
cmpq $0x0, (%rax)
je 0x2136a
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq 0x18(%rax), %rdi
movq -0x88(%rbp), %rax
movq 0x148(%rax), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq (%rax), %rsi
leaq -0x30(%rbp), %rdx
callq 0x3d5a0
testb $0x1, %al
jne 0x212ef
movq -0x18(%rbp), %rdi
movq -0x88(%rbp), %rax
movq 0x148(%rax), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq (%rax), %rdx
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x30(%rax), %r8
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movl %eax, %r9d
movl $0x24, %esi
leaq 0x89fa4(%rip), %rcx     # 0xab276
leaq 0x89357(%rip), %rax     # 0xaa630
movq %rax, (%rsp)
movl $0x781, 0x8(%rsp)       # imm = 0x781
callq 0x156d0
jmp 0x2158e
movq -0x80(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rdi
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq (%rax), %rax
movq -0x30(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x8(%rax), %rsi
movq -0x18(%rbp), %rdx
callq 0x3e4f0
movq -0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x2132a
jmp 0x2158e
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq 0x48(%rax), %rax
movq -0x88(%rbp), %rcx
movq 0x148(%rcx), %rcx
movq -0x38(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
movq 0x8(%rcx), %rcx
movq (%rax,%rcx,8), %rax
addq $0x8, %rax
movq %rax, -0x60(%rbp)
movq -0x30(%rbp), %rcx
movq -0x60(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x78(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rdi
movq -0x80(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rsi
callq 0x3d880
testb $0x1, %al
jne 0x2138f
jmp 0x21394
jmp 0x21572
movq -0x78(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rax
cmpl $0x4, (%rax)
jne 0x213cb
movq -0x80(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rax
cmpl $0x5, (%rax)
jne 0x213cb
movl $0x51, -0x4c(%rbp)
movl $0x1, -0x50(%rbp)
jmp 0x214fb
movq -0x78(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rax
cmpl $0x4, (%rax)
jne 0x21402
movq -0x80(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rax
cmpl $0x6, (%rax)
jne 0x21402
movl $0x98, -0x4c(%rbp)
movl $0x1, -0x50(%rbp)
jmp 0x214f9
movq -0x78(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rax
cmpl $0x5, (%rax)
je 0x21426
movq -0x78(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rax
cmpl $0x6, (%rax)
jne 0x2144b
movq -0x80(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rax
cmpl $0x4, (%rax)
jne 0x2144b
movl $0x52, -0x4c(%rbp)
movl $0x0, -0x50(%rbp)
jmp 0x214f7
movq -0x78(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rax
cmpl $0x6, (%rax)
jne 0x21474
movq -0x80(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rax
cmpl $0x5, (%rax)
jne 0x21474
jmp 0x21572
movq -0x78(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rax
cmpl $0x5, (%rax)
jne 0x214a8
movq -0x80(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rax
cmpl $0x6, (%rax)
jne 0x214a8
movl $0x97, -0x4c(%rbp)
movl $0x0, -0x50(%rbp)
jmp 0x214f3
movq -0x38(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x68(%rbp)
movq -0x8(%rbp), %rdi
movq -0x78(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rsi
movq -0x80(%rbp), %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rdx
movq -0x18(%rbp), %r9
leaq -0x70(%rbp), %rcx
leaq 0x1aa7(%rip), %r8       # 0x22f90
callq 0x4a900
jmp 0x2158e
jmp 0x214f5
jmp 0x214f7
jmp 0x214f9
jmp 0x214fb
movq -0x10(%rbp), %rax
movq (%rax), %rdi
movq -0x58(%rbp), %rax
movq 0x18(%rax), %rax
imulq $0x18, -0x38(%rbp), %rcx
addq %rcx, %rax
movq 0x10(%rax), %rsi
movl -0x4c(%rbp), %edx
movq -0x58(%rbp), %rax
movq 0x18(%rax), %rax
imulq $0x18, -0x38(%rbp), %rcx
addq %rcx, %rax
movq 0x8(%rax), %rcx
movq -0x18(%rbp), %r8
callq 0x38910
movq %rax, -0x48(%rbp)
movq -0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x21545
jmp 0x2158e
movq -0x48(%rbp), %rcx
movq -0x58(%rbp), %rax
movq 0x18(%rax), %rax
imulq $0x18, -0x38(%rbp), %rdx
addq %rdx, %rax
movq %rcx, 0x8(%rax)
movl -0x50(%rbp), %ecx
movq -0x58(%rbp), %rax
movq 0x18(%rax), %rax
imulq $0x18, -0x38(%rbp), %rdx
addq %rdx, %rax
movl %ecx, (%rax)
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0x21211
movq -0x20(%rbp), %rcx
movq -0x58(%rbp), %rax
movq %rcx, (%rax)
addq $0xa0, %rsp
popq %rbp
retq
nopw (%rax,%rax)