// File: /workspace/github_cpp_makefile_star2_O3/rossy[P]crossc/SPIRV-Cross/spirv_cross.cpp
// Function: spirv_cross::Compiler::AnalyzeVariableScopeAccessHandler::handle(spv::Op, unsigned int const*, unsigned int)
bool Compiler::AnalyzeVariableScopeAccessHandler::handle(spv::Op op, const uint32_t *args, uint32_t length)
{
	// Keep track of the types of temporaries, so we can hoist them out as necessary.
	uint32_t result_type, result_id;
	if (compiler.instruction_to_result_type(result_type, result_id, op, args, length))
		result_id_to_type[result_id] = result_type;

	switch (op)
	{
	case OpStore:
	{
		if (length < 2)
			return false;

		uint32_t ptr = args[0];
		auto *var = compiler.maybe_get_backing_variable(ptr);

		// If we store through an access chain, we have a partial write.
		if (var)
		{
			accessed_variables_to_block[var->self].insert(current_block->self);
			if (var->self == ptr)
				complete_write_variables_to_block[var->self].insert(current_block->self);
			else
				partial_write_variables_to_block[var->self].insert(current_block->self);
		}

		// Might try to store a Phi variable here.
		notify_variable_access(args[1], current_block->self);
		break;
	}

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

		uint32_t ptr = args[2];
		auto *var = compiler.maybe_get<SPIRVariable>(ptr);
		if (var)
			accessed_variables_to_block[var->self].insert(current_block->self);

		for (uint32_t i = 3; i < length; i++)
			notify_variable_access(args[i], current_block->self);

		// The result of an access chain is a fixed expression and is not really considered a temporary.
		auto &e = compiler.set<SPIRExpression>(args[1], "", args[0], true);
		auto *backing_variable = compiler.maybe_get_backing_variable(ptr);
		e.loaded_from = backing_variable ? backing_variable->self : 0;

		// Other backends might use SPIRAccessChain for this later.
		compiler.ir.ids[args[1]].set_allow_type_rewrite();
		break;
	}

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

		uint32_t lhs = args[0];
		uint32_t rhs = args[1];
		auto *var = compiler.maybe_get_backing_variable(lhs);

		// If we store through an access chain, we have a partial write.
		if (var)
		{
			accessed_variables_to_block[var->self].insert(current_block->self);
			if (var->self == lhs)
				complete_write_variables_to_block[var->self].insert(current_block->self);
			else
				partial_write_variables_to_block[var->self].insert(current_block->self);
		}

		var = compiler.maybe_get_backing_variable(rhs);
		if (var)
			accessed_variables_to_block[var->self].insert(current_block->self);
		break;
	}

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

		auto *var = compiler.maybe_get_backing_variable(args[2]);
		if (var)
			accessed_variables_to_block[var->self].insert(current_block->self);

		// Might try to copy a Phi variable here.
		notify_variable_access(args[2], current_block->self);
		break;
	}

	case OpLoad:
	{
		if (length < 3)
			return false;
		uint32_t ptr = args[2];
		auto *var = compiler.maybe_get_backing_variable(ptr);
		if (var)
			accessed_variables_to_block[var->self].insert(current_block->self);

		// Loaded value is a temporary.
		notify_variable_access(args[1], current_block->self);
		break;
	}

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

		length -= 3;
		args += 3;

		for (uint32_t i = 0; i < length; i++)
		{
			auto *var = compiler.maybe_get_backing_variable(args[i]);
			if (var)
			{
				accessed_variables_to_block[var->self].insert(current_block->self);
				// Assume we can get partial writes to this variable.
				partial_write_variables_to_block[var->self].insert(current_block->self);
			}

			// Cannot easily prove if argument we pass to a function is completely written.
			// Usually, functions write to a dummy variable,
			// which is then copied to in full to the real argument.

			// Might try to copy a Phi variable here.
			notify_variable_access(args[i], current_block->self);
		}

		// Return value may be a temporary.
		notify_variable_access(args[1], current_block->self);
		break;
	}

	case OpExtInst:
	{
		for (uint32_t i = 4; i < length; i++)
			notify_variable_access(args[i], current_block->self);
		notify_variable_access(args[1], current_block->self);
		break;
	}

	case OpArrayLength:
		// Uses literals, but cannot be a phi variable, so ignore.
		break;

		// Atomics shouldn't be able to access function-local variables.
		// Some GLSL builtins access a pointer.

	case OpCompositeInsert:
	case OpVectorShuffle:
		// Specialize for opcode which contains literals.
		for (uint32_t i = 1; i < 4; i++)
			notify_variable_access(args[i], current_block->self);
		break;

	case OpCompositeExtract:
		// Specialize for opcode which contains literals.
		for (uint32_t i = 1; i < 3; i++)
			notify_variable_access(args[i], current_block->self);
		break;

	default:
	{
		// Rather dirty way of figuring out where Phi variables are used.
		// As long as only IDs are used, we can scan through instructions and try to find any evidence that
		// the ID of a variable has been used.
		// There are potential false positives here where a literal is used in-place of an ID,
		// but worst case, it does not affect the correctness of the compile.
		// Exhaustive analysis would be better here, but it's not worth it for now.
		for (uint32_t i = 0; i < length; i++)
			notify_variable_access(args[i], current_block->self);
		break;
	}
	}
	return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movl %ecx, %ebp
