// File: /workspace/github_c_makefile_star2_O0/markdryan[P]subtilis/frontend/array_type.c
// Function: subtilis_array_index_calc
subtilis_exp_t *
subtilis_array_index_calc(subtilis_parser_t *p, const char *var_name,
			  const subtilis_type_t *type, size_t mem_reg,
			  size_t loc, subtilis_exp_t **e, size_t index_count,
			  subtilis_error_t *err)
{
	int i;
	int32_t dim_size;
	size_t last_index;
	subtilis_exp_t *one;
	int32_t offset;
	int32_t last_offset;
	int32_t block_size = 0;
	int dyn_start = 0;
	subtilis_exp_t *blocke = NULL;
	subtilis_exp_t *sizee = NULL;
	subtilis_exp_t *edup = NULL;
	subtilis_exp_t *maxe = NULL;
	subtilis_exp_t *blocke_dup = NULL;
	int64_t array_size;

	if (index_count != type->params.array.num_dims) {
		subtilis_error_bad_index_count(err, var_name,
					       p->l->stream->name, p->l->line);
		return NULL;
	}

	if (index_count == 1)
		return prv_1d_index_calc(p, var_name, type, mem_reg, loc, e,
					 index_count, err);

	offset = loc + SUBTIILIS_ARRAY_DIMS_OFF;

	/*
	 * First we compute the constant part of the array indexing.
	 * This can all be done at compile time if both the indexes and
	 * the dimensions are known to the compiler.  We start with the
	 * final index and work our way toward the first index.  Two
	 * sizes are returned here.
	 *
	 * array_size - the offset in elements from the beginning of the
	 * array we know we need to skip.  This does not include the
	 * offset of the last index, which is added later.
	 *
	 * block_size - the cummulative product elements of all the
	 * trailing dimensions that we've processed. dyn_start -
	 * contains the first index that could not be processed at
	 * compile time.  If dyn_start == indxex_count -1 none of the
	 * indices could be processed at compile time.
	 */

	array_size = prv_check_constant_dims(p, e, index_count, var_name, type,
					     &dyn_start, &block_size, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return NULL;

	sizee = subtilis_exp_new_int32((int32_t)array_size, err);
	if (err->type != SUBTILIS_ERROR_OK)
		return NULL;

	sizee = subtilis_type_if_exp_to_var(p, sizee, err);
	if (err->type != SUBTILIS_ERROR_OK)
		goto cleanup;

	last_index = index_count - 1;
	last_offset = offset + (sizeof(int32_t) * last_index);
	if (dyn_start == index_count - 1) {
		/*
		 * none of the indices could be processed at compile
		 * time, which means we don't know the block_size for
		 * the last element which the loop below needs.  So we
		 * need to compute it.
		 */

		dim_size = type->params.array.dims[last_index];
		maxe = prv_get_dynamic_dim_size(p, dim_size, last_offset,
						mem_reg, err);
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;

		one = subtilis_exp_new_int32(1, err);
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;

		blocke = subtilis_type_if_add(p, maxe, one, err);
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;

		dyn_start--;
	} else {
		blocke = subtilis_exp_new_int32(block_size, err);
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;
	}

	offset += (sizeof(int32_t) * dyn_start);

	/* Need to compute  the dynamic portion of the offset array */

	for (i = dyn_start; i >= 0; i--) {
		dim_size = type->params.array.dims[i];

		maxe = prv_check_dynamic_index(p, e[i], dim_size, offset,
					       mem_reg, err);
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;
		edup = subtilis_type_if_dup(e[i], err);
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;
		one = subtilis_exp_new_int32(1, err);
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;
		maxe = subtilis_type_if_add(p, maxe, one, err);
		one = NULL;
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;
		blocke_dup = subtilis_type_if_dup(blocke, err);
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;
		edup = subtilis_type_if_mul(p, blocke_dup, edup, err);
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;
		blocke = subtilis_type_if_mul(p, blocke, maxe, err);
		maxe = NULL;
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;
		sizee = subtilis_type_if_add(p, sizee, edup, err);
		edup = NULL;
		if (err->type != SUBTILIS_ERROR_OK)
			goto cleanup;

		offset -= sizeof(int32_t);
	}

	subtilis_exp_delete(blocke);

	/*
	 * Check and add the offset for the final index.  If it's
	 * constant and the last dimension is constant we'll have
	 * already checked it but hey hum.
	 */

	prv_check_last_index(p, var_name, e, type, last_offset, mem_reg, err);
	if (err->type != SUBTILIS_ERROR_OK)
		goto cleanup;

	edup = subtilis_type_if_dup(e[index_count - 1], err);
	if (err->type != SUBTILIS_ERROR_OK)
		goto cleanup;

	sizee = subtilis_type_if_add(p, edup, sizee, err);
	edup = NULL;
	if (err->type != SUBTILIS_ERROR_OK)
		goto cleanup;

	return prv_compute_element_address(p, type, mem_reg, loc, sizee, err);

cleanup:

	subtilis_exp_delete(blocke);
	subtilis_exp_delete(maxe);
	subtilis_exp_delete(edup);
	subtilis_exp_delete(sizee);

	return NULL;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq 0x18(%rbp), %rax
movq 0x10(%rbp), %rax
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movq %r9, -0x38(%rbp)
movl $0x0, -0x5c(%rbp)
movl $0x0, -0x60(%rbp)
movq $0x0, -0x68(%rbp)
movq $0x0, -0x70(%rbp)
movq $0x0, -0x78(%rbp)
movq $0x0, -0x80(%rbp)
movq $0x0, -0x88(%rbp)
movq 0x10(%rbp), %rax
movq -0x20(%rbp), %rcx
movslq 0x8(%rcx), %rcx
cmpq %rcx, %rax
je 0x5ee74
movq 0x18(%rbp), %rdi
movq -0x18(%rbp), %rdx
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq 0x30(%rax), %r8
movq -0x10(%rbp), %rax
movq (%rax), %rax
movl 0x38(%rax), %r9d
movl $0x3a, %esi
leaq 0x4c427(%rip), %rcx     # 0xab276
leaq 0x4db27(%rip), %rax     # 0xac97d
movq %rax, (%rsp)
movl $0x762, 0x8(%rsp)       # imm = 0x762
callq 0x156d0
movq $0x0, -0x8(%rbp)
jmp 0x5f2af
cmpq $0x1, 0x10(%rbp)
jne 0x5eeb2
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
movq -0x28(%rbp), %rcx
movq -0x30(%rbp), %r8
movq -0x38(%rbp), %r9
movq 0x10(%rbp), %r10
movq 0x18(%rbp), %rax
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
callq 0x5f2c0
movq %rax, -0x8(%rbp)
jmp 0x5f2af
movq -0x30(%rbp), %rax
addq $0x10, %rax
movl %eax, -0x54(%rbp)
movq -0x10(%rbp), %rdi
movq -0x38(%rbp), %rsi
movq 0x10(%rbp), %rdx
movq -0x18(%rbp), %rcx
movq -0x20(%rbp), %r8
movq 0x18(%rbp), %rax
leaq -0x60(%rbp), %r9
leaq -0x5c(%rbp), %r10
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
callq 0x5f3b0
movq %rax, -0x90(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5ef08
movq $0x0, -0x8(%rbp)
jmp 0x5f2af
movq -0x90(%rbp), %rax
movl %eax, %edi
movq 0x18(%rbp), %rsi
callq 0x37800
movq %rax, -0x70(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5ef34
movq $0x0, -0x8(%rbp)
jmp 0x5f2af
movq -0x10(%rbp), %rdi
movq -0x70(%rbp), %rsi
movq 0x18(%rbp), %rdx
callq 0x47c10
movq %rax, -0x70(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5ef57
jmp 0x5f283
movq 0x10(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x48(%rbp)
movslq -0x54(%rbp), %rax
movq -0x48(%rbp), %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movl %eax, -0x58(%rbp)
movslq -0x60(%rbp), %rax
movq 0x10(%rbp), %rcx
subq $0x1, %rcx
cmpq %rcx, %rax
jne 0x5f014
movq -0x20(%rbp), %rax
movq -0x48(%rbp), %rcx
movl 0xc(%rax,%rcx,4), %eax
movl %eax, -0x40(%rbp)
movq -0x10(%rbp), %rdi
movl -0x40(%rbp), %esi
movl -0x58(%rbp), %edx
movq -0x28(%rbp), %rcx
movq 0x18(%rbp), %r8
callq 0x5f5b0
movq %rax, -0x80(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5efc2
jmp 0x5f283
movq 0x18(%rbp), %rsi
movl $0x1, %edi
callq 0x37800
movq %rax, -0x50(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5efe2
jmp 0x5f283
movq -0x10(%rbp), %rdi
movq -0x80(%rbp), %rsi
movq -0x50(%rbp), %rdx
movq 0x18(%rbp), %rcx
callq 0x48e20
movq %rax, -0x68(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5f009
jmp 0x5f283
movl -0x60(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x5f034
movl -0x5c(%rbp), %edi
movq 0x18(%rbp), %rsi
callq 0x37800
movq %rax, -0x68(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5f032
jmp 0x5f283
jmp 0x5f034
movslq -0x60(%rbp), %rcx
shlq $0x2, %rcx
movslq -0x54(%rbp), %rax
addq %rcx, %rax
movl %eax, -0x54(%rbp)
movl -0x60(%rbp), %eax
movl %eax, -0x3c(%rbp)
cmpl $0x0, -0x3c(%rbp)
jl 0x5f1d3
movq -0x20(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movl 0xc(%rax,%rcx,4), %eax
movl %eax, -0x40(%rbp)
movq -0x10(%rbp), %rdi
movq -0x38(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
movl -0x40(%rbp), %edx
movl -0x54(%rbp), %ecx
movq -0x28(%rbp), %r8
movq 0x18(%rbp), %r9
callq 0x5f660
movq %rax, -0x80(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5f09a
jmp 0x5f283
movq -0x38(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
movq 0x18(%rbp), %rsi
callq 0x47d20
movq %rax, -0x78(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5f0c1
jmp 0x5f283
movq 0x18(%rbp), %rsi
movl $0x1, %edi
callq 0x37800
movq %rax, -0x50(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5f0e1
jmp 0x5f283
movq -0x10(%rbp), %rdi
movq -0x80(%rbp), %rsi
movq -0x50(%rbp), %rdx
movq 0x18(%rbp), %rcx
callq 0x48e20
movq %rax, -0x80(%rbp)
movq $0x0, -0x50(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5f110
jmp 0x5f283
movq -0x68(%rbp), %rdi
movq 0x18(%rbp), %rsi
callq 0x47d20
movq %rax, -0x88(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5f132
jmp 0x5f283
movq -0x10(%rbp), %rdi
movq -0x88(%rbp), %rsi
movq -0x78(%rbp), %rdx
movq 0x18(%rbp), %rcx
callq 0x48fb0
movq %rax, -0x78(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5f15c
jmp 0x5f283
movq -0x10(%rbp), %rdi
movq -0x68(%rbp), %rsi
movq -0x80(%rbp), %rdx
movq 0x18(%rbp), %rcx
callq 0x48fb0
movq %rax, -0x68(%rbp)
movq $0x0, -0x80(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5f18b
jmp 0x5f283
movq -0x10(%rbp), %rdi
movq -0x70(%rbp), %rsi
movq -0x78(%rbp), %rdx
movq 0x18(%rbp), %rcx
callq 0x48e20
movq %rax, -0x70(%rbp)
movq $0x0, -0x78(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5f1ba
jmp 0x5f283
movslq -0x54(%rbp), %rax
subq $0x4, %rax
movl %eax, -0x54(%rbp)
movl -0x3c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x5f04c
movq -0x68(%rbp), %rdi
callq 0x36ee0
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x38(%rbp), %rdx
movq -0x20(%rbp), %rcx
movl -0x58(%rbp), %r8d
movq -0x28(%rbp), %r9
movq 0x18(%rbp), %rax
movq %rax, (%rsp)
callq 0x5f720
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5f20c
jmp 0x5f283
movq -0x38(%rbp), %rax
movq 0x10(%rbp), %rcx
subq $0x1, %rcx
movq (%rax,%rcx,8), %rdi
movq 0x18(%rbp), %rsi
callq 0x47d20
movq %rax, -0x78(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5f234
jmp 0x5f283
movq -0x10(%rbp), %rdi
movq -0x78(%rbp), %rsi
movq -0x70(%rbp), %rdx
movq 0x18(%rbp), %rcx
callq 0x48e20
movq %rax, -0x70(%rbp)
movq $0x0, -0x78(%rbp)
movq 0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x5f260
jmp 0x5f283
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq -0x30(%rbp), %rcx
movq -0x70(%rbp), %r8
movq 0x18(%rbp), %r9
callq 0x5f840
movq %rax, -0x8(%rbp)
jmp 0x5f2af
movq -0x68(%rbp), %rdi
callq 0x36ee0
movq -0x80(%rbp), %rdi
callq 0x36ee0
movq -0x78(%rbp), %rdi
callq 0x36ee0
movq -0x70(%rbp), %rdi
callq 0x36ee0
movq $0x0, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0xa0, %rsp
popq %rbp
retq
nopl (%rax)