// File: /workspace/github_c_makefile_star2_O2/markdryan[P]subtilis/frontend/array_type.c
// Function: subtilis_array_get_dim
subtilis_exp_t *subtilis_array_get_dim(subtilis_parser_t *p, subtilis_exp_t *ar,
				       subtilis_exp_t *dim,
				       subtilis_error_t *err)
{
	int32_t requested_dim;
	int32_t dim_index;
	size_t num_dims;
	subtilis_ir_operand_t op;
	subtilis_exp_t *e = NULL;

	/*
	 * This is unfortunate as DIM(a()) may generate one add
	 * instruction for the array reference even though we don't
	 * actually need it. Hopefully, the optimiser will be able to
	 * get rid of it.
	 */

	num_dims = ar->type.params.array.num_dims;
	if (!dim) {
		e = subtilis_exp_new_int32(num_dims, err);
	} else {
		if (dim->type.type == SUBTILIS_TYPE_CONST_INTEGER) {
			if ((dim->exp.ir_op.integer <= 0) ||
			    (dim->exp.ir_op.integer > num_dims)) {
				subtilis_error_bad_index(
				    err, "dim", p->l->stream->name, p->l->line);
				goto cleanup;
			}
			dim_index = dim->exp.ir_op.integer - 1;
			requested_dim = ar->type.params.array.dims[dim_index];
			if (requested_dim != SUBTILIS_DYNAMIC_DIMENSION) {
				e = subtilis_exp_new_int32(requested_dim, err);
			} else {
				e = subtilis_type_if_load_from_mem(
				    p, &subtilis_type_integer,
				    ar->exp.ir_op.reg,
				    SUBTIILIS_ARRAY_DIMS_OFF +
					(sizeof(int32_t) * dim_index),
				    err);
			}
		} else {
			prv_check_dimension_num(p, dim, num_dims, err);
			if (err->type != SUBTILIS_ERROR_OK)
				goto cleanup;

			op.integer = 1;
			dim->exp.ir_op.reg = subtilis_ir_section_add_instr(
			    p->current, SUBTILIS_OP_INSTR_SUBI_I32,
			    dim->exp.ir_op, op, err);
			if (err->type != SUBTILIS_ERROR_OK)
				goto cleanup;
			/* TODO This is int32 specific */
			op.integer = 2;
			dim->exp.ir_op.reg = subtilis_ir_section_add_instr(
			    p->current, SUBTILIS_OP_INSTR_LSLI_I32,
			    dim->exp.ir_op, op, err);
			if (err->type != SUBTILIS_ERROR_OK)
				goto cleanup;
			op.reg = subtilis_ir_section_add_instr(
			    p->current, SUBTILIS_OP_INSTR_ADD_I32,
			    ar->exp.ir_op, dim->exp.ir_op, err);
			if (err->type != SUBTILIS_ERROR_OK)
				goto cleanup;
			e = subtilis_type_if_load_from_mem(
			    p, &subtilis_type_integer, op.reg,
			    SUBTIILIS_ARRAY_DIMS_OFF, err);
		}
	}

cleanup:

	subtilis_exp_delete(ar);
	subtilis_exp_delete(dim);

	return e;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
movq %rcx, %r15
movq %rdx, %rbx
movq %rsi, %r14
movq %rdi, %r12
movl 0x8(%rsi), %edi
testq %rdx, %rdx
je 0x41ac3
cmpl $0x1, (%rbx)
jne 0x41a40
movl 0x148(%rbx), %eax
testl %eax, %eax
setle %cl
cmpl %edi, %eax
seta %dl
orb %cl, %dl
cmpb $0x1, %dl
jne 0x41ab7
movq (%r12), %rax
movq 0x30(%rax), %r8
movl 0x38(%rax), %r9d
leaq 0x2df75(%rip), %rax     # 0x6f992
leaq 0x2bb65(%rip), %rdx     # 0x6d589
leaq 0x2c39a(%rip), %rcx     # 0x6ddc5
pushq $0x39
popq %rsi
movq %r15, %rdi
pushq $0x88c                  # imm = 0x88C
pushq %rax
callq 0x140cd
popq %rax
popq %rcx
jmp 0x41ab2
movq %r15, %rsi
callq 0x2a369
cmpl $0x0, (%r15)
jne 0x41ab2
pushq $0x1
popq %rdx
movq %r12, %rdi
movq %rbx, %rsi
movq %rax, %rcx
movq %r15, %r8
callq 0x40ee4
cmpl $0x0, (%r15)
jne 0x41ab2
movq 0x48(%r12), %rdi
movq 0x148(%rbx), %rdx
pushq $0xb
popq %rsi
pushq $0x1
popq %rcx
movq %r15, %r8
callq 0x2a819
movq %rax, 0x148(%rbx)
cmpl $0x0, (%r15)
jne 0x41ab2
movq 0x48(%r12), %rdi
pushq $0x4c
popq %rsi
pushq $0x2
popq %rcx
movq %rax, %rdx
movq %r15, %r8
callq 0x2a819
movq %rax, 0x148(%rbx)
cmpl $0x0, (%r15)
je 0x41b0e
xorl %r13d, %r13d
jmp 0x41ace
decl %eax
movl 0xc(%r14,%rax,4), %edi
cmpl $-0x1, %edi
je 0x41aeb
movq %r15, %rsi
callq 0x2a369
movq %rax, %r13
movq %r14, %rdi
callq 0x29d88
movq %rbx, %rdi
callq 0x29d88
movq %r13, %rax
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
movq 0x148(%r14), %rdx
leaq 0x10(,%rax,4), %rcx
leaq 0x2cdc7(%rip), %rsi     # 0x6e8c8
movq %r12, %rdi
movq %r15, %r8
callq 0x343a4
jmp 0x41acb
movq 0x48(%r12), %rdi
movq 0x148(%r14), %rdx
xorl %r13d, %r13d
xorl %esi, %esi
movq %rax, %rcx
movq %r15, %r8
callq 0x2a819
cmpl $0x0, (%r15)
jne 0x41ace
leaq 0x2cd91(%rip), %rsi     # 0x6e8c8
pushq $0x10
popq %rcx
movq %r12, %rdi
movq %rax, %rdx
jmp 0x41b04