// File: /workspace/github_c_makefile_star2_O3/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 $0x218, %rsp            # imm = 0x218
movl %r9d, %r12d
movq %r8, %r14
movq %rcx, -0x40(%rbp)
movq %rsi, %r13
movq %rdi, %r15
leaq -0x98(%rbp), %rbx
movl $0xa, %ecx
movq %rbx, %rdi
movq %rdx, %rsi
rep  movsq (%rsi), %es:(%rdi)
leaq 0xe0(%r15), %rax
movq %rax, -0x38(%rbp)
callq 0x5cf8
movq %rax, 0xe0(%r15)
movq %rdx, 0xe8(%r15)
movq %rbx, %rdi
callq 0x95ca
testl %eax, %eax
movq %r13, -0x48(%rbp)
je 0x6ffd
movl %r12d, -0x30(%rbp)
movq %r13, %rdi
movq %rbx, %rsi
callq 0x2ffc
movl %eax, 0xf8(%r15)
movl $0x14, %edi
movl $0x1, %esi
callq 0x10d0
movq %rax, %r12
xorl %edx, %edx
subl 0x70(%r13), %edx
leaq 0x88d6(%rip), %rsi      # 0xf7cc
movq %rax, %rdi
xorl %eax, %eax
callq 0x1160
movq %r13, %rdi
movq %rbx, %rsi
movq %r12, %rdx
callq 0x38e8
movl %eax, %r12d
movq %r13, %rdi
movq %rbx, %rsi
callq 0x3117
movl %r12d, 0xf0(%r15)
testl %eax, %eax
je 0x7016
xorl %eax, %eax
cmpl $0x0, -0x30(%rbp)
setne %al
leal 0x16(%rax,%rax,2), %eax
movl %eax, 0xa0(%r15)
movl $0x1, %edi
movl $0x100, %esi            # imm = 0x100
callq 0x10d0
movq %rax, %rbx
leaq -0x198(%rbp), %rdi
leaq -0x98(%rbp), %rax
movl $0xa, %ecx
movq %rax, %rsi
rep  movsq (%rsi), %es:(%rdi)
leaq -0x148(%rbp), %rdi
movl $0xa, %ecx
movq %rax, %rsi
rep  movsq (%rsi), %es:(%rdi)
leaq -0x238(%rbp), %rdi
movq %rax, %rsi
callq 0x96ed
movl $0x1, %edi
movl $0x100, %esi            # imm = 0x100
callq 0x10d0
movq %rax, %r13
movl $0xa0, %edx
movq %rax, %rdi
leaq -0x198(%rbp), %rsi
callq 0x1100
movl $0x7, 0xa0(%r13)
movl %r12d, 0xf0(%r13)
movl $0xa0, %edx
movq %rbx, %rdi
leaq -0x238(%rbp), %rsi
callq 0x1100
movl $0x6, %eax
movl %eax, 0xa0(%rbx)
movl %eax, 0xa8(%rbx)
movq %r13, 0xb0(%rbx)
movq -0x38(%rbp), %rdi
movq %rbx, %rsi
callq 0x5d9b
jmp 0x702c
testl %r12d, %r12d
movl $0xc, %eax
movl $0x17, %ecx
cmovel %eax, %ecx
movl %ecx, 0xa0(%r15)
jmp 0x702c
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)
movl (%r14), %eax
movq -0x40(%rbp), %rcx
testq %rcx, %rcx
je 0x7044
cmpl %eax, (%rcx)
jg 0x7105
testl %eax, %eax
jle 0x70d2
xorl %r15d, %r15d
leaq -0x198(%rbp), %rbx
movq 0x8(%r14), %rax
movq (%rax,%r15,8), %r12
movl $0x1, %edi
movl $0x100, %esi            # imm = 0x100
callq 0x10d0
movq %rax, %r13
movq %rbx, %rdi
movq -0x48(%rbp), %rsi
movq %r12, %rdx
callq 0x673b
movl $0x100, %edx            # imm = 0x100
movq %r13, %rdi
movq %rbx, %rsi
callq 0x1100
movq -0x40(%rbp), %rcx
testq %rcx, %rcx
je 0x70bb
movslq (%rcx), %rax
cmpq %rax, %r15
jge 0x70bb
movq 0x8(%rcx), %rax
movq (%rax,%r15,8), %r12
movq -0x48(%rbp), %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0x5f5f
testl %eax, %eax
je 0x70fa
movq -0x38(%rbp), %rdi
movq %r13, %rsi
callq 0x5d9b
incq %r15
movslq (%r14), %rax
cmpq %rax, %r15
jl 0x7056
leaq -0x98(%rbp), %rsi
movl $0xa, %ecx
movq -0x30(%rbp), %rax
movq %rax, %rdi
rep  movsq (%rsi), %es:(%rdi)
addq $0x218, %rsp            # imm = 0x218
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r12, %rdi
movq %r13, %rsi
callq 0x19b7
leaq 0x86c8(%rip), %rdi      # 0xf7d4
callq 0x9546