// File: rossy[P]crossc/SPIRV-Cross/spirv_glsl.cpp
// Function: spirv_cross::CompilerGLSL::emit_block_chain(spirv_cross::SPIRBlock&)
void CompilerGLSL::emit_block_chain(SPIRBlock &block)
{
	propagate_loop_dominators(block);

	bool select_branch_to_true_block = false;
	bool skip_direct_branch = false;
	bool emitted_for_loop_header = false;
	bool force_complex_continue_block = false;

	emit_hoisted_temporaries(block.declare_temporary);

	SPIRBlock::ContinueBlockType continue_type = SPIRBlock::ContinueNone;
	if (block.continue_block)
		continue_type = continue_block_type(get<SPIRBlock>(block.continue_block));

	// If we have loop variables, stop masking out access to the variable now.
	for (auto var : block.loop_variables)
		get<SPIRVariable>(var).loop_variable_enable = true;

	// This is the method often used by spirv-opt to implement loops.
	// The loop header goes straight into the continue block.
	// However, don't attempt this on ESSL 1.0, because if a loop variable is used in a continue block,
	// it *MUST* be used in the continue block. This loop method will not work.
	if (!is_legacy_es() && block_is_loop_candidate(block, SPIRBlock::MergeToSelectContinueForLoop))
	{
		flush_undeclared_variables(block);
		if (attempt_emit_loop_header(block, SPIRBlock::MergeToSelectContinueForLoop))
		{
			select_branch_to_true_block = true;
			emitted_for_loop_header = true;
			force_complex_continue_block = true;
		}
	}
	// This is the older loop behavior in glslang which branches to loop body directly from the loop header.
	else if (block_is_loop_candidate(block, SPIRBlock::MergeToSelectForLoop))
	{
		flush_undeclared_variables(block);
		if (attempt_emit_loop_header(block, SPIRBlock::MergeToSelectForLoop))
		{
			// The body of while, is actually just the true block, so always branch there unconditionally.
			select_branch_to_true_block = true;
			emitted_for_loop_header = true;
		}
	}
	// This is the newer loop behavior in glslang which branches from Loop header directly to
	// a new block, which in turn has a OpBranchSelection without a selection merge.
	else if (block_is_loop_candidate(block, SPIRBlock::MergeToDirectForLoop))
	{
		flush_undeclared_variables(block);
		if (attempt_emit_loop_header(block, SPIRBlock::MergeToDirectForLoop))
		{
			skip_direct_branch = true;
			emitted_for_loop_header = true;
		}
	}
	else if (continue_type == SPIRBlock::DoWhileLoop)
	{
		flush_undeclared_variables(block);
		emit_while_loop_initializers(block);
		// We have some temporaries where the loop header is the dominator.
		// We risk a case where we have code like:
		// for (;;) { create-temporary; break; } consume-temporary;
		// so force-declare temporaries here.
		emit_hoisted_temporaries(block.potential_declare_temporary);
		statement("do");
		begin_scope();

		emit_block_instructions(block);
	}
	else if (block.merge == SPIRBlock::MergeLoop)
	{
		flush_undeclared_variables(block);
		emit_while_loop_initializers(block);

		// We have a generic loop without any distinguishable pattern like for, while or do while.
		get<SPIRBlock>(block.continue_block).complex_continue = true;
		continue_type = SPIRBlock::ComplexLoop;

		// We have some temporaries where the loop header is the dominator.
		// We risk a case where we have code like:
		// for (;;) { create-temporary; break; } consume-temporary;
		// so force-declare temporaries here.
		emit_hoisted_temporaries(block.potential_declare_temporary);
		statement("for (;;)");
		begin_scope();

		emit_block_instructions(block);
	}
	else
	{
		emit_block_instructions(block);
	}

	// If we didn't successfully emit a loop header and we had loop variable candidates, we have a problem
	// as writes to said loop variables might have been masked out, we need a recompile.
	if (!emitted_for_loop_header && !block.loop_variables.empty())
	{
		force_recompile = true;
		for (auto var : block.loop_variables)
			get<SPIRVariable>(var).loop_variable = false;
		block.loop_variables.clear();
	}

	flush_undeclared_variables(block);
	bool emit_next_block = true;

	// Handle end of block.
	switch (block.terminator)
	{
	case SPIRBlock::Direct:
		// True when emitting complex continue block.
		if (block.loop_dominator == block.next_block)
		{
			branch(block.self, block.next_block);
			emit_next_block = false;
		}
		// True if MergeToDirectForLoop succeeded.
		else if (skip_direct_branch)
			emit_next_block = false;
		else if (is_continue(block.next_block) || is_break(block.next_block) || is_conditional(block.next_block))
		{
			branch(block.self, block.next_block);
			emit_next_block = false;
		}
		break;

	case SPIRBlock::Select:
		// True if MergeToSelectForLoop or MergeToSelectContinueForLoop succeeded.
		if (select_branch_to_true_block)
		{
			if (force_complex_continue_block)
			{
				assert(block.true_block == block.continue_block);

				// We're going to emit a continue block directly here, so make sure it's marked as complex.
				auto &complex_continue = get<SPIRBlock>(block.continue_block).complex_continue;
				bool old_complex = complex_continue;
				complex_continue = true;
				branch(block.self, block.true_block);
				complex_continue = old_complex;
			}
			else
				branch(block.self, block.true_block);
		}
		else
			branch(block.self, block.condition, block.true_block, block.false_block);
		break;

	case SPIRBlock::MultiSelect:
	{
		auto &type = expression_type(block.condition);
		bool uint32_t_case = type.basetype == SPIRType::UInt;

		SPIRBlock *old_emitting_switch = current_emitting_switch;
		current_emitting_switch = &block;

		if (block.need_ladder_break)
			statement("bool _", block.self, "_ladder_break = false;");

		emit_block_hints(block);
		statement("switch (", to_expression(block.condition), ")");
		begin_scope();

		// Multiple case labels can branch to same block, so find all unique blocks.
		bool emitted_default = false;
		unordered_set<uint32_t> emitted_blocks;

		for (auto &c : block.cases)
		{
			if (emitted_blocks.count(c.block) != 0)
				continue;

			// Emit all case labels which branch to our target.
			// FIXME: O(n^2), revisit if we hit shaders with 100++ case labels ...
			for (auto &other_case : block.cases)
			{
				if (other_case.block == c.block)
				{
					auto case_value = uint32_t_case ? convert_to_string(uint32_t(other_case.value)) :
					                                  convert_to_string(int32_t(other_case.value));
					statement("case ", case_value, ":");
				}
			}

			// Maybe we share with default block?
			if (block.default_block == c.block)
			{
				statement("default:");
				emitted_default = true;
			}

			// Complete the target.
			emitted_blocks.insert(c.block);

			begin_scope();
			branch(block.self, c.block);
			end_scope();
		}

		if (!emitted_default)
		{
			if (block.default_block != block.next_block)
			{
				statement("default:");
				begin_scope();
				if (is_break(block.default_block))
					SPIRV_CROSS_THROW("Cannot break; out of a switch statement and out of a loop at the same time ...");
				branch(block.self, block.default_block);
				end_scope();
			}
			else if (flush_phi_required(block.self, block.next_block))
			{
				statement("default:");
				begin_scope();
				flush_phi(block.self, block.next_block);
				statement("break;");
				end_scope();
			}
		}

		end_scope();

		if (block.need_ladder_break)
		{
			statement("if (_", block.self, "_ladder_break)");
			begin_scope();
			statement("break;");
			end_scope();
		}

		current_emitting_switch = old_emitting_switch;
		break;
	}

	case SPIRBlock::Return:
		for (auto &line : current_function->fixup_hooks_out)
			line();

		if (processing_entry_point)
			emit_fixup();

		if (block.return_value)
		{
			auto &type = expression_type(block.return_value);
			if (!type.array.empty() && !backend.can_return_array)
			{
				// If we cannot return arrays, we will have a special out argument we can write to instead.
				// The backend is responsible for setting this up, and redirection the return values as appropriate.
				if (ir.ids.at(block.return_value).get_type() != TypeUndef)
					emit_array_copy("SPIRV_Cross_return_value", block.return_value);

				if (!block_is_outside_flow_control_from_block(get<SPIRBlock>(current_function->entry_block), block) ||
				    block.loop_dominator != SPIRBlock::NoDominator)
				{
					statement("return;");
				}
			}
			else
			{
				// OpReturnValue can return Undef, so don't emit anything for this case.
				if (ir.ids.at(block.return_value).get_type() != TypeUndef)
					statement("return ", to_expression(block.return_value), ";");
			}
		}
		// If this block is the very final block and not called from control flow,
		// we do not need an explicit return which looks out of place. Just end the function here.
		// In the very weird case of for(;;) { return; } executing return is unconditional,
		// but we actually need a return here ...
		else if (!block_is_outside_flow_control_from_block(get<SPIRBlock>(current_function->entry_block), block) ||
		         block.loop_dominator != SPIRBlock::NoDominator)
		{
			statement("return;");
		}
		break;

	case SPIRBlock::Kill:
		statement(backend.discard_literal, ";");
		break;

	case SPIRBlock::Unreachable:
		emit_next_block = false;
		break;

	default:
		SPIRV_CROSS_THROW("Unimplemented block terminator.");
	}

	if (block.next_block && emit_next_block)
	{
		// If we hit this case, we're dealing with an unconditional branch, which means we will output
		// that block after this. If we had selection merge, we already flushed phi variables.
		if (block.merge != SPIRBlock::MergeSelection)
			flush_phi(block.self, block.next_block);

		// For merge selects we might have ignored the fact that a merge target
		// could have been a break; or continue;
		// We will need to deal with it here.
		if (is_loop_break(block.next_block))
		{
			// Cannot check for just break, because switch statements will also use break.
			assert(block.merge == SPIRBlock::MergeSelection);
			statement("break;");
		}
		else if (is_continue(block.next_block))
		{
			assert(block.merge == SPIRBlock::MergeSelection);
			branch_to_continue(block.self, block.next_block);
		}
		else
			emit_block_chain(get<SPIRBlock>(block.next_block));
	}

	if (block.merge == SPIRBlock::MergeLoop)
	{
		if (continue_type == SPIRBlock::DoWhileLoop)
		{
			// Make sure that we run the continue block to get the expressions set, but this
			// should become an empty string.
			// We have no fallbacks if we cannot forward everything to temporaries ...
			auto statements = emit_continue_block(block.continue_block);
			if (!statements.empty())
			{
				// The DoWhile block has side effects, force ComplexLoop pattern next pass.
				get<SPIRBlock>(block.continue_block).complex_continue = true;
				force_recompile = true;
			}

			end_scope_decl(join("while (", to_expression(get<SPIRBlock>(block.continue_block).condition), ")"));
		}
		else
			end_scope();

		// We cannot break out of two loops at once, so don't check for break; here.
		// Using block.self as the "from" block isn't quite right, but it has the same scope
		// and dominance structure, so it's fine.
		if (is_continue(block.merge_block))
			branch_to_continue(block.self, block.merge_block);
		else
			emit_block_chain(get<SPIRBlock>(block.merge_block));
	}

	// Forget about control dependent expressions now.
	block.invalidate_expressions.clear();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x300, %rsp            # imm = 0x300
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x288(%rbp)
movq -0x10(%rbp), %rsi
callq 0x9a040
movq -0x288(%rbp), %rdi
movb $0x0, -0x11(%rbp)
movb $0x0, -0x12(%rbp)
movb $0x0, -0x13(%rbp)
movb $0x0, -0x14(%rbp)
movq -0x10(%rbp), %rsi
addq $0x68, %rsi
callq 0x9b8a0
movl $0x0, -0x18(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x0, 0x20(%rax)
je 0x98351
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x20(%rax), %esi
callq 0x87d0
movq -0x288(%rbp), %rdi
movq %rax, %rsi
callq 0x23df0
movl %eax, -0x18(%rbp)
movq -0x10(%rbp), %rax
addq $0xd0, %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rdi
callq 0x86d0
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rdi
callq 0x8700
movq %rax, -0x30(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x8730
testb $0x1, %al
jne 0x9838c
jmp 0x983b8
leaq -0x28(%rbp), %rdi
callq 0x8770
movq -0x288(%rbp), %rdi
movl (%rax), %eax
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %esi
callq 0xfec0
movb $0x1, 0x65(%rax)
leaq -0x28(%rbp), %rdi
callq 0x8790
jmp 0x98379
movq -0x288(%rbp), %rdi
callq 0xa0800
testb $0x1, %al
jne 0x9841f
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl $0x2, %edx
callq 0x23620
testb $0x1, %al
jne 0x983e3
jmp 0x9841f
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x9b760
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl $0x2, %edx
callq 0x9af20
testb $0x1, %al
jne 0x9840e
jmp 0x9841a
movb $0x1, -0x11(%rbp)
movb $0x1, -0x13(%rbp)
movb $0x1, -0x14(%rbp)
jmp 0x985df
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
xorl %edx, %edx
callq 0x23620
testb $0x1, %al
jne 0x98437
jmp 0x9846c
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x9b760
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
xorl %edx, %edx
callq 0x9af20
testb $0x1, %al
jne 0x9845f
jmp 0x98467
movb $0x1, -0x11(%rbp)
movb $0x1, -0x13(%rbp)
jmp 0x985dd
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl $0x1, %edx
callq 0x23620
testb $0x1, %al
jne 0x98487
jmp 0x984bf
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x9b760
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl $0x1, %edx
callq 0x9af20
testb $0x1, %al
jne 0x984b2
jmp 0x984ba
movb $0x1, -0x12(%rbp)
movb $0x1, -0x13(%rbp)
jmp 0x985db
cmpl $0x3, -0x18(%rbp)
jne 0x98530
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x9b760
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x9a480
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
addq $0x80, %rsi
callq 0x9b8a0
movq -0x288(%rbp), %rdi
leaq 0xa9838(%rip), %rsi     # 0x141d42
callq 0xa8e60
movq -0x288(%rbp), %rdi
callq 0x5c200
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x891d0
jmp 0x985d9
movq -0x10(%rbp), %rax
cmpl $0x1, 0x10(%rax)
jne 0x985c7
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x9b760
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x9a480
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x20(%rax), %esi
callq 0x87d0
movq -0x288(%rbp), %rdi
movb $0x1, 0xb1(%rax)
movl $0x4, -0x18(%rbp)
movq -0x10(%rbp), %rsi
addq $0x80, %rsi
callq 0x9b8a0
movq -0x288(%rbp), %rdi
leaq 0xac99b(%rip), %rsi     # 0x144f3f
callq 0xa8f80
movq -0x288(%rbp), %rdi
callq 0x5c200
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x891d0
jmp 0x985d7
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x891d0
jmp 0x985d9
jmp 0x985db
jmp 0x985dd
jmp 0x985df
testb $0x1, -0x13(%rbp)
jne 0x98686
movq -0x10(%rbp), %rdi
addq $0xd0, %rdi
callq 0x8690
testb $0x1, %al
jne 0x98686
movq -0x288(%rbp), %rax
movb $0x1, 0x1d0(%rax)
movq -0x10(%rbp), %rax
addq $0xd0, %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rdi
callq 0x86d0
movq %rax, -0x48(%rbp)
movq -0x40(%rbp), %rdi
callq 0x8700
movq %rax, -0x50(%rbp)
leaq -0x48(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0x8730
testb $0x1, %al
jne 0x9864a
jmp 0x98676
leaq -0x48(%rbp), %rdi
callq 0x8770
movq -0x288(%rbp), %rdi
movl (%rax), %eax
movl %eax, -0x54(%rbp)
movl -0x54(%rbp), %esi
callq 0xfec0
movb $0x0, 0x64(%rax)
leaq -0x48(%rbp), %rdi
callq 0x8790
jmp 0x98637
movq -0x10(%rbp), %rdi
addq $0xd0, %rdi
callq 0x8a00
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x9b760
movb $0x1, -0x55(%rbp)
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0x290(%rbp)
subl $0x5, %eax
ja 0x9921d
movq -0x290(%rbp), %rax
leaq 0xa8229(%rip), %rcx     # 0x1408ec
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x10(%rbp), %rax
movl 0xb4(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x18(%rcx), %eax
jne 0x986ff
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x10(%rbp), %rax
movl 0x18(%rax), %edx
callq 0x99b90
movb $0x0, -0x55(%rbp)
jmp 0x98774
testb $0x1, -0x12(%rbp)
je 0x9870b
movb $0x0, -0x55(%rbp)
jmp 0x98772
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x18(%rax), %esi
callq 0x2fdb0
testb $0x1, %al
jne 0x98752
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x18(%rax), %esi
callq 0xa82f0
testb $0x1, %al
jne 0x98752
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x18(%rax), %esi
callq 0xa84a0
testb $0x1, %al
jne 0x98752
jmp 0x98770
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x10(%rbp), %rax
movl 0x18(%rax), %edx
callq 0x99b90
movb $0x0, -0x55(%rbp)
jmp 0x98772
jmp 0x98774
jmp 0x992f9
testb $0x1, -0x11(%rbp)
je 0x98831
testb $0x1, -0x14(%rbp)
je 0x98815
movq -0x10(%rbp), %rax
movl 0x2c(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x20(%rcx), %eax
jne 0x9879f
jmp 0x987be
leaq 0xac7a2(%rip), %rdi     # 0x144f48
leaq 0xa8a7f(%rip), %rsi     # 0x14122c
movl $0x267f, %edx           # imm = 0x267F
leaq 0xac7b8(%rip), %rcx     # 0x144f71
callq 0x7260
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x20(%rax), %esi
callq 0x87d0
movq -0x288(%rbp), %rdi
addq $0xb1, %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
movb (%rax), %al
andb $0x1, %al
movb %al, -0x61(%rbp)
movq -0x60(%rbp), %rax
movb $0x1, (%rax)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x10(%rbp), %rax
movl 0x2c(%rax), %edx
callq 0x99b90
movb -0x61(%rbp), %cl
movq -0x60(%rbp), %rax
andb $0x1, %cl
movb %cl, (%rax)
jmp 0x9882f
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x10(%rbp), %rax
movl 0x2c(%rax), %edx
callq 0x99b90
jmp 0x9885a
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x10(%rbp), %rax
movl 0x28(%rax), %edx
movq -0x10(%rbp), %rax
movl 0x2c(%rax), %ecx
movq -0x10(%rbp), %rax
movl 0x30(%rax), %r8d
callq 0x99d50
jmp 0x992f9
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x28(%rax), %esi
callq 0x1f760
movq %rax, %rcx
movq -0x288(%rbp), %rax
movq %rcx, -0x70(%rbp)
movq -0x70(%rbp), %rcx
cmpl $0x5, 0xc(%rcx)
sete %cl
andb $0x1, %cl
movb %cl, -0x71(%rbp)
movq 0x418(%rax), %rcx
movq %rcx, -0x80(%rbp)
movq -0x10(%rbp), %rcx
movq %rcx, 0x418(%rax)
movq -0x10(%rbp), %rax
testb $0x1, 0xb2(%rax)
je 0x988d6
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rdx
addq $0x8, %rdx
leaq 0xac6e5(%rip), %rsi     # 0x144faf
leaq 0xac6e5(%rip), %rcx     # 0x144fb6
callq 0xa90a0
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq (%rdi), %rax
movq 0x158(%rax), %rax
callq *%rax
movq -0x288(%rbp), %rsi
movq -0x10(%rbp), %rax
movl 0x28(%rax), %edx
leaq -0xa0(%rbp), %rdi
movq %rdi, -0x298(%rbp)
callq 0x71b50
movq -0x288(%rbp), %rdi
movq -0x298(%rbp), %rdx
leaq 0xac6aa(%rip), %rsi     # 0x144fcd
leaq 0xac5cf(%rip), %rcx     # 0x144ef9
callq 0xa91d0
jmp 0x98931
leaq -0xa0(%rbp), %rdi
callq 0x7708
movq -0x288(%rbp), %rdi
callq 0x5c200
movb $0x0, -0xad(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0x13cb0
movq -0x10(%rbp), %rax
addq $0x98, %rax
movq %rax, -0xf0(%rbp)
movq -0xf0(%rbp), %rdi
callq 0x8810
movq %rax, -0xf8(%rbp)
movq -0xf0(%rbp), %rdi
callq 0x8840
movq %rax, -0x100(%rbp)
leaq -0xf8(%rbp), %rdi
leaq -0x100(%rbp), %rsi
callq 0x8870
testb $0x1, %al
jne 0x989af
jmp 0x98c24
leaq -0xf8(%rbp), %rdi
callq 0x88b0
movq %rax, -0x108(%rbp)
movq -0x108(%rbp), %rsi
addq $0x4, %rsi
leaq -0xe8(%rbp), %rdi
callq 0x13520
movq %rax, -0x2a0(%rbp)
jmp 0x989e2
movq -0x2a0(%rbp), %rax
cmpq $0x0, %rax
je 0x98a2e
jmp 0x98c13
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
leaq -0xa0(%rbp), %rdi
callq 0x7708
jmp 0x9960d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
jmp 0x98ebc
movq -0x10(%rbp), %rax
addq $0x98, %rax
movq %rax, -0x110(%rbp)
movq -0x110(%rbp), %rdi
callq 0x8810
movq %rax, -0x118(%rbp)
movq -0x110(%rbp), %rdi
callq 0x8840
movq %rax, -0x120(%rbp)
leaq -0x118(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0x8870
testb $0x1, %al
jne 0x98a81
jmp 0x98b67
leaq -0x118(%rbp), %rdi
callq 0x88b0
movq %rax, -0x128(%rbp)
movq -0x128(%rbp), %rax
movl 0x4(%rax), %eax
movq -0x108(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jne 0x98b54
testb $0x1, -0x71(%rbp)
je 0x98ada
movq -0x128(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x14c(%rbp)
leaq -0x148(%rbp), %rdi
leaq -0x14c(%rbp), %rsi
callq 0xa22d0
jmp 0x98ad8
jmp 0x98b00
movq -0x128(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x150(%rbp)
leaq -0x148(%rbp), %rdi
leaq -0x150(%rbp), %rsi
callq 0xa2330
jmp 0x98afe
jmp 0x98b00
movq -0x288(%rbp), %rdi
leaq 0xac4c8(%rip), %rsi     # 0x144fd6
leaq 0xa5726(%rip), %rcx     # 0x13e23b
leaq -0x148(%rbp), %rdx
callq 0xa9300
jmp 0x98b23
leaq -0x148(%rbp), %rdi
callq 0x7708
jmp 0x98b54
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
leaq -0x148(%rbp), %rdi
callq 0x7708
jmp 0x98ebc
jmp 0x98b56
leaq -0x118(%rbp), %rdi
callq 0x88d0
jmp 0x98a65
movq -0x10(%rbp), %rax
movl 0x34(%rax), %eax
movq -0x108(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jne 0x98b96
movq -0x288(%rbp), %rdi
leaq 0xac454(%rip), %rsi     # 0x144fdc
callq 0xa8f80
jmp 0x98b8f
movb $0x1, -0xad(%rbp)
movq -0x108(%rbp), %rsi
addq $0x4, %rsi
leaq -0xe8(%rbp), %rdi
callq 0x2e890
movb %dl, -0x2a9(%rbp)
movq %rax, -0x2a8(%rbp)
jmp 0x98bbc
movq -0x288(%rbp), %rdi
movb -0x2a9(%rbp), %al
movq -0x2a8(%rbp), %rcx
movq %rcx, -0x160(%rbp)
movb %al, -0x158(%rbp)
callq 0x5c200
jmp 0x98be4
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x108(%rbp), %rax
movl 0x4(%rax), %edx
callq 0x99b90
jmp 0x98c03
movq -0x288(%rbp), %rdi
callq 0x876c0
jmp 0x98c11
jmp 0x98c13
leaq -0xf8(%rbp), %rdi
callq 0x88d0
jmp 0x98993
testb $0x1, -0xad(%rbp)
jne 0x98e27
movq -0x10(%rbp), %rax
movl 0x34(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x18(%rcx), %eax
je 0x98d99
movq -0x288(%rbp), %rdi
leaq 0xac389(%rip), %rsi     # 0x144fdc
callq 0xa8f80
jmp 0x98c5a
movq -0x288(%rbp), %rdi
callq 0x5c200
jmp 0x98c68
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x34(%rax), %esi
callq 0xa82f0
movb %al, -0x2aa(%rbp)
jmp 0x98c83
movb -0x2aa(%rbp), %al
testb $0x1, %al
jne 0x98c92
jmp 0x98d6e
movb $0x1, -0x182(%rbp)
movl $0x10, %edi
callq 0x71a0
movq %rax, -0x2c0(%rbp)
leaq -0x181(%rbp), %rdi
movq %rdi, -0x2b8(%rbp)
callq 0x7650
movq -0x2b8(%rbp), %rdx
leaq 0xac31a(%rip), %rsi     # 0x144fe5
leaq -0x180(%rbp), %rdi
callq 0x7520
jmp 0x98cd9
movq -0x2c0(%rbp), %rdi
leaq -0x180(%rbp), %rsi
callq 0x9c50
jmp 0x98cee
movq -0x2c0(%rbp), %rdi
movb $0x0, -0x182(%rbp)
leaq 0x1150d5(%rip), %rsi    # 0x1addd8
leaq -0x8f07a(%rip), %rdx    # 0x9c90
callq 0x7610
jmp 0x99619
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
jmp 0x98d46
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
leaq -0x180(%rbp), %rdi
callq 0x7708
leaq -0x181(%rbp), %rdi
callq 0x73d0
testb $0x1, -0x182(%rbp)
jne 0x98d5d
jmp 0x98d69
movq -0x2c0(%rbp), %rdi
callq 0x72c0
jmp 0x98ebc
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
movl 0x34(%rax), %edx
callq 0x99b90
jmp 0x98d86
movq -0x288(%rbp), %rdi
callq 0x876c0
jmp 0x98d94
jmp 0x98e25
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
movl 0x18(%rax), %edx
callq 0x996c0
movb %al, -0x2c1(%rbp)
jmp 0x98db7
movb -0x2c1(%rbp), %al
testb $0x1, %al
jne 0x98dc3
jmp 0x98e23
movq -0x288(%rbp), %rdi
leaq 0xac20b(%rip), %rsi     # 0x144fdc
callq 0xa8f80
jmp 0x98dd8
movq -0x288(%rbp), %rdi
callq 0x5c200
jmp 0x98de6
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
movl 0x18(%rax), %edx
callq 0x99760
jmp 0x98dfe
movq -0x288(%rbp), %rdi
leaq 0xb3568(%rip), %rsi     # 0x14c374
callq 0x9e710
jmp 0x98e13
movq -0x288(%rbp), %rdi
callq 0x876c0
jmp 0x98e21
jmp 0x98e23
jmp 0x98e25
jmp 0x98e27
movq -0x288(%rbp), %rdi
callq 0x876c0
jmp 0x98e35
movq -0x10(%rbp), %rax
testb $0x1, 0xb2(%rax)
je 0x98e99
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rdx
addq $0x8, %rdx
leaq 0xac1dc(%rip), %rsi     # 0x145034
leaq 0xac1db(%rip), %rcx     # 0x14503a
callq 0xa9430
jmp 0x98e66
movq -0x288(%rbp), %rdi
callq 0x5c200
jmp 0x98e74
movq -0x288(%rbp), %rdi
leaq 0xb34f2(%rip), %rsi     # 0x14c374
callq 0x9e710
jmp 0x98e89
movq -0x288(%rbp), %rdi
callq 0x876c0
jmp 0x98e97
jmp 0x98e99
movq -0x288(%rbp), %rax
movq -0x80(%rbp), %rcx
movq %rcx, 0x418(%rax)
leaq -0xe8(%rbp), %rdi
callq 0x13900
jmp 0x992f9
leaq -0xe8(%rbp), %rdi
callq 0x13900
jmp 0x9960d
movq -0x288(%rbp), %rax
movq 0x148(%rax), %rax
addq $0x98, %rax
movq %rax, -0x190(%rbp)
movq -0x190(%rbp), %rdi
callq 0xa7e40
movq %rax, -0x198(%rbp)
movq -0x190(%rbp), %rdi
callq 0xa7e70
movq %rax, -0x1a0(%rbp)
leaq -0x198(%rbp), %rdi
leaq -0x1a0(%rbp), %rsi
callq 0xa7ea0
testb $0x1, %al
jne 0x98f27
jmp 0x98f54
leaq -0x198(%rbp), %rdi
callq 0xa7ee0
movq %rax, -0x1a8(%rbp)
movq -0x1a8(%rbp), %rdi
callq 0xa7f00
leaq -0x198(%rbp), %rdi
callq 0xa7f40
jmp 0x98f0e
movq -0x288(%rbp), %rax
testb $0x1, 0x5d8(%rax)
je 0x98f74
movq -0x288(%rbp), %rdi
movq (%rdi), %rax
callq *0xc0(%rax)
movq -0x10(%rbp), %rax
cmpl $0x0, 0x24(%rax)
je 0x9919c
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x24(%rax), %esi
callq 0x1f760
movq %rax, -0x1b0(%rbp)
movq -0x1b0(%rbp), %rdi
addq $0x20, %rdi
callq 0x8690
testb $0x1, %al
jne 0x990f9
movq -0x288(%rbp), %rax
testb $0x1, 0x62e(%rax)
jne 0x990f9
movq -0x288(%rbp), %rdi
addq $0x8, %rdi
addq $0x18, %rdi
movq -0x10(%rbp), %rax
movl 0x24(%rax), %eax
movl %eax, %esi
callq 0xbbc0
movq %rax, %rdi
callq 0xfa00
cmpl $0xd, %eax
je 0x990a5
leaq -0x1d1(%rbp), %rdi
movq %rdi, -0x2d0(%rbp)
callq 0x7650
movq -0x2d0(%rbp), %rdx
leaq 0xac032(%rip), %rsi     # 0x145049
leaq -0x1d0(%rbp), %rdi
callq 0x7520
jmp 0x99025
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x24(%rax), %edx
movq (%rdi), %rax
movq 0x150(%rax), %rax
leaq -0x1d0(%rbp), %rsi
callq *%rax
jmp 0x99048
leaq -0x1d0(%rbp), %rdi
callq 0x7708
leaq -0x1d1(%rbp), %rdi
callq 0x73d0
jmp 0x990a5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
jmp 0x99094
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
leaq -0x1d0(%rbp), %rdi
callq 0x7708
leaq -0x1d1(%rbp), %rdi
callq 0x73d0
jmp 0x9960d
movq -0x288(%rbp), %rdi
movq 0x148(%rdi), %rax
movl 0x60(%rax), %esi
callq 0x87d0
movq -0x288(%rbp), %rdi
movq %rax, %rsi
movq -0x10(%rbp), %rdx
callq 0x23b20
testb $0x1, %al
jne 0x990d4
jmp 0x990e1
movq -0x10(%rbp), %rax
cmpl $-0x1, 0xb4(%rax)
je 0x990f4
movq -0x288(%rbp), %rdi
leaq 0xabf73(%rip), %rsi     # 0x145062
callq 0xa9560
jmp 0x9919a
movq -0x288(%rbp), %rdi
addq $0x8, %rdi
addq $0x18, %rdi
movq -0x10(%rbp), %rax
movl 0x24(%rax), %eax
movl %eax, %esi
callq 0xbbc0
movq %rax, %rdi
callq 0xfa00
cmpl $0xd, %eax
je 0x99198
movq -0x288(%rbp), %rsi
movq -0x10(%rbp), %rax
movl 0x24(%rax), %edx
leaq -0x1f8(%rbp), %rdi
movq %rdi, -0x2d8(%rbp)
callq 0x71b50
movq -0x288(%rbp), %rdi
movq -0x2d8(%rbp), %rdx
leaq 0xabf11(%rip), %rsi     # 0x14506a
leaq 0xaff46(%rip), %rcx     # 0x1490a6
callq 0xa8cb0
jmp 0x99167
leaq -0x1f8(%rbp), %rdi
callq 0x7708
jmp 0x99198
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
leaq -0x1f8(%rbp), %rdi
callq 0x7708
jmp 0x9960d
jmp 0x9919a
jmp 0x991ed
movq -0x288(%rbp), %rdi
movq 0x148(%rdi), %rax
movl 0x60(%rax), %esi
callq 0x87d0
movq -0x288(%rbp), %rdi
movq %rax, %rsi
movq -0x10(%rbp), %rdx
callq 0x23b20
testb $0x1, %al
jne 0x991cb
jmp 0x991d8
movq -0x10(%rbp), %rax
cmpl $-0x1, 0xb4(%rax)
je 0x991eb
movq -0x288(%rbp), %rdi
leaq 0xabe7c(%rip), %rsi     # 0x145062
callq 0xa9560
jmp 0x991ed
jmp 0x992f9
movq -0x288(%rbp), %rdi
movq %rdi, %rsi
addq $0x5e0, %rsi            # imm = 0x5E0
leaq 0xafe9c(%rip), %rdx     # 0x1490a6
callq 0xa4f50
jmp 0x992f9
movb $0x0, -0x55(%rbp)
jmp 0x992f9
movb $0x1, -0x21a(%rbp)
movl $0x10, %edi
callq 0x71a0
movq %rax, -0x2e8(%rbp)
leaq -0x219(%rbp), %rdi
movq %rdi, -0x2e0(%rbp)
callq 0x7650
movq -0x2e0(%rbp), %rdx
leaq 0xabe1c(%rip), %rsi     # 0x145072
leaq -0x218(%rbp), %rdi
callq 0x7520
jmp 0x99264
movq -0x2e8(%rbp), %rdi
leaq -0x218(%rbp), %rsi
callq 0x9c50
jmp 0x99279
movq -0x2e8(%rbp), %rdi
movb $0x0, -0x21a(%rbp)
leaq 0x114b4a(%rip), %rsi    # 0x1addd8
leaq -0x8f605(%rip), %rdx    # 0x9c90
callq 0x7610
jmp 0x99619
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
jmp 0x992d1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
leaq -0x218(%rbp), %rdi
callq 0x7708
leaq -0x219(%rbp), %rdi
callq 0x73d0
testb $0x1, -0x21a(%rbp)
jne 0x992e8
jmp 0x992f4
movq -0x2e8(%rbp), %rdi
callq 0x72c0
jmp 0x9960d
movq -0x10(%rbp), %rax
cmpl $0x0, 0x18(%rax)
je 0x99417
testb $0x1, -0x55(%rbp)
je 0x99417
movq -0x10(%rbp), %rax
cmpl $0x2, 0x10(%rax)
je 0x99335
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x10(%rbp), %rax
movl 0x18(%rax), %edx
callq 0x99760
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x18(%rax), %esi
callq 0xa8330
testb $0x1, %al
jne 0x9934e
jmp 0x99391
movq -0x10(%rbp), %rax
cmpl $0x2, 0x10(%rax)
jne 0x9935a
jmp 0x99379
leaq 0xabd31(%rip), %rdi     # 0x145092
leaq 0xa7ec4(%rip), %rsi     # 0x14122c
movl $0x2727, %edx           # imm = 0x2727
leaq 0xabbfd(%rip), %rcx     # 0x144f71
callq 0x7260
movq -0x288(%rbp), %rdi
leaq 0xb2fed(%rip), %rsi     # 0x14c374
callq 0x9e710
jmp 0x99415
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x18(%rax), %esi
callq 0x2fdb0
testb $0x1, %al
jne 0x993aa
jmp 0x993f1
movq -0x10(%rbp), %rax
cmpl $0x2, 0x10(%rax)
jne 0x993b6
jmp 0x993d5
leaq 0xabcd5(%rip), %rdi     # 0x145092
leaq 0xa7e68(%rip), %rsi     # 0x14122c
movl $0x272c, %edx           # imm = 0x272C
leaq 0xabba1(%rip), %rcx     # 0x144f71
callq 0x7260
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x10(%rbp), %rax
movl 0x18(%rax), %edx
callq 0x99960
jmp 0x99413
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x18(%rax), %esi
callq 0x87d0
movq -0x288(%rbp), %rdi
movq %rax, %rsi
callq 0x982d0
jmp 0x99415
jmp 0x99417
movq -0x10(%rbp), %rax
cmpl $0x1, 0x10(%rax)
jne 0x995f4
cmpl $0x3, -0x18(%rbp)
jne 0x9958f
movq -0x288(%rbp), %rsi
movq -0x10(%rbp), %rax
movl 0x20(%rax), %edx
leaq -0x240(%rbp), %rdi
callq 0x9a230
leaq -0x240(%rbp), %rdi
callq 0x75f0
testb $0x1, %al
jne 0x994aa
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x20(%rax), %esi
callq 0x87d0
movq %rax, -0x2f0(%rbp)
jmp 0x99475
movq -0x288(%rbp), %rax
movq -0x2f0(%rbp), %rcx
movb $0x1, 0xb1(%rcx)
movb $0x1, 0x1d0(%rax)
jmp 0x994aa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
jmp 0x99581
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x20(%rax), %esi
callq 0x87d0
movq %rax, -0x2f8(%rbp)
jmp 0x994c6
movq -0x288(%rbp), %rsi
movq -0x2f8(%rbp), %rax
movl 0x28(%rax), %edx
leaq -0x280(%rbp), %rdi
callq 0x71b50
jmp 0x994e5
leaq 0xaba0f(%rip), %rsi     # 0x144efb
leaq 0xaba06(%rip), %rcx     # 0x144ef9
leaq -0x260(%rbp), %rdi
leaq -0x280(%rbp), %rdx
callq 0xa9680
jmp 0x99508
movq -0x288(%rbp), %rdi
leaq -0x260(%rbp), %rsi
callq 0x61240
jmp 0x9951d
leaq -0x260(%rbp), %rdi
callq 0x7708
leaq -0x280(%rbp), %rdi
callq 0x7708
leaq -0x240(%rbp), %rdi
callq 0x7708
jmp 0x9959b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
jmp 0x99575
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
leaq -0x260(%rbp), %rdi
callq 0x7708
leaq -0x280(%rbp), %rdi
callq 0x7708
leaq -0x240(%rbp), %rdi
callq 0x7708
jmp 0x9960d
movq -0x288(%rbp), %rdi
callq 0x876c0
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x1c(%rax), %esi
callq 0x2fdb0
testb $0x1, %al
jne 0x995b4
jmp 0x995d0
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x10(%rbp), %rax
movl 0x1c(%rax), %edx
callq 0x99960
jmp 0x995f2
movq -0x288(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x1c(%rax), %esi
callq 0x87d0
movq -0x288(%rbp), %rdi
movq %rax, %rsi
callq 0x982d0
jmp 0x995f4
movq -0x10(%rbp), %rdi
addq $0xe8, %rdi
callq 0x8a00
addq $0x300, %rsp            # imm = 0x300
popq %rbp
retq
movq -0xa8(%rbp), %rdi
callq 0x7640
nopl (%rax)