// File: /workspace/github_cpp_makefile_star2_O2/rossy[P]crossc/SPIRV-Cross/spirv_glsl.cpp
// Function: spirv_cross::CompilerGLSL::flattened_access_chain_offset[abi:cxx11](spirv_cross::SPIRType const&, unsigned int const*, unsigned int, unsigned int, unsigned int, bool*, unsigned int*)
std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(const SPIRType &basetype,
                                                                             const uint32_t *indices, uint32_t count,
                                                                             uint32_t offset, uint32_t word_stride,
                                                                             bool *need_transpose,
                                                                             uint32_t *out_matrix_stride)
{
	// Start traversing type hierarchy at the proper non-pointer types.
	const auto *type = &get_non_pointer_type(basetype);

	// This holds the type of the current pointer which we are traversing through.
	// We always start out from a struct type which is the block.
	// This is primarily used to reflect the array strides and matrix strides later.
	// For the first access chain index, type_id won't be needed, so just keep it as 0, it will be set
	// accordingly as members of structs are accessed.
	assert(type->basetype == SPIRType::Struct);
	uint32_t type_id = 0;

	std::string expr;

	// Inherit matrix information in case we are access chaining a vector which might have come from a row major layout.
	bool row_major_matrix_needs_conversion = need_transpose ? *need_transpose : false;
	uint32_t matrix_stride = out_matrix_stride ? *out_matrix_stride : 0;

	for (uint32_t i = 0; i < count; i++)
	{
		uint32_t index = indices[i];

		// Arrays
		if (!type->array.empty())
		{
			// Here, the type_id will be a type ID for the array type itself.
			uint32_t array_stride = get_decoration(type_id, DecorationArrayStride);
			if (!array_stride)
				SPIRV_CROSS_THROW("SPIR-V does not define ArrayStride for buffer block.");

			auto *constant = maybe_get<SPIRConstant>(index);
			if (constant)
			{
				// Constant array access.
				offset += constant->scalar() * array_stride;
			}
			else
			{
				// Dynamic array access.
				if (array_stride % word_stride)
				{
					SPIRV_CROSS_THROW(
					    "Array stride for dynamic indexing must be divisible by the size of a 4-component vector. "
					    "Likely culprit here is a float or vec2 array inside a push constant block which is std430. "
					    "This cannot be flattened. Try using std140 layout instead.");
				}

				expr += to_enclosed_expression(index);
				expr += " * ";
				expr += convert_to_string(array_stride / word_stride);
				expr += " + ";
			}

			uint32_t parent_type = type->parent_type;
			type = &get<SPIRType>(parent_type);
			type_id = parent_type;

			// Type ID now refers to the array type with one less dimension.
		}
		// For structs, the index refers to a constant, which indexes into the members.
		// We also check if this member is a builtin, since we then replace the entire expression with the builtin one.
		else if (type->basetype == SPIRType::Struct)
		{
			index = get<SPIRConstant>(index).scalar();

			if (index >= type->member_types.size())
				SPIRV_CROSS_THROW("Member index is out of bounds!");

			offset += type_struct_member_offset(*type, index);
			type_id = type->member_types[index];

			auto &struct_type = *type;
			type = &get<SPIRType>(type->member_types[index]);

			if (type->columns > 1)
			{
				matrix_stride = type_struct_member_matrix_stride(struct_type, index);
				row_major_matrix_needs_conversion =
				    combined_decoration_for_member(struct_type, index).get(DecorationRowMajor);
			}
			else
				row_major_matrix_needs_conversion = false;
		}
		// Matrix -> Vector
		else if (type->columns > 1)
		{
			auto *constant = maybe_get<SPIRConstant>(index);
			if (constant)
			{
				index = get<SPIRConstant>(index).scalar();
				offset += index * (row_major_matrix_needs_conversion ? (type->width / 8) : matrix_stride);
			}
			else
			{
				uint32_t indexing_stride = row_major_matrix_needs_conversion ? (type->width / 8) : matrix_stride;
				// Dynamic array access.
				if (indexing_stride % word_stride)
				{
					SPIRV_CROSS_THROW(
					    "Matrix stride for dynamic indexing must be divisible by the size of a 4-component vector. "
					    "Likely culprit here is a row-major matrix being accessed dynamically. "
					    "This cannot be flattened. Try using std140 layout instead.");
				}

				expr += to_enclosed_expression(index);
				expr += " * ";
				expr += convert_to_string(indexing_stride / word_stride);
				expr += " + ";
			}

			uint32_t parent_type = type->parent_type;
			type = &get<SPIRType>(type->parent_type);
			type_id = parent_type;
		}
		// Vector -> Scalar
		else if (type->vecsize > 1)
		{
			auto *constant = maybe_get<SPIRConstant>(index);
			if (constant)
			{
				index = get<SPIRConstant>(index).scalar();
				offset += index * (row_major_matrix_needs_conversion ? matrix_stride : (type->width / 8));
			}
			else
			{
				uint32_t indexing_stride = row_major_matrix_needs_conversion ? matrix_stride : (type->width / 8);

				// Dynamic array access.
				if (indexing_stride % word_stride)
				{
					SPIRV_CROSS_THROW(
					    "Stride for dynamic vector indexing must be divisible by the size of a 4-component vector. "
					    "This cannot be flattened in legacy targets.");
				}

				expr += to_enclosed_expression(index);
				expr += " * ";
				expr += convert_to_string(indexing_stride / word_stride);
				expr += " + ";
			}

			uint32_t parent_type = type->parent_type;
			type = &get<SPIRType>(type->parent_type);
			type_id = parent_type;
		}
		else
			SPIRV_CROSS_THROW("Cannot subdivide a scalar value!");
	}

	if (need_transpose)
		*need_transpose = row_major_matrix_needs_conversion;
	if (out_matrix_stride)
		*out_matrix_stride = matrix_stride;

	return std::make_pair(expr, offset);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movl %r9d, %ebp
movl %r8d, %ebx
movq %rcx, 0x80(%rsp)
movq %rsi, %r13
movq %rdi, %r14
movq %rsi, %rdi
movq %rdx, %rsi
callq 0x11e4a
cmpl $0xc, 0xc(%rax)
jne 0x360f3
movq %rax, %r12
movl %ebp, 0x14(%rsp)
movq 0xe0(%rsp), %rcx
leaq 0x68(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movq 0xd8(%rsp), %rdx
movb $0x0, (%rax)
movl $0x0, 0x10(%rsp)
testq %rdx, %rdx
je 0x35af8
movb (%rdx), %bpl
jmp 0x35afa
xorl %ebp, %ebp
movq %r14, 0x78(%rsp)
testq %rcx, %rcx
je 0x35b0a
movl (%rcx), %eax
movl %eax, 0x10(%rsp)
movl %ebx, %eax
movq %rax, 0x88(%rsp)
xorl %ecx, %ecx
xorl %r14d, %r14d
cmpq %rcx, 0x88(%rsp)
je 0x35ec8
movq 0x80(%rsp), %rax
movq %rcx, 0x90(%rsp)
movl (%rax,%rcx,4), %ebx
movq 0x20(%r12), %rax
cmpq 0x28(%r12), %rax
je 0x35b81
movq %r13, %rdi
movl %r14d, %esi
pushq $0x6
popq %rdx
callq 0x12174
movl %eax, %r14d
testl %eax, %eax
je 0x35f27
movq %r13, %rdi
movl %ebx, %esi
callq 0x43b76
testq %rax, %rax
je 0x35c2a
imull 0x10(%rax), %r14d
addl %r14d, 0x14(%rsp)
jmp 0x35cb1
cmpl $0xc, 0xc(%r12)
jne 0x35cda
movq %r13, %rdi
movl %ebx, %esi
callq 0x17bce
movq %r13, %r15
movl 0x10(%rax), %r13d
movq 0x70(%r12), %rax
subq 0x68(%r12), %rax
sarq $0x2, %rax
cmpq %r13, %rax
jbe 0x35fc3
movq %r15, %rbx
movq %r15, %rdi
movq %r12, %rsi
movl %r13d, %edx
callq 0x1267e
movl %eax, %ebp
movq 0x68(%r12), %rax
movl (%rax,%r13,4), %r14d
movq %rbx, %rdi
movl %r14d, %esi
callq 0x90a4
movq %rax, %rbx
addl %ebp, 0x14(%rsp)
cmpl $0x2, 0x18(%rax)
jb 0x35d62
movq %r15, %rdi
movq %r12, %rsi
movl %r13d, %edx
callq 0x127d2
movl %eax, 0x10(%rsp)
leaq 0x18(%rsp), %rdi
movq %r15, %rsi
movq %r12, %rdx
movl %r13d, %ecx
callq 0x16ba6
movb 0x18(%rsp), %bpl
shrb $0x4, %bpl
leaq 0x20(%rsp), %rdi
callq 0xb51c
jmp 0x35d64
movl %r14d, %eax
xorl %edx, %edx
divl 0xd0(%rsp)
testl %edx, %edx
jne 0x35f75
movl %eax, %r14d
leaq 0x18(%rsp), %r15
movq %r15, %rdi
movq %r13, %rsi
movl %ebx, %edx
callq 0x2beca
leaq 0x58(%rsp), %rbx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x64f0
movq %r15, %rdi
callq 0x6548
movq %rbx, %rdi
leaq 0x5e8af(%rip), %rsi     # 0x94524
callq 0x64d0
leaq 0x18(%rsp), %rbx
movq %rbx, %rdi
movl %r14d, %esi
callq 0x1c182
leaq 0x58(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x64f0
movq %rbx, %rdi
callq 0x6548
movq %r14, %rdi
leaq 0x67f81(%rip), %rsi     # 0x9dc2d
callq 0x64d0
movl 0x9c(%r12), %r14d
movq %r13, %rdi
movl %r14d, %esi
callq 0x90a4
movq %rax, %rbx
movq 0x90(%rsp), %rcx
incq %rcx
movq %rbx, %r12
jmp 0x35b19
cmpl $0x2, 0x18(%r12)
jb 0x35d1a
movq %r13, %rdi
movl %ebx, %esi
callq 0x43b76
testq %rax, %rax
je 0x35d6c
movq %r13, %rdi
movl %ebx, %esi
callq 0x17bce
movl 0x10(%rsp), %ecx
testb $0x1, %bpl
je 0x35d0d
movl 0x10(%r12), %ecx
shrl $0x3, %ecx
imull 0x10(%rax), %ecx
addl %ecx, 0x14(%rsp)
jmp 0x35e02
cmpl $0x2, 0x14(%r12)
jb 0x36011
movq %r13, %rdi
movl %ebx, %esi
callq 0x43b76
testq %rax, %rax
je 0x35e1a
movq %r13, %rdi
movl %ebx, %esi
callq 0x17bce
movl 0x10(%rsp), %ecx
testb $0x1, %bpl
jne 0x35d55
movl 0x10(%r12), %ecx
shrl $0x3, %ecx
imull 0x10(%rax), %ecx
addl %ecx, 0x14(%rsp)
jmp 0x35eb0
xorl %ebp, %ebp
movq %r15, %r13
jmp 0x35cc7
movl 0x10(%rsp), %eax
testb $0x1, %bpl
je 0x35d7e
movl 0x10(%r12), %eax
shrl $0x3, %eax
xorl %edx, %edx
divl 0xd0(%rsp)
testl %edx, %edx
jne 0x360aa
movl %eax, %r14d
leaq 0x18(%rsp), %r15
movq %r15, %rdi
movq %r13, %rsi
movl %ebx, %edx
callq 0x2beca
leaq 0x58(%rsp), %rbx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x64f0
movq %r15, %rdi
callq 0x6548
movq %rbx, %rdi
leaq 0x5e75e(%rip), %rsi     # 0x94524
callq 0x64d0
leaq 0x18(%rsp), %rbx
movq %rbx, %rdi
movl %r14d, %esi
callq 0x1c182
leaq 0x58(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x64f0
movq %rbx, %rdi
callq 0x6548
movq %r14, %rdi
leaq 0x67e30(%rip), %rsi     # 0x9dc2d
callq 0x64d0
movl 0x9c(%r12), %r14d
movq %r13, %rdi
movl %r14d, %esi
callq 0x90a4
jmp 0x35cc4
movl 0x10(%rsp), %eax
testb $0x1, %bpl
jne 0x35e2c
movl 0x10(%r12), %eax
shrl $0x3, %eax
xorl %edx, %edx
divl 0xd0(%rsp)
testl %edx, %edx
jne 0x3605f
movl %eax, %r14d
leaq 0x18(%rsp), %r15
movq %r15, %rdi
movq %r13, %rsi
movl %ebx, %edx
callq 0x2beca
leaq 0x58(%rsp), %rbx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x64f0
movq %r15, %rdi
callq 0x6548
movq %rbx, %rdi
leaq 0x5e6b0(%rip), %rsi     # 0x94524
callq 0x64d0
leaq 0x18(%rsp), %rbx
movq %rbx, %rdi
movl %r14d, %esi
callq 0x1c182
leaq 0x58(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x64f0
movq %rbx, %rdi
callq 0x6548
movq %r14, %rdi
leaq 0x67d82(%rip), %rsi     # 0x9dc2d
callq 0x64d0
movl 0x9c(%r12), %r14d
movq %r13, %rdi
movl %r14d, %esi
callq 0x90a4
jmp 0x35cc4
movq 0xd8(%rsp), %rax
testq %rax, %rax
je 0x35edc
andb $0x1, %bpl
movb %bpl, (%rax)
movq 0xe0(%rsp), %rax
testq %rax, %rax
movq 0x78(%rsp), %rbx
je 0x35ef4
movl 0x10(%rsp), %ecx
movl %ecx, (%rax)
leaq 0x58(%rsp), %rsi
movq %rbx, %rdi
callq 0x63c0
movl 0x14(%rsp), %eax
movl %eax, 0x20(%rbx)
leaq 0x58(%rsp), %rdi
callq 0x6548
movq %rbx, %rax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
pushq $0x10
popq %rdi
callq 0x6140
movq %rax, %r14
leaq 0x5e970(%rip), %rsi     # 0x948a9
leaq 0x18(%rsp), %rdi
leaq 0xf(%rsp), %rdx
callq 0x6100
movb $0x1, %bpl
leaq 0x18(%rsp), %rsi
movq %r14, %rdi
callq 0x6f6e
xorl %ebp, %ebp
leaq 0xb0e5f(%rip), %rsi     # 0xe6dc0
movq 0xb2078(%rip), %rdx     # 0xe7fe0
movq %r14, %rdi
callq 0x6490
jmp 0x360f3
pushq $0x10
popq %rdi
callq 0x6140
movq %rax, %r14
leaq 0x5e957(%rip), %rsi     # 0x948de
leaq 0x18(%rsp), %rdi
leaq 0xf(%rsp), %rdx
callq 0x6100
movb $0x1, %bpl
leaq 0x18(%rsp), %rsi
movq %r14, %rdi
callq 0x6f6e
xorl %ebp, %ebp
leaq 0xb0e11(%rip), %rsi     # 0xe6dc0
movq 0xb202a(%rip), %rdx     # 0xe7fe0
movq %r14, %rdi
callq 0x6490
jmp 0x360f3
pushq $0x10
popq %rdi
callq 0x6140
movq %rax, %r14
leaq 0x5e553(%rip), %rsi     # 0x94528
leaq 0x18(%rsp), %rdi
leaq 0xf(%rsp), %rdx
callq 0x6100
movb $0x1, %bpl
leaq 0x18(%rsp), %rsi
movq %r14, %rdi
callq 0x6f6e
xorl %ebp, %ebp
leaq 0xb0dc3(%rip), %rsi     # 0xe6dc0
movq 0xb1fdc(%rip), %rdx     # 0xe7fe0
movq %r14, %rdi
callq 0x6490
jmp 0x360f3
pushq $0x10
popq %rdi
callq 0x6140
movq %rax, %r14
leaq 0x5e524(%rip), %rsi     # 0x94547
leaq 0x18(%rsp), %rdi
leaq 0xf(%rsp), %rdx
callq 0x6100
movb $0x1, %bpl
leaq 0x18(%rsp), %rsi
movq %r14, %rdi
callq 0x6f6e
xorl %ebp, %ebp
leaq 0xb0d75(%rip), %rsi     # 0xe6dc0
movq 0xb1f8e(%rip), %rdx     # 0xe7fe0
movq %r14, %rdi
callq 0x6490
jmp 0x360f3
pushq $0x10
popq %rdi
callq 0x6140
movq %rax, %r14
leaq 0x5ea37(%rip), %rsi     # 0x94aa8
leaq 0x18(%rsp), %rdi
leaq 0xf(%rsp), %rdx
callq 0x6100
movb $0x1, %bpl
leaq 0x18(%rsp), %rsi
movq %r14, %rdi
callq 0x6f6e
xorl %ebp, %ebp
leaq 0xb0d27(%rip), %rsi     # 0xe6dc0
movq 0xb1f40(%rip), %rdx     # 0xe7fe0
movq %r14, %rdi
callq 0x6490
jmp 0x360f3
pushq $0x10
popq %rdi
callq 0x6140
movq %rax, %r14
leaq 0x5e911(%rip), %rsi     # 0x949cd
leaq 0x18(%rsp), %rdi
leaq 0xf(%rsp), %rdx
callq 0x6100
movb $0x1, %bpl
leaq 0x18(%rsp), %rsi
movq %r14, %rdi
callq 0x6f6e
xorl %ebp, %ebp
leaq 0xb0cdc(%rip), %rsi     # 0xe6dc0
movq 0xb1ef5(%rip), %rdx     # 0xe7fe0
movq %r14, %rdi
callq 0x6490
leaq 0x5e6dc(%rip), %rdi     # 0x947d6
leaq 0x5bc27(%rip), %rsi     # 0x91d28
leaq 0x5e6f1(%rip), %rcx     # 0x947f9
movl $0x164d, %edx           # imm = 0x164D
callq 0x61c0
jmp 0x3615d
jmp 0x36171
jmp 0x3615d
jmp 0x36171
jmp 0x36184
jmp 0x3614a
jmp 0x36184
jmp 0x3614a
jmp 0x36184
jmp 0x3614a
jmp 0x36184
jmp 0x3614a
jmp 0x36184
jmp 0x3615d
jmp 0x36171
jmp 0x36184
jmp 0x36184
jmp 0x36184
jmp 0x3615d
jmp 0x36171
jmp 0x36184
jmp 0x36184
jmp 0x3615d
jmp 0x36171
jmp 0x36184
jmp 0x36184
jmp 0x3614a
jmp 0x36184
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x6548
jmp 0x36187
jmp 0x36184
jmp 0x36184
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x6548
testb %bpl, %bpl
jne 0x36174
jmp 0x36187
movq %rax, %rbx
movq %r14, %rdi
callq 0x6200
jmp 0x36187
jmp 0x36184
jmp 0x36184
jmp 0x36184
movq %rax, %rbx
leaq 0x58(%rsp), %rdi
callq 0x6548
movq %rbx, %rdi
callq 0x64b0
nop