Add a class for function lookups
Using a purpose-built class for function lookups instead of using
a combination of TFunction and a struct container for the this node
and arguments makes the code clearer.
BUG=angleproject:2267
TEST=angle_unittests
Change-Id: I3f345d836abeaa7f84cc46b4b840fd06c7e2e1a7
Reviewed-on: https://chromium-review.googlesource.com/897363
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler.gypi b/src/compiler.gypi
index be25a12..90a07c5 100644
--- a/src/compiler.gypi
+++ b/src/compiler.gypi
@@ -69,6 +69,8 @@
'compiler/translator/FlagStd140Structs.h',
'compiler/translator/FoldExpressions.cpp',
'compiler/translator/FoldExpressions.h',
+ 'compiler/translator/FunctionLookup.cpp',
+ 'compiler/translator/FunctionLookup.h',
'compiler/translator/HashNames.cpp',
'compiler/translator/HashNames.h',
'compiler/translator/ImmutableString.cpp',
diff --git a/src/compiler/translator/EmulatePrecision.cpp b/src/compiler/translator/EmulatePrecision.cpp
index 1470ace..da3ff5a 100644
--- a/src/compiler/translator/EmulatePrecision.cpp
+++ b/src/compiler/translator/EmulatePrecision.cpp
@@ -6,6 +6,8 @@
#include "compiler/translator/EmulatePrecision.h"
+#include "compiler/translator/FunctionLookup.h"
+
#include <memory>
namespace sh
@@ -713,7 +715,7 @@
const TVector<TConstParameter> ¶meters,
bool knownToNotHaveSideEffects)
{
- TString mangledName = TFunction::GetMangledNameFromCall(*functionName, *arguments);
+ TString mangledName = TFunctionLookup::GetMangledName(*functionName, *arguments);
if (mInternalFunctions.find(mangledName) == mInternalFunctions.end())
{
TFunction *func = new TFunction(mSymbolTable, functionName, new TType(returnType),
diff --git a/src/compiler/translator/FunctionLookup.cpp b/src/compiler/translator/FunctionLookup.cpp
new file mode 100644
index 0000000..ee575a8
--- /dev/null
+++ b/src/compiler/translator/FunctionLookup.cpp
@@ -0,0 +1,94 @@
+//
+// Copyright (c) 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FunctionLookup.cpp: Used for storing function calls that have not yet been resolved during
+// parsing.
+//
+
+#include "compiler/translator/FunctionLookup.h"
+
+namespace sh
+{
+
+namespace
+{
+
+const char kFunctionMangledNameSeparator = '(';
+
+} // anonymous namespace
+
+TFunctionLookup::TFunctionLookup(const TString *name, const TType *constructorType)
+ : mName(name), mConstructorType(constructorType), mThisNode(nullptr)
+{
+}
+
+// static
+TFunctionLookup *TFunctionLookup::CreateConstructor(const TType *type)
+{
+ ASSERT(type != nullptr);
+ return new TFunctionLookup(nullptr, type);
+}
+
+// static
+TFunctionLookup *TFunctionLookup::CreateFunctionCall(const TString *name)
+{
+ ASSERT(name != nullptr);
+ return new TFunctionLookup(name, nullptr);
+}
+
+const TString &TFunctionLookup::name() const
+{
+ return *mName;
+}
+
+const TString &TFunctionLookup::getMangledName() const
+{
+ return GetMangledName(*mName, mArguments);
+}
+
+const TString &TFunctionLookup::GetMangledName(const TString &functionName,
+ const TIntermSequence &arguments)
+{
+ std::string newName = functionName.c_str();
+ newName += kFunctionMangledNameSeparator;
+
+ for (TIntermNode *argument : arguments)
+ {
+ newName += argument->getAsTyped()->getType().getMangledName();
+ }
+ return *NewPoolTString(newName.c_str());
+}
+
+bool TFunctionLookup::isConstructor() const
+{
+ return mConstructorType != nullptr;
+}
+
+const TType &TFunctionLookup::constructorType() const
+{
+ return *mConstructorType;
+}
+
+void TFunctionLookup::setThisNode(TIntermTyped *thisNode)
+{
+ mThisNode = thisNode;
+}
+
+TIntermTyped *TFunctionLookup::thisNode() const
+{
+ return mThisNode;
+}
+
+void TFunctionLookup::addArgument(TIntermTyped *argument)
+{
+ mArguments.push_back(argument);
+}
+
+TIntermSequence &TFunctionLookup::arguments()
+{
+ return mArguments;
+}
+
+} // namespace sh
diff --git a/src/compiler/translator/FunctionLookup.h b/src/compiler/translator/FunctionLookup.h
new file mode 100644
index 0000000..1a62357
--- /dev/null
+++ b/src/compiler/translator/FunctionLookup.h
@@ -0,0 +1,51 @@
+//
+// Copyright (c) 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FunctionLookup.h: Used for storing function calls that have not yet been resolved during parsing.
+//
+
+#ifndef COMPILER_TRANSLATOR_FUNCTIONLOOKUP_H_
+#define COMPILER_TRANSLATOR_FUNCTIONLOOKUP_H_
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+// A function look-up.
+class TFunctionLookup : angle::NonCopyable
+{
+ public:
+ POOL_ALLOCATOR_NEW_DELETE();
+
+ static TFunctionLookup *CreateConstructor(const TType *type);
+ static TFunctionLookup *CreateFunctionCall(const TString *name);
+
+ const TString &name() const;
+ const TString &getMangledName() const;
+ static const TString &GetMangledName(const TString &functionName,
+ const TIntermSequence &arguments);
+
+ bool isConstructor() const;
+ const TType &constructorType() const;
+
+ void setThisNode(TIntermTyped *thisNode);
+ TIntermTyped *thisNode() const;
+
+ void addArgument(TIntermTyped *argument);
+ TIntermSequence &arguments();
+
+ private:
+ TFunctionLookup(const TString *name, const TType *constructorType);
+
+ const TString *mName;
+ const TType *const mConstructorType;
+ TIntermTyped *mThisNode;
+ TIntermSequence mArguments;
+};
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_FUNCTIONLOOKUP_H_
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 1582634..965327c 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -509,21 +509,6 @@
mType.setPrecision(precision);
}
-TString TIntermAggregate::getSymbolTableMangledName() const
-{
- ASSERT(!isConstructor());
- switch (mOp)
- {
- case EOpCallInternalRawFunction:
- case EOpCallBuiltInFunction:
- case EOpCallFunctionInAST:
- return TFunction::GetMangledNameFromCall(mFunction->name(), mArguments);
- default:
- TString opString = GetOperatorString(mOp);
- return TFunction::GetMangledNameFromCall(opString, mArguments);
- }
-}
-
const char *TIntermAggregate::functionName() const
{
ASSERT(!isConstructor());
diff --git a/src/compiler/translator/IntermNode.h b/src/compiler/translator/IntermNode.h
index 3db2464..764c11e 100644
--- a/src/compiler/translator/IntermNode.h
+++ b/src/compiler/translator/IntermNode.h
@@ -533,15 +533,6 @@
typedef TVector<TIntermNode *> TIntermSequence;
typedef TVector<int> TQualifierList;
-//
-// This is just to help yacc.
-//
-struct TIntermFunctionCallOrMethod
-{
- TIntermSequence *arguments;
- TIntermNode *thisNode;
-};
-
// Interface for node classes that have an arbitrarily sized set of children.
class TIntermAggregateBase
{
@@ -599,8 +590,6 @@
TIntermSequence *getSequence() override { return &mArguments; }
const TIntermSequence *getSequence() const override { return &mArguments; }
- TString getSymbolTableMangledName() const;
-
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
diff --git a/src/compiler/translator/IntermNode_util.cpp b/src/compiler/translator/IntermNode_util.cpp
index 5a20c82..1cbbcd4 100644
--- a/src/compiler/translator/IntermNode_util.cpp
+++ b/src/compiler/translator/IntermNode_util.cpp
@@ -8,6 +8,7 @@
#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/FunctionLookup.h"
#include "compiler/translator/SymbolTable.h"
namespace sh
@@ -21,7 +22,7 @@
const TSymbolTable &symbolTable,
int shaderVersion)
{
- TString mangledName = TFunction::GetMangledNameFromCall(name, *arguments);
+ const TString &mangledName = TFunctionLookup::GetMangledName(name, *arguments);
const TSymbol *symbol = symbolTable.findBuiltIn(mangledName, shaderVersion);
if (symbol)
{
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index c7c4c77..dc7ba1c 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -695,16 +695,16 @@
// Make sure the argument types are correct for constructing a specific type.
bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
- const TIntermSequence *arguments,
+ const TIntermSequence &arguments,
const TType &type)
{
- if (arguments->empty())
+ if (arguments.empty())
{
error(line, "constructor does not have any arguments", "constructor");
return false;
}
- for (TIntermNode *arg : *arguments)
+ for (TIntermNode *arg : arguments)
{
const TIntermTyped *argTyped = arg->getAsTyped();
ASSERT(argTyped != nullptr);
@@ -731,14 +731,14 @@
{
// The size of an unsized constructor should already have been determined.
ASSERT(!type.isUnsizedArray());
- if (static_cast<size_t>(type.getOutermostArraySize()) != arguments->size())
+ if (static_cast<size_t>(type.getOutermostArraySize()) != arguments.size())
{
error(line, "array constructor needs one argument per array element", "constructor");
return false;
}
// GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
// the array.
- for (TIntermNode *const &argNode : *arguments)
+ for (TIntermNode *const &argNode : arguments)
{
const TType &argType = argNode->getAsTyped()->getType();
if (mShaderVersion < 310 && argType.isArray())
@@ -756,7 +756,7 @@
else if (type.getBasicType() == EbtStruct)
{
const TFieldList &fields = type.getStruct()->fields();
- if (fields.size() != arguments->size())
+ if (fields.size() != arguments.size())
{
error(line,
"Number of constructor parameters does not match the number of structure fields",
@@ -766,8 +766,8 @@
for (size_t i = 0; i < fields.size(); i++)
{
- if (i >= arguments->size() ||
- (*arguments)[i]->getAsTyped()->getType() != *fields[i]->type())
+ if (i >= arguments.size() ||
+ arguments[i]->getAsTyped()->getType() != *fields[i]->type())
{
error(line, "Structure constructor arguments do not match structure fields",
"constructor");
@@ -787,7 +787,7 @@
bool full = false;
bool overFull = false;
bool matrixArg = false;
- for (TIntermNode *arg : *arguments)
+ for (TIntermNode *arg : arguments)
{
const TIntermTyped *argTyped = arg->getAsTyped();
ASSERT(argTyped != nullptr);
@@ -821,7 +821,7 @@
if (type.isMatrix() && matrixArg)
{
- if (arguments->size() != 1)
+ if (arguments.size() != 1)
{
error(line, "constructing matrix from matrix can only take one argument",
"constructor");
@@ -3418,19 +3418,12 @@
return new TFunction(&symbolTable, name, new TType(type), SymbolType::UserDefined, false);
}
-TFunction *TParseContext::addNonConstructorFunc(const TString *name, const TSourceLoc &loc)
+TFunctionLookup *TParseContext::addNonConstructorFunc(const TString *name)
{
- const TType *returnType = StaticType::GetQualified<EbtVoid, EvqTemporary>();
- // TODO(oetuaho): Some more appropriate data structure than TFunction could be used here. We're
- // really only interested in the mangled name of the function to look up the actual function
- // from the symbol table. If we just had the name string and the types of the parameters that
- // would be enough, but TFunction carries a lot of extra information in addition to that.
- // Besides function calls we do have to store constructor calls in the same data structure, for
- // them we need to store a TType.
- return new TFunction(&symbolTable, name, returnType, SymbolType::NotResolved, false);
+ return TFunctionLookup::CreateFunctionCall(name);
}
-TFunction *TParseContext::addConstructorFunc(const TPublicType &publicType)
+TFunctionLookup *TParseContext::addConstructorFunc(const TPublicType &publicType)
{
if (mShaderVersion < 300 && publicType.isArray())
{
@@ -3450,8 +3443,7 @@
getBasicString(publicType.getBasicType()));
type->setBasicType(EbtFloat);
}
-
- return new TFunction(&symbolTable, nullptr, type, SymbolType::NotResolved, true, EOpConstruct);
+ return TFunctionLookup::CreateConstructor(type);
}
void TParseContext::checkIsNotUnsizedArray(const TSourceLoc &line,
@@ -3502,18 +3494,19 @@
return parseParameterDeclarator(arrayType, name, nameLoc);
}
-bool TParseContext::checkUnsizedArrayConstructorArgumentDimensionality(TIntermSequence *arguments,
- TType type,
- const TSourceLoc &line)
+bool TParseContext::checkUnsizedArrayConstructorArgumentDimensionality(
+ const TIntermSequence &arguments,
+ TType type,
+ const TSourceLoc &line)
{
- if (arguments->empty())
+ if (arguments.empty())
{
error(line, "implicitly sized array constructor must have at least one argument", "[]");
return false;
}
- for (TIntermNode *arg : *arguments)
+ for (TIntermNode *arg : arguments)
{
- TIntermTyped *element = arg->getAsTyped();
+ const TIntermTyped *element = arg->getAsTyped();
ASSERT(element);
size_t dimensionalityFromElement = element->getType().getNumArraySizes() + 1u;
if (dimensionalityFromElement > type.getNumArraySizes())
@@ -3546,10 +3539,10 @@
//
// Returns a node to add to the tree regardless of if an error was generated or not.
//
-TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments,
- TType type,
- const TSourceLoc &line)
+TIntermTyped *TParseContext::addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line)
{
+ TType type = fnCall->constructorType();
+ TIntermSequence &arguments = fnCall->arguments();
if (type.isUnsizedArray())
{
if (!checkUnsizedArrayConstructorArgumentDimensionality(arguments, type, line))
@@ -3557,11 +3550,11 @@
type.sizeUnsizedArrays(nullptr);
return CreateZeroNode(type);
}
- TIntermTyped *firstElement = arguments->at(0)->getAsTyped();
+ TIntermTyped *firstElement = arguments.at(0)->getAsTyped();
ASSERT(firstElement);
if (type.getOutermostArraySize() == 0u)
{
- type.sizeOutermostUnsizedArray(static_cast<unsigned int>(arguments->size()));
+ type.sizeOutermostUnsizedArray(static_cast<unsigned int>(arguments.size()));
}
for (size_t i = 0; i < firstElement->getType().getNumArraySizes(); ++i)
{
@@ -3578,7 +3571,7 @@
return CreateZeroNode(type);
}
- TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, arguments);
+ TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, &arguments);
constructorNode->setLine(line);
return constructorNode->fold(mDiagnostics);
@@ -5744,56 +5737,39 @@
}
}
-TIntermSequence *TParseContext::createEmptyArgumentsList()
+TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunctionLookup *fnCall, const TSourceLoc &loc)
{
- return new TIntermSequence();
+ if (fnCall->thisNode() != nullptr)
+ {
+ return addMethod(fnCall, loc);
+ }
+ if (fnCall->isConstructor())
+ {
+ return addConstructor(fnCall, loc);
+ }
+ return addNonConstructorFunctionCall(fnCall, loc);
}
-TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
- TIntermSequence *arguments,
- TIntermNode *thisNode,
- const TSourceLoc &loc)
+TIntermTyped *TParseContext::addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc)
{
- if (thisNode != nullptr)
- {
- return addMethod(fnCall->name(), arguments, thisNode, loc);
- }
-
- TOperator op = fnCall->getBuiltInOp();
- if (op == EOpConstruct)
- {
- return addConstructor(arguments, fnCall->getReturnType(), loc);
- }
- else
- {
- ASSERT(op == EOpNull);
- return addNonConstructorFunctionCall(fnCall->name(), arguments, loc);
- }
-}
-
-TIntermTyped *TParseContext::addMethod(const TString &name,
- TIntermSequence *arguments,
- TIntermNode *thisNode,
- const TSourceLoc &loc)
-{
- TIntermTyped *typedThis = thisNode->getAsTyped();
+ TIntermTyped *thisNode = fnCall->thisNode();
// It's possible for the name pointer in the TFunction to be null in case it gets parsed as
// a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
// mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
// So accessing fnCall->name() below is safe.
- if (name != "length")
+ if (fnCall->name() != "length")
{
- error(loc, "invalid method", name.c_str());
+ error(loc, "invalid method", fnCall->name().c_str());
}
- else if (!arguments->empty())
+ else if (!fnCall->arguments().empty())
{
error(loc, "method takes no parameters", "length");
}
- else if (typedThis == nullptr || !typedThis->isArray())
+ else if (!thisNode->isArray())
{
error(loc, "length can only be called on arrays", "length");
}
- else if (typedThis->getQualifier() == EvqPerVertexIn &&
+ else if (thisNode->getQualifier() == EvqPerVertexIn &&
mGeometryShaderInputPrimitiveType == EptUndefined)
{
ASSERT(mShaderType == GL_GEOMETRY_SHADER_EXT);
@@ -5801,32 +5777,30 @@
}
else
{
- TIntermUnary *node = new TIntermUnary(EOpArrayLength, typedThis);
+ TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode);
node->setLine(loc);
return node->fold(mDiagnostics);
}
return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst));
}
-TIntermTyped *TParseContext::addNonConstructorFunctionCall(const TString &name,
- TIntermSequence *arguments,
+TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCall,
const TSourceLoc &loc)
{
// First find by unmangled name to check whether the function name has been
// hidden by a variable name or struct typename.
// If a function is found, check for one with a matching argument list.
- const TSymbol *symbol = symbolTable.find(name, mShaderVersion);
+ const TSymbol *symbol = symbolTable.find(fnCall->name(), mShaderVersion);
if (symbol != nullptr && !symbol->isFunction())
{
- error(loc, "function name expected", name.c_str());
+ error(loc, "function name expected", fnCall->name().c_str());
}
else
{
- symbol =
- symbolTable.find(TFunction::GetMangledNameFromCall(name, *arguments), mShaderVersion);
+ symbol = symbolTable.find(fnCall->getMangledName(), mShaderVersion);
if (symbol == nullptr)
{
- error(loc, "no matching overloaded function found", name.c_str());
+ error(loc, "no matching overloaded function found", fnCall->name().c_str());
}
else
{
@@ -5839,13 +5813,13 @@
checkCanUseExtension(loc, fnCandidate->extension());
}
TOperator op = fnCandidate->getBuiltInOp();
- if (fnCandidate->symbolType() == SymbolType::BuiltIn && op != EOpNull)
+ if (op != EOpNull)
{
// A function call mapped to a built-in operation.
if (fnCandidate->getParamCount() == 1)
{
// Treat it like a built-in unary operator.
- TIntermNode *unaryParamNode = arguments->front();
+ TIntermNode *unaryParamNode = fnCall->arguments().front();
TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
ASSERT(callNode != nullptr);
return callNode;
@@ -5853,7 +5827,7 @@
else
{
TIntermAggregate *callNode =
- TIntermAggregate::Create(*fnCandidate, op, arguments);
+ TIntermAggregate::Create(*fnCandidate, op, &fnCall->arguments());
callNode->setLine(loc);
// Some built-in functions have out parameters too.
@@ -5874,7 +5848,8 @@
// function with no op associated with it.
if (fnCandidate->symbolType() == SymbolType::BuiltIn)
{
- callNode = TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, arguments);
+ callNode = TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate,
+ &fnCall->arguments());
checkTextureOffsetConst(callNode);
checkTextureGather(callNode);
checkImageMemoryAccessForBuiltinFunctions(callNode);
@@ -5882,7 +5857,8 @@
}
else
{
- callNode = TIntermAggregate::CreateFunctionCall(*fnCandidate, arguments);
+ callNode =
+ TIntermAggregate::CreateFunctionCall(*fnCandidate, &fnCall->arguments());
checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
}
diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h
index 8527a20..9706236 100644
--- a/src/compiler/translator/ParseContext.h
+++ b/src/compiler/translator/ParseContext.h
@@ -11,6 +11,7 @@
#include "compiler/translator/Declarator.h"
#include "compiler/translator/Diagnostics.h"
#include "compiler/translator/DirectiveHandler.h"
+#include "compiler/translator/FunctionLookup.h"
#include "compiler/translator/QualifierTypes.h"
#include "compiler/translator/SymbolTable.h"
@@ -120,7 +121,7 @@
void checkIsScalarInteger(TIntermTyped *node, const char *token);
bool checkIsAtGlobalLevel(const TSourceLoc &line, const char *token);
bool checkConstructorArguments(const TSourceLoc &line,
- const TIntermSequence *arguments,
+ const TIntermSequence &arguments,
const TType &type);
// Returns a sanitized array size to use (the size is at least 1).
@@ -291,8 +292,8 @@
TFunction *parseFunctionHeader(const TPublicType &type,
const TString *name,
const TSourceLoc &location);
- TFunction *addNonConstructorFunc(const TString *name, const TSourceLoc &loc);
- TFunction *addConstructorFunc(const TPublicType &publicType);
+ TFunctionLookup *addNonConstructorFunc(const TString *name);
+ TFunctionLookup *addConstructorFunc(const TPublicType &publicType);
TParameter parseParameterDeclarator(const TPublicType &publicType,
const TString *name,
const TSourceLoc &nameLoc);
@@ -419,14 +420,10 @@
void checkImageMemoryAccessForUserDefinedFunctions(const TFunction *functionDefinition,
const TIntermAggregate *functionCall);
void checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall);
- TIntermSequence *createEmptyArgumentsList();
// fnCall is only storing the built-in op, and function name or constructor type. arguments
// has the arguments.
- TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall,
- TIntermSequence *arguments,
- TIntermNode *thisNode,
- const TSourceLoc &loc);
+ TIntermTyped *addFunctionCallOrMethod(TFunctionLookup *fnCall, const TSourceLoc &loc);
TIntermTyped *addTernarySelection(TIntermTyped *cond,
TIntermTyped *trueExpression,
@@ -523,7 +520,7 @@
void checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv);
- bool checkUnsizedArrayConstructorArgumentDimensionality(TIntermSequence *arguments,
+ bool checkUnsizedArrayConstructorArgumentDimensionality(const TIntermSequence &arguments,
TType type,
const TSourceLoc &line);
@@ -549,16 +546,9 @@
const TSourceLoc &loc);
TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
- TIntermTyped *addMethod(const TString &name,
- TIntermSequence *arguments,
- TIntermNode *thisNode,
- const TSourceLoc &loc);
- TIntermTyped *addConstructor(TIntermSequence *arguments,
- TType type,
- const TSourceLoc &line);
- TIntermTyped *addNonConstructorFunctionCall(const TString &name,
- TIntermSequence *arguments,
- const TSourceLoc &loc);
+ TIntermTyped *addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc);
+ TIntermTyped *addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line);
+ TIntermTyped *addNonConstructorFunctionCall(TFunctionLookup *fnCall, const TSourceLoc &loc);
// Return either the original expression or the folded version of the expression in case the
// folded node will validate the same way during subsequent parsing.
diff --git a/src/compiler/translator/Symbol.cpp b/src/compiler/translator/Symbol.cpp
index 664efcd..6ec6449 100644
--- a/src/compiler/translator/Symbol.cpp
+++ b/src/compiler/translator/Symbol.cpp
@@ -35,7 +35,7 @@
{
ASSERT(mSymbolType == SymbolType::BuiltIn || mExtension == TExtension::UNDEFINED);
ASSERT(mName != nullptr || mSymbolType == SymbolType::AngleInternal ||
- mSymbolType == SymbolType::NotResolved || mSymbolType == SymbolType::Empty);
+ mSymbolType == SymbolType::Empty);
ASSERT(mName == nullptr || *mName != "");
}
@@ -167,19 +167,6 @@
return NewPoolTString(newName.c_str());
}
-const TString &TFunction::GetMangledNameFromCall(const TString &functionName,
- const TIntermSequence &arguments)
-{
- std::string newName = functionName.c_str();
- newName += kFunctionMangledNameSeparator;
-
- for (TIntermNode *argument : arguments)
- {
- newName += argument->getAsTyped()->getType().getMangledName();
- }
- return *NewPoolTString(newName.c_str());
-}
-
bool TFunction::isMain() const
{
return symbolType() == SymbolType::UserDefined && name() == "main";
diff --git a/src/compiler/translator/Symbol.h b/src/compiler/translator/Symbol.h
index f6750c6..cff5d7a 100644
--- a/src/compiler/translator/Symbol.h
+++ b/src/compiler/translator/Symbol.h
@@ -24,8 +24,7 @@
BuiltIn,
UserDefined,
AngleInternal,
- Empty, // Meaning symbol without a name.
- NotResolved
+ Empty // Meaning symbol without a name.
};
// Symbol base class. (Can build functions or variables out of these...)
@@ -209,9 +208,6 @@
return *mangledName;
}
- static const TString &GetMangledNameFromCall(const TString &functionName,
- const TIntermSequence &arguments);
-
const TType &getReturnType() const { return *returnType; }
TOperator getBuiltInOp() const { return op; }
@@ -236,11 +232,9 @@
typedef TVector<TConstParameter> TParamList;
TParamList parameters;
- const TType *returnType;
+ const TType *const returnType;
mutable const TString *mangledName;
- // TODO(oetuaho): Remove op from TFunction once TFunction is not used for looking up builtins or
- // constructors.
- TOperator op;
+ const TOperator op; // Only set for built-ins
bool defined;
bool mHasPrototypeDeclaration;
bool mKnownToNotHaveSideEffects;
diff --git a/src/compiler/translator/glslang.y b/src/compiler/translator/glslang.y
index aeddf29..897e1e9 100644
--- a/src/compiler/translator/glslang.y
+++ b/src/compiler/translator/glslang.y
@@ -76,7 +76,6 @@
union {
TIntermNode *intermNode;
TIntermNodePair nodePair;
- TIntermFunctionCallOrMethod callOrMethodPair;
TIntermTyped *intermTypedNode;
TIntermAggregate *intermAggregate;
TIntermBlock *intermBlock;
@@ -93,6 +92,7 @@
TLayoutQualifier layoutQualifier;
TQualifier qualifier;
TFunction *function;
+ TFunctionLookup *functionLookup;
TParameter param;
TDeclarator *declarator;
TDeclaratorList *declaratorList;
@@ -236,10 +236,12 @@
%type <interm.declarator> struct_declarator
%type <interm.declaratorList> struct_declarator_list
%type <interm.fieldList> struct_declaration struct_declaration_list
-%type <interm.function> function_header function_declarator function_identifier
-%type <interm.function> function_header_with_parameters function_call_header
-%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
-%type <interm> function_call_or_method
+%type <interm.function> function_header function_declarator
+%type <interm.function> function_header_with_parameters
+%type <interm.functionLookup> function_identifier function_call_header
+%type <interm.functionLookup> function_call_header_with_parameters function_call_header_no_parameters
+%type <interm.functionLookup> function_call_generic function_call_or_method
+%type <interm> function_prototype
%type <lex> enter_struct
@@ -328,19 +330,18 @@
function_call
: function_call_or_method {
- $$ = context->addFunctionCallOrMethod($1.function, $1.callOrMethodPair.arguments, $1.callOrMethodPair.thisNode, @1);
+ $$ = context->addFunctionCallOrMethod($1, @1);
}
;
function_call_or_method
: function_call_generic {
$$ = $1;
- $$.callOrMethodPair.thisNode = nullptr;
}
| postfix_expression DOT function_call_generic {
ES3_OR_NEWER("", @3, "methods");
$$ = $3;
- $$.callOrMethodPair.thisNode = $1;
+ $$->setThisNode($1);
}
;
@@ -355,24 +356,21 @@
function_call_header_no_parameters
: function_call_header VOID_TYPE {
- $$.function = $1;
- $$.callOrMethodPair.arguments = context->createEmptyArgumentsList();
+ $$ = $1;
}
| function_call_header {
- $$.function = $1;
- $$.callOrMethodPair.arguments = context->createEmptyArgumentsList();
+ $$ = $1;
}
;
function_call_header_with_parameters
: function_call_header assignment_expression {
- $$.callOrMethodPair.arguments = context->createEmptyArgumentsList();
- $$.function = $1;
- $$.callOrMethodPair.arguments->push_back($2);
+ $$ = $1;
+ $$->addArgument($2);
}
| function_call_header_with_parameters COMMA assignment_expression {
- $$.function = $1.function;
- $$.callOrMethodPair.arguments->push_back($3);
+ $$ = $1;
+ $$->addArgument($3);
}
;
@@ -389,10 +387,10 @@
$$ = context->addConstructorFunc($1);
}
| IDENTIFIER {
- $$ = context->addNonConstructorFunc($1.string, @1);
+ $$ = context->addNonConstructorFunc($1.string);
}
| FIELD_SELECTION {
- $$ = context->addNonConstructorFunc($1.string, @1);
+ $$ = context->addNonConstructorFunc($1.string);
}
;
diff --git a/src/compiler/translator/glslang_tab.cpp b/src/compiler/translator/glslang_tab.cpp
index 00809dd..89bd638 100644
--- a/src/compiler/translator/glslang_tab.cpp
+++ b/src/compiler/translator/glslang_tab.cpp
@@ -317,7 +317,6 @@
union {
TIntermNode *intermNode;
TIntermNodePair nodePair;
- TIntermFunctionCallOrMethod callOrMethodPair;
TIntermTyped *intermTypedNode;
TIntermAggregate *intermAggregate;
TIntermBlock *intermBlock;
@@ -334,6 +333,7 @@
TLayoutQualifier layoutQualifier;
TQualifier qualifier;
TFunction *function;
+ TFunctionLookup *functionLookup;
TParameter param;
TDeclarator *declarator;
TDeclaratorList *declaratorList;
@@ -743,36 +743,36 @@
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 250, 250, 251, 254, 264, 267, 272, 277, 282,
- 287, 296, 302, 305, 308, 311, 314, 317, 323, 330,
- 336, 340, 348, 351, 357, 361, 368, 373, 380, 388,
- 391, 394, 400, 403, 406, 409, 416, 417, 418, 419,
- 427, 428, 431, 434, 441, 442, 445, 451, 452, 456,
- 463, 464, 467, 470, 473, 479, 480, 483, 489, 490,
- 497, 498, 505, 506, 513, 514, 520, 521, 527, 528,
- 534, 535, 541, 542, 548, 549, 550, 551, 555, 556,
- 557, 561, 565, 569, 573, 580, 583, 589, 596, 603,
- 606, 609, 613, 617, 621, 625, 629, 636, 643, 646,
- 653, 661, 678, 688, 691, 697, 701, 705, 709, 716,
- 723, 726, 730, 734, 739, 746, 750, 754, 758, 763,
- 770, 774, 780, 783, 789, 793, 800, 806, 810, 814,
- 817, 820, 829, 834, 838, 841, 844, 847, 850, 854,
- 857, 861, 864, 867, 870, 873, 876, 883, 890, 893,
- 896, 902, 909, 912, 918, 921, 924, 927, 933, 936,
- 943, 948, 955, 960, 971, 974, 977, 980, 983, 986,
- 990, 994, 998, 1002, 1006, 1010, 1014, 1018, 1022, 1026,
- 1030, 1034, 1038, 1042, 1046, 1050, 1054, 1058, 1062, 1066,
- 1070, 1077, 1080, 1083, 1086, 1089, 1092, 1095, 1098, 1101,
- 1104, 1107, 1110, 1113, 1116, 1119, 1122, 1125, 1128, 1131,
- 1141, 1148, 1155, 1158, 1161, 1164, 1167, 1170, 1173, 1176,
- 1179, 1182, 1185, 1188, 1191, 1194, 1197, 1205, 1205, 1208,
- 1208, 1214, 1217, 1223, 1226, 1233, 1237, 1243, 1246, 1252,
- 1256, 1260, 1261, 1267, 1268, 1269, 1270, 1271, 1272, 1273,
- 1277, 1281, 1281, 1281, 1288, 1289, 1293, 1293, 1294, 1294,
- 1299, 1303, 1310, 1314, 1321, 1322, 1326, 1332, 1336, 1345,
- 1345, 1352, 1355, 1361, 1365, 1371, 1371, 1376, 1376, 1380,
- 1380, 1388, 1391, 1397, 1400, 1406, 1410, 1417, 1420, 1423,
- 1426, 1429, 1437, 1443, 1449, 1452, 1458, 1458
+ 0, 252, 252, 253, 256, 266, 269, 274, 279, 284,
+ 289, 298, 304, 307, 310, 313, 316, 319, 325, 332,
+ 338, 341, 349, 352, 358, 361, 367, 371, 378, 386,
+ 389, 392, 398, 401, 404, 407, 414, 415, 416, 417,
+ 425, 426, 429, 432, 439, 440, 443, 449, 450, 454,
+ 461, 462, 465, 468, 471, 477, 478, 481, 487, 488,
+ 495, 496, 503, 504, 511, 512, 518, 519, 525, 526,
+ 532, 533, 539, 540, 546, 547, 548, 549, 553, 554,
+ 555, 559, 563, 567, 571, 578, 581, 587, 594, 601,
+ 604, 607, 611, 615, 619, 623, 627, 634, 641, 644,
+ 651, 659, 676, 686, 689, 695, 699, 703, 707, 714,
+ 721, 724, 728, 732, 737, 744, 748, 752, 756, 761,
+ 768, 772, 778, 781, 787, 791, 798, 804, 808, 812,
+ 815, 818, 827, 832, 836, 839, 842, 845, 848, 852,
+ 855, 859, 862, 865, 868, 871, 874, 881, 888, 891,
+ 894, 900, 907, 910, 916, 919, 922, 925, 931, 934,
+ 941, 946, 953, 958, 969, 972, 975, 978, 981, 984,
+ 988, 992, 996, 1000, 1004, 1008, 1012, 1016, 1020, 1024,
+ 1028, 1032, 1036, 1040, 1044, 1048, 1052, 1056, 1060, 1064,
+ 1068, 1075, 1078, 1081, 1084, 1087, 1090, 1093, 1096, 1099,
+ 1102, 1105, 1108, 1111, 1114, 1117, 1120, 1123, 1126, 1129,
+ 1139, 1146, 1153, 1156, 1159, 1162, 1165, 1168, 1171, 1174,
+ 1177, 1180, 1183, 1186, 1189, 1192, 1195, 1203, 1203, 1206,
+ 1206, 1212, 1215, 1221, 1224, 1231, 1235, 1241, 1244, 1250,
+ 1254, 1258, 1259, 1265, 1266, 1267, 1268, 1269, 1270, 1271,
+ 1275, 1279, 1279, 1279, 1286, 1287, 1291, 1291, 1292, 1292,
+ 1297, 1301, 1308, 1312, 1319, 1320, 1324, 1330, 1334, 1343,
+ 1343, 1350, 1353, 1359, 1363, 1369, 1369, 1374, 1374, 1378,
+ 1378, 1386, 1389, 1395, 1398, 1404, 1408, 1415, 1418, 1421,
+ 1424, 1427, 1435, 1441, 1447, 1450, 1456, 1456
};
#endif
@@ -2636,7 +2636,7 @@
case 19:
{
- (yyval.interm.intermTypedNode) = context->addFunctionCallOrMethod((yyvsp[0].interm).function, (yyvsp[0].interm).callOrMethodPair.arguments, (yyvsp[0].interm).callOrMethodPair.thisNode, (yylsp[0]));
+ (yyval.interm.intermTypedNode) = context->addFunctionCallOrMethod((yyvsp[0].interm.functionLookup), (yylsp[0]));
}
break;
@@ -2644,8 +2644,7 @@
case 20:
{
- (yyval.interm) = (yyvsp[0].interm);
- (yyval.interm).callOrMethodPair.thisNode = nullptr;
+ (yyval.interm.functionLookup) = (yyvsp[0].interm.functionLookup);
}
break;
@@ -2654,8 +2653,8 @@
{
ES3_OR_NEWER("", (yylsp[0]), "methods");
- (yyval.interm) = (yyvsp[0].interm);
- (yyval.interm).callOrMethodPair.thisNode = (yyvsp[-2].interm.intermTypedNode);
+ (yyval.interm.functionLookup) = (yyvsp[0].interm.functionLookup);
+ (yyval.interm.functionLookup)->setThisNode((yyvsp[-2].interm.intermTypedNode));
}
break;
@@ -2663,7 +2662,7 @@
case 22:
{
- (yyval.interm) = (yyvsp[-1].interm);
+ (yyval.interm.functionLookup) = (yyvsp[-1].interm.functionLookup);
}
break;
@@ -2671,7 +2670,7 @@
case 23:
{
- (yyval.interm) = (yyvsp[-1].interm);
+ (yyval.interm.functionLookup) = (yyvsp[-1].interm.functionLookup);
}
break;
@@ -2679,8 +2678,7 @@
case 24:
{
- (yyval.interm).function = (yyvsp[-1].interm.function);
- (yyval.interm).callOrMethodPair.arguments = context->createEmptyArgumentsList();
+ (yyval.interm.functionLookup) = (yyvsp[-1].interm.functionLookup);
}
break;
@@ -2688,8 +2686,7 @@
case 25:
{
- (yyval.interm).function = (yyvsp[0].interm.function);
- (yyval.interm).callOrMethodPair.arguments = context->createEmptyArgumentsList();
+ (yyval.interm.functionLookup) = (yyvsp[0].interm.functionLookup);
}
break;
@@ -2697,9 +2694,8 @@
case 26:
{
- (yyval.interm).callOrMethodPair.arguments = context->createEmptyArgumentsList();
- (yyval.interm).function = (yyvsp[-1].interm.function);
- (yyval.interm).callOrMethodPair.arguments->push_back((yyvsp[0].interm.intermTypedNode));
+ (yyval.interm.functionLookup) = (yyvsp[-1].interm.functionLookup);
+ (yyval.interm.functionLookup)->addArgument((yyvsp[0].interm.intermTypedNode));
}
break;
@@ -2707,8 +2703,8 @@
case 27:
{
- (yyval.interm).function = (yyvsp[-2].interm).function;
- (yyval.interm).callOrMethodPair.arguments->push_back((yyvsp[0].interm.intermTypedNode));
+ (yyval.interm.functionLookup) = (yyvsp[-2].interm.functionLookup);
+ (yyval.interm.functionLookup)->addArgument((yyvsp[0].interm.intermTypedNode));
}
break;
@@ -2716,7 +2712,7 @@
case 28:
{
- (yyval.interm.function) = (yyvsp[-1].interm.function);
+ (yyval.interm.functionLookup) = (yyvsp[-1].interm.functionLookup);
}
break;
@@ -2724,7 +2720,7 @@
case 29:
{
- (yyval.interm.function) = context->addConstructorFunc((yyvsp[0].interm.type));
+ (yyval.interm.functionLookup) = context->addConstructorFunc((yyvsp[0].interm.type));
}
break;
@@ -2732,7 +2728,7 @@
case 30:
{
- (yyval.interm.function) = context->addNonConstructorFunc((yyvsp[0].lex).string, (yylsp[0]));
+ (yyval.interm.functionLookup) = context->addNonConstructorFunc((yyvsp[0].lex).string);
}
break;
@@ -2740,7 +2736,7 @@
case 31:
{
- (yyval.interm.function) = context->addNonConstructorFunc((yyvsp[0].lex).string, (yylsp[0]));
+ (yyval.interm.functionLookup) = context->addNonConstructorFunc((yyvsp[0].lex).string);
}
break;
diff --git a/src/compiler/translator/glslang_tab.h b/src/compiler/translator/glslang_tab.h
index 048831b..1f1d9b7 100644
--- a/src/compiler/translator/glslang_tab.h
+++ b/src/compiler/translator/glslang_tab.h
@@ -228,7 +228,6 @@
union {
TIntermNode *intermNode;
TIntermNodePair nodePair;
- TIntermFunctionCallOrMethod callOrMethodPair;
TIntermTyped *intermTypedNode;
TIntermAggregate *intermAggregate;
TIntermBlock *intermBlock;
@@ -245,6 +244,7 @@
TLayoutQualifier layoutQualifier;
TQualifier qualifier;
TFunction *function;
+ TFunctionLookup *functionLookup;
TParameter param;
TDeclarator *declarator;
TDeclaratorList *declaratorList;
diff --git a/src/tests/test_utils/compiler_test.cpp b/src/tests/test_utils/compiler_test.cpp
index 24d24b6..cb2c9d1 100644
--- a/src/tests/test_utils/compiler_test.cpp
+++ b/src/tests/test_utils/compiler_test.cpp
@@ -10,6 +10,7 @@
#include "angle_gl.h"
#include "compiler/translator/Compiler.h"
+#include "compiler/translator/FunctionLookup.h"
#include "compiler/translator/IntermTraverse.h"
namespace sh
@@ -18,6 +19,22 @@
namespace
{
+const TString &GetSymbolTableMangledName(TIntermAggregate *node)
+{
+ ASSERT(!node->isConstructor());
+ switch (node->getOp())
+ {
+ case EOpCallInternalRawFunction:
+ case EOpCallBuiltInFunction:
+ case EOpCallFunctionInAST:
+ return TFunctionLookup::GetMangledName(node->getFunction()->name(),
+ *node->getSequence());
+ default:
+ TString opString = GetOperatorString(node->getOp());
+ return TFunctionLookup::GetMangledName(opString, *node->getSequence());
+ }
+}
+
class FunctionCallFinder : public TIntermTraverser
{
public:
@@ -30,7 +47,7 @@
bool visitAggregate(Visit visit, TIntermAggregate *node) override
{
- if (node->isFunctionCall() && node->getSymbolTableMangledName() == mFunctionMangledName)
+ if (node->isFunctionCall() && GetSymbolTableMangledName(node) == mFunctionMangledName)
{
mNodeFound = node;
return false;