// File: rossy[P]crossc/SPIRV-Cross/spirv_glsl.cpp
// Function: spirv_cross::CompilerGLSL::attempt_emit_loop_header(spirv_cross::SPIRBlock&, spirv_cross::SPIRBlock::Method)
bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method method)
{
	SPIRBlock::ContinueBlockType continue_type = continue_block_type(get<SPIRBlock>(block.continue_block));

	if (method == SPIRBlock::MergeToSelectForLoop || method == SPIRBlock::MergeToSelectContinueForLoop)
	{
		uint32_t current_count = statement_count;
		// If we're trying to create a true for loop,
		// we need to make sure that all opcodes before branch statement do not actually emit any code.
		// We can then take the condition expression and create a for (; cond ; ) { body; } structure instead.
		emit_block_instructions(block);

		bool condition_is_temporary = forced_temporaries.find(block.condition) == end(forced_temporaries);

		// This can work! We only did trivial things which could be forwarded in block body!
		if (current_count == statement_count && condition_is_temporary)
		{
			switch (continue_type)
			{
			case SPIRBlock::ForLoop:
			{
				// This block may be a dominating block, so make sure we flush undeclared variables before building the for loop header.
				flush_undeclared_variables(block);

				// Important that we do this in this order because
				// emitting the continue block can invalidate the condition expression.
				auto initializer = emit_for_loop_initializers(block);
				auto condition = to_expression(block.condition);
				emit_block_hints(block);
				if (method != SPIRBlock::MergeToSelectContinueForLoop)
				{
					auto continue_block = emit_continue_block(block.continue_block);
					statement("for (", initializer, "; ", condition, "; ", continue_block, ")");
				}
				else
					statement("for (", initializer, "; ", condition, "; )");
				break;
			}

			case SPIRBlock::WhileLoop:
				// This block may be a dominating block, so make sure we flush undeclared variables before building the while loop header.
				flush_undeclared_variables(block);
				emit_while_loop_initializers(block);
				emit_block_hints(block);
				statement("while (", to_expression(block.condition), ")");
				break;

			default:
				SPIRV_CROSS_THROW("For/while loop detected, but need while/for loop semantics.");
			}

			begin_scope();
			return true;
		}
		else
		{
			block.disable_block_optimization = true;
			force_recompile = true;
			begin_scope(); // We'll see an end_scope() later.
			return false;
		}
	}
	else if (method == SPIRBlock::MergeToDirectForLoop)
	{
		auto &child = get<SPIRBlock>(block.next_block);

		// This block may be a dominating block, so make sure we flush undeclared variables before building the for loop header.
		flush_undeclared_variables(child);

		uint32_t current_count = statement_count;

		// If we're trying to create a true for loop,
		// we need to make sure that all opcodes before branch statement do not actually emit any code.
		// We can then take the condition expression and create a for (; cond ; ) { body; } structure instead.
		emit_block_instructions(child);

		bool condition_is_temporary = forced_temporaries.find(child.condition) == end(forced_temporaries);

		if (current_count == statement_count && condition_is_temporary)
		{
			propagate_loop_dominators(child);

			switch (continue_type)
			{
			case SPIRBlock::ForLoop:
			{
				// Important that we do this in this order because
				// emitting the continue block can invalidate the condition expression.
				auto initializer = emit_for_loop_initializers(block);
				auto condition = to_expression(child.condition);
				auto continue_block = emit_continue_block(block.continue_block);
				emit_block_hints(block);
				statement("for (", initializer, "; ", condition, "; ", continue_block, ")");
				break;
			}

			case SPIRBlock::WhileLoop:
				emit_while_loop_initializers(block);
				emit_block_hints(block);
				statement("while (", to_expression(child.condition), ")");
				break;

			default:
				SPIRV_CROSS_THROW("For/while loop detected, but need while/for loop semantics.");
			}

			begin_scope();
			branch(child.self, child.true_block);
			return true;
		}
		else
		{
			block.disable_block_optimization = true;
			force_recompile = true;
			begin_scope(); // We'll see an end_scope() later.
			return false;
		}
	}
	else
		return false;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x210, %rsp            # imm = 0x210
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl %edx, -0x1c(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x1c0(%rbp)
movq -0x18(%rbp), %rax
movl 0x20(%rax), %esi
callq 0x87d0
movq -0x1c0(%rbp), %rdi
movq %rax, %rsi
callq 0x23df0
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x1c(%rbp)
je 0x9af6f
cmpl $0x2, -0x1c(%rbp)
jne 0x9b335
movq -0x1c0(%rbp), %rdi
movl 0x750(%rdi), %eax
movl %eax, -0x24(%rbp)
movq -0x18(%rbp), %rsi
callq 0x891d0
movq -0x1c0(%rbp), %rdi
addq $0x228, %rdi            # imm = 0x228
movq -0x18(%rbp), %rsi
addq $0x28, %rsi
callq 0x2ff00
movq -0x1c0(%rbp), %rdi
movq %rax, -0x30(%rbp)
addq $0x228, %rdi            # imm = 0x228
callq 0x2ff30
movq %rax, -0x38(%rbp)
leaq -0x30(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x2eb30
movq -0x1c0(%rbp), %rcx
andb $0x1, %al
movb %al, -0x25(%rbp)
movl -0x24(%rbp), %eax
cmpl 0x750(%rcx), %eax
jne 0x9b30e
testb $0x1, -0x25(%rbp)
je 0x9b30e
movl -0x20(%rbp), %eax
movl %eax, -0x1c4(%rbp)
subl $0x1, %eax
je 0x9b014
jmp 0x9b000
movl -0x1c4(%rbp), %eax
subl $0x2, %eax
je 0x9b177
jmp 0x9b223
movq -0x1c0(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x9b760
movq -0x1c0(%rbp), %rsi
movq -0x18(%rbp), %rdx
leaq -0x58(%rbp), %rdi
callq 0x9a560
movq -0x1c0(%rbp), %rsi
movq -0x18(%rbp), %rax
movl 0x28(%rax), %edx
leaq -0x78(%rbp), %rdi
callq 0x71b50
jmp 0x9b051
movq -0x1c0(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq (%rdi), %rax
movq 0x158(%rax), %rax
callq *%rax
jmp 0x9b06a
cmpl $0x2, -0x1c(%rbp)
je 0x9b11c
movq -0x1c0(%rbp), %rsi
movq -0x18(%rbp), %rax
movl 0x20(%rax), %edx
leaq -0xa8(%rbp), %rdi
callq 0x9a230
jmp 0x9b090
movq -0x1c0(%rbp), %rdi
leaq 0xa9e5b(%rip), %rcx     # 0x144ef9
movq %rsp, %rax
movq %rcx, 0x8(%rax)
leaq -0xa8(%rbp), %rcx
movq %rcx, (%rax)
leaq 0xa9e38(%rip), %rsi     # 0x144eee
leaq 0xa9e37(%rip), %r9      # 0x144ef4
leaq -0x58(%rbp), %rdx
leaq -0x78(%rbp), %r8
movq %r9, %rcx
callq 0xa89e0
jmp 0x9b0cf
leaq -0xa8(%rbp), %rdi
callq 0x7708
jmp 0x9b149
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x9b169
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x9b160
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x7708
jmp 0x9b160
movq -0x1c0(%rbp), %rdi
leaq 0xa9dc4(%rip), %rsi     # 0x144eee
leaq 0xa9dc3(%rip), %rcx     # 0x144ef4
leaq 0xa9dbf(%rip), %r9      # 0x144ef7
leaq -0x58(%rbp), %rdx
leaq -0x78(%rbp), %r8
callq 0xa8b60
jmp 0x9b147
jmp 0x9b149
leaq -0x78(%rbp), %rdi
callq 0x7708
leaq -0x58(%rbp), %rdi
callq 0x7708
jmp 0x9b2f9
leaq -0x78(%rbp), %rdi
callq 0x7708
leaq -0x58(%rbp), %rdi
callq 0x7708
jmp 0x9b74f
movq -0x1c0(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x9b760
movq -0x1c0(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x9a480
movq -0x1c0(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq (%rdi), %rax
movq 0x158(%rax), %rax
callq *%rax
movq -0x1c0(%rbp), %rsi
movq -0x18(%rbp), %rax
movl 0x28(%rax), %edx
leaq -0xc8(%rbp), %rdi
movq %rdi, -0x1d0(%rbp)
callq 0x71b50
movq -0x1c0(%rbp), %rdi
movq -0x1d0(%rbp), %rdx
leaq 0xa9d17(%rip), %rsi     # 0x144efb
leaq 0xa9d0e(%rip), %rcx     # 0x144ef9
callq 0xa8cb0
jmp 0x9b1f2
leaq -0xc8(%rbp), %rdi
callq 0x7708
jmp 0x9b2f9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x7708
jmp 0x9b74f
movb $0x1, -0xea(%rbp)
movl $0x10, %edi
callq 0x71a0
movq %rax, -0x1e0(%rbp)
leaq -0xe9(%rbp), %rdi
movq %rdi, -0x1d8(%rbp)
callq 0x7650
movq -0x1d8(%rbp), %rdx
leaq 0xa9ca7(%rip), %rsi     # 0x144f03
leaq -0xe8(%rbp), %rdi
callq 0x7520
jmp 0x9b26a
movq -0x1e0(%rbp), %rdi
leaq -0xe8(%rbp), %rsi
callq 0x9c50
jmp 0x9b27f
movq -0x1e0(%rbp), %rdi
movb $0x0, -0xea(%rbp)
leaq 0x112b44(%rip), %rsi    # 0x1addd8
leaq -0x9160b(%rip), %rdx    # 0x9c90
callq 0x7610
jmp 0x9b758
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x9b2d1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0x7708
leaq -0xe9(%rbp), %rdi
callq 0x73d0
testb $0x1, -0xea(%rbp)
jne 0x9b2e8
jmp 0x9b2f4
movq -0x1e0(%rbp), %rdi
callq 0x72c0
jmp 0x9b74f
movq -0x1c0(%rbp), %rdi
callq 0x5c200
movb $0x1, -0x1(%rbp)
jmp 0x9b741
movq -0x1c0(%rbp), %rdi
movq -0x18(%rbp), %rax
movb $0x1, 0xb0(%rax)
movb $0x1, 0x1d0(%rdi)
callq 0x5c200
movb $0x0, -0x1(%rbp)
jmp 0x9b741
cmpl $0x1, -0x1c(%rbp)
jne 0x9b73d
movq -0x1c0(%rbp), %rdi
movq -0x18(%rbp), %rax
movl 0x18(%rax), %esi
callq 0x87d0
movq -0x1c0(%rbp), %rdi
movq %rax, -0xf8(%rbp)
movq -0xf8(%rbp), %rsi
callq 0x9b760
movq -0x1c0(%rbp), %rdi
movl 0x750(%rdi), %eax
movl %eax, -0xfc(%rbp)
movq -0xf8(%rbp), %rsi
callq 0x891d0
movq -0x1c0(%rbp), %rdi
addq $0x228, %rdi            # imm = 0x228
movq -0xf8(%rbp), %rsi
addq $0x28, %rsi
callq 0x2ff00
movq -0x1c0(%rbp), %rdi
movq %rax, -0x108(%rbp)
addq $0x228, %rdi            # imm = 0x228
callq 0x2ff30
movq %rax, -0x110(%rbp)
leaq -0x108(%rbp), %rdi
leaq -0x110(%rbp), %rsi
callq 0x2eb30
movq -0x1c0(%rbp), %rcx
andb $0x1, %al
movb %al, -0xfd(%rbp)
movl -0xfc(%rbp), %eax
cmpl 0x750(%rcx), %eax
jne 0x9b719
testb $0x1, -0xfd(%rbp)
je 0x9b719
movq -0x1c0(%rbp), %rdi
movq -0xf8(%rbp), %rsi
callq 0x9a040
movl -0x20(%rbp), %eax
movl %eax, -0x1e4(%rbp)
subl $0x1, %eax
je 0x9b442
jmp 0x9b42e
movl -0x1e4(%rbp), %eax
subl $0x2, %eax
je 0x9b575
jmp 0x9b614
movq -0x1c0(%rbp), %rsi
movq -0x18(%rbp), %rdx
leaq -0x130(%rbp), %rdi
callq 0x9a560
movq -0x1c0(%rbp), %rsi
movq -0xf8(%rbp), %rax
movl 0x28(%rax), %edx
leaq -0x150(%rbp), %rdi
callq 0x71b50
jmp 0x9b478
movq -0x1c0(%rbp), %rsi
movq -0x18(%rbp), %rax
movl 0x20(%rax), %edx
leaq -0x170(%rbp), %rdi
callq 0x9a230
jmp 0x9b494
movq -0x1c0(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq (%rdi), %rax
movq 0x158(%rax), %rax
callq *%rax
jmp 0x9b4ad
movq -0x1c0(%rbp), %rdi
leaq 0xa9a3e(%rip), %rcx     # 0x144ef9
movq %rsp, %rax
movq %rcx, 0x8(%rax)
leaq -0x170(%rbp), %rcx
movq %rcx, (%rax)
leaq 0xa9a1b(%rip), %rsi     # 0x144eee
leaq 0xa9a1a(%rip), %r9      # 0x144ef4
leaq -0x130(%rbp), %rdx
leaq -0x150(%rbp), %r8
movq %r9, %rcx
callq 0xa89e0
jmp 0x9b4f2
leaq -0x170(%rbp), %rdi
callq 0x7708
leaq -0x150(%rbp), %rdi
callq 0x7708
leaq -0x130(%rbp), %rdi
callq 0x7708
jmp 0x9b6e7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x9b564
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x9b558
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x170(%rbp), %rdi
callq 0x7708
leaq -0x150(%rbp), %rdi
callq 0x7708
leaq -0x130(%rbp), %rdi
callq 0x7708
jmp 0x9b74f
movq -0x1c0(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x9a480
movq -0x1c0(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq (%rdi), %rax
movq 0x158(%rax), %rax
callq *%rax
movq -0x1c0(%rbp), %rsi
movq -0xf8(%rbp), %rax
movl 0x28(%rax), %edx
leaq -0x190(%rbp), %rdi
movq %rdi, -0x1f0(%rbp)
callq 0x71b50
movq -0x1c0(%rbp), %rdi
movq -0x1f0(%rbp), %rdx
leaq 0xa9926(%rip), %rsi     # 0x144efb
leaq 0xa991d(%rip), %rcx     # 0x144ef9
callq 0xa8cb0
jmp 0x9b5e3
leaq -0x190(%rbp), %rdi
callq 0x7708
jmp 0x9b6e7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x190(%rbp), %rdi
callq 0x7708
jmp 0x9b74f
movb $0x1, -0x1b2(%rbp)
movl $0x10, %edi
callq 0x71a0
movq %rax, -0x200(%rbp)
leaq -0x1b1(%rbp), %rdi
movq %rdi, -0x1f8(%rbp)
callq 0x7650
movq -0x1f8(%rbp), %rdx
leaq 0xa98b6(%rip), %rsi     # 0x144f03
leaq -0x1b0(%rbp), %rdi
callq 0x7520
jmp 0x9b65b
movq -0x200(%rbp), %rdi
leaq -0x1b0(%rbp), %rsi
callq 0x9c50
jmp 0x9b670
movq -0x200(%rbp), %rdi
movb $0x0, -0x1b2(%rbp)
leaq 0x112753(%rip), %rsi    # 0x1addd8
leaq -0x919fc(%rip), %rdx    # 0x9c90
callq 0x7610
jmp 0x9b758
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x9b6c2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x1b0(%rbp), %rdi
callq 0x7708
leaq -0x1b1(%rbp), %rdi
callq 0x73d0
testb $0x1, -0x1b2(%rbp)
jne 0x9b6d9
jmp 0x9b6e5
movq -0x200(%rbp), %rdi
callq 0x72c0
jmp 0x9b74f
movq -0x1c0(%rbp), %rdi
callq 0x5c200
movq -0x1c0(%rbp), %rdi
movq -0xf8(%rbp), %rax
movl 0x8(%rax), %esi
movq -0xf8(%rbp), %rax
movl 0x2c(%rax), %edx
callq 0x99b90
movb $0x1, -0x1(%rbp)
jmp 0x9b741
movq -0x1c0(%rbp), %rdi
movq -0x18(%rbp), %rax
movb $0x1, 0xb0(%rax)
movb $0x1, 0x1d0(%rdi)
callq 0x5c200
movb $0x0, -0x1(%rbp)
jmp 0x9b741
movb $0x0, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x210, %rsp            # imm = 0x210
popq %rbp
retq
movq -0x80(%rbp), %rdi
callq 0x7640
nopl (%rax,%rax)