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