// File: /workspace/github_cpp_makefile_star2_O2/rossy[P]crossc/SPIRV-Cross/spirv_glsl.cpp
// Function: spirv_cross::CompilerGLSL::build_composite_combiner[abi:cxx11](unsigned int, unsigned int const*, unsigned int)
string CompilerGLSL::build_composite_combiner(uint32_t return_type, const uint32_t *elems, uint32_t length)
{
	uint32_t base = 0;
	string op;
	string subop;

	// Can only merge swizzles for vectors.
	auto &type = get<SPIRType>(return_type);
	bool can_apply_swizzle_opt = type.basetype != SPIRType::Struct && type.array.empty() && type.columns == 1;
	bool swizzle_optimization = false;

	for (uint32_t i = 0; i < length; i++)
	{
		auto *e = maybe_get<SPIRExpression>(elems[i]);

		// If we're merging another scalar which belongs to the same base
		// object, just merge the swizzles to avoid triggering more than 1 expression read as much as possible!
		if (can_apply_swizzle_opt && e && e->base_expression && e->base_expression == base)
		{
			// Only supposed to be used for vector swizzle -> scalar.
			assert(!e->expression.empty() && e->expression.front() == '.');
			subop += e->expression.substr(1, string::npos);
			swizzle_optimization = true;
		}
		else
		{
			// We'll likely end up with duplicated swizzles, e.g.
			// foobar.xyz.xyz from patterns like
			// OpVectorShuffle
			// OpCompositeExtract x 3
			// OpCompositeConstruct 3x + other scalar.
			// Just modify op in-place.
			if (swizzle_optimization)
			{
				if (backend.swizzle_is_function)
					subop += "()";

				// Don't attempt to remove unity swizzling if we managed to remove duplicate swizzles.
				// The base "foo" might be vec4, while foo.xyz is vec3 (OpVectorShuffle) and looks like a vec3 due to the .xyz tacked on.
				// We only want to remove the swizzles if we're certain that the resulting base will be the same vecsize.
				// Essentially, we can only remove one set of swizzles, since that's what we have control over ...
				// Case 1:
				//  foo.yxz.xyz: Duplicate swizzle kicks in, giving foo.yxz, we are done.
				//               foo.yxz was the result of OpVectorShuffle and we don't know the type of foo.
				// Case 2:
				//  foo.xyz: Duplicate swizzle won't kick in.
				//           If foo is vec3, we can remove xyz, giving just foo.
				if (!remove_duplicate_swizzle(subop))
					remove_unity_swizzle(base, subop);

				// Strips away redundant parens if we created them during component extraction.
				strip_enclosed_expression(subop);
				swizzle_optimization = false;
				op += subop;
			}
			else
				op += subop;

			if (i)
				op += ", ";
			subop = to_expression(elems[i]);
		}

		base = e ? e->base_expression : 0;
	}

	if (swizzle_optimization)
	{
		if (backend.swizzle_is_function)
			subop += "()";

		if (!remove_duplicate_swizzle(subop))
			remove_unity_swizzle(base, subop);
		// Strips away redundant parens if we created them during component extraction.
		strip_enclosed_expression(subop);
	}

	op += subop;
	return op;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movl %r8d, %ebp
movq %rcx, 0x30(%rsp)
movq %rsi, %r14
leaq 0x10(%rdi), %rax
movq %rax, (%rdi)
andq $0x0, 0x8(%rdi)
xorl %eax, %eax
movq %rdi, 0x8(%rsp)
movb %al, 0x10(%rdi)
leaq 0x20(%rsp), %rcx
movq %rcx, -0x10(%rcx)
andq $0x0, -0x8(%rcx)
movb %al, (%rcx)
movq %rsi, %rdi
movl %edx, %esi
callq 0x90a4
xorl %ebx, %ebx
cmpl $0xc, 0xc(%rax)
movl $0x0, %ecx
je 0x37089
movq 0x20(%rax), %rcx
cmpq 0x28(%rax), %rcx
je 0x37082
xorl %ecx, %ecx
jmp 0x37089
cmpl $0x1, 0x18(%rax)
sete %cl
movl %ebp, %eax
movq %rax, 0x40(%rsp)
xorb $0x1, %cl
movq %rcx, 0x38(%rsp)
leaq 0x48(%rsp), %r12
xorl %r15d, %r15d
xorl %r13d, %r13d
cmpq %r15, 0x40(%rsp)
je 0x371eb
movq 0x30(%rsp), %rax
movl (%rax,%r15,4), %esi
movq %r14, %rdi
callq 0x16fde
movq %rax, %rbp
testq %rax, %rax
sete %al
orb 0x38(%rsp), %al
jne 0x3712a
movl 0xc(%rbp), %eax
testl %eax, %eax
setne %cl
cmpl %ebx, %eax
sete %al
andb %cl, %al
cmpb $0x1, %al
jne 0x3712a
cmpq $0x0, 0x18(%rbp)
je 0x37263
movq %rbp, %rsi
addq $0x10, %rsi
movq (%rsi), %rax
cmpb $0x2e, (%rax)
jne 0x37263
movq %r12, %rdi
pushq $0x1
popq %rdx
pushq $-0x1
popq %rcx
callq 0x62b0
leaq 0x10(%rsp), %rdi
movq %r12, %rsi
callq 0x64f0
movq %r12, %rdi
callq 0x6548
movb $0x1, %r13b
jmp 0x371dc
testb $0x1, %r13b
je 0x37189
cmpb $0x1, 0x620(%r14)
jne 0x3714b
leaq 0x10(%rsp), %rdi
leaq 0x5c7ea(%rip), %rsi     # 0x93930
callq 0x64d0
movq %r14, %rdi
leaq 0x10(%rsp), %rsi
callq 0x2abf8
testb %al, %al
jne 0x3716b
movq %r14, %rdi
movl %ebx, %esi
leaq 0x10(%rsp), %rdx
callq 0x36eb6
leaq 0x10(%rsp), %rsi
callq 0x2be62
movq 0x8(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x64f0
xorl %r13d, %r13d
jmp 0x37198
movq 0x8(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x64f0
testq %r15, %r15
je 0x371ae
movq 0x8(%rsp), %rdi
leaq 0x5dee2(%rip), %rsi     # 0x9508b
callq 0x64d0
movq 0x30(%rsp), %rax
movl (%rax,%r15,4), %edx
movq %r12, %rdi
movq %r14, %rsi
callq 0x2b9f0
leaq 0x10(%rsp), %rdi
movq %r12, %rsi
callq 0x6320
movq %r12, %rdi
callq 0x6548
testq %rbp, %rbp
je 0x371e1
movl 0xc(%rbp), %ebx
jmp 0x371e3
xorl %ebx, %ebx
incq %r15
jmp 0x370a3
testb $0x1, %r13b
je 0x37236
cmpb $0x1, 0x620(%r14)
jne 0x3720c
leaq 0x5c72e(%rip), %rsi     # 0x93930
leaq 0x10(%rsp), %rdi
callq 0x64d0
leaq 0x10(%rsp), %rsi
movq %r14, %rdi
callq 0x2abf8
testb %al, %al
jne 0x3722c
leaq 0x10(%rsp), %rdx
movq %r14, %rdi
movl %ebx, %esi
callq 0x36eb6
leaq 0x10(%rsp), %rsi
callq 0x2be62
leaq 0x10(%rsp), %rsi
movq 0x8(%rsp), %rdi
callq 0x64f0
leaq 0x10(%rsp), %rdi
callq 0x6548
movq 0x8(%rsp), %rax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x5d935(%rip), %rdi     # 0x94b9f
leaq 0x5aab7(%rip), %rsi     # 0x91d28
leaq 0x5d95e(%rip), %rcx     # 0x94bd6
movl $0x17ba, %edx           # imm = 0x17BA
callq 0x61c0
jmp 0x37299
jmp 0x37299
movq %rax, %rbx
leaq 0x48(%rsp), %rdi
callq 0x6548
jmp 0x3729c
jmp 0x37299
jmp 0x37299
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x6548
movq 0x8(%rsp), %rdi
callq 0x6548
movq %rbx, %rdi
callq 0x64b0