Deal with case where a block is somehow emitted in a duplicated fashion.

We seen to have to deal with a case where a block is used multiple times
without any "proper" structured control flow, so we risk losing deferred
declaration state.
This commit is contained in:
Hans-Kristian Arntzen 2019-06-05 12:35:30 +02:00
parent af40a212c2
commit c09ca74c61

View File

@ -10558,6 +10558,8 @@ void CompilerGLSL::emit_function(SPIRFunction &func, const Bitset &return_flags)
for (auto &v : func.local_variables) for (auto &v : func.local_variables)
{ {
auto &var = get<SPIRVariable>(v); auto &var = get<SPIRVariable>(v);
var.deferred_declaration = false;
if (var.storage == StorageClassWorkgroup) if (var.storage == StorageClassWorkgroup)
{ {
// Special variable type which cannot have initializer, // Special variable type which cannot have initializer,
@ -10617,6 +10619,13 @@ void CompilerGLSL::emit_function(SPIRFunction &func, const Bitset &return_flags)
var.deferred_declaration = false; var.deferred_declaration = false;
} }
// Enforce declaration order for regression testing purposes.
for (auto &block_id : func.blocks)
{
auto &block = get<SPIRBlock>(block_id);
sort(begin(block.dominated_variables), end(block.dominated_variables));
}
for (auto &line : current_function->fixup_hooks_in) for (auto &line : current_function->fixup_hooks_in)
line(); line();
@ -11245,8 +11254,6 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method
void CompilerGLSL::flush_undeclared_variables(SPIRBlock &block) void CompilerGLSL::flush_undeclared_variables(SPIRBlock &block)
{ {
// Enforce declaration order for regression testing purposes.
sort(begin(block.dominated_variables), end(block.dominated_variables));
for (auto &v : block.dominated_variables) for (auto &v : block.dominated_variables)
flush_variable_declaration(v); flush_variable_declaration(v);
} }
@ -11293,6 +11300,15 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
for (auto var : block.loop_variables) for (auto var : block.loop_variables)
get<SPIRVariable>(var).loop_variable_enable = true; get<SPIRVariable>(var).loop_variable_enable = true;
// Remember deferred declaration state. We will restore it before returning.
SmallVector<bool, 64> rearm_dominated_variables(block.dominated_variables.size());
for (size_t i = 0; i < block.dominated_variables.size(); i++)
{
uint32_t var_id = block.dominated_variables[i];
auto &var = get<SPIRVariable>(var_id);
rearm_dominated_variables[i] = var.deferred_declaration;
}
// This is the method often used by spirv-opt to implement loops. // This is the method often used by spirv-opt to implement loops.
// The loop header goes straight into the continue block. // 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, // However, don't attempt this on ESSL 1.0, because if a loop variable is used in a continue block,
@ -11671,6 +11687,15 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
// Forget about control dependent expressions now. // Forget about control dependent expressions now.
block.invalidate_expressions.clear(); block.invalidate_expressions.clear();
// After we return, we must be out of scope, so if we somehow have to re-emit this function,
// re-declare variables if necessary.
assert(rearm_dominated_variables.size() == block.dominated_variables.size());
for (size_t i = 0; i < block.dominated_variables.size(); i++)
{
uint32_t var = block.dominated_variables[i];
get<SPIRVariable>(var).deferred_declaration = rearm_dominated_variables[i];
}
} }
void CompilerGLSL::begin_scope() void CompilerGLSL::begin_scope()