// File: /workspace/github_c_makefile_star2_O2/markdryan[P]subtilis/frontend/reference_type.c
// Function: subtilis_reference_type_grow
void subtilis_reference_type_grow(subtilis_parser_t *p, size_t a1_loc,
				  size_t a1_mem_reg, size_t a1_size_reg,
				  size_t gran_reg, size_t a2_size_reg,
				  size_t ret_reg, subtilis_error_t *err)
{
	subtilis_ir_operand_t a1_size;
	subtilis_ir_operand_t a2_size;
	subtilis_ir_operand_t new_size;
	subtilis_ir_operand_t op1;
	subtilis_ir_operand_t op2;
	subtilis_ir_operand_t a1_data;
	subtilis_ir_operand_t a1_heap;
	subtilis_ir_operand_t store;
	subtilis_ir_operand_t ref_count;
	subtilis_ir_operand_t a1_gt_zero_label;
	subtilis_ir_operand_t malloc_label;
	subtilis_ir_operand_t realloc_label;
	subtilis_ir_operand_t copy_label;
	subtilis_ir_operand_t alloc_only_label;
	subtilis_ir_operand_t ptr;
	subtilis_ir_operand_t gran;
	size_t alloc_size_reg;
	size_t dest_reg;

	a1_size.reg = a1_size_reg;
	a2_size.reg = a2_size_reg;
	store.reg = a1_mem_reg;
	gran.reg = gran_reg;
	ptr.reg = p->current->reg_counter++;

	a1_gt_zero_label.label = subtilis_ir_section_new_label(p->current);
	malloc_label.label = subtilis_ir_section_new_label(p->current);
	realloc_label.label = subtilis_ir_section_new_label(p->current);
	copy_label.label = subtilis_ir_section_new_label(p->current);
	alloc_only_label.label = subtilis_ir_section_new_label(p->current);

	new_size.reg = subtilis_ir_section_add_instr(
	    p->current, SUBTILIS_OP_INSTR_ADD_I32, a1_size, a2_size, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	if (gran_reg == SIZE_MAX) {
		alloc_size_reg = new_size.reg;
	} else {
		alloc_size_reg = subtilis_ir_section_add_instr(
		    p->current, SUBTILIS_OP_INSTR_ADD_I32, a1_size, gran, err);
		if (err->type != SUBTILIS_ERROR_OK)
			return;
	}

	/*
	 * Our target reference type may have a size of zero.  If so no getref
	 */

	subtilis_ir_section_add_instr_reg(p->current, SUBTILIS_OP_INSTR_JMPC,
					  a1_size, a1_gt_zero_label,
					  alloc_only_label, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	subtilis_ir_section_add_label(p->current, a1_gt_zero_label.label, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	op2.integer = a1_loc + SUBTIILIS_REFERENCE_DATA_OFF;
	a1_data.reg = subtilis_ir_section_add_instr(
	    p->current, SUBTILIS_OP_INSTR_LOADO_I32, store, op2, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	op2.integer = a1_loc + SUBTIILIS_REFERENCE_HEAP_OFF;
	a1_heap.reg = subtilis_ir_section_add_instr(
	    p->current, SUBTILIS_OP_INSTR_LOADO_I32, store, op2, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	/*
	 * If our object only has one reference we can realloc it.  Otherwise
	 * we need to malloc and copy.
	 */

	ref_count.reg = subtilis_ir_section_add_instr2(
	    p->current, SUBTILIS_OP_INSTR_GETREF, a1_heap, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	op2.integer = 1;
	ref_count.reg = subtilis_ir_section_add_instr(
	    p->current, SUBTILIS_OP_INSTR_EQI_I32, ref_count, op2, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	subtilis_ir_section_add_instr_reg(p->current, SUBTILIS_OP_INSTR_JMPC_NF,
					  ref_count, realloc_label,
					  malloc_label, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	subtilis_ir_section_add_label(p->current, malloc_label.label, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	dest_reg = subtilis_reference_type_re_malloc(
	    p, a1_mem_reg, a1_loc, a1_heap.reg, a1_data.reg, a1_size.reg,
	    new_size.reg, alloc_size_reg, true, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	op1.reg = dest_reg;
	subtilis_ir_section_add_instr_no_reg2(p->current, SUBTILIS_OP_INSTR_MOV,
					      ptr, op1, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	subtilis_ir_section_add_instr_no_reg(p->current, SUBTILIS_OP_INSTR_JMP,
					     copy_label, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	subtilis_ir_section_add_label(p->current, alloc_only_label.label, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	dest_reg = subtilis_reference_type_raw_alloc(p, alloc_size_reg, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	subtilis_reference_type_set_size(p, a1_mem_reg, a1_loc, new_size.reg,
					 err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	subtilis_reference_type_set_orig_size(p, a1_mem_reg, a1_loc,
					      new_size.reg, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	subtilis_reference_set_data(p, dest_reg, a1_mem_reg, a1_loc, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	subtilis_reference_set_heap(p, dest_reg, a1_mem_reg, a1_loc, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	op1.reg = dest_reg;
	subtilis_ir_section_add_instr_no_reg2(p->current, SUBTILIS_OP_INSTR_MOV,
					      ptr, op1, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	subtilis_ir_section_add_instr_no_reg(p->current, SUBTILIS_OP_INSTR_JMP,
					     copy_label, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	subtilis_ir_section_add_label(p->current, realloc_label.label, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	dest_reg = subtilis_reference_type_realloc(
	    p, a1_loc, a1_mem_reg, a1_heap.reg, a1_data.reg, a1_size.reg,
	    new_size.reg, a2_size.reg, alloc_size_reg, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	op1.reg = dest_reg;
	subtilis_ir_section_add_instr_no_reg2(p->current, SUBTILIS_OP_INSTR_MOV,
					      ptr, op1, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	subtilis_ir_section_add_label(p->current, copy_label.label, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return;

	op1.reg = ret_reg;
	subtilis_ir_section_add_instr_reg(p->current, SUBTILIS_OP_INSTR_ADD_I32,
					  op1, ptr, a1_size, err);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %r9, %r15
movq %r8, %r12
movq %rcx, %rbx
movq %rdx, 0x10(%rsp)
movq %rsi, 0x8(%rsp)
movq %rdi, %r13
movq 0x98(%rsp), %r14
movq 0x90(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0x48(%rdi), %rdi
movq 0x18(%rdi), %rax
movq %rax, 0x20(%rsp)
incq %rax
movq %rax, 0x18(%rdi)
callq 0x2b774
movq %rax, %rbp
movq 0x48(%r13), %rdi
callq 0x2b774
movq %rax, 0x40(%rsp)
movq 0x48(%r13), %rdi
callq 0x2b774
movq %rax, 0x38(%rsp)
movq 0x48(%r13), %rdi
callq 0x2b774
movq %rax, 0x28(%rsp)
movq 0x48(%r13), %rdi
callq 0x2b774
movq %rax, 0x18(%rsp)
movq 0x48(%r13), %rdi
xorl %esi, %esi
movq %rbx, %rdx
movq %r15, 0x48(%rsp)
movq %r15, %rcx
movq %r14, %r8
callq 0x2a819
cmpl $0x0, (%r14)
je 0x4b770
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %r15
cmpq $-0x1, %r12
je 0x4b793
movq 0x48(%r13), %rdi
xorl %esi, %esi
movq %rbx, %rdx
movq %r12, %rcx
movq %r14, %r8
callq 0x2a819
cmpl $0x0, (%r14)
jne 0x4b761
movq %rax, %r12
movq 0x48(%r13), %rdi
pushq $0x43
popq %rsi
movq %rbx, %rdx
movq %rbp, %rcx
movq 0x18(%rsp), %r8
movq %r14, %r9
callq 0x2a8c1
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x48(%r13), %rdi
movq %rbp, %rsi
movq %r14, %rdx
callq 0x2b781
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x8(%rsp), %rax
leal 0x4(%rax), %ecx
movq 0x48(%r13), %rdi
pushq $0x12
popq %rsi
movq 0x10(%rsp), %rdx
movq %r14, %r8
callq 0x2a819
movq %rax, 0x30(%rsp)
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x8(%rsp), %rax
leal 0x8(%rax), %ecx
movq 0x48(%r13), %rdi
pushq $0x12
popq %rsi
movq 0x10(%rsp), %rdx
movq %r14, %r8
callq 0x2a819
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x48(%r13), %rdi
pushq $0x7a
popq %rsi
movq %rax, %rdx
movq %r14, %rcx
movq %rax, %rbp
callq 0x2a981
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x48(%r13), %rdi
pushq $0x2d
popq %rsi
pushq $0x1
popq %rcx
movq %rax, %rdx
movq %r14, %r8
callq 0x2a819
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x48(%r13), %rdi
pushq $0x44
popq %rsi
movq %rax, %rdx
movq 0x38(%rsp), %rcx
movq 0x40(%rsp), %r8
movq %r14, %r9
callq 0x2a8c1
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x48(%r13), %rdi
movq 0x40(%rsp), %rsi
movq %r14, %rdx
callq 0x2b781
cmpl $0x0, (%r14)
jne 0x4b761
movq %rbp, %rcx
movq %r13, %rdi
movq 0x10(%rsp), %rsi
movq 0x8(%rsp), %rdx
movq 0x30(%rsp), %r8
movq %rbx, %r9
pushq %r14
pushq $0x1
pushq %r12
pushq %r15
callq 0x4acdd
addq $0x20, %rsp
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x48(%r13), %rdi
pushq $0x1d
popq %rsi
movq 0x20(%rsp), %rdx
movq %rax, %rcx
movq %r14, %r8
callq 0x2a9a4
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x48(%r13), %rdi
pushq $0x45
popq %rsi
movq 0x28(%rsp), %rdx
movq %r14, %rcx
callq 0x2a997
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x48(%r13), %rdi
movq 0x18(%rsp), %rsi
movq %r14, %rdx
callq 0x2b781
cmpl $0x0, (%r14)
jne 0x4b761
movq %r13, %rdi
movq %r12, %rsi
movq %r14, %rdx
callq 0x4ae20
movq %rax, 0x18(%rsp)
cmpl $0x0, (%r14)
jne 0x4b761
movq %r15, %rcx
movq %r13, %rdi
movq 0x10(%rsp), %rsi
movq 0x8(%rsp), %rdx
movq %r14, %r8
callq 0x4acc2
cmpl $0x0, (%r14)
jne 0x4b761
movq %r15, %rcx
movq %r13, %rdi
movq 0x10(%rsp), %rsi
movq 0x8(%rsp), %rdx
movq %r14, %r8
callq 0x4aeaf
cmpl $0x0, (%r14)
jne 0x4b761
movq %r13, %rdi
movq 0x18(%rsp), %rsi
movq 0x10(%rsp), %rdx
movq 0x8(%rsp), %rcx
movq %r14, %r8
callq 0x4ab59
cmpl $0x0, (%r14)
jne 0x4b761
movq %r13, %rdi
movq 0x18(%rsp), %rsi
movq 0x10(%rsp), %rdx
movq 0x8(%rsp), %rcx
movq %r14, %r8
callq 0x4ab75
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x48(%r13), %rdi
pushq $0x1d
popq %rsi
movq 0x20(%rsp), %rdx
movq 0x18(%rsp), %rcx
movq %r14, %r8
callq 0x2a9a4
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x48(%r13), %rdi
pushq $0x45
popq %rsi
movq 0x28(%rsp), %rdx
movq %r14, %rcx
callq 0x2a997
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x48(%r13), %rdi
movq 0x38(%rsp), %rsi
movq %r14, %rdx
callq 0x2b781
cmpl $0x0, (%r14)
jne 0x4b761
movq %r13, %rdi
movq 0x8(%rsp), %rsi
movq 0x10(%rsp), %rdx
movq %rbp, %rcx
movq 0x30(%rsp), %r8
movq %rbx, %r9
pushq %r14
pushq %r12
pushq 0x58(%rsp)
pushq %r15
callq 0x4b1f9
addq $0x20, %rsp
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x48(%r13), %rdi
pushq $0x1d
popq %rsi
movq 0x20(%rsp), %rdx
movq %rax, %rcx
movq %r14, %r8
callq 0x2a9a4
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x48(%r13), %rdi
movq 0x28(%rsp), %rsi
movq %r14, %rdx
callq 0x2b781
cmpl $0x0, (%r14)
jne 0x4b761
movq 0x48(%r13), %rdi
xorl %esi, %esi
movq 0x50(%rsp), %rdx
movq 0x20(%rsp), %rcx
movq %rbx, %r8
movq %r14, %r9
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2a8c1