// File: rossy[P]crossc/SPIRV-Cross/spirv_cross.cpp
// Function: spirv_cross::Compiler::InterfaceVariableAccessHandler::handle(spv::Op, unsigned int const*, unsigned int)
bool Compiler::InterfaceVariableAccessHandler::handle(Op opcode, const uint32_t *args, uint32_t length)
{
	uint32_t variable = 0;
	switch (opcode)
	{
	// Need this first, otherwise, GCC complains about unhandled switch statements.
	default:
		break;

	case OpFunctionCall:
	{
		// Invalid SPIR-V.
		if (length < 3)
			return false;

		uint32_t count = length - 3;
		args += 3;
		for (uint32_t i = 0; i < count; i++)
		{
			auto *var = compiler.maybe_get<SPIRVariable>(args[i]);
			if (var && storage_class_is_interface(var->storage))
				variables.insert(args[i]);
		}
		break;
	}

	case OpAtomicStore:
	case OpStore:
		// Invalid SPIR-V.
		if (length < 1)
			return false;
		variable = args[0];
		break;

	case OpCopyMemory:
	{
		if (length < 2)
			return false;

		auto *var = compiler.maybe_get<SPIRVariable>(args[0]);
		if (var && storage_class_is_interface(var->storage))
			variables.insert(variable);

		var = compiler.maybe_get<SPIRVariable>(args[1]);
		if (var && storage_class_is_interface(var->storage))
			variables.insert(variable);
		break;
	}

	case OpExtInst:
	{
		if (length < 5)
			return false;
		uint32_t extension_set = args[2];
		if (compiler.get<SPIRExtension>(extension_set).ext == SPIRExtension::SPV_AMD_shader_explicit_vertex_parameter)
		{
			enum AMDShaderExplicitVertexParameter
			{
				InterpolateAtVertexAMD = 1
			};

			auto op = static_cast<AMDShaderExplicitVertexParameter>(args[3]);

			switch (op)
			{
			case InterpolateAtVertexAMD:
			{
				auto *var = compiler.maybe_get<SPIRVariable>(args[4]);
				if (var && storage_class_is_interface(var->storage))
					variables.insert(args[4]);
				break;
			}

			default:
				break;
			}
		}
		break;
	}

	case OpAccessChain:
	case OpInBoundsAccessChain:
	case OpLoad:
	case OpCopyObject:
	case OpImageTexelPointer:
	case OpAtomicLoad:
	case OpAtomicExchange:
	case OpAtomicCompareExchange:
	case OpAtomicCompareExchangeWeak:
	case OpAtomicIIncrement:
	case OpAtomicIDecrement:
	case OpAtomicIAdd:
	case OpAtomicISub:
	case OpAtomicSMin:
	case OpAtomicUMin:
	case OpAtomicSMax:
	case OpAtomicUMax:
	case OpAtomicAnd:
	case OpAtomicOr:
	case OpAtomicXor:
		// Invalid SPIR-V.
		if (length < 3)
			return false;
		variable = args[2];
		break;
	}

	if (variable)
	{
		auto *var = compiler.maybe_get<SPIRVariable>(variable);
		if (var && storage_class_is_interface(var->storage))
			variables.insert(variable);
	}
	return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq %rdx, -0x20(%rbp)
movl %ecx, -0x24(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xb8(%rbp)
movl $0x0, -0x28(%rbp)
movl -0x14(%rbp), %eax
addl $-0xc, %eax
movl %eax, %ecx
movq %rcx, -0xb0(%rbp)
subl $0xe6, %eax
ja 0x21768
movq -0xb0(%rbp), %rax
leaq 0x11d459(%rip), %rcx    # 0x13ebb8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
jmp 0x21999
cmpl $0x3, -0x24(%rbp)
jae 0x2177c
movb $0x0, -0x1(%rbp)
jmp 0x219ff
movl -0x24(%rbp), %eax
subl $0x3, %eax
movl %eax, -0x2c(%rbp)
movq -0x20(%rbp), %rax
addq $0xc, %rax
movq %rax, -0x20(%rbp)
movl $0x0, -0x30(%rbp)
movl -0x30(%rbp), %eax
cmpl -0x2c(%rbp), %eax
jae 0x21809
movq -0xb8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x20(%rbp), %rax
movl -0x30(%rbp), %ecx
movl (%rax,%rcx,4), %esi
callq 0x2ecf0
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0x217fc
movq -0x38(%rbp), %rax
movl 0x10(%rax), %edi
callq 0x20680
testb $0x1, %al
jne 0x217d7
jmp 0x217fc
movq -0xb8(%rbp), %rax
movq 0x10(%rax), %rdi
movq -0x20(%rbp), %rsi
movl -0x30(%rbp), %eax
shlq $0x2, %rax
addq %rax, %rsi
callq 0x2e890
movq %rax, -0x48(%rbp)
movb %dl, -0x40(%rbp)
jmp 0x217fe
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x21798
jmp 0x21999
cmpl $0x1, -0x24(%rbp)
jae 0x2181d
movb $0x0, -0x1(%rbp)
jmp 0x219ff
movq -0x20(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x28(%rbp)
jmp 0x21999
cmpl $0x2, -0x24(%rbp)
jae 0x2183a
movb $0x0, -0x1(%rbp)
jmp 0x219ff
movq -0xb8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x20(%rbp), %rax
movl (%rax), %esi
callq 0x2ecf0
movq %rax, -0x50(%rbp)
cmpq $0x0, -0x50(%rbp)
je 0x21888
movq -0x50(%rbp), %rax
movl 0x10(%rax), %edi
callq 0x20680
testb $0x1, %al
jne 0x2186d
jmp 0x21888
movq -0xb8(%rbp), %rax
movq 0x10(%rax), %rdi
leaq -0x28(%rbp), %rsi
callq 0x2e890
movq %rax, -0x60(%rbp)
movb %dl, -0x58(%rbp)
movq -0xb8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x20(%rbp), %rax
movl 0x4(%rax), %esi
callq 0x2ecf0
movq %rax, -0x50(%rbp)
cmpq $0x0, -0x50(%rbp)
je 0x218d7
movq -0x50(%rbp), %rax
movl 0x10(%rax), %edi
callq 0x20680
testb $0x1, %al
jne 0x218bc
jmp 0x218d7
movq -0xb8(%rbp), %rax
movq 0x10(%rax), %rdi
leaq -0x28(%rbp), %rsi
callq 0x2e890
movq %rax, -0x70(%rbp)
movb %dl, -0x68(%rbp)
jmp 0x21999
cmpl $0x5, -0x24(%rbp)
jae 0x218eb
movb $0x0, -0x1(%rbp)
jmp 0x219ff
movq -0xb8(%rbp), %rax
movq -0x20(%rbp), %rcx
movl 0x8(%rcx), %ecx
movl %ecx, -0x74(%rbp)
movq 0x8(%rax), %rdi
movl -0x74(%rbp), %esi
callq 0x2ed50
cmpl $0x3, 0xc(%rax)
jne 0x21981
movq -0x20(%rbp), %rax
movl 0xc(%rax), %eax
movl %eax, -0x78(%rbp)
movl -0x78(%rbp), %eax
subl $0x1, %eax
jne 0x2197d
jmp 0x21922
movq -0xb8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x20(%rbp), %rax
movl 0x10(%rax), %esi
callq 0x2ecf0
movq %rax, -0x80(%rbp)
cmpq $0x0, -0x80(%rbp)
je 0x2197b
movq -0x80(%rbp), %rax
movl 0x10(%rax), %edi
callq 0x20680
testb $0x1, %al
jne 0x21956
jmp 0x2197b
movq -0xb8(%rbp), %rax
movq 0x10(%rax), %rdi
movq -0x20(%rbp), %rsi
addq $0x10, %rsi
callq 0x2e890
movq %rax, -0x90(%rbp)
movb %dl, -0x88(%rbp)
jmp 0x2197f
jmp 0x2197f
jmp 0x21981
jmp 0x21999
cmpl $0x3, -0x24(%rbp)
jae 0x2198f
movb $0x0, -0x1(%rbp)
jmp 0x219ff
movq -0x20(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x28(%rbp)
cmpl $0x0, -0x28(%rbp)
je 0x219fb
movq -0xb8(%rbp), %rax
movq 0x8(%rax), %rdi
movl -0x28(%rbp), %esi
callq 0x2ecf0
movq %rax, -0x98(%rbp)
cmpq $0x0, -0x98(%rbp)
je 0x219f9
movq -0x98(%rbp), %rax
movl 0x10(%rax), %edi
callq 0x20680
testb $0x1, %al
jne 0x219d8
jmp 0x219f9
movq -0xb8(%rbp), %rax
movq 0x10(%rax), %rdi
leaq -0x28(%rbp), %rsi
callq 0x2e890
movq %rax, -0xa8(%rbp)
movb %dl, -0xa0(%rbp)
jmp 0x219fb
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0xc0, %rsp
popq %rbp
retq
nopl (%rax)