// File: /workspace/github_c_makefile_star2_O2/hsjoihs[P]c-compiler/typecheck_expression.c
// Function: func_call_expr
struct Expr
func_call_expr(struct AnalyzerState *ptr_ps, const struct Type *ref_ret_type,
               const struct Vector /*<TypeAndIdent>*/ *nullable_ref_param_infos,
               const struct Vector /* <UntypedExpr> */ *ref_arg_exprs_vec,
               int is_fp_call)
{
	const struct Type ret_type = *ref_ret_type;

	struct Expr expr;
	expr.args = init_vector();

	if (is_struct_or_union(&ret_type)) {
		expr.size_info_for_struct_or_union_assign = size_of(ptr_ps, &ret_type);
		char *str = calloc(20, sizeof(char));
		sprintf(str, "@anon%d", -ptr_ps->newest_offset);

		int offset = add_local_var_to_scope(ptr_ps, &ret_type, str);

		enum SystemVAbiClass abi_class =
		    system_v_abi_class_of(ptr_ps, &ret_type);

		expr.local_var_offset = offset;

		if (abi_class == INTEGER_CLASS) {
			expr.category = is_fp_call ? FPCALL_EXPR_RETURNING_INTEGER_CLASS
			                           : FUNCCALL_EXPR_RETURNING_INTEGER_CLASS;
		} else {
			expr.category = is_fp_call ? FPCALL_EXPR_RETURNING_MEMORY_CLASS
			                           : FUNCCALL_EXPR_RETURNING_MEMORY_CLASS;

			struct Expr *ptr_arg = calloc(1, sizeof(struct Expr));

			/* push pointer to anon as the first argument */
			{
				struct Expr anon_var_expr;
				anon_var_expr.details.type = ret_type;
				anon_var_expr.details.true_type = ret_type;
				anon_var_expr.category = LOCAL_VAR_;
				anon_var_expr.local_var_offset = offset;

				const struct Type ptr_to_type_ = ptr_to_type(&ret_type);
				*ptr_arg = unary_op_(&anon_var_expr, OP_AND, &ptr_to_type_);
			}
			push_vector(&expr.args, ptr_arg);
		}
	} else {
		expr.category = is_fp_call ? FPCALL_EXPR : FUNCCALL_EXPR;
	}

	if (nullable_ref_param_infos &&
	    nullable_ref_param_infos->length > ref_arg_exprs_vec->length) {
		simple_error("the number of argument that is passed is less than the "
		             "expected number of parameters");
	}

	for (int counter = 0; counter < ref_arg_exprs_vec->length; counter++) {
		const struct UntypedExpr *ptr = ref_arg_exprs_vec->vector[counter];

		struct Expr *ptr_arg = calloc(1, sizeof(struct Expr));
		*ptr_arg = typecheck_expression(ptr_ps, ptr);

		/* Note that `nullable_ref_param_infos->length` can be smaller than
		 * `ref_arg_exprs_vec->length` if you are calling a variable-argument
		 * function. In that case we ignore the typecheck. */

		if (nullable_ref_param_infos &&
		    counter < nullable_ref_param_infos->length) {
			const struct TypeAndIdent *pti =
			    nullable_ref_param_infos->vector[counter];
			if (!is_compatible(ptr_ps, &pti->type, &ptr_arg->details.type)) {
				fprintf(stderr, "Expected type `");
				debug_print_type(&pti->type);
				fprintf(stderr, "` for parameter `%s`, but got `",
				        pti->ident_str);
				debug_print_type(&ptr_arg->details.type);
				fprintf(stderr, "`.\n");
				exit(EXIT_FAILURE);
			}
		}

		push_vector(&expr.args, ptr_arg);
	}

	expr.details.type = ret_type;
	return expr;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2c8, %rsp            # imm = 0x2C8
movl %r9d, %r12d
movq %r8, %r14
movq %rcx, -0x40(%rbp)
movq %rsi, %r13
movq %rdi, %r15
pushq $0xa
popq %rcx
leaq -0xa0(%rbp), %rbx
movq %rbx, %rdi
movq %rdx, %rsi
rep  movsq (%rsi), %es:(%rdi)
leaq 0xe0(%r15), %rax
movq %rax, -0x38(%rbp)
callq 0x49e0
movq %rax, 0xe0(%r15)
movq %rdx, 0xe8(%r15)
movq %rbx, %rdi
callq 0x81cb
testl %eax, %eax
je 0x5e59
movl %r12d, -0x30(%rbp)
leaq -0xa0(%rbp), %r12
movq %r13, %rdi
movq %r12, %rsi
callq 0x1e24
movl %eax, 0xf8(%r15)
pushq $0x14
popq %rdi
pushq $0x1
popq %rsi
callq 0x10d0
movq %rax, %rbx
xorl %edx, %edx
subl 0x70(%r13), %edx
leaq 0x8a86(%rip), %rsi      # 0xe7f0
movq %rax, %rdi
xorl %eax, %eax
callq 0x1160
movq %r13, %rdi
movq %r12, %rsi
movq %rbx, %rdx
callq 0x289c
movl %eax, %ebx
movq %r13, %rdi
movq %r12, %rsi
callq 0x2038
movl %ebx, 0xf0(%r15)
testl %eax, %eax
je 0x5e6e
xorl %eax, %eax
cmpl $0x0, -0x30(%rbp)
setne %al
leal (%rax,%rax,2), %eax
addl $0x16, %eax
movl %eax, 0xa0(%r15)
pushq $0x1
popq %rdi
movl $0x100, %esi            # imm = 0x100
callq 0x10d0
movq %rax, %r12
pushq $0xa
popq %rax
leaq -0x1f0(%rbp), %rdi
leaq -0xa0(%rbp), %rdx
movq %rax, %rcx
movq %rdx, %rsi
rep  movsq (%rsi), %es:(%rdi)
leaq -0x1a0(%rbp), %r8
movq %rax, %rcx
movq %r8, %rdi
movq %rdx, %rsi
rep  movsq (%rsi), %es:(%rdi)
movl $0x7, 0x50(%r8)
movl %ebx, 0xa0(%r8)
leaq -0xf0(%rbp), %rdi
movq %rdx, %rsi
callq 0x862d
movq %r14, %rbx
movq %r13, %r14
leaq -0x2f0(%rbp), %r13
pushq $0x11
popq %rdx
movq %r13, %rdi
leaq -0x1f0(%rbp), %rsi
leaq -0xf0(%rbp), %rcx
callq 0x50a8
movl $0x100, %edx            # imm = 0x100
movq %r12, %rdi
movq %r13, %rsi
movq %r14, %r13
movq %rbx, %r14
callq 0x1100
movq -0x38(%rbp), %rdi
movq %r12, %rsi
callq 0x4a57
jmp 0x5e84
testl %r12d, %r12d
pushq $0xc
popq %rax
pushq $0x17
popq %rcx
cmovel %eax, %ecx
movl %ecx, 0xa0(%r15)
jmp 0x5e84
xorl %eax, %eax
cmpl $0x0, -0x30(%rbp)
setne %al
leal (%rax,%rax,2), %eax
addl $0x15, %eax
movl %eax, 0xa0(%r15)
movq %r15, -0x30(%rbp)
movq -0x40(%rbp), %rax
testq %rax, %rax
je 0x5e9c
movl (%rax), %eax
cmpl (%r14), %eax
jg 0x5fc0
xorl %r15d, %r15d
movq %r14, -0x50(%rbp)
movq %r13, -0x48(%rbp)
movslq (%r14), %rax
cmpq %rax, %r15
jge 0x5f38
movq 0x8(%r14), %rax
movq (%rax,%r15,8), %r12
movl $0x100, %esi            # imm = 0x100
pushq $0x1
popq %rdi
callq 0x10d0
movq %rax, %rbx
leaq -0x1f0(%rbp), %r14
movq %r14, %rdi
movq %r13, %rsi
movq %r12, %rdx
callq 0x54d7
movl $0x100, %edx            # imm = 0x100
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1100
movq -0x40(%rbp), %rcx
testq %rcx, %rcx
je 0x5f1c
movslq (%rcx), %rax
cmpq %rax, %r15
jge 0x5f1c
movq 0x8(%rcx), %rax
movq (%rax,%r15,8), %r13
movq -0x48(%rbp), %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x4d1c
testl %eax, %eax
je 0x5f5e
movq -0x38(%rbp), %rdi
movq %rbx, %rsi
callq 0x4a57
incq %r15
movq -0x48(%rbp), %r13
movq -0x50(%rbp), %r14
jmp 0x5ea7
pushq $0xa
popq %rcx
leaq -0xa0(%rbp), %rsi
movq -0x30(%rbp), %rax
movq %rax, %rdi
rep  movsq (%rsi), %es:(%rdi)
addq $0x2c8, %rsp            # imm = 0x2C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x10093(%rip), %r15     # 0x15ff8
movq (%r15), %rcx
leaq 0x88de(%rip), %rdi      # 0xe84d
pushq $0xf
popq %rsi
pushq $0x1
popq %r14
movq %r14, %rdx
callq 0x1180
movq %r13, %rdi
callq 0x827e
movq (%r15), %rdi
movq 0x50(%r13), %rdx
leaq 0x88c9(%rip), %rsi      # 0xe85d
xorl %eax, %eax
callq 0x10f0
movq %rbx, %rdi
callq 0x827e
movq (%r15), %rcx
leaq 0xb730(%rip), %rdi      # 0x116dd
pushq $0x3
popq %rsi
movq %r14, %rdx
callq 0x1180
pushq $0x1
popq %rdi
callq 0x1170
leaq 0x8831(%rip), %rdi      # 0xe7f8
callq 0x814d