// File: rossy[P]crossc/SPIRV-Cross/spirv_cross.cpp
// Function: spirv_cross::Compiler::BufferAccessHandler::handle(spv::Op, unsigned int const*, unsigned int)
bool Compiler::BufferAccessHandler::handle(Op opcode, const uint32_t *args, uint32_t length)
{
	if (opcode != OpAccessChain && opcode != OpInBoundsAccessChain)
		return true;

	// Invalid SPIR-V.
	if (length < 4)
		return false;

	if (args[2] != id)
		return true;

	// Don't bother traversing the entire access chain tree yet.
	// If we access a struct member, assume we access the entire member.
	uint32_t index = compiler.get<SPIRConstant>(args[3]).scalar();

	// Seen this index already.
	if (seen.find(index) != end(seen))
		return true;
	seen.insert(index);

	auto &type = compiler.expression_type(id);
	uint32_t offset = compiler.type_struct_member_offset(type, index);

	size_t range;
	// If we have another member in the struct, deduce the range by looking at the next member.
	// This is okay since structs in SPIR-V can have padding, but Offset decoration must be
	// monotonically increasing.
	// Of course, this doesn't take into account if the SPIR-V for some reason decided to add
	// very large amounts of padding, but that's not really a big deal.
	if (index + 1 < type.member_types.size())
	{
		range = compiler.type_struct_member_offset(type, index + 1) - offset;
	}
	else
	{
		// No padding, so just deduce it from the size of the member directly.
		range = compiler.get_declared_struct_member_size(type, index);
	}

	ranges.push_back({ index, offset, range });
	return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq %rdx, -0x20(%rbp)
movl %ecx, -0x24(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x80(%rbp)
cmpl $0x41, -0x14(%rbp)
je 0x24b66
cmpl $0x42, -0x14(%rbp)
je 0x24b66
movb $0x1, -0x1(%rbp)
jmp 0x24ccc
cmpl $0x4, -0x24(%rbp)
jae 0x24b75
movb $0x0, -0x1(%rbp)
jmp 0x24ccc
movq -0x80(%rbp), %rcx
movq -0x20(%rbp), %rax
movl 0x8(%rax), %eax
cmpl 0x18(%rcx), %eax
je 0x24b8e
movb $0x1, -0x1(%rbp)
jmp 0x24ccc
movq -0x80(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x20(%rbp), %rax
movl 0xc(%rax), %esi
callq 0x2e950
movq %rax, %rdi
xorl %edx, %edx
movl %edx, %esi
callq 0x2f560
movq -0x80(%rbp), %rdi
movl %eax, -0x28(%rbp)
addq $0x20, %rdi
leaq -0x28(%rbp), %rsi
callq 0x2ff00
movq -0x80(%rbp), %rdi
movq %rax, -0x30(%rbp)
addq $0x20, %rdi
callq 0x2ff30
movq %rax, -0x38(%rbp)
leaq -0x30(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x2fed0
testb $0x1, %al
jne 0x24bea
jmp 0x24bf3
movb $0x1, -0x1(%rbp)
jmp 0x24ccc
movq -0x80(%rbp), %rdi
addq $0x20, %rdi
leaq -0x28(%rbp), %rsi
callq 0x2e890
movq %rax, %rcx
movq -0x80(%rbp), %rax
movq %rcx, -0x48(%rbp)
movb %dl, -0x40(%rbp)
movq 0x8(%rax), %rdi
movl 0x18(%rax), %esi
callq 0x1f760
movq %rax, %rcx
movq -0x80(%rbp), %rax
movq %rcx, -0x50(%rbp)
movq 0x8(%rax), %rdi
movq -0x50(%rbp), %rsi
movl -0x28(%rbp), %edx
callq 0x24050
movl %eax, -0x54(%rbp)
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, %eax
movq %rax, -0x88(%rbp)
movq -0x50(%rbp), %rdi
addq $0x68, %rdi
callq 0x8650
movq %rax, %rcx
movq -0x88(%rbp), %rax
cmpq %rcx, %rax
jae 0x24c89
movq -0x80(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x50(%rbp), %rsi
movl -0x28(%rbp), %edx
addl $0x1, %edx
callq 0x24050
subl -0x54(%rbp), %eax
movl %eax, %eax
movq %rax, -0x60(%rbp)
jmp 0x24ca2
movq -0x80(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x50(%rbp), %rsi
movl -0x28(%rbp), %edx
movq (%rdi), %rax
callq *0x30(%rax)
movq %rax, -0x60(%rbp)
movq -0x80(%rbp), %rax
movq 0x10(%rax), %rdi
movl -0x28(%rbp), %eax
movl %eax, -0x78(%rbp)
movl -0x54(%rbp), %eax
movq %rax, -0x70(%rbp)
movq -0x60(%rbp), %rax
movq %rax, -0x68(%rbp)
leaq -0x78(%rbp), %rsi
callq 0x2ff60
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x90, %rsp
popq %rbp
retq
nopw (%rax,%rax)