// File: /workspace/github_cpp_makefile_star2_O1/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 0x17d9b
movabsq $0x6c040000000, %rdx    # imm = 0x6C040000000
btq %rax, %rdx
jae 0x17c59
movq 0x8(%r14), %rdi
movl 0x8(%r15), %esi
callq 0x12cda
testq %rax, %rax
je 0x17cc5
movq 0x8(%r14), %rdi
movl 0xc(%rax), %esi
callq 0xa426
xorl %r13d, %r13d
cmpl $0xd, 0xc(%rax)
jne 0x17cc8
cmpl $0x1, 0x8c(%rax)
jne 0x17cc8
cmpl $0x5, 0x84(%rax)
je 0x17cc8
movq 0x8(%r14), %rax
movb $0x1, %r13b
cmpl $0x0, 0x39c(%rax)
jne 0x17cc8
movl $0x10, %edi
callq 0x6140
movq %rax, %rbx
leaq 0x20(%rsp), %r15
movq %r15, -0x10(%r15)
leaq 0x9e3ca(%rip), %rsi     # 0xb5fd7
leaq 0x9e43e(%rip), %rdx     # 0xb6052
leaq 0x10(%rsp), %rdi
callq 0x7c64
movb $0x1, %bpl
leaq 0x10(%rsp), %rsi
movq %rbx, %rdi
callq 0x6320
leaq 0xe5163(%rip), %rax     # 0xfcd98
addq $0x10, %rax
movq %rax, (%rbx)
xorl %ebp, %ebp
leaq 0xe513b(%rip), %rsi     # 0xfcd80
movq 0xe638c(%rip), %rdx     # 0xfdfd8
movq %rbx, %rdi
callq 0x6470
jmp 0x18254
movl $0x3, %edx
btq %rax, %rdx
jae 0x17cd2
cmpl $0x3, %ecx
jb 0x17dad
movl (%r15), %esi
movl %esi, 0x4(%rsp)
movq 0x8(%r14), %rdi
callq 0xa426
movl 0xc(%rax), %ecx
cmpl $0xf, %ecx
je 0x181f0
cmpl $0xd, %ecx
jne 0x181de
cmpl $0x1, 0x8c(%rax)
jne 0x181de
movl 0x4(%r15), %ebx
movl 0x8(%r15), %ebp
movq 0x8(%r14), %rdi
leaq 0x10(%rsp), %r8
movb $0x1, (%r8)
leaq 0x9dbf4(%rip), %rdx     # 0xb58af
leaq 0x4(%rsp), %rcx
jmp 0x17f0a
xorl %r13d, %r13d
testb %r13b, %r13b
jne 0x17cdf
jmp 0x181de
cmpq $0x15, %rax
jne 0x17d9b
xorl %r13d, %r13d
movq 0x90(%r14), %rax
cmpq 0x70(%r14), %rax
je 0x17d7b
cmpq 0x98(%r14), %rax
jne 0x17d09
movq 0xa8(%r14), %rcx
movl $0x200, %eax            # imm = 0x200
addq -0x8(%rcx), %rax
movq -0x8(%rax), %rbx
cmpb $0x1, 0xca(%rbx)
jne 0x17d7b
movl 0x8(%r15), %ebp
movq 0x8(%r14), %rdi
movl %ebp, %esi
callq 0x12cda
testq %rax, %rax
je 0x17d2d
movl 0x8(%rax), %ebp
movq 0x8(%r14), %rdi
leaq 0x39c(%rdi), %rax
leaq 0xc(%r15), %rcx
testb %r13b, %r13b
cmovneq %rax, %rcx
movl (%rcx), %r12d
movl %r12d, %esi
callq 0x12cda
testq %rax, %rax
je 0x17d57
movl 0x8(%rax), %r12d
movq 0x8(%r14), %rdi
movl (%r15), %esi
callq 0xa426
movzbl 0x88(%rax), %r8d
movq %r14, %rdi
movq %rbx, %rsi
movl %ebp, %edx
movl %r12d, %ecx
callq 0x17260
movl 0x8(%r15), %esi
movq %r14, %rdi
callq 0x16fb4
movl %eax, %ebp
testb %r13b, %r13b
je 0x17db5
movq 0x8(%r14), %rax
movl 0x39c(%rax), %r12d
jmp 0x17dc4
cmpl $0x3d, %esi
jne 0x181de
cmpl $0x3, %ecx
jae 0x17eb6
xorl %r12d, %r12d
jmp 0x181de
movl 0xc(%r15), %esi
movq %r14, %rdi
callq 0x16fb4
movl %eax, %r12d
movq 0x8(%r14), %rdi
movq 0x1d8(%rdi), %rcx
movq 0x1e0(%rdi), %rax
movq %rax, %r8
subq %rcx, %r8
sarq $0x2, %r8
movabsq $-0x5555555555555555, %rdx # imm = 0xAAAAAAAAAAAAAAAB
imulq %rdx, %r8
sarq $0x2, %r8
testq %r8, %r8
jle 0x17e58
leaq (%r8,%r8,2), %r9
shlq $0x4, %r9
addq %rcx, %r9
incq %r8
addq $0x18, %rcx
movq %rcx, %rsi
cmpl %ebp, -0x14(%rsi)
jne 0x17e1b
cmpl %r12d, -0x10(%rsi)
je 0x17f28
cmpl %ebp, -0x8(%rsi)
jne 0x17e2a
cmpl %r12d, -0x4(%rsi)
je 0x17f2e
cmpl %ebp, 0x4(%rsi)
jne 0x17e39
cmpl %r12d, 0x8(%rsi)
je 0x17f38
cmpl %ebp, 0x10(%rsi)
jne 0x17e48
cmpl %r12d, 0x14(%rsi)
je 0x17f34
decq %r8
addq $0x30, %rsi
cmpq $0x1, %r8
jg 0x17e0c
movq %r9, %rcx
movq %rax, %r8
subq %rcx, %r8
sarq $0x2, %r8
imulq %rdx, %r8
cmpq $0x1, %r8
je 0x17e9d
cmpq $0x2, %r8
je 0x17e8e
movq %rax, %rsi
cmpq $0x3, %r8
jne 0x17f38
cmpl %ebp, 0x4(%rcx)
jne 0x17e8a
cmpl %r12d, 0x8(%rcx)
je 0x17eae
addq $0xc, %rcx
cmpl %ebp, 0x4(%rcx)
jne 0x17e99
cmpl %r12d, 0x8(%rcx)
je 0x17eae
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, %rsi
jmp 0x17f38
movl (%r15), %esi
movl %esi, 0x10(%rsp)
movq 0x8(%r14), %rdi
callq 0xa426
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 0x17ee9
testb %al, %al
je 0x181de
movl 0x4(%r15), %ebx
movl 0x8(%r15), %ebp
movq 0x8(%r14), %rdi
leaq 0x4(%rsp), %r8
movb $0x1, (%r8)
leaq 0x9d9aa(%rip), %rdx     # 0xb58af
leaq 0x10(%rsp), %rcx
movl %ebx, %esi
callq 0x1c27a
movq 0x8(%r14), %rdi
movl %ebx, %esi
movl %ebp, %edx
movl $0x1, %ecx
callq 0x12d38
jmp 0x181de
addq $-0x18, %rsi
jmp 0x17f38
addq $-0xc, %rsi
jmp 0x17f38
addq $0xc, %rsi
cmpq %rax, %rsi
jne 0x181db
testb %r13b, %r13b
je 0x1801b
addq $0x8, %rdi
movl $0x1, %esi
callq 0x2561c
movq 0x8(%r14), %rdi
movl %eax, 0x8(%rsp)
movl %eax, %esi
callq 0x1c15a
movq %rax, %rbx
movq 0x8(%r14), %r13
movl 0x8(%r15), %esi
movq %r13, %rdi
callq 0x13116
movq %r13, %rdi
movl %eax, %esi
callq 0x1b9de
movq %rax, %r15
movl 0x8(%rax), %eax
movl %eax, 0x8(%rbx)
movups 0xc(%r15), %xmm0
movups %xmm0, 0xc(%rbx)
leaq 0x20(%rbx), %rdi
leaq 0x20(%r15), %rsi
callq 0x1c2c2
leaq 0x38(%rbx), %rdi
leaq 0x38(%r15), %rsi
callq 0x1c398
movq 0x60(%r15), %rax
movq %rax, 0x60(%rbx)
leaq 0x68(%rbx), %rdi
leaq 0x68(%r15), %rsi
callq 0x1c2c2
movups 0x80(%r15), %xmm0
movups 0x90(%r15), %xmm1
movups %xmm0, 0x80(%rbx)
movups %xmm1, 0x90(%rbx)
cmpq %rbx, %r15
je 0x17ffe
movl $0xa0, %eax
movq %rbx, %rdi
addq %rax, %rdi
addq %rax, %r15
movq %r15, %rsi
callq 0xd5d6
movl 0x8(%rsp), %r13d
movl %r13d, 0x8(%rbx)
movl $0xe, 0xc(%rbx)
movb $0x0, 0x88(%rbx)
movl %ebp, 0xc(%rsp)
jmp 0x18023
movl (%r15), %r13d
movl %r12d, 0xc(%rsp)
movq 0x8(%r14), %rdi
addq $0x8, %rdi
movl $0x2, %esi
callq 0x2561c
movl %eax, 0x4(%rsp)
leal 0x1(%rax), %r15d
movq 0x8(%r14), %rdi
movl %eax, %esi
callq 0x1c15a
movq %rax, %rbx
movq 0x8(%r14), %rdi
movl %r13d, %esi
callq 0xa426
movq %rax, %r13
movl 0x8(%rax), %eax
movl %eax, 0x8(%rbx)
movups 0xc(%r13), %xmm0
movups %xmm0, 0xc(%rbx)
leaq 0x20(%rbx), %rdi
leaq 0x20(%r13), %rsi
movq %rdi, 0x38(%rsp)
callq 0x1c2c2
leaq 0x38(%rbx), %rdi
leaq 0x38(%r13), %rsi
movq %rdi, 0x30(%rsp)
callq 0x1c398
movq 0x60(%r13), %rax
movq %rax, 0x60(%rbx)
leaq 0x68(%rbx), %rdi
leaq 0x68(%r13), %rsi
callq 0x1c2c2
movups 0x80(%r13), %xmm0
movups 0x90(%r13), %xmm1
movups %xmm0, 0x80(%rbx)
movups %xmm1, 0x90(%rbx)
cmpq %rbx, %r13
je 0x180db
movl $0xa0, %eax
movq %rbx, %rdi
addq %rax, %rdi
addq %rax, %r13
movq %r13, %rsi
callq 0xd5d6
movb $0x1, 0x60(%rbx)
xorl %eax, %eax
movl %eax, 0x64(%rbx)
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 0x1c196
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 0xd540
testb $0x1, 0x60(%rbx,%r15)
je 0x1814e
leaq (%rbx,%r13), %rax
addq $0x60, %rax
orb $0x1, (%rax)
movq 0x8(%r14), %rdi
movl %ebp, %esi
callq 0x12cda
testq %rax, %rax
je 0x1818c
movq 0x8(%r14), %rdi
movl 0xc(%rax), %esi
callq 0xa426
movq %rax, %rbx
leaq 0x20(%rax), %rsi
movq 0x38(%rsp), %rdi
callq 0x1c2c2
addq $0x38, %rbx
movq 0x30(%rsp), %rdi
movq %rbx, %rsi
callq 0x1c398
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 0x181ca
movl 0x18(%rsp), %eax
movl %eax, 0x8(%rsi)
movq 0x10(%rsp), %rax
movq %rax, (%rsi)
addq $0xc, 0x1e0(%rdi)
jmp 0x181db
addq $0x1d8, %rdi            # imm = 0x1D8
leaq 0x10(%rsp), %rdx
callq 0x234e0
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 0x9dd58(%rip), %rsi     # 0xb5f65
leaq 0x9ddc2(%rip), %rdx     # 0xb5fd6
leaq 0x10(%rsp), %rdi
callq 0x7c64
movb $0x1, %bpl
leaq 0x10(%rsp), %rsi
movq %rbx, %rdi
callq 0x6320
leaq 0xe4b63(%rip), %rax     # 0xfcd98
addq $0x10, %rax
movq %rax, (%rbx)
xorl %ebp, %ebp
leaq 0xe4b3b(%rip), %rsi     # 0xfcd80
movq 0xe5d8c(%rip), %rdx     # 0xfdfd8
movq %rbx, %rdi
callq 0x6470
jmp 0x18258
jmp 0x18274
movq %rax, %r14
movq 0x10(%rsp), %rdi
cmpq %r15, %rdi
je 0x1827a
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x6260
jmp 0x1827a
movq %rax, %r14
movb $0x1, %bpl
testb %bpl, %bpl
je 0x18287
movq %rbx, %rdi
callq 0x6200
movq %r14, %rdi
callq 0x64a0
nop