// File: /workspace/github_c_makefile_star2_O2/markdryan[P]subtilis/frontend/parser_mem.c
// Function: subtilis_parser_append_exp
subtilis_exp_t *subtilis_parser_append_exp(subtilis_parser_t *p,
					   subtilis_token_t *t,
					   subtilis_error_t *err)
{
	bool check_size;
	bool tmp;
	subtilis_exp_t *objs[3] = {NULL};
	subtilis_exp_t *retval = NULL;
	const subtilis_symbol_t *s;
	size_t i;

	prv_append_statement(p, t, objs, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return NULL;

	retval = subtilis_type_if_dup(objs[0], err);
	if (err->type != SUBTILIS_ERROR_OK)
		goto cleanup;

	tmp = objs[0]->temporary;

	subtilis_type_if_append(p, objs[0], objs[1], objs[2], err);
	objs[0] = NULL;
	objs[1] = NULL;
	objs[2] = NULL;
	if (err->type != SUBTILIS_ERROR_OK)
		goto cleanup;

	/*
	 * If we're appending to a non-temporary variable with a ref
	 * count of 1 we  need to temporarily increase its reference
	 * count for the remainder of the current block.  This is to prevent
	 * a use after free error  which can happen when appending to an
	 * existing variable and then assigning the return value to that same
	 * variable.
	 *
	 * We could just push the existing reference, rather than making a copy
	 * and make some fake entry in the symbol table, with a size of 0, but
	 * this seems a bit hacky.  Would result in smaller code if we could get
	 * it to work though.
	 */

	if (subtilis_type_if_is_reference(&retval->type) && !tmp) {
		check_size = !subtilis_type_if_is_array(&retval->type);
		s = subtilis_symbol_table_insert_tmp(p->local_st, &retval->type,
						     NULL, err);
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;

		subtilis_reference_type_init_ref(p, SUBTILIS_IR_REG_LOCAL,
						 s->loc, retval->exp.ir_op.reg,
						 check_size, true, err);
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;

		subtilis_reference_type_push_reference(
		    p, &retval->type, SUBTILIS_IR_REG_LOCAL, s->loc, err);
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;
	}

	return retval;

cleanup:
	subtilis_exp_delete(retval);

	for (i = 0; i < 3; i++)
		subtilis_exp_delete(objs[i]);

	return NULL;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x30, %rsp
movq %rdx, %r14
movq %rdi, %r15
xorps %xmm0, %xmm0
leaq 0x10(%rsp), %rdx
movaps %xmm0, (%rdx)
andq $0x0, 0x10(%rdx)
movq %r14, %rcx
callq 0x250d4
cmpl $0x0, (%r14)
je 0x2520b
xorl %ebx, %ebx
movq %rbx, %rax
addq $0x30, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
movq 0x10(%rsp), %rdi
movq %r14, %rsi
callq 0x341c4
movq %rax, %rbx
cmpl $0x0, (%r14)
jne 0x25256
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
movq 0x158(%rsi), %r12
movq 0x20(%rsp), %rcx
movq %r15, %rdi
movq %r14, %r8
callq 0x3472e
andq $0x0, 0x20(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x10(%rsp)
cmpl $0x0, (%r14)
je 0x25278
movq %rbx, %rdi
callq 0x29d88
xorl %ebx, %ebx
xorl %r14d, %r14d
cmpq $0x3, %r14
je 0x251fb
movq 0x10(%rsp,%r14,8), %rdi
callq 0x29d88
incq %r14
jmp 0x25263
movq %rbx, %rdi
callq 0x35808
testb %al, %al
je 0x251fb
testq %r12, %r12
jne 0x251fb
movq %rbx, %rdi
callq 0x357cc
movl %eax, %ebp
movq 0x68(%r15), %rdi
movq %rbx, %rsi
xorl %edx, %edx
movq %r14, %rcx
callq 0x2cee3
cmpl $0x0, (%r14)
jne 0x25256
movq %rax, %r12
xorb $0x1, %bpl
movq (%rax), %rdx
movq 0x148(%rbx), %rcx
movq %r14, (%rsp)
movzbl %bpl, %r8d
pushq $0x2
popq %rsi
pushq $0x1
popq %r9
movq %r15, %rdi
callq 0x4a250
cmpl $0x0, (%r14)
jne 0x25256
movq (%r12), %rcx
pushq $0x2
popq %rdx
movq %r15, %rdi
movq %rbx, %rsi
movq %r14, %r8
callq 0x4a8be
cmpl $0x0, (%r14)
jne 0x25256
jmp 0x251fb