// File: /workspace/github_c_makefile_star2_O0/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
subq $0x430, %rsp            # imm = 0x430
movq %rdi, -0x418(%rbp)
movq %rdi, -0x420(%rbp)
movq %rsi, -0x8(%rbp)
movq %rdx, -0x10(%rbp)
movq %rcx, -0x18(%rbp)
movq %r8, -0x20(%rbp)
movl %r9d, -0x24(%rbp)
movq -0x10(%rbp), %rsi
leaq -0x78(%rbp), %rdi
movl $0x50, %edx
callq 0x10e0
callq 0x61d0
movq -0x418(%rbp), %rdi
movq %rax, -0x88(%rbp)
movq %rdx, -0x80(%rbp)
movq -0x88(%rbp), %rax
movq %rax, 0xe0(%rdi)
movq -0x80(%rbp), %rax
movq %rax, 0xe8(%rdi)
leaq -0x78(%rbp), %rdi
callq 0xb250
cmpl $0x0, %eax
je 0x7f2c
movq -0x8(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x2570
movl %eax, %ecx
movq -0x418(%rbp), %rax
movl %ecx, 0xf8(%rax)
movl $0x14, %edi
movl $0x1, %esi
callq 0x10b0
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rdi
movq -0x8(%rbp), %rax
xorl %edx, %edx
subl 0x70(%rax), %edx
leaq 0xcc0a(%rip), %rsi      # 0x149d4
movb $0x0, %al
callq 0x1140
movq -0x8(%rbp), %rdi
movq -0x90(%rbp), %rdx
leaq -0x78(%rbp), %rsi
callq 0x3540
movl %eax, -0x94(%rbp)
movq -0x8(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x28c0
movl %eax, %ecx
movq -0x418(%rbp), %rax
movl %ecx, -0x98(%rbp)
movl -0x94(%rbp), %ecx
movl %ecx, 0xf0(%rax)
cmpl $0x0, -0x98(%rbp)
jne 0x7e41
movq -0x418(%rbp), %rax
movl -0x24(%rbp), %esi
movl $0x15, %ecx
movl $0x18, %edx
cmpl $0x0, %esi
cmovnel %edx, %ecx
movl %ecx, 0xa0(%rax)
jmp 0x7f2a
movq -0x418(%rbp), %rax
movl -0x24(%rbp), %esi
movl $0x16, %ecx
movl $0x19, %edx
cmpl $0x0, %esi
cmovnel %edx, %ecx
movl %ecx, 0xa0(%rax)
movl $0x1, %edi
movl $0x100, %esi            # imm = 0x100
callq 0x10b0
movq %rax, -0xa0(%rbp)
leaq -0x1a0(%rbp), %rdi
leaq -0x78(%rbp), %rsi
movl $0x50, %edx
callq 0x10e0
leaq -0x1a0(%rbp), %rdi
addq $0x50, %rdi
leaq -0x78(%rbp), %rsi
movl $0x50, %edx
callq 0x10e0
movl $0x7, -0x100(%rbp)
movl -0x94(%rbp), %eax
movl %eax, -0xb0(%rbp)
leaq -0x1f0(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0xb8a0
movq -0xa0(%rbp), %rax
movq %rax, -0x428(%rbp)
leaq -0x2f0(%rbp), %rdi
leaq -0x1a0(%rbp), %rsi
movl $0x11, %edx
leaq -0x1f0(%rbp), %rcx
callq 0x6c40
movq -0x428(%rbp), %rdi
leaq -0x2f0(%rbp), %rsi
movl $0x100, %edx            # imm = 0x100
callq 0x10e0
movq -0x418(%rbp), %rdi
addq $0xe0, %rdi
movq -0xa0(%rbp), %rsi
callq 0x62c0
jmp 0x7f4c
movq -0x418(%rbp), %rax
movl -0x24(%rbp), %esi
movl $0xc, %ecx
movl $0x17, %edx
cmpl $0x0, %esi
cmovnel %edx, %ecx
movl %ecx, 0xa0(%rax)
cmpq $0x0, -0x18(%rbp)
je 0x7f6d
movq -0x18(%rbp), %rax
movl (%rax), %eax
movq -0x20(%rbp), %rcx
cmpl (%rcx), %eax
jle 0x7f6d
leaq 0xca74(%rip), %rdi      # 0x149dc
callq 0xb150
movl $0x0, -0x2f4(%rbp)
movl -0x2f4(%rbp), %eax
movq -0x20(%rbp), %rcx
cmpl (%rcx), %eax
jge 0x80ee
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x2f4(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x300(%rbp)
movl $0x1, %edi
movl $0x100, %esi            # imm = 0x100
callq 0x10b0
movq %rax, -0x308(%rbp)
movq -0x308(%rbp), %rax
movq %rax, -0x430(%rbp)
movq -0x8(%rbp), %rsi
movq -0x300(%rbp), %rdx
leaq -0x408(%rbp), %rdi
callq 0x7130
movq -0x430(%rbp), %rdi
leaq -0x408(%rbp), %rsi
movl $0x100, %edx            # imm = 0x100
callq 0x10e0
cmpq $0x0, -0x18(%rbp)
je 0x80c0
movl -0x2f4(%rbp), %eax
movq -0x18(%rbp), %rcx
cmpl (%rcx), %eax
jge 0x80c0
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x2f4(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x410(%rbp)
movq -0x8(%rbp), %rdi
movq -0x410(%rbp), %rsi
movq -0x308(%rbp), %rdx
callq 0x66f0
cmpl $0x0, %eax
jne 0x80be
movq 0x13fa8(%rip), %rax     # 0x1bff8
movq (%rax), %rdi
leaq 0xc9d7(%rip), %rsi      # 0x14a31
movb $0x0, %al
callq 0x10d0
movq -0x410(%rbp), %rdi
callq 0xb390
movq 0x13f84(%rip), %rax     # 0x1bff8
movq (%rax), %rdi
movq -0x410(%rbp), %rax
movq 0x50(%rax), %rdx
leaq 0xc9b8(%rip), %rsi      # 0x14a41
movb $0x0, %al
callq 0x10d0
movq -0x308(%rbp), %rdi
callq 0xb390
movq 0x13f55(%rip), %rax     # 0x1bff8
movq (%rax), %rdi
leaq 0xf7b9(%rip), %rsi      # 0x17866
movb $0x0, %al
callq 0x10d0
movl $0x1, %edi
callq 0x1150
jmp 0x80c0
movq -0x418(%rbp), %rdi
addq $0xe0, %rdi
movq -0x308(%rbp), %rsi
callq 0x62c0
movl -0x2f4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2f4(%rbp)
jmp 0x7f77
movq -0x418(%rbp), %rdi
leaq -0x78(%rbp), %rsi
movl $0x50, %edx
callq 0x10e0
movq -0x420(%rbp), %rax
addq $0x430, %rsp            # imm = 0x430
popq %rbp
retq
nopw %cs:(%rax,%rax)