Deal with loop variable initializers for non-for loops.

This commit is contained in:
Hans-Kristian Arntzen 2018-08-06 12:52:22 +02:00
parent 5ba15a5a2f
commit 3a268796e2
2 changed files with 16 additions and 1 deletions

View File

@ -9292,6 +9292,16 @@ string CompilerGLSL::emit_continue_block(uint32_t continue_block)
return merge(statements);
}
void CompilerGLSL::emit_while_loop_initializers(const SPIRBlock &block)
{
// While loops do not take initializers, so declare all of them outside.
for (auto &loop_var : block.loop_variables)
{
auto &var = get<SPIRVariable>(loop_var);
statement(variable_decl(var), ";");
}
}
string CompilerGLSL::emit_for_loop_initializers(const SPIRBlock &block)
{
if (block.loop_variables.empty())
@ -9409,12 +9419,12 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method
{
// This block may be a dominating block, so make sure we flush undeclared variables before building the for loop header.
flush_undeclared_variables(block);
emit_block_hints(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);
@ -9428,6 +9438,7 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method
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;
@ -9482,6 +9493,7 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method
}
case SPIRBlock::WhileLoop:
emit_while_loop_initializers(block);
emit_block_hints(block);
statement("while (", to_expression(child.condition), ")");
break;
@ -9600,6 +9612,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
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;
@ -9613,6 +9626,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &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;

View File

@ -549,6 +549,7 @@ protected:
void find_static_extensions();
std::string emit_for_loop_initializers(const SPIRBlock &block);
void emit_while_loop_initializers(const SPIRBlock &block);
bool for_loop_initializers_are_same_type(const SPIRBlock &block);
bool optimize_read_modify_write(const SPIRType &type, const std::string &lhs, const std::string &rhs);
void fixup_image_load_store_access();