// File: rossy[P]crossc/SPIRV-Cross/spirv_msl.cpp
// Function: spirv_cross::CompilerMSL::OpCodePreprocessor::get_spv_func_impl(spv::Op, unsigned int const*)
CompilerMSL::SPVFuncImpl CompilerMSL::OpCodePreprocessor::get_spv_func_impl(Op opcode, const uint32_t *args)
{
	switch (opcode)
	{
	case OpFMod:
		return SPVFuncImplMod;

	case OpFunctionCall:
	{
		auto &return_type = compiler.get<SPIRType>(args[0]);
		if (return_type.array.size() > 1)
		{
			if (return_type.array.size() > SPVFuncImplArrayCopyMultidimMax)
				SPIRV_CROSS_THROW("Cannot support this many dimensions for arrays of arrays.");
			return static_cast<SPVFuncImpl>(SPVFuncImplArrayCopyMultidimBase + return_type.array.size());
		}
		else if (return_type.array.size() > 0)
			return SPVFuncImplArrayCopy;

		break;
	}

	case OpStore:
	{
		// Get the result type of the RHS. Since this is run as a pre-processing stage,
		// we must extract the result type directly from the Instruction, rather than the ID.
		uint32_t id_lhs = args[0];
		uint32_t id_rhs = args[1];

		const SPIRType *type = nullptr;
		if (compiler.ir.ids[id_rhs].get_type() != TypeNone)
		{
			// Could be a constant, or similar.
			type = &compiler.expression_type(id_rhs);
		}
		else
		{
			// Or ... an expression.
			uint32_t tid = result_types[id_rhs];
			if (tid)
				type = &compiler.get<SPIRType>(tid);
		}

		auto *var = compiler.maybe_get<SPIRVariable>(id_lhs);

		// Are we simply assigning to a statically assigned variable which takes a constant?
		// Don't bother emitting this function.
		bool static_expression_lhs =
		    var && var->storage == StorageClassFunction && var->statically_assigned && var->remapped_variable;
		if (type && compiler.is_array(*type) && !static_expression_lhs)
		{
			if (type->array.size() > 1)
			{
				if (type->array.size() > SPVFuncImplArrayCopyMultidimMax)
					SPIRV_CROSS_THROW("Cannot support this many dimensions for arrays of arrays.");
				return static_cast<SPVFuncImpl>(SPVFuncImplArrayCopyMultidimBase + type->array.size());
			}
			else
				return SPVFuncImplArrayCopy;
		}

		break;
	}

	case OpImageFetch:
	case OpImageRead:
	case OpImageWrite:
	{
		// Retrieve the image type, and if it's a Buffer, emit a texel coordinate function
		uint32_t tid = result_types[args[opcode == OpImageWrite ? 0 : 2]];
		if (tid && compiler.get<SPIRType>(tid).image.dim == DimBuffer)
			return SPVFuncImplTexelBufferCoords;

		if (opcode == OpImageFetch && compiler.msl_options.swizzle_texture_samples)
			return SPVFuncImplTextureSwizzle;

		break;
	}

	case OpImageSampleExplicitLod:
	case OpImageSampleProjExplicitLod:
	case OpImageSampleDrefExplicitLod:
	case OpImageSampleProjDrefExplicitLod:
	case OpImageSampleImplicitLod:
	case OpImageSampleProjImplicitLod:
	case OpImageSampleDrefImplicitLod:
	case OpImageSampleProjDrefImplicitLod:
	case OpImageGather:
	case OpImageDrefGather:
		if (compiler.msl_options.swizzle_texture_samples)
			return SPVFuncImplTextureSwizzle;
		break;

	case OpCompositeConstruct:
	{
		auto &type = compiler.get<SPIRType>(args[0]);
		if (type.array.size() > 1) // We need to use copies to build the composite.
			return static_cast<SPVFuncImpl>(SPVFuncImplArrayCopyMultidimBase + type.array.size() - 1);
		break;
	}

	case OpExtInst:
	{
		uint32_t extension_set = args[2];
		if (compiler.get<SPIRExtension>(extension_set).ext == SPIRExtension::GLSL)
		{
			GLSLstd450 op_450 = static_cast<GLSLstd450>(args[3]);
			switch (op_450)
			{
			case GLSLstd450Radians:
				return SPVFuncImplRadians;
			case GLSLstd450Degrees:
				return SPVFuncImplDegrees;
			case GLSLstd450FindILsb:
				return SPVFuncImplFindILsb;
			case GLSLstd450FindSMsb:
				return SPVFuncImplFindSMsb;
			case GLSLstd450FindUMsb:
				return SPVFuncImplFindUMsb;
			case GLSLstd450MatrixInverse:
			{
				auto &mat_type = compiler.get<SPIRType>(args[0]);
				switch (mat_type.columns)
				{
				case 2:
					return SPVFuncImplInverse2x2;
				case 3:
					return SPVFuncImplInverse3x3;
				case 4:
					return SPVFuncImplInverse4x4;
				default:
					break;
				}
				break;
			}
			default:
				break;
			}
		}
		break;
	}

	default:
		break;
	}
	return SPVFuncImplNone;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x110, %rsp            # imm = 0x110
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xd8(%rbp)
movl -0x14(%rbp), %eax
addl $-0xc, %eax
movl %eax, %ecx
movq %rcx, -0xd0(%rbp)
subl $0x81, %eax
ja 0x10e473
movq -0xd0(%rbp), %rax
leaq 0x3c51f(%rip), %rcx     # 0x14a398
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x1, -0x4(%rbp)
jmp 0x10e47c
movq -0xd8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x20(%rbp), %rax
movl (%rax), %esi
callq 0xea90
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rdi
addq $0x20, %rdi
callq 0x8650
cmpq $0x1, %rax
jbe 0x10dfa7
movq -0x28(%rbp), %rdi
addq $0x20, %rdi
callq 0x8650
cmpq $0x6, %rax
jbe 0x10df8e
movb $0x1, -0x5d(%rbp)
movl $0x10, %edi
callq 0x71a0
movq %rax, -0xe8(%rbp)
leaq -0x49(%rbp), %rdi
movq %rdi, -0xe0(%rbp)
callq 0x7650
movq -0xe0(%rbp), %rdx
leaq 0x3fbff(%rip), %rsi     # 0x14db08
leaq -0x48(%rbp), %rdi
callq 0x7520
jmp 0x10df14
movq -0xe8(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x9c50
jmp 0x10df26
movq -0xe8(%rbp), %rdi
movb $0x0, -0x5d(%rbp)
leaq 0x9fea0(%rip), %rsi     # 0x1addd8
leaq -0x1042af(%rip), %rdx   # 0x9c90
callq 0x7610
jmp 0x10e491
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x10df6c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x7708
leaq -0x49(%rbp), %rdi
callq 0x73d0
testb $0x1, -0x5d(%rbp)
jne 0x10df7d
jmp 0x10df89
movq -0xe8(%rbp), %rdi
callq 0x72c0
jmp 0x10e488
movq -0x28(%rbp), %rdi
addq $0x20, %rdi
callq 0x8650
addq $0x7, %rax
movl %eax, -0x4(%rbp)
jmp 0x10e47c
movq -0x28(%rbp), %rdi
addq $0x20, %rdi
callq 0x8650
cmpq $0x0, %rax
jbe 0x10dfc6
movl $0x8, -0x4(%rbp)
jmp 0x10e47c
jmp 0x10dfc8
jmp 0x10e475
movq -0xd8(%rbp), %rax
movq -0x20(%rbp), %rcx
movl (%rcx), %ecx
movl %ecx, -0x64(%rbp)
movq -0x20(%rbp), %rcx
movl 0x4(%rcx), %ecx
movl %ecx, -0x68(%rbp)
movq $0x0, -0x70(%rbp)
movq 0x8(%rax), %rdi
addq $0x8, %rdi
addq $0x18, %rdi
movl -0x68(%rbp), %eax
movl %eax, %esi
callq 0xbdb0
movq %rax, %rdi
callq 0xfa00
cmpl $0x0, %eax
je 0x10e02b
movq -0xd8(%rbp), %rax
movq 0x8(%rax), %rdi
movl -0x68(%rbp), %esi
callq 0x1f760
movq %rax, -0x70(%rbp)
jmp 0x10e063
movq -0xd8(%rbp), %rdi
addq $0x10, %rdi
leaq -0x68(%rbp), %rsi
callq 0x30850
movl (%rax), %eax
movl %eax, -0x74(%rbp)
cmpl $0x0, -0x74(%rbp)
je 0x10e061
movq -0xd8(%rbp), %rax
movq 0x8(%rax), %rdi
movl -0x74(%rbp), %esi
callq 0xea90
movq %rax, -0x70(%rbp)
jmp 0x10e063
movq -0xd8(%rbp), %rax
movq 0x8(%rax), %rdi
movl -0x64(%rbp), %esi
callq 0x116b0
movq %rax, -0x80(%rbp)
xorl %eax, %eax
cmpq $0x0, -0x80(%rbp)
movb %al, -0xe9(%rbp)
je 0x10e0ba
movq -0x80(%rbp), %rcx
xorl %eax, %eax
cmpl $0x7, 0x10(%rcx)
movb %al, -0xe9(%rbp)
jne 0x10e0ba
movq -0x80(%rbp), %rcx
xorl %eax, %eax
testb $0x1, 0x39(%rcx)
movb %al, -0xe9(%rbp)
je 0x10e0ba
movq -0x80(%rbp), %rax
movb 0x5b(%rax), %al
movb %al, -0xe9(%rbp)
movb -0xe9(%rbp), %al
andb $0x1, %al
movb %al, -0x81(%rbp)
cmpq $0x0, -0x70(%rbp)
je 0x10e220
movq -0xd8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x70(%rbp), %rsi
callq 0x208a0
testb $0x1, %al
jne 0x10e0f0
jmp 0x10e220
testb $0x1, -0x81(%rbp)
jne 0x10e220
movq -0x70(%rbp), %rdi
addq $0x20, %rdi
callq 0x8650
cmpq $0x1, %rax
jbe 0x10e214
movq -0x70(%rbp), %rdi
addq $0x20, %rdi
callq 0x8650
cmpq $0x6, %rax
jbe 0x10e1fb
movb $0x1, -0xaa(%rbp)
movl $0x10, %edi
callq 0x71a0
movq %rax, -0x100(%rbp)
leaq -0xa9(%rbp), %rdi
movq %rdi, -0xf8(%rbp)
callq 0x7650
movq -0xf8(%rbp), %rdx
leaq 0x3f9a4(%rip), %rsi     # 0x14db08
leaq -0xa8(%rbp), %rdi
callq 0x7520
jmp 0x10e172
movq -0x100(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x9c50
jmp 0x10e187
movq -0x100(%rbp), %rdi
movb $0x0, -0xaa(%rbp)
leaq 0x9fc3c(%rip), %rsi     # 0x1addd8
leaq -0x104513(%rip), %rdx   # 0x9c90
callq 0x7610
jmp 0x10e491
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0x10e1d3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x7708
leaq -0xa9(%rbp), %rdi
callq 0x73d0
testb $0x1, -0xaa(%rbp)
jne 0x10e1ea
jmp 0x10e1f6
movq -0x100(%rbp), %rdi
callq 0x72c0
jmp 0x10e488
movq -0x70(%rbp), %rdi
addq $0x20, %rdi
callq 0x8650
addq $0x7, %rax
movl %eax, -0x4(%rbp)
jmp 0x10e47c
movl $0x8, -0x4(%rbp)
jmp 0x10e47c
jmp 0x10e475
movq -0xd8(%rbp), %rdi
addq $0x10, %rdi
movq -0x20(%rbp), %rsi
movl -0x14(%rbp), %edx
movl $0x2, %eax
xorl %ecx, %ecx
cmpl $0x63, %edx
cmovel %ecx, %eax
cltq
shlq $0x2, %rax
addq %rax, %rsi
callq 0x30850
movl (%rax), %eax
movl %eax, -0xb0(%rbp)
cmpl $0x0, -0xb0(%rbp)
je 0x10e28e
movq -0xd8(%rbp), %rax
movq 0x8(%rax), %rdi
movl -0xb0(%rbp), %esi
callq 0xea90
cmpl $0x5, 0x84(%rax)
jne 0x10e28e
movl $0xe, -0x4(%rbp)
jmp 0x10e47c
cmpl $0x5f, -0x14(%rbp)
jne 0x10e2b4
movq -0xd8(%rbp), %rax
movq 0x8(%rax), %rax
testb $0x1, 0x7df(%rax)
je 0x10e2b4
movl $0x18, -0x4(%rbp)
jmp 0x10e47c
jmp 0x10e475
movq -0xd8(%rbp), %rax
movq 0x8(%rax), %rax
testb $0x1, 0x7df(%rax)
je 0x10e2d9
movl $0x18, -0x4(%rbp)
jmp 0x10e47c
jmp 0x10e475
movq -0xd8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x20(%rbp), %rax
movl (%rax), %esi
callq 0xea90
movq %rax, -0xb8(%rbp)
movq -0xb8(%rbp), %rdi
addq $0x20, %rdi
callq 0x8650
cmpq $0x1, %rax
jbe 0x10e331
movq -0xb8(%rbp), %rdi
addq $0x20, %rdi
callq 0x8650
addq $0x7, %rax
subq $0x1, %rax
movl %eax, -0x4(%rbp)
jmp 0x10e47c
jmp 0x10e475
movq -0xd8(%rbp), %rax
movq -0x20(%rbp), %rcx
movl 0x8(%rcx), %ecx
movl %ecx, -0xbc(%rbp)
movq 0x8(%rax), %rdi
movl -0xbc(%rbp), %esi
callq 0xa6ba0
cmpl $0x1, 0xc(%rax)
jne 0x10e471
movq -0x20(%rbp), %rax
movl 0xc(%rax), %eax
movl %eax, -0xc0(%rbp)
movl -0xc0(%rbp), %eax
movl %eax, -0x104(%rbp)
subl $0xb, %eax
je 0x10e3c7
jmp 0x10e383
movl -0x104(%rbp), %eax
subl $0xc, %eax
je 0x10e3d3
jmp 0x10e390
movl -0x104(%rbp), %eax
subl $0x22, %eax
je 0x10e400
jmp 0x10e39d
movl -0x104(%rbp), %eax
subl $0x49, %eax
je 0x10e3df
jmp 0x10e3aa
movl -0x104(%rbp), %eax
subl $0x4a, %eax
je 0x10e3eb
jmp 0x10e3b7
movl -0x104(%rbp), %eax
subl $0x4b, %eax
je 0x10e3f7
jmp 0x10e46d
movl $0x2, -0x4(%rbp)
jmp 0x10e47c
movl $0x3, -0x4(%rbp)
jmp 0x10e47c
movl $0x4, -0x4(%rbp)
jmp 0x10e47c
movl $0x5, -0x4(%rbp)
jmp 0x10e47c
movl $0x6, -0x4(%rbp)
jmp 0x10e47c
movq -0xd8(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x20(%rbp), %rax
movl (%rax), %esi
callq 0xea90
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rax
movl 0x18(%rax), %eax
movl %eax, -0x108(%rbp)
subl $0x2, %eax
je 0x10e44e
jmp 0x10e434
movl -0x108(%rbp), %eax
subl $0x3, %eax
je 0x10e457
jmp 0x10e441
movl -0x108(%rbp), %eax
subl $0x4, %eax
je 0x10e460
jmp 0x10e469
movl $0x11, -0x4(%rbp)
jmp 0x10e47c
movl $0x10, -0x4(%rbp)
jmp 0x10e47c
movl $0xf, -0x4(%rbp)
jmp 0x10e47c
jmp 0x10e46b
jmp 0x10e46f
jmp 0x10e46f
jmp 0x10e471
jmp 0x10e475
jmp 0x10e475
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x110, %rsp            # imm = 0x110
popq %rbp
retq
movq -0x58(%rbp), %rdi
callq 0x7640
nopw %cs:(%rax,%rax)