SPV return from main: Simplify a legacy design such returns are not jumps to exit block.

Structured control-flow rules allow leaving the middle of a construct through
a return, but not through a jump to a block that does a return.

Addresses issue #58.
This commit is contained in:
John Kessenich 2015-09-14 20:58:02 -06:00
parent 5f5b205ce9
commit e770b3e6cf
74 changed files with 9648 additions and 9816 deletions

View file

@ -454,7 +454,7 @@ TGlslangToSpvTraverser::~TGlslangToSpvTraverser()
if (! mainTerminated) {
spv::Block* lastMainBlock = shaderEntry->getLastBlock();
builder.setBuildPoint(lastMainBlock);
builder.leaveFunction(true);
builder.leaveFunction();
}
}
@ -854,7 +854,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
} else {
if (inMain)
mainTerminated = true;
builder.leaveFunction(inMain);
builder.leaveFunction();
inMain = false;
}
@ -1276,12 +1276,10 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
builder.createLoopContinue();
break;
case glslang::EOpReturn:
if (inMain)
builder.makeMainReturn();
else if (node->getExpression())
if (node->getExpression())
builder.makeReturn(false, builder.accessChainLoad(convertGlslangToSpvType(node->getExpression()->getType())));
else
builder.makeReturn();
builder.makeReturn(false);
builder.clearAccessChain();
break;

View file

@ -65,8 +65,7 @@ Builder::Builder(unsigned int userNumber) :
builderNumber(userNumber << 16 | SpvBuilderMagic),
buildPoint(0),
uniqueId(0),
mainFunction(0),
stageExit(0)
mainFunction(0)
{
clearAccessChain();
}
@ -723,19 +722,10 @@ Function* Builder::makeMain()
std::vector<Id> params;
mainFunction = makeFunctionEntry(makeVoidType(), "main", params, &entry);
stageExit = new Block(getUniqueId(), *mainFunction);
return mainFunction;
}
// Comments in header
void Builder::closeMain()
{
setBuildPoint(stageExit);
stageExit->addInstruction(new Instruction(NoResult, NoType, OpReturn));
mainFunction->addBlock(stageExit);
}
// Comments in header
Function* Builder::makeFunctionEntry(Id returnType, const char* name, std::vector<Id>& paramTypes, Block **entry)
{
@ -756,14 +746,9 @@ Function* Builder::makeFunctionEntry(Id returnType, const char* name, std::vecto
}
// Comments in header
void Builder::makeReturn(bool implicit, Id retVal, bool isMain)
void Builder::makeReturn(bool implicit, Id retVal)
{
if (isMain && retVal)
MissingFunctionality("return value from main()");
if (isMain)
createBranch(stageExit);
else if (retVal) {
if (retVal) {
Instruction* inst = new Instruction(NoResult, NoType, OpReturnValue);
inst->addIdOperand(retVal);
buildPoint->addInstruction(inst);
@ -775,7 +760,7 @@ void Builder::makeReturn(bool implicit, Id retVal, bool isMain)
}
// Comments in header
void Builder::leaveFunction(bool main)
void Builder::leaveFunction()
{
Block* block = buildPoint;
Function& function = buildPoint->getParent();
@ -791,10 +776,8 @@ void Builder::leaveFunction(bool main)
// Given that this block is at the end of a function, it must be right after an
// explicit return, just remove it.
function.popBlock(block);
} else if (main)
makeMainReturn(true);
else {
// We're get a return instruction at the end of the current 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.
@ -805,9 +788,6 @@ void Builder::leaveFunction(bool main)
}
}
}
if (main)
closeMain();
}
// Comments in header

View file

@ -195,23 +195,16 @@ public:
// Make the main function.
Function* makeMain();
// Return from main. Implicit denotes a return at the very end of main.
void makeMainReturn(bool implicit = false) { makeReturn(implicit, 0, true); }
// Close the main function.
void closeMain();
// Make a shader-style function, and create its entry block if entry is non-zero.
// Return the function, pass back the entry.
Function* makeFunctionEntry(Id returnType, const char* name, std::vector<Id>& paramTypes, Block **entry = 0);
// Create a return. Pass whether it is a return form main, and the return
// value (if applicable). In the case of an implicit return, no post-return
// block is inserted.
void makeReturn(bool implicit = false, Id retVal = 0, bool isMain = false);
// Create a return. An 'implicit' return is one not appearing in the source
// code. In the case of an implicit return, no post-return block is inserted.
void makeReturn(bool implicit, Id retVal = 0);
// Generate all the code needed to finish up a function.
void leaveFunction(bool main);
void leaveFunction();
// Create a discard.
void makeDiscard();
@ -516,7 +509,6 @@ protected:
Block* buildPoint;
Id uniqueId;
Function* mainFunction;
Block* stageExit;
AccessChain accessChain;
// special blocks of instructions for output