// File: /workspace/github_cpp_makefile_star2_O3/rossy[P]crossc/SPIRV-Cross/spirv_msl.cpp
// Function: spirv_cross::CompilerMSL::extract_global_variables_from_function(unsigned int, std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int>>&, std::unordered_set<unsigned int, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<unsigned int>>&, std::unordered_set<unsigned int, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<unsigned int>>&)
void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std::set<uint32_t> &added_arg_ids,
                                                         unordered_set<uint32_t> &global_var_ids,
                                                         unordered_set<uint32_t> &processed_func_ids)
{
	// Avoid processing a function more than once
	if (processed_func_ids.find(func_id) != processed_func_ids.end())
	{
		// Return function global variables
		added_arg_ids = function_global_vars[func_id];
		return;
	}

	processed_func_ids.insert(func_id);

	auto &func = get<SPIRFunction>(func_id);

	// Recursively establish global args added to functions on which we depend.
	for (auto block : func.blocks)
	{
		auto &b = get<SPIRBlock>(block);
		for (auto &i : b.ops)
		{
			auto ops = stream(i);
			auto op = static_cast<Op>(i.op);

			switch (op)
			{
			case OpLoad:
			case OpInBoundsAccessChain:
			case OpAccessChain:
			{
				uint32_t base_id = ops[2];
				if (global_var_ids.find(base_id) != global_var_ids.end())
					added_arg_ids.insert(base_id);

				auto &type = get<SPIRType>(ops[0]);
				if (type.basetype == SPIRType::Image && type.image.dim == DimSubpassData)
				{
					// Implicitly reads gl_FragCoord.
					assert(builtin_frag_coord_id != 0);
					added_arg_ids.insert(builtin_frag_coord_id);
				}

				if (msl_options.swizzle_texture_samples && has_sampled_images && is_sampled_image_type(type))
				{
					// Implicitly reads spvAuxBuffer.
					assert(aux_buffer_id != 0);
					added_arg_ids.insert(aux_buffer_id);
				}

				break;
			}

			case OpFunctionCall:
			{
				// First see if any of the function call args are globals
				for (uint32_t arg_idx = 3; arg_idx < i.length; arg_idx++)
				{
					uint32_t arg_id = ops[arg_idx];
					if (global_var_ids.find(arg_id) != global_var_ids.end())
						added_arg_ids.insert(arg_id);
				}

				// Then recurse into the function itself to extract globals used internally in the function
				uint32_t inner_func_id = ops[2];
				std::set<uint32_t> inner_func_args;
				extract_global_variables_from_function(inner_func_id, inner_func_args, global_var_ids,
				                                       processed_func_ids);
				added_arg_ids.insert(inner_func_args.begin(), inner_func_args.end());
				break;
			}

			case OpStore:
			{
				uint32_t base_id = ops[0];
				if (global_var_ids.find(base_id) != global_var_ids.end())
					added_arg_ids.insert(base_id);
				break;
			}

			default:
				break;
			}

			// TODO: Add all other operations which can affect memory.
			// We should consider a more unified system here to reduce boiler-plate.
			// This kind of analysis is done in several places ...
		}
	}

	function_global_vars[func_id] = added_arg_ids;

	// Add the global variables as arguments to the function
	if (func_id != ir.default_entry_point)
	{
		for (uint32_t arg_id : added_arg_ids)
		{
			auto &var = get<SPIRVariable>(arg_id);
			uint32_t type_id = var.basetype;
			auto *p_type = &get<SPIRType>(type_id);

			if (is_builtin_variable(var) && p_type->basetype == SPIRType::Struct)
			{
				// Get the non-pointer type
				type_id = get_non_pointer_type_id(type_id);
				p_type = &get<SPIRType>(type_id);

				uint32_t mbr_idx = 0;
				for (auto &mbr_type_id : p_type->member_types)
				{
					BuiltIn builtin;
					bool is_builtin = is_member_builtin(*p_type, mbr_idx, &builtin);
					if (is_builtin && has_active_builtin(builtin, var.storage))
					{
						// Add a arg variable with the same type and decorations as the member
						uint32_t next_ids = ir.increase_bound_by(2);
						uint32_t ptr_type_id = next_ids + 0;
						uint32_t var_id = next_ids + 1;

						// Make sure we have an actual pointer type,
						// so that we will get the appropriate address space when declaring these builtins.
						auto &ptr = set<SPIRType>(ptr_type_id, get<SPIRType>(mbr_type_id));
						ptr.self = mbr_type_id;
						ptr.storage = var.storage;
						ptr.pointer = true;

						func.add_parameter(mbr_type_id, var_id, true);
						set<SPIRVariable>(var_id, ptr_type_id, StorageClassFunction);
						ir.meta[var_id].decoration = ir.meta[type_id].members[mbr_idx];
					}
					mbr_idx++;
				}
			}
			else
			{
				uint32_t next_id = ir.increase_bound_by(1);
				func.add_parameter(type_id, next_id, true);
				set<SPIRVariable>(next_id, type_id, StorageClassFunction, 0, arg_id);

				// Ensure the existing variable has a valid name and the new variable has all the same meta info
				set_name(arg_id, ensure_valid_name(to_name(arg_id), "v"));
				ir.meta[next_id] = ir.meta[arg_id];
			}
		}
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xd8, %rsp
movq %r8, %r12
movq %rcx, %r13
movq %rdx, %r14
movq %rdi, %rbx
leaq 0xc(%rsp), %rax
movl %esi, (%rax)
movq %r8, %rdi
movq %rax, %rsi
callq 0x21122
testq %rax, %rax
je 0x8e29c
addq $0x788, %rbx            # imm = 0x788
leaq 0xc(%rsp), %rsi
movq %rbx, %rdi
callq 0xa7d40
movq %r14, %rdi
movq %rax, %rsi
callq 0xa714a
jmp 0x8e9ef
leaq 0x48(%rsp), %rdx
movq %r12, (%rdx)
leaq 0xc(%rsp), %r15
movq %r12, 0x28(%rsp)
movq %r12, %rdi
movq %r15, %rsi
callq 0x1f510
movl (%r15), %esi
movq %rbx, %rdi
callq 0xb98a
movq 0x68(%rax), %rcx
movq %rax, 0x80(%rsp)
movq 0x70(%rax), %rax
movq %rax, 0x38(%rsp)
cmpq %rax, %rcx
movq %rbx, 0x30(%rsp)
je 0x8e4d5
leaq 0x7c0(%rbx), %rax
movq %rax, 0x10(%rsp)
leaq 0x7c8(%rbx), %rax
movq %rax, 0x40(%rsp)
leaq 0x48(%rsp), %r12
movq %rcx, 0x20(%rsp)
movl (%rcx), %esi
movq %rbx, %rdi
callq 0x7870
movq 0x38(%rax), %rbp
movq 0x40(%rax), %rax
movq %rax, 0x18(%rsp)
cmpq %rax, %rbp
je 0x8e4c1
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x1b2ac
movq %rax, %r15
movzwl (%rbp), %eax
addl $-0x39, %eax
cmpl $0x9, %eax
ja 0x8e4b2
leaq 0x315ca(%rip), %rcx     # 0xbf918
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl 0x8(%r15), %eax
movl %eax, 0x48(%rsp)
movq %r13, %rdi
movq %r12, %rsi
callq 0x21122
testq %rax, %rax
je 0x8e37a
movq %r14, %rdi
movq %r12, %rsi
callq 0xa8026
movl (%r15), %esi
movq %rbx, %rdi
callq 0xa3ea
movq %rax, %r15
cmpl $0xd, 0xc(%rax)
jne 0x8e3ae
cmpl $0x6, 0x84(%r15)
jne 0x8e3ae
movq 0x10(%rsp), %rsi
cmpl $0x0, (%rsi)
je 0x8ea01
movq %r14, %rdi
callq 0xa8026
cmpb $0x1, 0x7df(%rbx)
jne 0x8e4b2
cmpb $0x1, 0x934(%rbx)
jne 0x8e4b2
movq %rbx, %rdi
movq %r15, %rsi
callq 0x14b1c
testb %al, %al
je 0x8e4b2
movq 0x40(%rsp), %rsi
cmpl $0x0, (%rsi)
je 0x8ea20
movq %r14, %rdi
jmp 0x8e40f
movl (%r15), %eax
movl %eax, 0x48(%rsp)
movq %r13, %rdi
movq %r12, %rsi
callq 0x21122
testq %rax, %rax
je 0x8e4b2
movq %r14, %rdi
movq %r12, %rsi
callq 0xa8026
jmp 0x8e4b2
movq %r14, %rbx
cmpl $0x4, 0x8(%rbp)
jb 0x8e456
movl $0x3, %r14d
movl (%r15,%r14,4), %eax
movl %eax, 0x48(%rsp)
movq %r13, %rdi
movq %r12, %rsi
callq 0x21122
testq %rax, %rax
je 0x8e44b
movq %rbx, %rdi
movq %r12, %rsi
callq 0xa8026
incq %r14
movl 0x8(%rbp), %eax
cmpq %rax, %r14
jb 0x8e428
movl 0x8(%r15), %esi
movl $0x0, 0x50(%rsp)
xorl %eax, %eax
movq %rax, 0x58(%rsp)
leaq 0x50(%rsp), %r15
movq %r15, 0x60(%rsp)
movq %r15, 0x68(%rsp)
movq %rax, 0x70(%rsp)
movq 0x30(%rsp), %rdi
movq %r12, %rdx
movq %r13, %rcx
movq 0x28(%rsp), %r8
callq 0x8e244
movq %rbx, %r14
movq 0x60(%rsp), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0xa8134
movq %r12, %rdi
callq 0xa70fa
movq 0x30(%rsp), %rbx
addq $0xc, %rbp
cmpq 0x18(%rsp), %rbp
jne 0x8e329
movq 0x20(%rsp), %rcx
addq $0x4, %rcx
cmpq 0x38(%rsp), %rcx
jne 0x8e304
leaq 0x788(%rbx), %rdi
leaq 0xc(%rsp), %r15
movq %r15, %rsi
callq 0xa7d40
movq %rax, %rdi
movq %r14, %rsi
callq 0xa714a
movl (%r15), %eax
cmpl 0x108(%rbx), %eax
je 0x8e9ef
movq 0x18(%r14), %r12
addq $0x8, %r14
cmpq %r14, %r12
je 0x8e9ef
leaq 0x8(%rbx), %rax
movq %rax, 0x20(%rsp)
leaq 0x48(%rsp), %r13
leaq 0x88(%rsp), %rbp
movq %r14, 0xa8(%rsp)
movl 0x20(%r12), %esi
movl %esi, 0x8(%rsp)
movq %rbx, %rdi
callq 0xb3ca
movq %rax, %r14
movl 0xc(%rax), %esi
movl %esi, (%rsp)
movq %rbx, %rdi
callq 0xa3ea
movq %rax, %r15
movq %rbx, %rdi
movq %r14, 0x18(%rsp)
movq %r14, %rsi
callq 0x13330
testb %al, %al
movq %r12, 0xb0(%rsp)
je 0x8e764
cmpl $0xc, 0xc(%r15)
jne 0x8e764
movl (%rsp), %esi
movq %rbx, %rdi
callq 0x14a6a
movl %eax, (%rsp)
movq %rbx, %rdi
movl %eax, %esi
callq 0xa3ea
movq 0x68(%rax), %r14
movq 0x70(%rax), %r12
cmpq %r12, %r14
je 0x8e9c9
movq %rax, %r15
xorl %ebp, %ebp
movq %rax, 0x40(%rsp)
movq %r12, 0x38(%rsp)
movq %rbx, %rdi
movq %r15, %rsi
movl %ebp, %edx
movq %r13, %rcx
callq 0x133ea
testb %al, %al
je 0x8e750
movl 0x48(%rsp), %esi
movq 0x18(%rsp), %rax
movl 0x10(%rax), %edx
movq %rbx, %rdi
callq 0x1a1a0
testb %al, %al
je 0x8e750
movq 0x20(%rsp), %rdi
movl $0x2, %esi
callq 0x24f8a
movl %eax, %r15d
movl %eax, 0x4(%rsp)
leal 0x1(%r15), %r12d
movl (%r14), %esi
movq %rbx, %rdi
callq 0xa3ea
movq %rbx, %rdi
movl %r15d, %esi
movq %rax, %rdx
callq 0x7c44c
movl (%r14), %esi
movl %esi, 0x8(%rax)
movq 0x18(%rsp), %rcx
movl 0x10(%rcx), %ecx
movl %ecx, 0x64(%rax)
movb $0x1, 0x60(%rax)
movq 0x80(%rsp), %rdi
movl %r12d, %edx
movl $0x1, %ecx
callq 0xa3564
movl $0x7, 0x7c(%rsp)
movq %rbx, %rdi
movl %r12d, %esi
leaq 0x4(%rsp), %rdx
leaq 0x7c(%rsp), %rcx
callq 0x7c48e
movl (%rsp), %eax
movq 0x38(%rbx), %rbx
imulq $0x148, %rax, %rax      # imm = 0x148
movl %ebp, %ecx
movq 0xd0(%rbx,%rax), %rax
movq %rax, 0x28(%rsp)
imulq $0xd0, %rcx, %rcx
movq %rcx, 0x10(%rsp)
leaq (%rax,%rcx), %r15
imulq $0x148, %r12, %r13      # imm = 0x148
leaq (%rbx,%r13), %r12
movq %r12, %rdi
movq %r15, %rsi
callq 0x6170
leaq (%rbx,%r13), %rdi
addq $0x20, %rdi
movq 0x10(%rsp), %rax
movq 0x28(%rsp), %rcx
leaq (%rcx,%rax), %rsi
addq $0x20, %rsi
callq 0x6170
addq %rbx, %r13
addq $0x40, %r13
movq 0x10(%rsp), %rax
movq 0x28(%rsp), %rcx
leaq (%rcx,%rax), %rbx
addq $0x40, %rbx
movq %r13, %rdi
movq %rbx, %rsi
callq 0x6170
movq 0x20(%rbx), %rax
movq %rax, 0x20(%r13)
cmpq %r12, %r15
je 0x8e709
leaq 0x68(%r12), %rdi
leaq 0x68(%r15), %rsi
callq 0x1d5b4
movups 0xa0(%r15), %xmm0
movups 0xb0(%r15), %xmm1
movups 0xbd(%r15), %xmm2
movups %xmm2, 0xbd(%r12)
movups %xmm1, 0xb0(%r12)
movups %xmm0, 0xa0(%r12)
movq 0x30(%rsp), %rbx
leaq 0x48(%rsp), %r13
movq 0x40(%rsp), %r15
movq 0x38(%rsp), %r12
incl %ebp
addq $0x4, %r14
cmpq %r12, %r14
jne 0x8e5ba
jmp 0x8e9c9
movq 0x20(%rsp), %rdi
movl $0x1, %esi
callq 0x24f8a
movl %eax, %r14d
movl (%rsp), %esi
movq 0x80(%rsp), %rdi
movl %eax, %edx
movl $0x1, %ecx
callq 0xa3564
movl $0x7, 0x48(%rsp)
movl $0x0, 0x4(%rsp)
movq %rbx, %rdi
movl %r14d, 0x18(%rsp)
movl %r14d, %esi
movq %rsp, %rdx
movq %r13, %rcx
leaq 0x4(%rsp), %r8
leaq 0x8(%rsp), %r9
callq 0xa35b0
movl 0x8(%rsp), %r15d
movq (%rbx), %rax
leaq 0xb8(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
movl %r15d, %edx
movl $0x1, %ecx
callq *0x38(%rax)
leaq 0x98(%rsp), %rax
movq %rax, 0x88(%rsp)
movq %rbp, %rdi
leaq 0x31cd4(%rip), %rsi     # 0xc04cc
leaq 0x31cce(%rip), %rdx     # 0xc04cd
callq 0x7be0
movq %r13, %rdi
movq %r14, %rdx
movq %rbp, %rcx
callq 0x8eaca
movq %rbx, %rdi
movl %r15d, %esi
movq %r13, %rdx
callq 0x14a44
movq 0x48(%rsp), %rdi
leaq 0x58(%rsp), %rax
cmpq %rax, %rdi
je 0x8e83c
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x6260
movq 0x88(%rsp), %rdi
leaq 0x98(%rsp), %rax
cmpq %rax, %rdi
je 0x8e861
movq 0x98(%rsp), %rsi
incq %rsi
callq 0x6260
movq 0xb8(%rsp), %rdi
leaq 0xc8(%rsp), %rax
cmpq %rax, %rdi
je 0x8e886
movq 0xc8(%rsp), %rsi
incq %rsi
callq 0x6260
movl 0x8(%rsp), %eax
movq %rax, 0x10(%rsp)
movq 0x38(%rbx), %r12
imulq $0x148, %rax, %rbp      # imm = 0x148
leaq (%r12,%rbp), %r15
movl 0x18(%rsp), %r14d
movl %r14d, %eax
imulq $0x148, %rax, %rbx      # imm = 0x148
leaq (%r12,%rbx), %r13
movq %r13, %rdi
movq %r15, %rsi
callq 0x6170
leaq (%r12,%rbx), %rdi
addq $0x20, %rdi
leaq (%r12,%rbp), %rsi
addq $0x20, %rsi
callq 0x6170
addq %r12, %rbx
addq $0x40, %rbx
addq %rbp, %r12
addq $0x40, %r12
movq %rbx, %rdi
movq %r12, %rsi
callq 0x6170
movq 0x20(%r12), %rax
movq %rax, 0x20(%rbx)
cmpl %r14d, 0x10(%rsp)
jne 0x8e93e
movups 0xa0(%r15), %xmm0
movups 0xb0(%r15), %xmm1
movups 0xbd(%r15), %xmm2
movups %xmm2, 0xbd(%r13)
movups %xmm1, 0xb0(%r13)
movups %xmm0, 0xa0(%r13)
movl $0xd0, %eax
leaq (%rax,%r13), %rdi
leaq (%r15,%rax), %rsi
callq 0x1d4de
jmp 0x8e99f
leaq 0x68(%r13), %rdi
leaq 0x68(%r15), %rsi
callq 0x1d5b4
movups 0xa0(%r15), %xmm0
movups 0xb0(%r15), %xmm1
movups 0xbd(%r15), %xmm2
movups %xmm2, 0xbd(%r13)
movups %xmm1, 0xb0(%r13)
movups %xmm0, 0xa0(%r13)
movl $0xd0, %eax
leaq (%rax,%r13), %rdi
leaq (%r15,%rax), %rsi
callq 0x1d4de
movl $0xe8, %eax
leaq (%rax,%r13), %rdi
leaq (%r15,%rax), %rsi
callq 0x1e032
movl $0x120, %eax            # imm = 0x120
leaq (%rax,%r13), %rdi
leaq (%r15,%rax), %rsi
callq 0x6170
movq 0x140(%r15), %rax
movq %rax, 0x140(%r13)
movq 0x30(%rsp), %rbx
leaq 0x48(%rsp), %r13
movq 0xb0(%rsp), %rdi
callq 0x62e0
movq %rax, %r12
cmpq 0xa8(%rsp), %rax
leaq 0x88(%rsp), %rbp
jne 0x8e532
addq $0xd8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x319e0(%rip), %rdi     # 0xc03e8
leaq 0x319f4(%rip), %rsi     # 0xc0403
leaq 0x31a07(%rip), %rcx     # 0xc041d
movl $0x276, %edx            # imm = 0x276
callq 0x61b0
leaq 0x31a92(%rip), %rdi     # 0xc04b9
leaq 0x319d5(%rip), %rsi     # 0xc0403
leaq 0x319e8(%rip), %rcx     # 0xc041d
movl $0x27d, %edx            # imm = 0x27D
callq 0x61b0
movq %rax, %rbx
jmp 0x8ea63
movq %rax, %rbx
movq 0x48(%rsp), %rdi
leaq 0x58(%rsp), %rax
cmpq %rax, %rdi
je 0x8ea63
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x6260
movq 0x88(%rsp), %rdi
leaq 0x98(%rsp), %rax
cmpq %rax, %rdi
je 0x8ea8d
movq 0x98(%rsp), %rsi
incq %rsi
callq 0x6260
jmp 0x8ea8d
movq %rax, %rbx
movq 0xb8(%rsp), %rdi
leaq 0xc8(%rsp), %rax
cmpq %rax, %rdi
je 0x8eac1
movq 0xc8(%rsp), %rsi
incq %rsi
callq 0x6260
jmp 0x8eac1
movq %rax, %rbx
leaq 0x48(%rsp), %rdi
callq 0xa70fa
movq %rbx, %rdi
callq 0x64a0
nop