Don't remove SPIR-V blocks before codegen.
A removed block releases its instructions, so Module::idToInstruction suddenly contains dangling references. The original motivation for block removal was to skip some unreachable blocks, but that's already achieved by InReadableOrder.cpp. Also updated stale comments.
This commit is contained in:
@@ -1412,9 +1412,11 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
|
||||
builder.createBranch(&blocks.head);
|
||||
} else {
|
||||
// Spec requires back edges to target header blocks, and every header
|
||||
// block must dominate its merge block. Create an empty header block
|
||||
// here to ensure these conditions are met even when body contains
|
||||
// non-trivial control flow.
|
||||
// block must dominate its merge block. Make a header block first to
|
||||
// ensure these conditions are met. By definition, it will contain
|
||||
// OpLoopMerge, followed by a block-ending branch. But we don't want to
|
||||
// put any other body instructions in it, since the body may have
|
||||
// arbitrary instructions, including merges of its own.
|
||||
builder.setBuildPoint(&blocks.head);
|
||||
builder.createLoopMerge(&blocks.merge, &blocks.continue_target, spv::LoopControlMaskNone);
|
||||
builder.createBranch(&blocks.body);
|
||||
@@ -1435,12 +1437,9 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
|
||||
builder.accessChainLoad(convertGlslangToSpvType(node->getTest()->getType()));
|
||||
builder.createConditionalBranch(condition, &blocks.head, &blocks.merge);
|
||||
} else {
|
||||
// TODO: unless there was a break instruction somewhere in the body,
|
||||
// this is an infinite loop, so we should abort code generation with
|
||||
// a warning. As it stands now, nothing will jump to the merge
|
||||
// block, and it may be dropped as unreachable by the SPIR-V dumper.
|
||||
// That, in turn, will result in a non-existing %ID in the LoopMerge
|
||||
// above.
|
||||
// TODO: unless there was a break/return/discard instruction
|
||||
// somewhere in the body, this is an infinite loop, so we should
|
||||
// issue a warning.
|
||||
builder.createBranch(&blocks.head);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -855,24 +855,10 @@ void Builder::leaveFunction()
|
||||
|
||||
// If our function did not contain a return, add a return void now.
|
||||
if (! block->isTerminated()) {
|
||||
|
||||
// Whether we're in an unreachable (non-entry) block.
|
||||
bool unreachable = function.getEntryBlock() != block && block->getPredecessors().empty();
|
||||
|
||||
if (unreachable) {
|
||||
// Given that this block is at the end of a function, it must be right after an
|
||||
// explicit return, just remove it.
|
||||
function.removeBlock(block);
|
||||
} else {
|
||||
// We'll add a return instruction at the end of the current block,
|
||||
// which for a non-void function is really error recovery (?), as the source
|
||||
// being translated should have had an explicit return, which would have been
|
||||
// followed by an unreachable block, which was handled above.
|
||||
if (function.getReturnType() == makeVoidType())
|
||||
makeReturn(true);
|
||||
else {
|
||||
makeReturn(true, createUndefined(function.getReturnType()));
|
||||
}
|
||||
if (function.getReturnType() == makeVoidType())
|
||||
makeReturn(true);
|
||||
else {
|
||||
makeReturn(true, createUndefined(function.getReturnType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,12 +205,6 @@ public:
|
||||
|
||||
void dump(std::vector<unsigned int>& out) const
|
||||
{
|
||||
// skip the degenerate unreachable blocks
|
||||
// TODO: code gen: skip all unreachable blocks (transitive closure)
|
||||
// (but, until that's done safer to keep non-degenerate unreachable blocks, in case others depend on something)
|
||||
if (unreachable && instructions.size() <= 2)
|
||||
return;
|
||||
|
||||
instructions[0]->dump(out);
|
||||
for (int i = 0; i < (int)localVariables.size(); ++i)
|
||||
localVariables[i]->dump(out);
|
||||
|
||||
Reference in New Issue
Block a user