Fix HLSL compiler error with else-rewriting in functions.
In functions with return types where we would use if-else rewriting,
we would potentially generate a spurious HLSL error that warned of
branches with no return value in the function.
This was causing a maps regression where overlays would not draw
in Earth mode.
BUG=346463
BUG=391697
Change-Id: I9f4fa959057a3a2dab6cdd98f8381b5871cabf03
Reviewed-on: https://chromium-review.googlesource.com/206824
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Nicolas Capens <capn@chromium.org>
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/207834
diff --git a/src/compiler/translator/RewriteElseBlocks.cpp b/src/compiler/translator/RewriteElseBlocks.cpp
index 8a9e29e..46e510c 100644
--- a/src/compiler/translator/RewriteElseBlocks.cpp
+++ b/src/compiler/translator/RewriteElseBlocks.cpp
@@ -36,11 +36,18 @@
return unary;
}
+ElseBlockRewriter::ElseBlockRewriter()
+ : TIntermTraverser(true, false, true, false),
+ mTemporaryIndex(0),
+ mFunctionType(NULL)
+{}
+
bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node)
{
switch (node->getOp())
{
case EOpSequence:
+ if (visit == PostVisit)
{
for (size_t statementIndex = 0; statementIndex != node->getSequence().size(); statementIndex++)
{
@@ -63,6 +70,11 @@
}
break;
+ case EOpFunction:
+ // Store the current function context (see comment below)
+ mFunctionType = ((visit == PreVisit) ? &node->getType() : NULL);
+ break;
+
default: break;
}
@@ -82,8 +94,22 @@
TIntermBinary *storeCondition = MakeNewBinary(EOpInitialize, conditionSymbolA,
typedCondition, resultType);
TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolB);
+ TIntermNode *negatedElse = NULL;
+
+ // crbug.com/346463
+ // D3D generates error messages claiming a function has no return value, when rewriting
+ // an if-else clause that returns something non-void in a function. By appending dummy
+ // returns (that are unreachable) we can silence this compile error.
+ if (mFunctionType && mFunctionType->getBasicType() != EbtVoid)
+ {
+ TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() :
+ mFunctionType->getBasicString();
+ TString rawText = "return (" + typeString + ")0";
+ negatedElse = new TIntermRaw(*mFunctionType, rawText);
+ }
+
TIntermSelection *falseBlock = new TIntermSelection(negatedCondition,
- selection->getFalseBlock(), NULL);
+ selection->getFalseBlock(), negatedElse);
TIntermSelection *newIfElse = new TIntermSelection(conditionSymbolC,
selection->getTrueBlock(), falseBlock);
diff --git a/src/compiler/translator/RewriteElseBlocks.h b/src/compiler/translator/RewriteElseBlocks.h
index 1022133..172928f 100644
--- a/src/compiler/translator/RewriteElseBlocks.h
+++ b/src/compiler/translator/RewriteElseBlocks.h
@@ -18,16 +18,14 @@
class ElseBlockRewriter : public TIntermTraverser
{
public:
- ElseBlockRewriter()
- : TIntermTraverser(false, false, true, false)
- , mTemporaryIndex(0)
- {}
+ ElseBlockRewriter();
protected:
bool visitAggregate(Visit visit, TIntermAggregate *aggregate);
private:
int mTemporaryIndex;
+ const TType *mFunctionType;
TIntermNode *rewriteSelection(TIntermSelection *selection);
};