// File: rossy[P]crossc/SPIRV-Cross/spirv_glsl.cpp
// Function: spirv_cross::CompilerGLSL::emit_texture_op(spirv_cross::Instruction const&)
void CompilerGLSL::emit_texture_op(const Instruction &i)
{
	auto *ops = stream(i);
	auto op = static_cast<Op>(i.op);
	uint32_t length = i.length;

	vector<uint32_t> inherited_expressions;

	uint32_t result_type = ops[0];
	uint32_t id = ops[1];
	uint32_t img = ops[2];
	uint32_t coord = ops[3];
	uint32_t dref = 0;
	uint32_t comp = 0;
	bool gather = false;
	bool proj = false;
	bool fetch = false;
	const uint32_t *opt = nullptr;

	inherited_expressions.push_back(coord);

	switch (op)
	{
	case OpImageSampleDrefImplicitLod:
	case OpImageSampleDrefExplicitLod:
		dref = ops[4];
		opt = &ops[5];
		length -= 5;
		break;

	case OpImageSampleProjDrefImplicitLod:
	case OpImageSampleProjDrefExplicitLod:
		dref = ops[4];
		opt = &ops[5];
		length -= 5;
		proj = true;
		break;

	case OpImageDrefGather:
		dref = ops[4];
		opt = &ops[5];
		length -= 5;
		gather = true;
		break;

	case OpImageGather:
		comp = ops[4];
		opt = &ops[5];
		length -= 5;
		gather = true;
		break;

	case OpImageFetch:
	case OpImageRead: // Reads == fetches in Metal (other langs will not get here)
		opt = &ops[4];
		length -= 4;
		fetch = true;
		break;

	case OpImageSampleProjImplicitLod:
	case OpImageSampleProjExplicitLod:
		opt = &ops[4];
		length -= 4;
		proj = true;
		break;

	default:
		opt = &ops[4];
		length -= 4;
		break;
	}

	// Bypass pointers because we need the real image struct
	auto &type = expression_type(img);
	auto &imgtype = get<SPIRType>(type.self);

	uint32_t coord_components = 0;
	switch (imgtype.image.dim)
	{
	case spv::Dim1D:
		coord_components = 1;
		break;
	case spv::Dim2D:
		coord_components = 2;
		break;
	case spv::Dim3D:
		coord_components = 3;
		break;
	case spv::DimCube:
		coord_components = 3;
		break;
	case spv::DimBuffer:
		coord_components = 1;
		break;
	default:
		coord_components = 2;
		break;
	}

	if (dref)
		inherited_expressions.push_back(dref);

	if (proj)
		coord_components++;
	if (imgtype.image.arrayed)
		coord_components++;

	uint32_t bias = 0;
	uint32_t lod = 0;
	uint32_t grad_x = 0;
	uint32_t grad_y = 0;
	uint32_t coffset = 0;
	uint32_t offset = 0;
	uint32_t coffsets = 0;
	uint32_t sample = 0;
	uint32_t flags = 0;

	if (length)
	{
		flags = *opt++;
		length--;
	}

	auto test = [&](uint32_t &v, uint32_t flag) {
		if (length && (flags & flag))
		{
			v = *opt++;
			inherited_expressions.push_back(v);
			length--;
		}
	};

	test(bias, ImageOperandsBiasMask);
	test(lod, ImageOperandsLodMask);
	test(grad_x, ImageOperandsGradMask);
	test(grad_y, ImageOperandsGradMask);
	test(coffset, ImageOperandsConstOffsetMask);
	test(offset, ImageOperandsOffsetMask);
	test(coffsets, ImageOperandsConstOffsetsMask);
	test(sample, ImageOperandsSampleMask);

	string expr;
	bool forward = false;
	expr += to_function_name(img, imgtype, !!fetch, !!gather, !!proj, !!coffsets, (!!coffset || !!offset),
	                         (!!grad_x || !!grad_y), !!dref, lod);
	expr += "(";
	expr += to_function_args(img, imgtype, fetch, gather, proj, coord, coord_components, dref, grad_x, grad_y, lod,
	                         coffset, offset, bias, comp, sample, &forward);
	expr += ")";

	// texture(samplerXShadow) returns float. shadowX() returns vec4. Swizzle here.
	if (is_legacy() && image_is_comparison(imgtype, img))
		expr += ".r";

	emit_op(result_type, id, expr, forward);
	for (auto &inherit : inherited_expressions)
		inherit_expression_dependencies(id, inherit);

	switch (op)
	{
	case OpImageSampleDrefImplicitLod:
	case OpImageSampleImplicitLod:
	case OpImageSampleProjImplicitLod:
	case OpImageSampleProjDrefImplicitLod:
		register_control_dependent_expression(id);
		break;

	default:
		break;
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x228, %rsp            # imm = 0x228
movq %rdi, -0x30(%rbp)
movq %rsi, -0x38(%rbp)
movq -0x30(%rbp), %rdi
movq %rdi, -0x188(%rbp)
movq -0x38(%rbp), %rsi
callq 0x2e560
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rax
movzwl (%rax), %eax
movl %eax, -0x44(%rbp)
movq -0x38(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x48(%rbp)
leaq -0x60(%rbp), %rdi
movq %rdi, -0x180(%rbp)
callq 0x8210
movq -0x180(%rbp), %rdi
movq -0x40(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x64(%rbp)
movq -0x40(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x68(%rbp)
movq -0x40(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x6c(%rbp)
movq -0x40(%rbp), %rax
movl 0xc(%rax), %eax
movl %eax, -0x70(%rbp)
movl $0x0, -0x74(%rbp)
movl $0x0, -0x78(%rbp)
movb $0x0, -0x79(%rbp)
movb $0x0, -0x7a(%rbp)
movb $0x0, -0x7b(%rbp)
movq $0x0, -0x88(%rbp)
leaq -0x70(%rbp), %rsi
callq 0x88f0
jmp 0x7bca6
movl -0x44(%rbp), %eax
addl $-0x59, %eax
movl %eax, %ecx
movq %rcx, -0x190(%rbp)
subl $0x9, %eax
ja 0x7bdca
movq -0x190(%rbp), %rax
leaq 0xc4814(%rip), %rcx     # 0x1404e0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x7c551
movq -0x40(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0x74(%rbp)
movq -0x40(%rbp), %rax
addq $0x14, %rax
movq %rax, -0x88(%rbp)
movl -0x48(%rbp), %eax
subl $0x5, %eax
movl %eax, -0x48(%rbp)
jmp 0x7bde2
movq -0x40(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0x74(%rbp)
movq -0x40(%rbp), %rax
addq $0x14, %rax
movq %rax, -0x88(%rbp)
movl -0x48(%rbp), %eax
subl $0x5, %eax
movl %eax, -0x48(%rbp)
movb $0x1, -0x7a(%rbp)
jmp 0x7bde2
movq -0x40(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0x74(%rbp)
movq -0x40(%rbp), %rax
addq $0x14, %rax
movq %rax, -0x88(%rbp)
movl -0x48(%rbp), %eax
subl $0x5, %eax
movl %eax, -0x48(%rbp)
movb $0x1, -0x79(%rbp)
jmp 0x7bde2
movq -0x40(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0x78(%rbp)
movq -0x40(%rbp), %rax
addq $0x14, %rax
movq %rax, -0x88(%rbp)
movl -0x48(%rbp), %eax
subl $0x5, %eax
movl %eax, -0x48(%rbp)
movb $0x1, -0x79(%rbp)
jmp 0x7bde2
movq -0x40(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x88(%rbp)
movl -0x48(%rbp), %eax
subl $0x4, %eax
movl %eax, -0x48(%rbp)
movb $0x1, -0x7b(%rbp)
jmp 0x7bde2
movq -0x40(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x88(%rbp)
movl -0x48(%rbp), %eax
subl $0x4, %eax
movl %eax, -0x48(%rbp)
movb $0x1, -0x7a(%rbp)
jmp 0x7bde2
movq -0x40(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x88(%rbp)
movl -0x48(%rbp), %eax
subl $0x4, %eax
movl %eax, -0x48(%rbp)
movq -0x188(%rbp), %rdi
movl -0x6c(%rbp), %esi
callq 0x1f760
movq %rax, -0x198(%rbp)
jmp 0x7bdfa
movq -0x188(%rbp), %rdi
movq -0x198(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0xa0(%rbp), %rax
movl 0x8(%rax), %esi
callq 0xea90
movq %rax, -0x1a0(%rbp)
jmp 0x7be27
movq -0x1a0(%rbp), %rax
movq %rax, -0xa8(%rbp)
movl $0x0, -0xac(%rbp)
movq -0xa8(%rbp), %rax
movl 0x84(%rax), %eax
movq %rax, -0x1a8(%rbp)
subq $0x5, %rax
ja 0x7beac
movq -0x1a8(%rbp), %rax
leaq 0xc46a1(%rip), %rcx     # 0x140508
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x1, -0xac(%rbp)
jmp 0x7beb6
movl $0x2, -0xac(%rbp)
jmp 0x7beb6
movl $0x3, -0xac(%rbp)
jmp 0x7beb6
movl $0x3, -0xac(%rbp)
jmp 0x7beb6
movl $0x1, -0xac(%rbp)
jmp 0x7beb6
movl $0x2, -0xac(%rbp)
cmpl $0x0, -0x74(%rbp)
je 0x7becd
leaq -0x60(%rbp), %rdi
leaq -0x74(%rbp), %rsi
callq 0x88f0
jmp 0x7becb
jmp 0x7becd
testb $0x1, -0x7a(%rbp)
je 0x7bee2
movl -0xac(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xac(%rbp)
movq -0xa8(%rbp), %rax
testb $0x1, 0x89(%rax)
je 0x7bf01
movl -0xac(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xac(%rbp)
movl $0x0, -0xb0(%rbp)
movl $0x0, -0xb4(%rbp)
movl $0x0, -0xb8(%rbp)
movl $0x0, -0xbc(%rbp)
movl $0x0, -0xc0(%rbp)
movl $0x0, -0xc4(%rbp)
movl $0x0, -0xc8(%rbp)
movl $0x0, -0xcc(%rbp)
movl $0x0, -0xd0(%rbp)
cmpl $0x0, -0x48(%rbp)
je 0x7bf87
movq -0x88(%rbp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, -0x88(%rbp)
movl (%rax), %eax
movl %eax, -0xd0(%rbp)
movl -0x48(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x48(%rbp)
leaq -0x48(%rbp), %rax
movq %rax, -0xf0(%rbp)
leaq -0xd0(%rbp), %rax
movq %rax, -0xe8(%rbp)
leaq -0x88(%rbp), %rax
movq %rax, -0xe0(%rbp)
leaq -0x60(%rbp), %rax
movq %rax, -0xd8(%rbp)
leaq -0xf0(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
movl $0x1, %edx
callq 0x7c570
jmp 0x7bfd3
leaq -0xf0(%rbp), %rdi
leaq -0xb4(%rbp), %rsi
movl $0x2, %edx
callq 0x7c570
jmp 0x7bfed
leaq -0xf0(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
movl $0x4, %edx
callq 0x7c570
jmp 0x7c007
leaq -0xf0(%rbp), %rdi
leaq -0xbc(%rbp), %rsi
movl $0x4, %edx
callq 0x7c570
jmp 0x7c021
leaq -0xf0(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
movl $0x8, %edx
callq 0x7c570
jmp 0x7c03b
leaq -0xf0(%rbp), %rdi
leaq -0xc4(%rbp), %rsi
movl $0x10, %edx
callq 0x7c570
jmp 0x7c055
leaq -0xf0(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
movl $0x20, %edx
callq 0x7c570
jmp 0x7c06f
leaq -0xf0(%rbp), %rdi
leaq -0xcc(%rbp), %rsi
movl $0x40, %edx
callq 0x7c570
jmp 0x7c089
leaq -0x110(%rbp), %rdi
callq 0x7530
movb $0x0, -0x111(%rbp)
movl -0x6c(%rbp), %eax
movl %eax, -0x1bc(%rbp)
movq -0xa8(%rbp), %rax
movq %rax, -0x1b8(%rbp)
movb -0x7b(%rbp), %al
xorb $-0x1, %al
xorb $-0x1, %al
movb %al, -0x1ad(%rbp)
movb -0x79(%rbp), %al
xorb $-0x1, %al
xorb $-0x1, %al
movb %al, -0x1ac(%rbp)
movb -0x7a(%rbp), %al
xorb $-0x1, %al
xorb $-0x1, %al
movb %al, -0x1ab(%rbp)
cmpl $0x0, -0xc8(%rbp)
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
movb %al, -0x1aa(%rbp)
movb $0x1, %al
cmpl $0x0, -0xc0(%rbp)
movb %al, -0x1a9(%rbp)
jne 0x7c113
cmpl $0x0, -0xc4(%rbp)
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
movb %al, -0x1a9(%rbp)
movb -0x1a9(%rbp), %al
movb %al, -0x1be(%rbp)
movb $0x1, %al
cmpl $0x0, -0xb8(%rbp)
movb %al, -0x1bd(%rbp)
jne 0x7c144
cmpl $0x0, -0xbc(%rbp)
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
movb %al, -0x1bd(%rbp)
movq -0x1b8(%rbp), %rcx
movl -0x1bc(%rbp), %edx
movq -0x188(%rbp), %rsi
movb -0x1ac(%rbp), %dil
movb -0x1ad(%rbp), %r8b
movb -0x1ab(%rbp), %r10b
movb -0x1aa(%rbp), %r11b
movb -0x1be(%rbp), %bl
movb -0x1bd(%rbp), %r14b
movl -0x74(%rbp), %eax
testl %eax, %eax
setne %r15b
movl -0xb4(%rbp), %r12d
movq (%rsi), %rax
movq 0xd8(%rax), %rax
movq %rsp, %r9
movl %r12d, 0x28(%r9)
movzbl %r15b, %r15d
movl %r15d, 0x20(%r9)
movzbl %r14b, %r14d
andl $0x1, %r14d
movl %r14d, 0x18(%r9)
movzbl %bl, %ebx
andl $0x1, %ebx
movl %ebx, 0x10(%r9)
movzbl %r11b, %r11d
andl $0x1, %r11d
movl %r11d, 0x8(%r9)
movzbl %r10b, %r10d
andl $0x1, %r10d
movl %r10d, (%r9)
movzbl %r8b, %r8d
andl $0x1, %r8d
movzbl %dil, %r9d
andl $0x1, %r9d
leaq -0x138(%rbp), %rdi
callq *%rax
jmp 0x7c1f2
leaq -0x110(%rbp), %rdi
leaq -0x138(%rbp), %rsi
callq 0x7470
jmp 0x7c207
leaq -0x138(%rbp), %rdi
callq 0x7708
leaq 0xd1113(%rip), %rsi     # 0x14d32d
leaq -0x110(%rbp), %rdi
callq 0x7340
jmp 0x7c228
movq -0x188(%rbp), %rax
movl -0x6c(%rbp), %edx
movq -0xa8(%rbp), %rcx
movl -0x70(%rbp), %r11d
movl -0xac(%rbp), %ebx
movl -0x74(%rbp), %r14d
movl -0xb8(%rbp), %r15d
movl -0xbc(%rbp), %r12d
movl -0xb4(%rbp), %r13d
movl -0xc0(%rbp), %esi
movl -0xc4(%rbp), %edi
movl %edi, -0x1cc(%rbp)
movl -0xb0(%rbp), %edi
movl %edi, -0x1d0(%rbp)
movl -0x78(%rbp), %edi
movl %edi, -0x1d4(%rbp)
movl -0xcc(%rbp), %edi
movl %edi, -0x1d8(%rbp)
movq (%rax), %rax
movq 0xe0(%rax), %rax
movq %rax, -0x1c8(%rbp)
movzbl -0x79(%rbp), %r9d
movzbl -0x7b(%rbp), %r8d
movzbl -0x7a(%rbp), %r10d
movq %rsp, %rdi
movq %rdi, -0x1e0(%rbp)
leaq -0x111(%rbp), %rax
movq %rax, 0x60(%rdi)
movl -0x1d8(%rbp), %eax
movl %eax, 0x58(%rdi)
movl -0x1d4(%rbp), %eax
movl %eax, 0x50(%rdi)
movl -0x1d0(%rbp), %eax
movl %eax, 0x48(%rdi)
movl -0x1cc(%rbp), %eax
movl %eax, 0x40(%rdi)
movq -0x1c8(%rbp), %rax
movl %esi, 0x38(%rdi)
movq -0x188(%rbp), %rsi
movl %r13d, 0x30(%rdi)
movl %r12d, 0x28(%rdi)
movl %r15d, 0x20(%rdi)
movl %r14d, 0x18(%rdi)
movl %ebx, 0x10(%rdi)
movl %r11d, 0x8(%rdi)
andl $0x1, %r10d
movl %r10d, (%rdi)
andl $0x1, %r8d
andl $0x1, %r9d
leaq -0x158(%rbp), %rdi
callq *%rax
jmp 0x7c32a
leaq -0x110(%rbp), %rdi
leaq -0x158(%rbp), %rsi
callq 0x7470
jmp 0x7c33f
leaq -0x158(%rbp), %rdi
callq 0x7708
leaq 0xc8ba7(%rip), %rsi     # 0x144ef9
leaq -0x110(%rbp), %rdi
callq 0x7340
jmp 0x7c360
movq -0x188(%rbp), %rdi
callq 0x9f610
movb %al, -0x1e1(%rbp)
jmp 0x7c374
movb -0x1e1(%rbp), %al
testb $0x1, %al
jne 0x7c383
jmp 0x7c421
movq -0x188(%rbp), %rdi
movq -0xa8(%rbp), %rsi
movl -0x6c(%rbp), %edx
callq 0x2c890
movb %al, -0x1e2(%rbp)
jmp 0x7c3a1
movb -0x1e2(%rbp), %al
testb $0x1, %al
jne 0x7c3ad
jmp 0x7c421
leaq 0xc665c(%rip), %rsi     # 0x142a10
leaq -0x110(%rbp), %rdi
callq 0x7340
jmp 0x7c3c2
jmp 0x7c421
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x7c545
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x138(%rbp), %rdi
callq 0x7708
jmp 0x7c545
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x158(%rbp), %rdi
callq 0x7708
jmp 0x7c545
movq -0x188(%rbp), %rdi
movl -0x64(%rbp), %esi
movl -0x68(%rbp), %edx
movzbl -0x111(%rbp), %r8d
andl $0x1, %r8d
leaq -0x110(%rbp), %rcx
xorl %r9d, %r9d
callq 0x784f0
jmp 0x7c44b
leaq -0x60(%rbp), %rax
movq %rax, -0x160(%rbp)
movq -0x160(%rbp), %rdi
callq 0x86d0
movq %rax, -0x168(%rbp)
movq -0x160(%rbp), %rdi
callq 0x8700
movq %rax, -0x170(%rbp)
leaq -0x168(%rbp), %rdi
leaq -0x170(%rbp), %rsi
callq 0x8730
testb $0x1, %al
jne 0x7c495
jmp 0x7c4d2
leaq -0x168(%rbp), %rdi
callq 0x8770
movq -0x188(%rbp), %rdi
movq %rax, -0x178(%rbp)
movl -0x68(%rbp), %esi
movq -0x178(%rbp), %rax
movl (%rax), %edx
callq 0x25500
jmp 0x7c4c2
jmp 0x7c4c4
leaq -0x168(%rbp), %rdi
callq 0x8790
jmp 0x7c47c
movl -0x44(%rbp), %eax
movl %eax, -0x1e8(%rbp)
subl $0x57, %eax
je 0x7c509
jmp 0x7c4e2
movl -0x1e8(%rbp), %eax
subl $0x59, %eax
je 0x7c509
jmp 0x7c4ef
movl -0x1e8(%rbp), %eax
subl $0x5b, %eax
je 0x7c509
jmp 0x7c4fc
movl -0x1e8(%rbp), %eax
subl $0x5d, %eax
jne 0x7c51c
jmp 0x7c509
movq -0x188(%rbp), %rdi
movl -0x68(%rbp), %esi
callq 0x7c5f0
jmp 0x7c51a
jmp 0x7c51e
jmp 0x7c51e
leaq -0x110(%rbp), %rdi
callq 0x7708
leaq -0x60(%rbp), %rdi
callq 0x8430
addq $0x228, %rsp            # imm = 0x228
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq -0x110(%rbp), %rdi
callq 0x7708
leaq -0x60(%rbp), %rdi
callq 0x8430
movq -0x90(%rbp), %rdi
callq 0x7640
nopw %cs:(%rax,%rax)