Commit 8ad9e757 by Olli Etuaho Committed by Commit Bot

Always store function headers in TIntermFunctionPrototype nodes

TIntermFunctionDefinition nodes now have a TIntermFunctionPrototype child that stores the function signature, instead of having a separate type and an aggregate child that stores the parameters. This makes parsing functions simpler, and paves the way for further simplifications of function parsing, like reducing conversions between symbol table structures and AST structures. TIntermAggregate is now only used for function calls. BUG=angleproject:1490 TEST=angle_unittests, angle_end2end_tests Change-Id: Ib56a77b5ef5123b142963a18499690bf37fed987 Reviewed-on: https://chromium-review.googlesource.com/427945Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 2cf7c51e
......@@ -33,8 +33,8 @@ class AddDefaultReturnStatementsTraverser : private TIntermTraverser
static bool IsFunctionWithoutReturnStatement(TIntermFunctionDefinition *node, TType *returnType)
{
*returnType = node->getType();
if (node->getType().getBasicType() == EbtVoid)
*returnType = node->getFunctionPrototype()->getType();
if (returnType->getBasicType() == EbtVoid)
{
return false;
}
......
......@@ -92,31 +92,13 @@ bool ArrayReturnValueToOutParameterTraverser::visitFunctionDefinition(
Visit visit,
TIntermFunctionDefinition *node)
{
if (node->isArray() && visit == PreVisit)
if (node->getFunctionPrototype()->isArray() && visit == PreVisit)
{
// Replace the parameters child node of the function definition with another node
// that has the out parameter added.
// Also set the function to return void.
TIntermAggregate *params = node->getFunctionParameters();
ASSERT(params != nullptr && params->getOp() == EOpParameters);
TIntermAggregate *replacementParams = new TIntermAggregate;
replacementParams->setOp(EOpParameters);
CopyAggregateChildren(params, replacementParams);
replacementParams->getSequence()->push_back(CreateReturnValueOutSymbol(node->getType()));
replacementParams->setLine(params->getLine());
queueReplacementWithParent(node, params, replacementParams, OriginalNode::IS_DROPPED);
node->setType(TType(EbtVoid));
// Replacing the function header is done on visitFunctionPrototype().
mInFunctionWithArrayReturnValue = true;
}
if (visit == PostVisit)
{
// This isn't conditional on node->isArray() since the type has already been changed on
// PreVisit.
mInFunctionWithArrayReturnValue = false;
}
return true;
......@@ -128,7 +110,7 @@ bool ArrayReturnValueToOutParameterTraverser::visitFunctionPrototype(Visit visit
if (visit == PreVisit && node->isArray())
{
// Replace the whole prototype node with another node that has the out parameter
// added.
// added. Also set the function to return void.
TIntermFunctionPrototype *replacement = new TIntermFunctionPrototype(TType(EbtVoid));
CopyAggregateChildren(node, replacement);
replacement->getSequence()->push_back(CreateReturnValueOutSymbol(node->getType()));
......
......@@ -44,14 +44,8 @@ TIntermFunctionDefinition *CreateFunctionDefinitionNode(const char *name,
TIntermBlock *functionBody,
const int functionId)
{
TType returnType(EbtVoid);
TIntermAggregate *paramsNode = new TIntermAggregate(EOpParameters);
TIntermFunctionDefinition *functionNode =
new TIntermFunctionDefinition(returnType, paramsNode, functionBody);
SetInternalFunctionName(functionNode->getFunctionSymbolInfo(), name);
functionNode->getFunctionSymbolInfo()->setId(functionId);
return functionNode;
TIntermFunctionPrototype *prototypeNode = CreateFunctionPrototypeNode(name, functionId);
return new TIntermFunctionDefinition(prototypeNode, functionBody);
}
TIntermAggregate *CreateFunctionCallNode(const char *name, const int functionId)
......
......@@ -640,9 +640,6 @@ bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
{
case EOpConstructStruct:
break;
case EOpParameters:
visitChildren = false;
break;
case EOpFunctionCall:
{
// Function call.
......
......@@ -211,7 +211,7 @@ bool TIntermInvariantDeclaration::replaceChildNode(TIntermNode *original, TInter
bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{
REPLACE_IF_IS(mParameters, TIntermAggregate, original, replacement);
REPLACE_IF_IS(mPrototype, TIntermFunctionPrototype, original, replacement);
REPLACE_IF_IS(mBody, TIntermBlock, original, replacement);
return false;
}
......
......@@ -552,47 +552,6 @@ class TFunctionSymbolInfo
int mId;
};
// Node for function definitions.
class TIntermFunctionDefinition : public TIntermTyped
{
public:
// TODO(oetuaho@nvidia.com): See if TFunctionSymbolInfo could be added to constructor
// parameters.
TIntermFunctionDefinition(const TType &type, TIntermAggregate *parameters, TIntermBlock *body)
: TIntermTyped(type), mParameters(parameters), mBody(body)
{
ASSERT(parameters != nullptr);
ASSERT(body != nullptr);
}
TIntermFunctionDefinition *getAsFunctionDefinition() override { return this; }
void traverse(TIntermTraverser *it) override;
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
TIntermTyped *deepCopy() const override
{
UNREACHABLE();
return nullptr;
}
bool hasSideEffects() const override
{
UNREACHABLE();
return true;
}
TIntermAggregate *getFunctionParameters() const { return mParameters; }
TIntermBlock *getBody() const { return mBody; }
TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; }
const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
private:
TIntermAggregate *mParameters;
TIntermBlock *mBody;
TFunctionSymbolInfo mFunctionInfo;
};
typedef TVector<TIntermNode *> TIntermSequence;
typedef TVector<int> TQualifierList;
......@@ -706,10 +665,13 @@ class TIntermBlock : public TIntermNode, public TIntermAggregateBase
TIntermSequence mStatements;
};
// Function prototype declaration. The type of the node is the function return type.
// Function prototype. May be in the AST either as a function prototype declaration or as a part of
// a function definition. The type of the node is the function return type.
class TIntermFunctionPrototype : public TIntermTyped, public TIntermAggregateBase
{
public:
// TODO(oetuaho@nvidia.com): See if TFunctionSymbolInfo could be added to constructor
// parameters.
TIntermFunctionPrototype(const TType &type) : TIntermTyped(type) {}
~TIntermFunctionPrototype() {}
......@@ -743,6 +705,35 @@ class TIntermFunctionPrototype : public TIntermTyped, public TIntermAggregateBas
TFunctionSymbolInfo mFunctionInfo;
};
// Node for function definitions. The prototype child node stores the function header including
// parameters, and the body child node stores the function body.
class TIntermFunctionDefinition : public TIntermNode
{
public:
TIntermFunctionDefinition(TIntermFunctionPrototype *prototype, TIntermBlock *body)
: TIntermNode(), mPrototype(prototype), mBody(body)
{
ASSERT(prototype != nullptr);
ASSERT(body != nullptr);
}
TIntermFunctionDefinition *getAsFunctionDefinition() override { return this; }
void traverse(TIntermTraverser *it) override;
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
TIntermFunctionPrototype *getFunctionPrototype() const { return mPrototype; }
TIntermBlock *getBody() const { return mBody; }
const TFunctionSymbolInfo *getFunctionSymbolInfo() const
{
return mPrototype->getFunctionSymbolInfo();
}
private:
TIntermFunctionPrototype *mPrototype;
TIntermBlock *mBody;
};
// Struct, interface block or variable declaration. Can contain multiple variable declarators.
class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase
{
......@@ -1168,7 +1159,6 @@ class TLValueTrackingTraverser : public TIntermTraverser
void traverseBinary(TIntermBinary *node) final;
void traverseUnary(TIntermUnary *node) final;
void traverseFunctionPrototype(TIntermFunctionPrototype *node) final;
void traverseFunctionDefinition(TIntermFunctionDefinition *node) final;
void traverseAggregate(TIntermAggregate *node) final;
protected:
......
......@@ -466,7 +466,7 @@ void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *nod
incrementDepth(node);
mInGlobalScope = false;
node->getFunctionParameters()->traverse(this);
node->getFunctionPrototype()->traverse(this);
if (inVisit)
visit = visitFunctionDefinition(InVisit, node);
node->getBody()->traverse(this);
......@@ -625,16 +625,6 @@ void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
visitAggregate(PostVisit, node);
}
void TLValueTrackingTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
{
TIntermAggregate *params = node->getFunctionParameters();
ASSERT(params != nullptr);
ASSERT(params->getOp() == EOpParameters);
addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), params->getSequence());
TIntermTraverser::traverseFunctionDefinition(node);
}
void TLValueTrackingTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node)
{
TIntermSequence *sequence = node->getSequence();
......
......@@ -10,7 +10,7 @@ const char *GetOperatorString(TOperator op)
{
switch (op)
{
// Note: ops from EOpNull to EOpParameters can't be handled here.
// Note: EOpNull and EOpFunctionCall can't be handled here.
case EOpNegative:
return "-";
......
......@@ -14,7 +14,6 @@ enum TOperator
{
EOpNull, // if in a node, should only mean a node is still being built
EOpFunctionCall,
EOpParameters, // an aggregate listing the parameters to a function
//
// Unary operators
......
......@@ -835,26 +835,9 @@ bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node)
bool TOutputGLSLBase::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
{
TInfoSinkBase &out = objSink();
ASSERT(visit == PreVisit);
{
const TType &type = node->getType();
writeVariableType(type);
if (type.isArray())
out << arrayBrackets(type);
}
out << " " << hashFunctionNameIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
incrementDepth(node);
// Traverse function parameters.
TIntermAggregate *params = node->getFunctionParameters()->getAsAggregate();
ASSERT(params->getOp() == EOpParameters);
params->traverse(this);
// Traverse function body.
TIntermFunctionPrototype *prototype = node->getFunctionPrototype();
prototype->traverse(this);
visitCodeBlock(node->getBody());
decrementDepth();
......@@ -905,14 +888,6 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
else
out << ")";
break;
case EOpParameters:
// Function parameters.
ASSERT(visit == PreVisit);
out << "(";
writeFunctionParameters(*(node->getSequence()));
out << ")";
visitChildren = false;
break;
case EOpConstructFloat:
case EOpConstructVec2:
case EOpConstructVec3:
......
......@@ -1473,9 +1473,9 @@ bool OutputHLSL::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition
ASSERT(index != CallDAG::InvalidIndex);
mCurrentFunctionMetadata = &mASTMetadataList[index];
out << TypeString(node->getType()) << " ";
out << TypeString(node->getFunctionPrototype()->getType()) << " ";
TIntermSequence *parameters = node->getFunctionParameters()->getSequence();
TIntermSequence *parameters = node->getFunctionPrototype()->getSequence();
if (node->getFunctionSymbolInfo()->isMain())
{
......@@ -1733,9 +1733,6 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
return false;
}
case EOpParameters:
outputTriplet(out, visit, "(", ", ", ")\n{\n");
break;
case EOpConstructFloat:
outputConstructor(out, visit, node->getType(), "vec1", node->getSequence());
break;
......
......@@ -2395,6 +2395,46 @@ void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &type
}
}
TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
const TFunction &function,
const TSourceLoc &location,
bool insertParametersToSymbolTable)
{
TIntermFunctionPrototype *prototype = new TIntermFunctionPrototype(function.getReturnType());
// TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
// point to the data that already exists in the symbol table.
prototype->getFunctionSymbolInfo()->setFromFunction(function);
prototype->setLine(location);
for (size_t i = 0; i < function.getParamCount(); i++)
{
const TConstParameter &param = function.getParam(i);
// If the parameter has no name, it's not an error, just don't add it to symbol table (could
// be used for unused args).
if (param.name != nullptr)
{
TVariable *variable = new TVariable(param.name, *param.type);
// Insert the parameter in the symbol table.
if (insertParametersToSymbolTable && !symbolTable.declare(variable))
{
error(location, "redefinition", variable->getName().c_str());
prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
continue;
}
TIntermSymbol *symbol = intermediate.addSymbol(
variable->getUniqueId(), variable->getName(), variable->getType(), location);
prototype->appendParameter(symbol);
}
else
{
prototype->appendParameter(intermediate.addSymbol(0, "", *param.type, location));
}
}
return prototype;
}
TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
const TFunction &parsedFunction,
const TSourceLoc &location)
......@@ -2412,29 +2452,8 @@ TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
}
function->setHasPrototypeDeclaration();
TIntermFunctionPrototype *prototype = new TIntermFunctionPrototype(function->getReturnType());
// TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
// point to the data that already exists in the symbol table.
prototype->getFunctionSymbolInfo()->setFromFunction(*function);
prototype->setLine(location);
for (size_t i = 0; i < function->getParamCount(); i++)
{
const TConstParameter &param = function->getParam(i);
if (param.name != 0)
{
TVariable variable(param.name, *param.type);
TIntermSymbol *paramSymbol = intermediate.addSymbol(
variable.getUniqueId(), variable.getName(), variable.getType(), location);
prototype->appendParameter(paramSymbol);
}
else
{
TIntermSymbol *paramSymbol = intermediate.addSymbol(0, "", *param.type, location);
prototype->appendParameter(paramSymbol);
}
}
TIntermFunctionPrototype *prototype =
createPrototypeNodeFromFunction(*function, location, false);
symbolTable.pop();
......@@ -2448,15 +2467,15 @@ TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
}
TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
const TFunction &function,
TIntermAggregate *functionParameters,
TIntermFunctionPrototype *functionPrototype,
TIntermBlock *functionBody,
const TSourceLoc &location)
{
// Check that non-void functions have at least one return statement.
if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
{
error(location, "function does not return a value:", function.getName().c_str());
error(location, "function does not return a value:",
functionPrototype->getFunctionSymbolInfo()->getName().c_str());
}
if (functionBody == nullptr)
......@@ -2465,18 +2484,16 @@ TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
functionBody->setLine(location);
}
TIntermFunctionDefinition *functionNode =
new TIntermFunctionDefinition(function.getReturnType(), functionParameters, functionBody);
new TIntermFunctionDefinition(functionPrototype, functionBody);
functionNode->setLine(location);
functionNode->getFunctionSymbolInfo()->setFromFunction(function);
symbolTable.pop();
return functionNode;
}
void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
TFunction **function,
TIntermAggregate **aggregateOut)
TIntermFunctionPrototype **prototypeOut)
{
ASSERT(function);
ASSERT(*function);
......@@ -2528,54 +2545,11 @@ void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
}
}
//
// Remember the return type for later checking for RETURN statements.
//
// Remember the return type for later checking for return statements.
mCurrentFunctionType = &((*function)->getReturnType());
mFunctionReturnsValue = false;
//
// Insert parameters into the symbol table.
// If the parameter has no name, it's not an error, just don't insert it
// (could be used for unused args).
//
// Also, accumulate the list of parameters into the HIL, so lower level code
// knows where to find parameters.
//
TIntermAggregate *paramNodes = new TIntermAggregate;
for (size_t i = 0; i < (*function)->getParamCount(); i++)
{
const TConstParameter &param = (*function)->getParam(i);
if (param.name != 0)
{
TVariable *variable = new TVariable(param.name, *param.type);
//
// Insert the parameters with name in the symbol table.
//
if (!symbolTable.declare(variable))
{
error(location, "redefinition", variable->getName().c_str());
paramNodes = intermediate.growAggregate(
paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
continue;
}
//
// Add the parameter to the HIL
//
TIntermSymbol *symbol = intermediate.addSymbol(
variable->getUniqueId(), variable->getName(), variable->getType(), location);
paramNodes = intermediate.growAggregate(paramNodes, symbol, location);
}
else
{
paramNodes = intermediate.growAggregate(
paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
}
}
intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
*aggregateOut = paramNodes;
*prototypeOut = createPrototypeNodeFromFunction(**function, location, true);
setLoopNestingLevel(0);
}
......
......@@ -242,13 +242,12 @@ class TParseContext : angle::NonCopyable
void parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder);
TIntermFunctionPrototype *addFunctionPrototypeDeclaration(const TFunction &parsedFunction,
const TSourceLoc &location);
TIntermFunctionDefinition *addFunctionDefinition(const TFunction &function,
TIntermAggregate *functionParameters,
TIntermFunctionDefinition *addFunctionDefinition(TIntermFunctionPrototype *functionPrototype,
TIntermBlock *functionBody,
const TSourceLoc &location);
void parseFunctionDefinitionHeader(const TSourceLoc &location,
TFunction **function,
TIntermAggregate **aggregateOut);
TIntermFunctionPrototype **prototypeOut);
TFunction *parseFunctionDeclarator(const TSourceLoc &location, TFunction *function);
TFunction *parseFunctionHeader(const TPublicType &type,
const TString *name,
......@@ -419,6 +418,10 @@ class TParseContext : angle::NonCopyable
TIntermTyped *right,
const TSourceLoc &loc);
TIntermFunctionPrototype *createPrototypeNodeFromFunction(const TFunction &function,
const TSourceLoc &location,
bool insertParametersToSymbolTable);
// Set to true when the last/current declarator list was started with an empty declaration.
bool mDeferredSingleDeclarationErrorCheck;
......
......@@ -195,18 +195,28 @@ TIntermFunctionDefinition *GetIndexFunctionDefinition(TType type, bool write)
numCases = type.getNominalSize();
}
TIntermAggregate *paramsNode = new TIntermAggregate(EOpParameters);
TIntermFunctionPrototype *prototypeNode = nullptr;
if (write)
{
prototypeNode = new TIntermFunctionPrototype(TType(EbtVoid));
}
else
{
prototypeNode = new TIntermFunctionPrototype(fieldType);
}
prototypeNode->getFunctionSymbolInfo()->setNameObj(GetIndexFunctionName(type, write));
TQualifier baseQualifier = EvqInOut;
if (!write)
baseQualifier = EvqIn;
TIntermSymbol *baseParam = CreateBaseSymbol(type, baseQualifier);
paramsNode->getSequence()->push_back(baseParam);
prototypeNode->getSequence()->push_back(baseParam);
TIntermSymbol *indexParam = CreateIndexSymbol();
paramsNode->getSequence()->push_back(indexParam);
prototypeNode->getSequence()->push_back(indexParam);
if (write)
{
TIntermSymbol *valueParam = CreateValueSymbol(fieldType);
paramsNode->getSequence()->push_back(valueParam);
prototypeNode->getSequence()->push_back(valueParam);
}
TIntermBlock *statementList = new TIntermBlock();
......@@ -276,16 +286,8 @@ TIntermFunctionDefinition *GetIndexFunctionDefinition(TType type, bool write)
bodyNode->getSequence()->push_back(ifNode);
bodyNode->getSequence()->push_back(useLastBlock);
TIntermFunctionDefinition *indexingFunction = nullptr;
if (write)
{
indexingFunction = new TIntermFunctionDefinition(TType(EbtVoid), paramsNode, bodyNode);
}
else
{
indexingFunction = new TIntermFunctionDefinition(fieldType, paramsNode, bodyNode);
}
indexingFunction->getFunctionSymbolInfo()->setNameObj(GetIndexFunctionName(type, write));
TIntermFunctionDefinition *indexingFunction =
new TIntermFunctionDefinition(prototypeNode, bodyNode);
return indexingFunction;
}
......
......@@ -41,7 +41,7 @@ ElseBlockRewriter::ElseBlockRewriter() : TIntermTraverser(true, false, true), mF
bool ElseBlockRewriter::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
{
// Store the current function context (see comment below)
mFunctionType = ((visit == PreVisit) ? &node->getType() : nullptr);
mFunctionType = ((visit == PreVisit) ? &node->getFunctionPrototype()->getType() : nullptr);
return true;
}
......
......@@ -15,14 +15,14 @@ ValidateMaxParameters::ValidateMaxParameters(unsigned int maxParameters)
{
}
bool ValidateMaxParameters::visitAggregate(Visit visit, TIntermAggregate *node)
bool ValidateMaxParameters::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
{
if (!mValid)
{
return false;
}
if (node->getOp() == EOpParameters && node->getSequence()->size() > mMaxParameters)
if (node->getFunctionPrototype()->getSequence()->size() > mMaxParameters)
{
mValid = false;
}
......
......@@ -20,7 +20,7 @@ class ValidateMaxParameters : public TIntermTraverser
static bool validate(TIntermNode *root, unsigned int maxParameters);
protected:
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
private:
ValidateMaxParameters(unsigned int maxParameters);
......
......@@ -98,33 +98,30 @@ bool TVersionGLSL::visitInvariantDeclaration(Visit, TIntermInvariantDeclaration
return true;
}
bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node)
bool TVersionGLSL::visitFunctionPrototype(Visit, TIntermFunctionPrototype *node)
{
bool visitChildren = true;
switch (node->getOp())
const TIntermSequence &params = *(node->getSequence());
for (TIntermSequence::const_iterator iter = params.begin(); iter != params.end(); ++iter)
{
case EOpParameters:
const TIntermTyped *param = (*iter)->getAsTyped();
if (param->isArray())
{
const TIntermSequence &params = *(node->getSequence());
for (TIntermSequence::const_iterator iter = params.begin(); iter != params.end();
++iter)
TQualifier qualifier = param->getQualifier();
if ((qualifier == EvqOut) || (qualifier == EvqInOut))
{
const TIntermTyped *param = (*iter)->getAsTyped();
if (param->isArray())
{
TQualifier qualifier = param->getQualifier();
if ((qualifier == EvqOut) || (qualifier == EvqInOut))
{
ensureVersionIsAtLeast(GLSL_VERSION_120);
break;
}
}
ensureVersionIsAtLeast(GLSL_VERSION_120);
break;
}
// Fully processed. No need to visit children.
visitChildren = false;
break;
}
}
// Fully processed. No need to visit children.
return false;
}
bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node)
{
switch (node->getOp())
{
case EOpConstructMat2:
case EOpConstructMat2x3:
case EOpConstructMat2x4:
......@@ -149,8 +146,7 @@ bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node)
default:
break;
}
return visitChildren;
return true;
}
void TVersionGLSL::ensureVersionIsAtLeast(int version)
......
......@@ -62,6 +62,7 @@ class TVersionGLSL : public TIntermTraverser
void visitSymbol(TIntermSymbol *node) override;
bool visitAggregate(Visit, TIntermAggregate *node) override;
bool visitInvariantDeclaration(Visit, TIntermInvariantDeclaration *node) override;
bool visitFunctionPrototype(Visit, TIntermFunctionPrototype *node) override;
bool visitDeclaration(Visit, TIntermDeclaration *node) override;
private:
......
......@@ -80,6 +80,7 @@ using namespace sh;
TIntermAggregate *intermAggregate;
TIntermBlock *intermBlock;
TIntermDeclaration *intermDeclaration;
TIntermFunctionPrototype *intermFunctionPrototype;
TIntermSwitch *intermSwitch;
TIntermCase *intermCase;
};
......@@ -1528,10 +1529,10 @@ external_declaration
function_definition
: function_prototype {
context->parseFunctionDefinitionHeader(@1, &($1.function), &$1.intermAggregate);
context->parseFunctionDefinitionHeader(@1, &($1.function), &($1.intermFunctionPrototype));
}
compound_statement_no_new_scope {
$$ = context->addFunctionDefinition(*($1.function), $1.intermAggregate, $3, @1);
$$ = context->addFunctionDefinition($1.intermFunctionPrototype, $3, @1);
}
;
......
......@@ -312,6 +312,7 @@ union YYSTYPE
TIntermAggregate *intermAggregate;
TIntermBlock *intermBlock;
TIntermDeclaration *intermDeclaration;
TIntermFunctionPrototype *intermFunctionPrototype;
TIntermSwitch *intermSwitch;
TIntermCase *intermCase;
};
......@@ -736,36 +737,36 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
0, 244, 244, 245, 248, 258, 261, 266, 271, 276,
281, 287, 290, 293, 296, 299, 302, 308, 315, 326,
330, 338, 341, 347, 351, 358, 364, 373, 381, 387,
393, 402, 405, 408, 411, 421, 422, 423, 424, 432,
433, 436, 439, 446, 447, 450, 456, 457, 461, 468,
469, 472, 475, 478, 484, 485, 488, 494, 495, 502,
503, 510, 511, 518, 519, 525, 526, 532, 533, 539,
540, 546, 547, 554, 555, 556, 557, 561, 562, 563,
567, 571, 575, 579, 586, 589, 595, 602, 609, 612,
615, 624, 628, 632, 636, 640, 647, 654, 657, 664,
672, 692, 702, 710, 735, 739, 743, 747, 754, 761,
764, 768, 772, 777, 782, 789, 793, 797, 801, 806,
811, 818, 822, 828, 831, 837, 841, 848, 854, 858,
862, 865, 868, 877, 883, 891, 894, 914, 933, 940,
944, 948, 951, 954, 957, 960, 963, 971, 978, 981,
984, 990, 997, 1000, 1006, 1009, 1012, 1015, 1021, 1024,
1029, 1040, 1043, 1046, 1049, 1052, 1055, 1059, 1063, 1067,
1071, 1075, 1079, 1083, 1087, 1091, 1095, 1099, 1103, 1107,
1111, 1115, 1119, 1123, 1127, 1131, 1135, 1139, 1142, 1145,
1148, 1151, 1154, 1157, 1160, 1163, 1166, 1169, 1172, 1175,
1178, 1181, 1184, 1187, 1190, 1193, 1200, 1206, 1209, 1212,
1215, 1218, 1221, 1224, 1227, 1230, 1233, 1236, 1239, 1242,
1245, 1257, 1257, 1260, 1260, 1266, 1269, 1275, 1278, 1285,
1289, 1295, 1301, 1313, 1317, 1321, 1322, 1328, 1329, 1330,
1331, 1332, 1333, 1334, 1338, 1339, 1339, 1339, 1348, 1349,
1353, 1353, 1354, 1354, 1359, 1362, 1371, 1376, 1383, 1384,
1388, 1395, 1399, 1406, 1406, 1413, 1416, 1423, 1427, 1440,
1440, 1445, 1445, 1451, 1451, 1459, 1462, 1468, 1471, 1477,
1481, 1488, 1491, 1494, 1497, 1500, 1509, 1515, 1521, 1524,
1530, 1530
0, 245, 245, 246, 249, 259, 262, 267, 272, 277,
282, 288, 291, 294, 297, 300, 303, 309, 316, 327,
331, 339, 342, 348, 352, 359, 365, 374, 382, 388,
394, 403, 406, 409, 412, 422, 423, 424, 425, 433,
434, 437, 440, 447, 448, 451, 457, 458, 462, 469,
470, 473, 476, 479, 485, 486, 489, 495, 496, 503,
504, 511, 512, 519, 520, 526, 527, 533, 534, 540,
541, 547, 548, 555, 556, 557, 558, 562, 563, 564,
568, 572, 576, 580, 587, 590, 596, 603, 610, 613,
616, 625, 629, 633, 637, 641, 648, 655, 658, 665,
673, 693, 703, 711, 736, 740, 744, 748, 755, 762,
765, 769, 773, 778, 783, 790, 794, 798, 802, 807,
812, 819, 823, 829, 832, 838, 842, 849, 855, 859,
863, 866, 869, 878, 884, 892, 895, 915, 934, 941,
945, 949, 952, 955, 958, 961, 964, 972, 979, 982,
985, 991, 998, 1001, 1007, 1010, 1013, 1016, 1022, 1025,
1030, 1041, 1044, 1047, 1050, 1053, 1056, 1060, 1064, 1068,
1072, 1076, 1080, 1084, 1088, 1092, 1096, 1100, 1104, 1108,
1112, 1116, 1120, 1124, 1128, 1132, 1136, 1140, 1143, 1146,
1149, 1152, 1155, 1158, 1161, 1164, 1167, 1170, 1173, 1176,
1179, 1182, 1185, 1188, 1191, 1194, 1201, 1207, 1210, 1213,
1216, 1219, 1222, 1225, 1228, 1231, 1234, 1237, 1240, 1243,
1246, 1258, 1258, 1261, 1261, 1267, 1270, 1276, 1279, 1286,
1290, 1296, 1302, 1314, 1318, 1322, 1323, 1329, 1330, 1331,
1332, 1333, 1334, 1335, 1339, 1340, 1340, 1340, 1349, 1350,
1354, 1354, 1355, 1355, 1360, 1363, 1372, 1377, 1384, 1385,
1389, 1396, 1400, 1407, 1407, 1414, 1417, 1424, 1428, 1441,
1441, 1446, 1446, 1452, 1452, 1460, 1463, 1469, 1472, 1478,
1482, 1489, 1492, 1495, 1498, 1501, 1510, 1516, 1522, 1525,
1531, 1531
};
#endif
......@@ -4951,7 +4952,7 @@ yyreduce:
case 290:
{
context->parseFunctionDefinitionHeader((yylsp[0]), &((yyvsp[0].interm).function), &(yyvsp[0].interm).intermAggregate);
context->parseFunctionDefinitionHeader((yylsp[0]), &((yyvsp[0].interm).function), &((yyvsp[0].interm).intermFunctionPrototype));
}
break;
......@@ -4959,7 +4960,7 @@ yyreduce:
case 291:
{
(yyval.interm.intermNode) = context->addFunctionDefinition(*((yyvsp[-2].interm).function), (yyvsp[-2].interm).intermAggregate, (yyvsp[0].interm.intermBlock), (yylsp[-2]));
(yyval.interm.intermNode) = context->addFunctionDefinition((yyvsp[-2].interm).intermFunctionPrototype, (yyvsp[0].interm.intermBlock), (yylsp[-2]));
}
break;
......
......@@ -224,6 +224,7 @@ union YYSTYPE {
TIntermAggregate *intermAggregate;
TIntermBlock *intermBlock;
TIntermDeclaration *intermDeclaration;
TIntermFunctionPrototype *intermFunctionPrototype;
TIntermSwitch *intermSwitch;
TIntermCase *intermCase;
};
......
......@@ -494,7 +494,7 @@ bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefin
{
TInfoSinkBase &out = sink;
OutputTreeText(out, node, mDepth);
OutputFunction(out, "Function Definition", node->getFunctionSymbolInfo());
out << "Function Definition:\n";
out << "\n";
return true;
}
......@@ -537,10 +537,6 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpFunctionCall:
OutputFunction(out, "Function Call", node->getFunctionSymbolInfo());
break;
case EOpParameters:
out << "Function Parameters: ";
break;
case EOpConstructFloat:
out << "Construct float";
break;
......@@ -703,8 +699,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
out << "Bad aggregation op";
}
if (node->getOp() != EOpParameters)
out << " (" << node->getCompleteString() << ")";
out << " (" << node->getCompleteString() << ")";
out << "\n";
......
......@@ -91,7 +91,6 @@ TEST_F(TypeTrackingTest, FunctionPrototypeMangling)
compile(shaderString);
ASSERT_FALSE(foundErrorInIntermediateTree());
ASSERT_TRUE(foundInIntermediateTree("Function Prototype: fun(f1;"));
ASSERT_TRUE(foundInIntermediateTree("Function Definition: fun(f1;"));
}
TEST_F(TypeTrackingTest, BuiltInFunctionResultPrecision)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment