// File: /workspace/github_cpp_makefile_star2_O1/rossy[P]crossc/SPIRV-Cross/spirv_cross.cpp
// Function: spirv_cross::Compiler::find_function_local_luts(spirv_cross::SPIRFunction&, spirv_cross::Compiler::AnalyzeVariableScopeAccessHandler const&)
void Compiler::find_function_local_luts(SPIRFunction &entry, const AnalyzeVariableScopeAccessHandler &handler)
{
	auto &cfg = *function_cfgs.find(entry.self)->second;

	// For each variable which is statically accessed.
	for (auto &accessed_var : handler.accessed_variables_to_block)
	{
		auto &blocks = accessed_var.second;
		auto &var = get<SPIRVariable>(accessed_var.first);
		auto &type = expression_type(accessed_var.first);

		// Only consider function local variables here.
		if (var.storage != StorageClassFunction)
			continue;

		// We cannot be a phi variable.
		if (var.phi_variable)
			continue;

		// Only consider arrays here.
		if (type.array.empty())
			continue;

		// HACK: Do not consider structs. This is a quirk with how types are currently being emitted.
		// Structs are emitted after specialization constants and composite constants.
		// FIXME: Fix declaration order so declared constants can have struct types.
		if (type.basetype == SPIRType::Struct)
			continue;

		// If the variable has an initializer, make sure it is a constant expression.
		uint32_t static_constant_expression = 0;
		if (var.initializer)
		{
			if (ir.ids[var.initializer].get_type() != TypeConstant)
				continue;
			static_constant_expression = var.initializer;

			// There can be no stores to this variable, we have now proved we have a LUT.
			if (handler.complete_write_variables_to_block.count(var.self) != 0 ||
			    handler.partial_write_variables_to_block.count(var.self) != 0)
				continue;
		}
		else
		{
			// We can have one, and only one write to the variable, and that write needs to be a constant.

			// No partial writes allowed.
			if (handler.partial_write_variables_to_block.count(var.self) != 0)
				continue;

			auto itr = handler.complete_write_variables_to_block.find(var.self);

			// No writes?
			if (itr == end(handler.complete_write_variables_to_block))
				continue;

			// We write to the variable in more than one block.
			auto &write_blocks = itr->second;
			if (write_blocks.size() != 1)
				continue;

			// The write needs to happen in the dominating block.
			DominatorBuilder builder(cfg);
			for (auto &block : blocks)
				builder.add_block(block);
			uint32_t dominator = builder.get_dominator();

			// The complete write happened in a branch or similar, cannot deduce static expression.
			if (write_blocks.count(dominator) == 0)
				continue;

			// Find the static expression for this variable.
			StaticExpressionAccessHandler static_expression_handler(*this, var.self);
			traverse_all_reachable_opcodes(get<SPIRBlock>(dominator), static_expression_handler);

			// We want one, and exactly one write
			if (static_expression_handler.write_count != 1 || static_expression_handler.static_expression == 0)
				continue;

			// Is it a constant expression?
			if (ir.ids[static_expression_handler.static_expression].get_type() != TypeConstant)
				continue;

			// We found a LUT!
			static_constant_expression = static_expression_handler.static_expression;
		}

		get<SPIRConstant>(static_constant_expression).is_used_as_lut = true;
		var.static_expression = static_constant_expression;
		var.statically_assigned = true;
		var.remapped_variable = true;
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rdx, %r13
movq %rdi, %r14
addq $0x3a0, %rdi            # imm = 0x3A0
movl 0x8(%rsi), %ecx
leaq 0x8(%rsi), %r8
movq %rcx, %rax
xorl %edx, %edx
divq 0x3a8(%r14)
movq %rdx, %rsi
movq %r8, %rdx
callq 0x23bfa
movq 0x28(%r13), %rbx
testq %rbx, %rbx
je 0x196f3
movq (%rax), %rax
movq 0x10(%rax), %rax
movq %rax, 0x30(%rsp)
leaq 0xc0(%r13), %rax
movq %rax, 0x10(%rsp)
leaq 0xf8(%r13), %rax
movq %rax, 0x18(%rsp)
movl 0x8(%rbx), %esi
movq %r14, %rdi
callq 0xb40a
movq %rax, %r15
movl 0x8(%rbx), %esi
movq %r14, %rdi
callq 0x13116
movq %r14, %rdi
movl %eax, %esi
callq 0x1b9de
cmpl $0x7, 0x10(%r15)
jne 0x19533
cmpb $0x0, 0x5a(%r15)
je 0x19540
movq (%rbx), %rbx
testq %rbx, %rbx
jne 0x19502
jmp 0x196f3
movq 0x20(%rax), %rcx
cmpq 0x28(%rax), %rcx
je 0x19533
cmpl $0xc, 0xc(%rax)
je 0x19533
movl 0x18(%r15), %ebp
testq %rbp, %rbp
je 0x1959b
movq 0x20(%r14), %rax
movq %rbp, %rcx
shlq $0x4, %rcx
cmpl $0x3, 0x8(%rax,%rcx)
jne 0x19533
movq %r15, %r12
addq $0x8, %r12
movq 0x10(%rsp), %rdi
movq %r12, %rsi
callq 0x23c40
testq %rax, %rax
jne 0x19533
movq 0x18(%rsp), %rdi
movq %r12, %rsi
callq 0x23c40
testq %rax, %rax
jne 0x19533
jmp 0x196d0
movq %r15, %r12
addq $0x8, %r12
movq 0x18(%rsp), %rdi
movq %r12, %rsi
callq 0x23c40
testq %rax, %rax
jne 0x19533
movl (%r12), %ecx
movq %rcx, %rax
xorl %edx, %edx
movq %r13, 0x28(%rsp)
divq 0xc8(%r13)
movq 0x10(%rsp), %rdi
movq %rdx, %rsi
movq %r12, %rdx
callq 0x23792
movl $0x0, %ecx
testq %rax, %rax
je 0x195ea
movq (%rax), %rcx
testq %rcx, %rcx
leaq 0x38(%rsp), %rdi
je 0x196bf
xorl %ebp, %ebp
cmpq $0x1, 0x28(%rcx)
movl $0x0, %eax
jne 0x196c3
movq %rcx, 0x20(%rsp)
movq 0x30(%rsp), %rsi
movq %rdi, %r13
callq 0x76aa
movq 0x20(%rbx), %rbp
testq %rbp, %rbp
je 0x19636
movl 0x8(%rbp), %esi
movq %r13, %rdi
callq 0x76b6
movq (%rbp), %rbp
jmp 0x19620
movq 0x20(%rsp), %rdi
addq $0x10, %rdi
movl 0x40(%rsp), %eax
movl %eax, 0xc(%rsp)
leaq 0xc(%rsp), %rsi
callq 0x1fbce
testq %rax, %rax
je 0x196bf
movl (%r12), %edx
leaq 0x48(%rsp), %r12
movq %r12, %rdi
movq %r14, %rsi
callq 0x19426
movl 0xc(%rsp), %esi
movq %r14, %rdi
callq 0x78fe
movq %r14, %rdi
movq %rax, %rsi
movq %r12, %rdx
callq 0x154dc
movl 0x5c(%rsp), %ecx
cmpl $0x1, 0x60(%rsp)
setne %al
testl %ecx, %ecx
sete %dl
xorl %ebp, %ebp
orb %al, %dl
movl $0x0, %eax
jne 0x196c3
movl %ecx, %ecx
movq 0x20(%r14), %rax
movq %rcx, %rdx
shlq $0x4, %rdx
cmpl $0x3, 0x8(%rax,%rdx)
sete %al
movl $0x0, %ebp
cmovel %ecx, %ebp
jmp 0x196c3
xorl %ebp, %ebp
xorl %eax, %eax
testb %al, %al
movq 0x28(%rsp), %r13
je 0x19533
movq %r14, %rdi
movl %ebp, %esi
callq 0x1c66e
movb $0x1, %cl
movb %cl, 0x10a(%rax)
movl %ebp, 0x3c(%r15)
movb %cl, 0x39(%r15)
movb %cl, 0x5b(%r15)
jmp 0x19533
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq