// File: /workspace/github_cpp_makefile_star2_O2/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 $0x18, %rsp
movl %ecx, %r12d
movq %rdx, %r15
movl %esi, %r13d
movq %rdi, %r14
leaq 0xc(%rsp), %rsi
leaq 0x8(%rsp), %rdx
movl %r13d, %ecx
movq %r15, %r8
movl %r12d, %r9d
callq 0x15226
testb %al, %al
je 0x14de9
movl 0xc(%rsp), %ebx
leaq 0x88(%r14), %rdi
leaq 0x8(%rsp), %rsi
callq 0x1d40e
movl %ebx, (%rax)
movb $0x1, %bpl
leal -0x39(%r13), %eax
cmpl $0x1a, %eax
ja 0x14e9d
leaq 0x7ab10(%rip), %rcx     # 0x8f910
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
cmpl $0x3, %r12d
jb 0x15135
movl 0x8(%r15), %ebp
movq 0x8(%r14), %rdi
movl %ebp, %esi
callq 0xa9e4
testq %rax, %rax
je 0x14e4a
leaq 0x18(%r14), %rdi
addq $0x8, %rax
movq %rax, %rsi
callq 0x1e658
movq 0x130(%r14), %rsi
addq $0x8, %rsi
movq %rax, %rdi
callq 0x1af30
movl %r12d, %ebx
pushq $0x3
popq %r12
cmpq %rbx, %r12
jae 0x14ef8
movl (%r15,%r12,4), %esi
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
movq %r14, %rdi
callq 0x14c4e
incq %r12
jmp 0x14e51
pushq $0x1
popq %rbx
cmpq $0x4, %rbx
je 0x15215
movl (%r15,%rbx,4), %esi
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
movq %r14, %rdi
callq 0x14c4e
incq %rbx
jmp 0x14e78
cmpl $0xc, %r13d
jne 0x14ece
movl %r12d, %ebx
pushq $0x4
popq %r12
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
cmpq %rbx, %r12
jae 0x1513c
movl (%r15,%r12,4), %esi
movq %r14, %rdi
callq 0x14c4e
incq %r12
jmp 0x14eaa
movl %r12d, %ebx
xorl %r12d, %r12d
cmpq %r12, %rbx
je 0x15215
movl (%r15,%r12,4), %esi
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
movq %r14, %rdi
callq 0x14c4e
incq %r12
jmp 0x14ed4
movq 0x8(%r14), %rdi
movl 0x4(%r15), %esi
leaq 0x7(%rsp), %r8
movb $0x1, (%r8)
leaq 0x7a977(%rip), %rdx     # 0x8f887
movq %r15, %rcx
callq 0x17be4
movq %rax, %rbx
movq 0x8(%r14), %rdi
movl %ebp, %esi
callq 0x1067e
testq %rax, %rax
je 0x151f8
movl 0x8(%rax), %eax
jmp 0x151fa
cmpl $0x2, %r12d
jb 0x15135
movl (%r15), %ebp
movq 0x8(%r14), %rdi
movl %ebp, %esi
callq 0x1067e
testq %rax, %rax
je 0x14faf
movq %rax, %r12
leaq 0x18(%r14), %rdi
movq %rax, %rbx
addq $0x8, %rbx
movq %rbx, %rsi
callq 0x1e658
movq 0x130(%r14), %rsi
addq $0x8, %rsi
movq %rax, %rdi
callq 0x1af30
leaq 0xf8(%r14), %rdi
leaq 0xc0(%r14), %rax
cmpl %ebp, 0x8(%r12)
cmoveq %rax, %rdi
movq %rbx, %rsi
callq 0x1e658
movq 0x130(%r14), %rsi
addq $0x8, %rsi
movq %rax, %rdi
callq 0x1af30
movl 0x4(%r15), %esi
jmp 0x151e1
cmpl $0x3, %r12d
jb 0x15135
movl 0x8(%r15), %esi
movq 0x8(%r14), %rdi
callq 0x1067e
testq %rax, %rax
je 0x14ff7
leaq 0x18(%r14), %rdi
addq $0x8, %rax
movq %rax, %rsi
callq 0x1e658
movq 0x130(%r14), %rsi
addq $0x8, %rsi
movq %rax, %rdi
callq 0x1af30
movl 0x4(%r15), %esi
jmp 0x15040
cmpl $0x3, %r12d
jb 0x15135
movq 0x8(%r14), %rdi
movl 0x8(%r15), %esi
callq 0x1067e
testq %rax, %rax
je 0x1503c
leaq 0x18(%r14), %rdi
addq $0x8, %rax
movq %rax, %rsi
callq 0x1e658
movq 0x130(%r14), %rsi
addq $0x8, %rsi
movq %rax, %rdi
callq 0x1af30
movl 0x8(%r15), %esi
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
jmp 0x15140
cmpl $0x2, %r12d
jb 0x15135
movl (%r15), %r12d
movl 0x4(%r15), %ebp
movq 0x8(%r14), %rdi
movl %r12d, %esi
callq 0x1067e
testq %rax, %rax
je 0x150cb
movq %rax, %r15
leaq 0x18(%r14), %rdi
movq %rax, %rbx
addq $0x8, %rbx
movq %rbx, %rsi
callq 0x1e658
movq 0x130(%r14), %rsi
addq $0x8, %rsi
movq %rax, %rdi
callq 0x1af30
leaq 0xf8(%r14), %rdi
leaq 0xc0(%r14), %rax
cmpl %r12d, 0x8(%r15)
cmoveq %rax, %rdi
movq %rbx, %rsi
callq 0x1e658
movq 0x130(%r14), %rsi
addq $0x8, %rsi
movq %rax, %rdi
callq 0x1af30
movq 0x8(%r14), %rdi
movl %ebp, %esi
callq 0x1067e
testq %rax, %rax
je 0x151f3
leaq 0x18(%r14), %rdi
addq $0x8, %rax
movq %rax, %rsi
callq 0x1e658
movq 0x130(%r14), %rsi
addq $0x8, %rsi
movq %rax, %rdi
callq 0x1af30
jmp 0x151f3
xorl %ebx, %ebx
cmpq $0x2, %rbx
je 0x15215
movl 0x4(%r15,%rbx,4), %esi
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
movq %r14, %rdi
callq 0x14c4e
incq %rbx
jmp 0x15109
cmpl $0x3, %r12d
jae 0x1514d
xorl %ebp, %ebp
jmp 0x15215
movl 0x4(%r15), %esi
movq %r14, %rdi
callq 0x14c4e
jmp 0x15215
addl $-0x3, %r12d
leaq 0x18(%r14), %rax
movq %rax, 0x10(%rsp)
leaq 0xf8(%r14), %rbp
xorl %r13d, %r13d
cmpq %r13, %r12
je 0x151dd
movq 0x8(%r14), %rdi
movl 0xc(%r15,%r13,4), %esi
callq 0x1067e
testq %rax, %rax
je 0x151c1
movq %rax, %rbx
addq $0x8, %rbx
movq 0x10(%rsp), %rdi
movq %rbx, %rsi
callq 0x1e658
movq 0x130(%r14), %rsi
addq $0x8, %rsi
movq %rax, %rdi
callq 0x1af30
movq %rbp, %rdi
movq %rbx, %rsi
callq 0x1e658
movq 0x130(%r14), %rsi
addq $0x8, %rsi
movq %rax, %rdi
callq 0x1af30
movl 0xc(%r15,%r13,4), %esi
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
movq %r14, %rdi
callq 0x14c4e
incq %r13
jmp 0x15164
movl 0x10(%r15), %esi
movq 0x130(%r14), %rax
movl 0x8(%rax), %edx
movq %r14, %rdi
callq 0x14c4e
movb $0x1, %bpl
jmp 0x15215
xorl %eax, %eax
movb $0x1, %bpl
movl %eax, 0x34(%rbx)
movq 0x8(%r14), %rax
movl 0x4(%r15), %ecx
movq 0x20(%rax), %rax
shlq $0x4, %rcx
movb $0x1, 0xc(%rax,%rcx)
movl %ebp, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq