// File: /workspace/github_cpp_makefile_star2_O3/rossy[P]crossc/SPIRV-Cross/spirv_cross.cpp
// Function: spirv_cross::Compiler::CombinedImageSamplerHandler::handle(spv::Op, unsigned int const*, unsigned int)
bool Compiler::CombinedImageSamplerHandler::handle(Op opcode, const uint32_t *args, uint32_t length)
{
	// We need to figure out where samplers and images are loaded from, so do only the bare bones compilation we need.
	bool is_fetch = false;

	switch (opcode)
	{
	case OpLoad:
	{
		if (length < 3)
			return false;

		uint32_t result_type = args[0];

		auto &type = compiler.get<SPIRType>(result_type);
		bool separate_image = type.basetype == SPIRType::Image && type.image.sampled == 1;
		bool separate_sampler = type.basetype == SPIRType::Sampler;

		// If not separate image or sampler, don't bother.
		if (!separate_image && !separate_sampler)
			return true;

		uint32_t id = args[1];
		uint32_t ptr = args[2];
		compiler.set<SPIRExpression>(id, "", result_type, true);
		compiler.register_read(id, ptr, true);
		return true;
	}

	case OpInBoundsAccessChain:
	case OpAccessChain:
	{
		if (length < 3)
			return false;

		// Technically, it is possible to have arrays of textures and arrays of samplers and combine them, but this becomes essentially
		// impossible to implement, since we don't know which concrete sampler we are accessing.
		// One potential way is to create a combinatorial explosion where N textures and M samplers are combined into N * M sampler2Ds,
		// but this seems ridiculously complicated for a problem which is easy to work around.
		// Checking access chains like this assumes we don't have samplers or textures inside uniform structs, but this makes no sense.

		uint32_t result_type = args[0];

		auto &type = compiler.get<SPIRType>(result_type);
		bool separate_image = type.basetype == SPIRType::Image && type.image.sampled == 1;
		bool separate_sampler = type.basetype == SPIRType::Sampler;
		if (separate_sampler)
			SPIRV_CROSS_THROW(
			    "Attempting to use arrays or structs of separate samplers. This is not possible to statically "
			    "remap to plain GLSL.");

		if (separate_image)
		{
			uint32_t id = args[1];
			uint32_t ptr = args[2];
			compiler.set<SPIRExpression>(id, "", result_type, true);
			compiler.register_read(id, ptr, true);
		}
		return true;
	}

	case OpImageFetch:
	case OpImageQuerySizeLod:
	case OpImageQuerySize:
	case OpImageQueryLevels:
	case OpImageQuerySamples:
	{
		// If we are fetching from a plain OpTypeImage or querying LOD, we must pre-combine with our dummy sampler.
		auto *var = compiler.maybe_get_backing_variable(args[2]);
		if (!var)
			return true;

		auto &type = compiler.get<SPIRType>(var->basetype);
		if (type.basetype == SPIRType::Image && type.image.sampled == 1 && type.image.dim != DimBuffer)
		{
			if (compiler.dummy_sampler_id == 0)
				SPIRV_CROSS_THROW("texelFetch without sampler was found, but no dummy sampler has been created with "
				                  "build_dummy_sampler_for_combined_images().");

			// Do it outside.
			is_fetch = true;
			break;
		}

		return true;
	}

	case OpSampledImage:
		// Do it outside.
		break;

	default:
		return true;
	}

	// Registers sampler2D calls used in case they are parameters so
	// that their callees know which combined image samplers to propagate down the call stack.
	if (!functions.empty())
	{
		auto &callee = *functions.top();
		if (callee.do_combined_parameters)
		{
			uint32_t image_id = args[2];

			auto *image = compiler.maybe_get_backing_variable(image_id);
			if (image)
				image_id = image->self;

			uint32_t sampler_id = is_fetch ? compiler.dummy_sampler_id : args[3];
			auto *sampler = compiler.maybe_get_backing_variable(sampler_id);
			if (sampler)
				sampler_id = sampler->self;

			auto &combined_type = compiler.get<SPIRType>(args[0]);
			register_combined_image_sampler(callee, image_id, sampler_id, combined_type.image.depth);
		}
	}

	// For function calls, we need to remap IDs which are function parameters into global variables.
	// This information is statically known from the current place in the call stack.
	// Function parameters are not necessarily pointers, so if we don't have a backing variable, remapping will know
	// which backing variable the image/sample came from.
	uint32_t image_id = remap_parameter(args[2]);
	uint32_t sampler_id = is_fetch ? compiler.dummy_sampler_id : remap_parameter(args[3]);

	auto itr = find_if(begin(compiler.combined_image_samplers), end(compiler.combined_image_samplers),
	                   [image_id, sampler_id](const CombinedImageSampler &combined) {
		                   return combined.image_id == image_id && combined.sampler_id == sampler_id;
	                   });

	if (itr == end(compiler.combined_image_samplers))
	{
		uint32_t sampled_type;
		if (is_fetch)
		{
			// Have to invent the sampled image type.
			sampled_type = compiler.ir.increase_bound_by(1);
			auto &type = compiler.set<SPIRType>(sampled_type);
			type = compiler.expression_type(args[2]);
			type.self = sampled_type;
			type.basetype = SPIRType::SampledImage;
			type.image.depth = false;
		}
		else
		{
			sampled_type = args[0];
		}

		auto id = compiler.ir.increase_bound_by(2);
		auto type_id = id + 0;
		auto combined_id = id + 1;

		// Make a new type, pointer to OpTypeSampledImage, so we can make a variable of this type.
		// We will probably have this type lying around, but it doesn't hurt to make duplicates for internal purposes.
		auto &type = compiler.set<SPIRType>(type_id);
		auto &base = compiler.get<SPIRType>(sampled_type);
		type = base;
		type.pointer = true;
		type.storage = StorageClassUniformConstant;

		// Build new variable.
		compiler.set<SPIRVariable>(combined_id, type_id, StorageClassUniformConstant, 0);

		// Inherit RelaxedPrecision (and potentially other useful flags if deemed relevant).
		auto &new_flags = compiler.ir.meta[combined_id].decoration.decoration_flags;
		// Fetch inherits precision from the image, not sampler (there is no sampler).
		auto &old_flags = compiler.ir.meta[is_fetch ? image_id : sampler_id].decoration.decoration_flags;
		new_flags.reset();
		if (old_flags.get(DecorationRelaxedPrecision))
			new_flags.set(DecorationRelaxedPrecision);

		// Propagate the array type for the original image as well.
		auto *var = compiler.maybe_get_backing_variable(image_id);
		if (var)
		{
			auto &parent_type = compiler.get<SPIRType>(var->basetype);
			type.array = parent_type.array;
			type.array_size_literal = parent_type.array_size_literal;
		}

		compiler.combined_image_samplers.push_back({ combined_id, image_id, sampler_id });
	}

	return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rdx, %r15
movq %rdi, %r14
movb $0x1, %r12b
leal -0x41(%rsi), %eax
cmpl $0x2a, %eax
ja 0x178e9
movabsq $0x6c040000000, %rdx    # imm = 0x6C040000000
btq %rax, %rdx
jae 0x177b6
movq 0x8(%r14), %rdi
movl 0x8(%r15), %esi
callq 0x12c9a
testq %rax, %rax
je 0x17d32
movq 0x8(%r14), %rdi
movl 0xc(%rax), %esi
callq 0xa3ea
cmpl $0xd, 0xc(%rax)
jne 0x17d32
cmpl $0x1, 0x8c(%rax)
jne 0x17d32
cmpl $0x5, 0x84(%rax)
je 0x17d32
movq 0x8(%r14), %rax
movb $0x1, %r13b
cmpl $0x0, 0x39c(%rax)
jne 0x1782f
movl $0x10, %edi
callq 0x6140
movq %rax, %rbx
leaq 0x20(%rsp), %r15
movq %r15, -0x10(%r15)
leaq 0x9d86a(%rip), %rsi     # 0xb4fd4
leaq 0x9d8de(%rip), %rdx     # 0xb504f
leaq 0x10(%rsp), %rdi
callq 0x7be0
movb $0x1, %bpl
leaq 0x10(%rsp), %rsi
movq %rbx, %rdi
callq 0x6320
leaq 0xe4636(%rip), %rax     # 0xfbdc8
addq $0x10, %rax
movq %rax, (%rbx)
xorl %ebp, %ebp
leaq 0xe460e(%rip), %rsi     # 0xfbdb0
movq 0xe582f(%rip), %rdx     # 0xfcfd8
movq %rbx, %rdi
callq 0x6470
jmp 0x17da8
movl $0x3, %edx
btq %rax, %rdx
jae 0x17822
cmpl $0x3, %ecx
jb 0x178fb
movl (%r15), %esi
movl %esi, 0x4(%rsp)
movq 0x8(%r14), %rdi
callq 0xa3ea
movl 0xc(%rax), %ecx
cmpl $0xf, %ecx
je 0x17d44
cmpl $0xd, %ecx
jne 0x17d32
cmpl $0x1, 0x8c(%rax)
jne 0x17d32
movl 0x4(%r15), %ebx
movl 0x8(%r15), %ebp
movq 0x8(%r14), %rdi
leaq 0x10(%rsp), %r8
movb $0x1, (%r8)
leaq 0x9d097(%rip), %rdx     # 0xb48af
leaq 0x4(%rsp), %rcx
jmp 0x17a57
cmpq $0x15, %rax
jne 0x178e9
xorl %r13d, %r13d
movq 0x90(%r14), %rax
cmpq 0x70(%r14), %rax
je 0x178c9
cmpq 0x98(%r14), %rax
jne 0x17859
movq 0xa8(%r14), %rcx
movl $0x200, %eax            # imm = 0x200
addq -0x8(%rcx), %rax
movq -0x8(%rax), %r12
cmpb $0x1, 0xca(%r12)
jne 0x178c9
movl 0x8(%r15), %ebp
movq 0x8(%r14), %rdi
movl %ebp, %esi
callq 0x12c9a
testq %rax, %rax
je 0x1787f
movl 0x8(%rax), %ebp
movq 0x8(%r14), %rdi
leaq 0x39c(%rdi), %rax
leaq 0xc(%r15), %rcx
testb %r13b, %r13b
cmovneq %rax, %rcx
movl (%rcx), %ebx
movl %ebx, %esi
callq 0x12c9a
testq %rax, %rax
je 0x178a6
movl 0x8(%rax), %ebx
movq 0x8(%r14), %rdi
movl (%r15), %esi
callq 0xa3ea
movzbl 0x88(%rax), %r8d
movq %r14, %rdi
movq %r12, %rsi
movl %ebp, %edx
movl %ebx, %ecx
callq 0x16df0
movl 0x8(%r15), %esi
movq %r14, %rdi
callq 0x16b8c
movl %eax, %ebp
testb %r13b, %r13b
je 0x17903
movq 0x8(%r14), %rdi
movl 0x39c(%rdi), %r12d
jmp 0x17916
cmpl $0x3d, %esi
jne 0x17d32
cmpl $0x3, %ecx
jae 0x17a03
xorl %r12d, %r12d
jmp 0x17d32
movl 0xc(%r15), %esi
movq %r14, %rdi
callq 0x16b8c
movl %eax, %r12d
movq 0x8(%r14), %rdi
movq 0x1d8(%rdi), %rdx
movq 0x1e0(%rdi), %rax
movq %rax, %r9
subq %rdx, %r9
movq %r9, %r8
sarq $0x2, %r8
movabsq $-0x5555555555555555, %rsi # imm = 0xAAAAAAAAAAAAAAAB
imulq %rsi, %r8
sarq $0x2, %r8
testq %r8, %r8
jle 0x179ab
leaq (%r8,%r8,2), %rcx
shlq $0x4, %rcx
addq %rdx, %rcx
incq %r8
addq $0x18, %rdx
cmpl %ebp, -0x14(%rdx)
jne 0x17969
cmpl %r12d, -0x10(%rdx)
je 0x17a75
cmpl %ebp, -0x8(%rdx)
jne 0x17978
cmpl %r12d, -0x4(%rdx)
je 0x17a7b
cmpl %ebp, 0x4(%rdx)
jne 0x17987
cmpl %r12d, 0x8(%rdx)
je 0x17a85
cmpl %ebp, 0x10(%rdx)
jne 0x17996
cmpl %r12d, 0x14(%rdx)
je 0x17a81
decq %r8
addq $0x30, %rdx
cmpq $0x1, %r8
jg 0x1795a
movq %rax, %r9
subq %rcx, %r9
jmp 0x179ae
movq %rdx, %rcx
sarq $0x2, %r9
imulq %rsi, %r9
cmpq $0x1, %r9
je 0x179ea
cmpq $0x2, %r9
je 0x179db
cmpq $0x3, %r9
jne 0x17a8e
cmpl %ebp, 0x4(%rcx)
jne 0x179d7
cmpl %r12d, 0x8(%rcx)
je 0x179fb
addq $0xc, %rcx
cmpl %ebp, 0x4(%rcx)
jne 0x179e6
cmpl %r12d, 0x8(%rcx)
je 0x179fb
addq $0xc, %rcx
movl 0x4(%rcx), %edx
xorl %ebp, %edx
movl 0x8(%rcx), %esi
xorl %r12d, %esi
orl %edx, %esi
cmovneq %rax, %rcx
movq %rcx, %rdx
jmp 0x17a85
movl (%r15), %esi
movl %esi, 0x10(%rsp)
movq 0x8(%r14), %rdi
callq 0xa3ea
movl 0xc(%rax), %ecx
movl 0x8c(%rax), %eax
movl %ecx, %edx
xorl $0xd, %edx
xorl $0x1, %eax
orl %edx, %eax
sete %al
cmpl $0xf, %ecx
je 0x17a36
testb %al, %al
je 0x17d32
movl 0x4(%r15), %ebx
movl 0x8(%r15), %ebp
movq 0x8(%r14), %rdi
leaq 0x4(%rsp), %r8
movb $0x1, (%r8)
leaq 0x9ce5d(%rip), %rdx     # 0xb48af
leaq 0x10(%rsp), %rcx
movl %ebx, %esi
callq 0x1bc1c
movq 0x8(%r14), %rdi
movl %ebx, %esi
movl %ebp, %edx
movl $0x1, %ecx
callq 0x12cf8
jmp 0x17d32
addq $-0x18, %rdx
jmp 0x17a85
addq $-0xc, %rdx
jmp 0x17a85
addq $0xc, %rdx
cmpq %rax, %rdx
jne 0x17d2f
testb %r13b, %r13b
je 0x17b6d
addq $0x8, %rdi
movl $0x1, %esi
callq 0x24f8a
movq 0x8(%r14), %rdi
movl %eax, 0x8(%rsp)
movl %eax, %esi
callq 0x1bafc
movq %rax, %r13
movq 0x8(%r14), %rbx
movl 0x8(%r15), %esi
movq %rbx, %rdi
callq 0x130d0
movq %rbx, %rdi
movl %eax, %esi
callq 0x1b382
movq %rax, %r15
movl 0x8(%rax), %eax
movl %eax, 0x8(%r13)
movups 0xc(%r15), %xmm0
movups %xmm0, 0xc(%r13)
leaq 0x20(%r13), %rdi
leaq 0x20(%r15), %rsi
callq 0x1bc64
leaq 0x38(%r13), %rdi
leaq 0x38(%r15), %rsi
callq 0x1bd48
movq 0x60(%r15), %rax
movq %rax, 0x60(%r13)
leaq 0x68(%r13), %rdi
leaq 0x68(%r15), %rsi
callq 0x1bc64
movups 0x80(%r15), %xmm0
movups 0x90(%r15), %xmm1
movups %xmm0, 0x80(%r13)
movups %xmm1, 0x90(%r13)
cmpq %r13, %r15
je 0x17b4f
movl $0xa0, %eax
movq %r13, %rdi
addq %rax, %rdi
addq %rax, %r15
movq %r15, %rsi
callq 0xd596
movl 0x8(%rsp), %ebx
movl %ebx, 0x8(%r13)
movl $0xe, 0xc(%r13)
movb $0x0, 0x88(%r13)
movl %ebp, 0xc(%rsp)
jmp 0x17b75
movl (%r15), %ebx
movl %r12d, 0xc(%rsp)
movq 0x8(%r14), %rdi
addq $0x8, %rdi
movl $0x2, %esi
callq 0x24f8a
movl %eax, 0x4(%rsp)
leal 0x1(%rax), %r15d
movq 0x8(%r14), %rdi
movl %eax, %esi
callq 0x1bafc
movq %rax, %r13
movq 0x8(%r14), %rdi
movl %ebx, %esi
callq 0xa3ea
movq %rax, %rbx
movl 0x8(%rax), %eax
movl %eax, 0x8(%r13)
movups 0xc(%rbx), %xmm0
movups %xmm0, 0xc(%r13)
leaq 0x20(%r13), %rdi
leaq 0x20(%rbx), %rsi
movq %rdi, 0x38(%rsp)
callq 0x1bc64
leaq 0x38(%r13), %rdi
leaq 0x38(%rbx), %rsi
movq %rdi, 0x30(%rsp)
callq 0x1bd48
movq 0x60(%rbx), %rax
movq %rax, 0x60(%r13)
leaq 0x68(%r13), %rdi
leaq 0x68(%rbx), %rsi
callq 0x1bc64
movups 0x80(%rbx), %xmm0
movups 0x90(%rbx), %xmm1
movups %xmm0, 0x80(%r13)
movups %xmm1, 0x90(%r13)
cmpq %r13, %rbx
je 0x17c2d
movl $0xa0, %eax
movq %r13, %rdi
addq %rax, %rdi
addq %rax, %rbx
movq %rbx, %rsi
callq 0xd596
movb $0x1, 0x60(%r13)
xorl %eax, %eax
movl %eax, 0x64(%r13)
movq 0x8(%r14), %rdi
leaq 0x10(%rsp), %rcx
movl %eax, (%rcx)
leaq 0x44(%rsp), %r8
movl %eax, (%r8)
leaq 0x4(%rsp), %rdx
movl %r15d, %esi
callq 0x1bb38
movq 0x8(%r14), %rax
movl %r15d, 0x8(%rsp)
movl %r15d, %ecx
movq 0x38(%rax), %rbx
imulq $0x148, %rcx, %r13      # imm = 0x148
movl 0xc(%rsp), %eax
imulq $0x148, %rax, %r15      # imm = 0x148
leaq (%rbx,%r13), %rdi
addq $0x68, %rdi
movq $0x0, -0x8(%rdi)
callq 0xd500
testb $0x1, 0x60(%rbx,%r15)
je 0x17ca2
leaq (%rbx,%r13), %rax
addq $0x60, %rax
orb $0x1, (%rax)
movq 0x8(%r14), %rdi
movl %ebp, %esi
callq 0x12c9a
testq %rax, %rax
je 0x17ce0
movq 0x8(%r14), %rdi
movl 0xc(%rax), %esi
callq 0xa3ea
movq %rax, %rbx
leaq 0x20(%rax), %rsi
movq 0x38(%rsp), %rdi
callq 0x1bc64
addq $0x38, %rbx
movq 0x30(%rsp), %rdi
movq %rbx, %rsi
callq 0x1bd48
movq 0x8(%r14), %rdi
movl 0x8(%rsp), %eax
movl %eax, 0x10(%rsp)
movl %ebp, 0x14(%rsp)
movl %r12d, 0x18(%rsp)
movq 0x1e0(%rdi), %rsi
cmpq 0x1e8(%rdi), %rsi
je 0x17d1e
movl 0x18(%rsp), %eax
movl %eax, 0x8(%rsi)
movq 0x10(%rsp), %rax
movq %rax, (%rsi)
addq $0xc, 0x1e0(%rdi)
jmp 0x17d2f
addq $0x1d8, %rdi            # imm = 0x1D8
leaq 0x10(%rsp), %rdx
callq 0x22e16
movb $0x1, %r12b
movl %r12d, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x10, %edi
callq 0x6140
movq %rax, %rbx
leaq 0x20(%rsp), %r15
movq %r15, -0x10(%r15)
leaq 0x9d201(%rip), %rsi     # 0xb4f62
leaq 0x9d26b(%rip), %rdx     # 0xb4fd3
leaq 0x10(%rsp), %rdi
callq 0x7be0
movb $0x1, %bpl
leaq 0x10(%rsp), %rsi
movq %rbx, %rdi
callq 0x6320
leaq 0xe403f(%rip), %rax     # 0xfbdc8
addq $0x10, %rax
movq %rax, (%rbx)
xorl %ebp, %ebp
leaq 0xe4017(%rip), %rsi     # 0xfbdb0
movq 0xe5238(%rip), %rdx     # 0xfcfd8
movq %rbx, %rdi
callq 0x6470
jmp 0x17dac
jmp 0x17dcd
movq %rax, %r14
movq 0x10(%rsp), %rdi
cmpq %r15, %rdi
je 0x17dc6
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x6260
testb %bpl, %bpl
jne 0x17dd0
jmp 0x17dd8
movq %rax, %r14
movq %rbx, %rdi
callq 0x6200
movq %r14, %rdi
callq 0x64a0