movq %rdx, %r15
movl %esi, %r12d
movq %rdi, %r14
leaq 0x14(%rsp), %rsi
leaq 0x10(%rsp), %rdx
movl %r12d, %ecx
movq %r15, %r8
movl %ebp, %r9d
callq 0x18e82
testb %al, %al
je 0x189ec
movl 0x14(%rsp), %ebx
leaq 0x88(%r14), %rdi
leaq 0x10(%rsp), %rsi
callq 0x21d9e
movl %ebx, (%rax)
movb $0x1, %r13b
leal -0x39(%r12), %eax
cmpl $0x1a, %eax
ja 0x18aea
leaq 0x9bf54(%rip), %rcx     # 0xb4958
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
cmpl $0x3, %ebp
jb 0x18cd0
movl 0x8(%r15), %r12d
movq 0x8(%r14), %rdi
movl %r12d, %esi
callq 0xc7b4
testq %rax, %rax
je 0x18a56
leaq 0x18(%r14), %rdi
addq $0x8, %rax
movq %rax, %rsi
callq 0x23124
movq 0x130(%r14), %rsi
addq $0x8, %rsi
leaq 0x8(%rsp), %rdx
movq %rax, (%rdx)
movq %rax, %rdi
callq 0x1f510
cmpl $0x3, %ebp
je 0x18a81
movl %ebp, %ebx
movl $0x3, %r13d
movl (%r15,%r13,4), %esi
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
movq %r14, %rdi
callq 0x188c6
incq %r13
cmpq %r13, %rbx
jne 0x18a63
movq 0x8(%r14), %rdi
movl 0x4(%r15), %esi
leaq 0x8(%rsp), %r8
movb $0x1, (%r8)
leaq 0x9be16(%rip), %rdx     # 0xb48af
movq %r15, %rcx
callq 0x1c06a
movq %rax, %rbx
movq 0x8(%r14), %rdi
movl %r12d, %esi
callq 0x12c9a
testq %rax, %rax
je 0x18da9
movl 0x8(%rax), %eax
jmp 0x18dab
movl $0x1, %ebx
movl (%r15,%rbx,4), %esi
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
movq %r14, %rdi
callq 0x188c6
incq %rbx
cmpq $0x4, %rbx
jne 0x18ac6
jmp 0x18e08
cmpl $0xc, %r12d
jne 0x18b24
cmpl $0x5, %ebp
jb 0x18df2
movl %ebp, %ebx
movl $0x4, %r12d
movl (%r15,%r12,4), %esi
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
movq %r14, %rdi
callq 0x188c6
incq %r12
cmpq %r12, %rbx
jne 0x18b01
jmp 0x18df2
testl %ebp, %ebp
je 0x18e08
movl %ebp, %ebx
xorl %r12d, %r12d
movl (%r15,%r12,4), %esi
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
movq %r14, %rdi
callq 0x188c6
incq %r12
cmpq %r12, %rbx
jne 0x18b31
jmp 0x18e08
cmpl $0x2, %ebp
jb 0x18cd0
movl (%r15), %ebp
movq 0x8(%r14), %rdi
movl %ebp, %esi
callq 0x12c9a
testq %rax, %rax
je 0x18df2
movq %rax, %r12
movq %rax, %rbx
leaq 0x18(%r14), %rdi
addq $0x8, %r12
movq %r12, %rsi
callq 0x23124
movq 0x130(%r14), %rsi
addq $0x8, %rsi
leaq 0x8(%rsp), %rdx
movq %rax, (%rdx)
movq %rax, %rdi
callq 0x1f510
cmpl %ebp, 0x8(%rbx)
jne 0x18dc8
leaq 0xc0(%r14), %rdi
jmp 0x18dcf
cmpl $0x3, %ebp
jb 0x18cd0
movl 0x8(%r15), %esi
movq 0x8(%r14), %rdi
callq 0x12c9a
testq %rax, %rax
je 0x18df2
leaq 0x18(%r14), %rdi
addq $0x8, %rax
movq %rax, %rsi
jmp 0x18dd2
cmpl $0x3, %ebp
jb 0x18cd0
movq 0x8(%r14), %rdi
movl 0x8(%r15), %esi
callq 0x12c9a
testq %rax, %rax
je 0x18c2f
leaq 0x18(%r14), %rdi
addq $0x8, %rax
movq %rax, %rsi
callq 0x23124
movq 0x130(%r14), %rsi
addq $0x8, %rsi
leaq 0x8(%rsp), %rdx
movq %rax, (%rdx)
movq %rax, %rdi
callq 0x1f510
movl 0x8(%r15), %esi
jmp 0x18df6
cmpl $0x2, %ebp
jb 0x18cd0
movl (%r15), %r12d
movl 0x4(%r15), %ebp
movq 0x8(%r14), %rdi
movl %r12d, %esi
callq 0x12c9a
testq %rax, %rax
je 0x18e44
movq %rax, %r15
movq %rax, %rbx
leaq 0x18(%r14), %rdi
addq $0x8, %r15
movq %r15, %rsi
callq 0x23124
movq 0x130(%r14), %rsi
addq $0x8, %rsi
leaq 0x8(%rsp), %rdx
movq %rax, (%rdx)
movq %rax, %rdi
callq 0x1f510
cmpl %r12d, 0x8(%rbx)
jne 0x18e1a
leaq 0xc0(%r14), %rdi
jmp 0x18e21
xorl %ebx, %ebx
movl 0x4(%r15,%rbx,4), %esi
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
movq %r14, %rdi
callq 0x188c6
incq %rbx
cmpq $0x2, %rbx
jne 0x18ca6
jmp 0x18e08
cmpl $0x3, %ebp
jae 0x18cd8
xorl %r13d, %r13d
jmp 0x18e08
addl $-0x3, %ebp
je 0x18d8e
leaq 0x18(%r14), %rax
movq %rax, 0x20(%rsp)
leaq 0xf8(%r14), %rax
movq %rax, 0x18(%rsp)
movl %ebp, %r12d
xorl %r13d, %r13d
leaq 0x8(%rsp), %rbp
movq 0x8(%r14), %rdi
movl 0xc(%r15,%r13,4), %esi
callq 0x12c9a
testq %rax, %rax
je 0x18d6b
movq %rax, %rbx
addq $0x8, %rbx
movq 0x20(%rsp), %rdi
movq %rbx, %rsi
callq 0x23124
movq 0x130(%r14), %rsi
addq $0x8, %rsi
movq %rax, 0x8(%rsp)
movq %rax, %rdi
movq %rbp, %rdx
callq 0x1f510
movq 0x18(%rsp), %rdi
movq %rbx, %rsi
callq 0x23124
movq 0x130(%r14), %rsi
addq $0x8, %rsi
movq %rax, 0x8(%rsp)
movq %rax, %rdi
movq %rbp, %rdx
callq 0x1f510
movl 0xc(%r15,%r13,4), %esi
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
movq %r14, %rdi
callq 0x188c6
incq %r13
cmpq %r13, %r12
jne 0x18d01
movl 0x10(%r15), %esi
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
movq %r14, %rdi
callq 0x188c6
movb $0x1, %r13b
jmp 0x18e08
xorl %eax, %eax
movb $0x1, %r13b
movl %eax, 0x34(%rbx)
movq 0x8(%r14), %rax
movl 0x4(%r15), %ecx
movq 0x20(%rax), %rax
shlq $0x4, %rcx
movb $0x1, 0xc(%rax,%rcx)
jmp 0x18e08
leaq 0xf8(%r14), %rdi
movq %r12, %rsi
callq 0x23124
movq 0x130(%r14), %rsi
addq $0x8, %rsi
leaq 0x8(%rsp), %rdx
movq %rax, (%rdx)
movq %rax, %rdi
callq 0x1f510
movl 0x4(%r15), %esi
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
movq %r14, %rdi
callq 0x188c6
movl %r13d, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xf8(%r14), %rdi
movq %r15, %rsi
callq 0x23124
movq 0x130(%r14), %rsi
addq $0x8, %rsi
leaq 0x8(%rsp), %rdx
movq %rax, (%rdx)
movq %rax, %rdi
callq 0x1f510
movq 0x8(%r14), %rdi
movl %ebp, %esi
callq 0x12c9a
testq %rax, %rax
je 0x18e08
leaq 0x18(%r14), %rdi
addq $0x8, %rax
movq %rax, %rsi
callq 0x23124
movq 0x130(%r14), %rsi
addq $0x8, %rsi
leaq 0x8(%rsp), %rdx
movq %rax, (%rdx)
movq %rax, %rdi
callq 0x1f510
jmp 0x18e08
nop