Commit 95ed1947 by Olli Etuaho Committed by Commit Bot

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/897363Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 5c5d7dee
......@@ -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',
......
......@@ -6,6 +6,8 @@
#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/FunctionLookup.h"
#include <memory>
namespace sh
......@@ -713,7 +715,7 @@ const TFunction *EmulatePrecision::getInternalFunction(TString *functionName,
const TVector<TConstParameter> &parameters,
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),
......
//
// 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
//
// 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_
......@@ -509,21 +509,6 @@ void TIntermAggregate::setBuiltInFunctionPrecision()
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());
......
......@@ -533,15 +533,6 @@ class TIntermUnary : public TIntermOperator
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 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
TIntermSequence *getSequence() override { return &mArguments; }
const TIntermSequence *getSequence() const override { return &mArguments; }
TString getSymbolTableMangledName() const;
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
......
......@@ -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 TFunction *LookUpBuiltInFunction(const TString &name,
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)
{
......
......@@ -695,16 +695,16 @@ bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &id
// 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 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
{
// 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 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
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 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
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 TParseContext::checkConstructorArguments(const TSourceLoc &line,
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 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
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 @@ TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
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 @@ TFunction *TParseContext::addConstructorFunc(const TPublicType &publicType)
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 @@ TParameter TParseContext::parseParameterArrayDeclarator(const TString *name,
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 @@ bool TParseContext::checkUnsizedArrayConstructorArgumentDimensionality(TIntermSe
//
// 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 @@ TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments,
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 @@ TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments,
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 @@ void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
}
}
TIntermSequence *TParseContext::createEmptyArgumentsList()
TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunctionLookup *fnCall, const TSourceLoc &loc)
{
return new TIntermSequence();
}
TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
TIntermSequence *arguments,
TIntermNode *thisNode,
const TSourceLoc &loc)
{
if (thisNode != nullptr)
if (fnCall->thisNode() != nullptr)
{
return addMethod(fnCall->name(), arguments, thisNode, loc);
return addMethod(fnCall, loc);
}
TOperator op = fnCall->getBuiltInOp();
if (op == EOpConstruct)
if (fnCall->isConstructor())
{
return addConstructor(arguments, fnCall->getReturnType(), loc);
}
else
{
ASSERT(op == EOpNull);
return addNonConstructorFunctionCall(fnCall->name(), arguments, loc);
return addConstructor(fnCall, loc);
}
return addNonConstructorFunctionCall(fnCall, loc);
}
TIntermTyped *TParseContext::addMethod(const TString &name,
TIntermSequence *arguments,
TIntermNode *thisNode,
const TSourceLoc &loc)
TIntermTyped *TParseContext::addMethod(TFunctionLookup *fnCall, 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 @@ TIntermTyped *TParseContext::addMethod(const TString &name,
}
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 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(const TString &name,
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 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(const TString &name,
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 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(const TString &name,
// 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 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(const TString &name,
}
else
{
callNode = TIntermAggregate::CreateFunctionCall(*fnCandidate, arguments);
callNode =
TIntermAggregate::CreateFunctionCall(*fnCandidate, &fnCall->arguments());
checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
}
......
......@@ -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 @@ class TParseContext : angle::NonCopyable
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 @@ class TParseContext : angle::NonCopyable
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 @@ class TParseContext : angle::NonCopyable
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 @@ class TParseContext : angle::NonCopyable
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 @@ class TParseContext : angle::NonCopyable
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.
......
......@@ -35,7 +35,7 @@ TSymbol::TSymbol(TSymbolTable *symbolTable,
{
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 @@ const TString *TFunction::buildMangledName() const
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";
......
......@@ -24,8 +24,7 @@ enum class SymbolType
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 @@ class TFunction : public TSymbol
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 @@ class TFunction : public TSymbol
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;
......
......@@ -76,7 +76,6 @@ using namespace sh;
union {
TIntermNode *intermNode;
TIntermNodePair nodePair;
TIntermFunctionCallOrMethod callOrMethodPair;
TIntermTyped *intermTypedNode;
TIntermAggregate *intermAggregate;
TIntermBlock *intermBlock;
......@@ -93,6 +92,7 @@ using namespace sh;
TLayoutQualifier layoutQualifier;
TQualifier qualifier;
TFunction *function;
TFunctionLookup *functionLookup;
TParameter param;
TDeclarator *declarator;
TDeclaratorList *declaratorList;
......@@ -236,10 +236,12 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons
%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 @@ integer_expression
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_generic
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 @@ function_identifier
$$ = context->addConstructorFunc($1);
}
| IDENTIFIER {
$$ = context->addNonConstructorFunc($1.string, @1);
$$ = context->addNonConstructorFunc($1.string);
}
| FIELD_SELECTION {
$$ = context->addNonConstructorFunc($1.string, @1);
$$ = context->addNonConstructorFunc($1.string);
}
;
......
......@@ -317,7 +317,6 @@ union YYSTYPE
union {
TIntermNode *intermNode;
TIntermNodePair nodePair;
TIntermFunctionCallOrMethod callOrMethodPair;
TIntermTyped *intermTypedNode;
TIntermAggregate *intermAggregate;
TIntermBlock *intermBlock;
......@@ -334,6 +333,7 @@ union YYSTYPE
TLayoutQualifier layoutQualifier;
TQualifier qualifier;
TFunction *function;
TFunctionLookup *functionLookup;
TParameter param;
TDeclarator *declarator;
TDeclaratorList *declaratorList;
......@@ -743,36 +743,36 @@ static const yytype_uint8 yytranslate[] =
/* 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 @@ yyreduce:
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 @@ yyreduce:
case 20:
{
(yyval.interm) = (yyvsp[0].interm);
(yyval.interm).callOrMethodPair.thisNode = nullptr;
(yyval.interm.functionLookup) = (yyvsp[0].interm.functionLookup);
}
break;
......@@ -2654,8 +2653,8 @@ yyreduce:
{
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 @@ yyreduce:
case 22:
{
(yyval.interm) = (yyvsp[-1].interm);
(yyval.interm.functionLookup) = (yyvsp[-1].interm.functionLookup);
}
break;
......@@ -2671,7 +2670,7 @@ yyreduce:
case 23:
{
(yyval.interm) = (yyvsp[-1].interm);
(yyval.interm.functionLookup) = (yyvsp[-1].interm.functionLookup);
}
break;
......@@ -2679,8 +2678,7 @@ yyreduce:
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 @@ yyreduce:
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 @@ yyreduce:
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 @@ yyreduce:
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 @@ yyreduce:
case 28:
{
(yyval.interm.function) = (yyvsp[-1].interm.function);
(yyval.interm.functionLookup) = (yyvsp[-1].interm.functionLookup);
}
break;
......@@ -2724,7 +2720,7 @@ yyreduce:
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 @@ yyreduce:
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 @@ yyreduce:
case 31:
{
(yyval.interm.function) = context->addNonConstructorFunc((yyvsp[0].lex).string, (yylsp[0]));
(yyval.interm.functionLookup) = context->addNonConstructorFunc((yyvsp[0].lex).string);
}
break;
......
......@@ -228,7 +228,6 @@ union YYSTYPE
union {
TIntermNode *intermNode;
TIntermNodePair nodePair;
TIntermFunctionCallOrMethod callOrMethodPair;
TIntermTyped *intermTypedNode;
TIntermAggregate *intermAggregate;
TIntermBlock *intermBlock;
......@@ -245,6 +244,7 @@ union YYSTYPE
TLayoutQualifier layoutQualifier;
TQualifier qualifier;
TFunction *function;
TFunctionLookup *functionLookup;
TParameter param;
TDeclarator *declarator;
TDeclaratorList *declaratorList;
......
......@@ -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 sh
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 @@ class FunctionCallFinder : public TIntermTraverser
bool visitAggregate(Visit visit, TIntermAggregate *node) override
{
if (node->isFunctionCall() && node->getSymbolTableMangledName() == mFunctionMangledName)
if (node->isFunctionCall() && GetSymbolTableMangledName(node) == mFunctionMangledName)
{
mNodeFound = node;
return false;
......
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