Commit af6fc1b4 by Olli Etuaho Committed by Commit Bot

Make aggregate node creation more robust

Now aggregate nodes are always built with their return type, op and arguments set. They'll determine their qualifier and precision automatically. This fixes setting of gotPrecisionFromChildren in a few cases. This will also make it easier to split TIntermAggregate further into specialized classes if that is desired. BUG=angleproject:1490 TEST=angle_unittests Change-Id: I1fbe0c75679c517a22d44dfc1ea160ad7a7fdfda Reviewed-on: https://chromium-review.googlesource.com/433468Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent ccab69d6
...@@ -43,17 +43,17 @@ TIntermSymbol *CreateReturnValueOutSymbol(const TType &type) ...@@ -43,17 +43,17 @@ TIntermSymbol *CreateReturnValueOutSymbol(const TType &type)
TIntermAggregate *CreateReplacementCall(TIntermAggregate *originalCall, TIntermAggregate *CreateReplacementCall(TIntermAggregate *originalCall,
TIntermTyped *returnValueTarget) TIntermTyped *returnValueTarget)
{ {
TIntermAggregate *replacementCall = new TIntermAggregate(EOpCallFunctionInAST); TIntermSequence *replacementArguments = new TIntermSequence();
replacementCall->setType(TType(EbtVoid)); TIntermSequence *originalArguments = originalCall->getSequence();
*replacementCall->getFunctionSymbolInfo() = *originalCall->getFunctionSymbolInfo(); for (auto &arg : *originalArguments)
replacementCall->setLine(originalCall->getLine());
TIntermSequence *replacementParameters = replacementCall->getSequence();
TIntermSequence *originalParameters = originalCall->getSequence();
for (auto &param : *originalParameters)
{ {
replacementParameters->push_back(param); replacementArguments->push_back(arg);
} }
replacementParameters->push_back(returnValueTarget); replacementArguments->push_back(returnValueTarget);
TIntermAggregate *replacementCall =
new TIntermAggregate(TType(EbtVoid), EOpCallFunctionInAST, replacementArguments);
*replacementCall->getFunctionSymbolInfo() = *originalCall->getFunctionSymbolInfo();
replacementCall->setLine(originalCall->getLine());
return replacementCall; return replacementCall;
} }
......
...@@ -50,10 +50,10 @@ TIntermFunctionDefinition *CreateFunctionDefinitionNode(const char *name, ...@@ -50,10 +50,10 @@ TIntermFunctionDefinition *CreateFunctionDefinitionNode(const char *name,
TIntermAggregate *CreateFunctionCallNode(const char *name, const int functionId) TIntermAggregate *CreateFunctionCallNode(const char *name, const int functionId)
{ {
TIntermAggregate *functionNode = new TIntermAggregate(EOpCallFunctionInAST);
SetInternalFunctionName(functionNode->getFunctionSymbolInfo(), name);
TType returnType(EbtVoid); TType returnType(EbtVoid);
functionNode->setType(returnType); TIntermAggregate *functionNode =
new TIntermAggregate(returnType, EOpCallFunctionInAST, nullptr);
SetInternalFunctionName(functionNode->getFunctionSymbolInfo(), name);
functionNode->getFunctionSymbolInfo()->setId(functionId); functionNode->getFunctionSymbolInfo()->setId(functionId);
return functionNode; return functionNode;
} }
......
...@@ -427,13 +427,14 @@ bool canRoundFloat(const TType &type) ...@@ -427,13 +427,14 @@ bool canRoundFloat(const TType &type)
(type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium); (type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium);
} }
TIntermAggregate *createInternalFunctionCallNode(TString name, TIntermNode *child) TIntermAggregate *createInternalFunctionCallNode(const TType &type,
TString name,
TIntermSequence *arguments)
{ {
TIntermAggregate *callNode = new TIntermAggregate(EOpCallInternalRawFunction); TName nameObj(TFunction::GetMangledNameFromCall(name, *arguments));
TName nameObj(TFunction::mangleName(name));
nameObj.setInternal(true); nameObj.setInternal(true);
TIntermAggregate *callNode = new TIntermAggregate(type, EOpCallInternalRawFunction, arguments);
callNode->getFunctionSymbolInfo()->setNameObj(nameObj); callNode->getFunctionSymbolInfo()->setNameObj(nameObj);
callNode->getSequence()->push_back(child);
return callNode; return callNode;
} }
...@@ -444,9 +445,9 @@ TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild) ...@@ -444,9 +445,9 @@ TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild)
roundFunctionName = "angle_frm"; roundFunctionName = "angle_frm";
else else
roundFunctionName = "angle_frl"; roundFunctionName = "angle_frl";
TIntermAggregate *callNode = createInternalFunctionCallNode(roundFunctionName, roundedChild); TIntermSequence *arguments = new TIntermSequence();
callNode->setType(roundedChild->getType()); arguments->push_back(roundedChild);
return callNode; return createInternalFunctionCallNode(roundedChild->getType(), roundFunctionName, arguments);
} }
TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left, TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left,
...@@ -459,9 +460,10 @@ TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left, ...@@ -459,9 +460,10 @@ TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left,
else else
strstr << "angle_compound_" << opNameStr << "_frl"; strstr << "angle_compound_" << opNameStr << "_frl";
TString functionName = strstr.str().c_str(); TString functionName = strstr.str().c_str();
TIntermAggregate *callNode = createInternalFunctionCallNode(functionName, left); TIntermSequence *arguments = new TIntermSequence();
callNode->getSequence()->push_back(right); arguments->push_back(left);
return callNode; arguments->push_back(right);
return createInternalFunctionCallNode(TType(EbtVoid), functionName, arguments);
} }
bool parentUsesResult(TIntermNode *parent, TIntermNode *node) bool parentUsesResult(TIntermNode *parent, TIntermNode *node)
......
...@@ -272,12 +272,48 @@ bool TIntermAggregateBase::insertChildNodes(TIntermSequence::size_type position, ...@@ -272,12 +272,48 @@ bool TIntermAggregateBase::insertChildNodes(TIntermSequence::size_type position,
return true; return true;
} }
TIntermAggregate::TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments)
: TIntermOperator(op), mUseEmulatedFunction(false), mGotPrecisionFromChildren(false)
{
if (arguments != nullptr)
{
mArguments.swap(*arguments);
}
setTypePrecisionAndQualifier(type);
}
void TIntermAggregate::setTypePrecisionAndQualifier(const TType &type)
{
setType(type);
mType.setQualifier(EvqTemporary);
if (!isFunctionCall())
{
if (isConstructor())
{
// Structs should not be precision qualified, the individual members may be.
// Built-in types on the other hand should be precision qualified.
if (mOp != EOpConstructStruct)
{
setPrecisionFromChildren();
}
}
else
{
setPrecisionForBuiltInOp();
}
if (areChildrenConstQualified())
{
mType.setQualifier(EvqConst);
}
}
}
bool TIntermAggregate::areChildrenConstQualified() bool TIntermAggregate::areChildrenConstQualified()
{ {
for (TIntermNode *&child : mSequence) for (TIntermNode *&arg : mArguments)
{ {
TIntermTyped *typed = child->getAsTyped(); TIntermTyped *typedArg = arg->getAsTyped();
if (typed && typed->getQualifier() != EvqConst) if (typedArg && typedArg->getQualifier() != EvqConst)
{ {
return false; return false;
} }
...@@ -295,8 +331,8 @@ void TIntermAggregate::setPrecisionFromChildren() ...@@ -295,8 +331,8 @@ void TIntermAggregate::setPrecisionFromChildren()
} }
TPrecision precision = EbpUndefined; TPrecision precision = EbpUndefined;
TIntermSequence::iterator childIter = mSequence.begin(); TIntermSequence::iterator childIter = mArguments.begin();
while (childIter != mSequence.end()) while (childIter != mArguments.end())
{ {
TIntermTyped *typed = (*childIter)->getAsTyped(); TIntermTyped *typed = (*childIter)->getAsTyped();
if (typed) if (typed)
...@@ -321,11 +357,13 @@ bool TIntermAggregate::setPrecisionForSpecialBuiltInOp() ...@@ -321,11 +357,13 @@ bool TIntermAggregate::setPrecisionForSpecialBuiltInOp()
switch (mOp) switch (mOp)
{ {
case EOpBitfieldExtract: case EOpBitfieldExtract:
mType.setPrecision(mSequence[0]->getAsTyped()->getPrecision()); mType.setPrecision(mArguments[0]->getAsTyped()->getPrecision());
mGotPrecisionFromChildren = true;
return true; return true;
case EOpBitfieldInsert: case EOpBitfieldInsert:
mType.setPrecision(GetHigherPrecision(mSequence[0]->getAsTyped()->getPrecision(), mType.setPrecision(GetHigherPrecision(mArguments[0]->getAsTyped()->getPrecision(),
mSequence[1]->getAsTyped()->getPrecision())); mArguments[1]->getAsTyped()->getPrecision()));
mGotPrecisionFromChildren = true;
return true; return true;
case EOpUaddCarry: case EOpUaddCarry:
case EOpUsubBorrow: case EOpUsubBorrow:
...@@ -343,17 +381,15 @@ void TIntermAggregate::setBuiltInFunctionPrecision() ...@@ -343,17 +381,15 @@ void TIntermAggregate::setBuiltInFunctionPrecision()
ASSERT(mOp == EOpCallBuiltInFunction); ASSERT(mOp == EOpCallBuiltInFunction);
TPrecision precision = EbpUndefined; TPrecision precision = EbpUndefined;
TIntermSequence::iterator childIter = mSequence.begin(); for (TIntermNode *arg : mArguments)
while (childIter != mSequence.end())
{ {
TIntermTyped *typed = (*childIter)->getAsTyped(); TIntermTyped *typed = arg->getAsTyped();
// ESSL spec section 8: texture functions get their precision from the sampler. // ESSL spec section 8: texture functions get their precision from the sampler.
if (typed && IsSampler(typed->getBasicType())) if (typed && IsSampler(typed->getBasicType()))
{ {
precision = typed->getPrecision(); precision = typed->getPrecision();
break; break;
} }
++childIter;
} }
// ESSL 3.0 spec section 8: textureSize always gets highp precision. // ESSL 3.0 spec section 8: textureSize always gets highp precision.
// All other functions that take a sampler are assumed to be texture functions. // All other functions that take a sampler are assumed to be texture functions.
...@@ -497,8 +533,7 @@ TIntermTyped *TIntermTyped::CreateZero(const TType &type) ...@@ -497,8 +533,7 @@ TIntermTyped *TIntermTyped::CreateZero(const TType &type)
return node; return node;
} }
TIntermAggregate *constructor = new TIntermAggregate(sh::TypeToConstructorOperator(type)); TIntermSequence *arguments = new TIntermSequence();
constructor->setType(constType);
if (type.isArray()) if (type.isArray())
{ {
...@@ -508,7 +543,7 @@ TIntermTyped *TIntermTyped::CreateZero(const TType &type) ...@@ -508,7 +543,7 @@ TIntermTyped *TIntermTyped::CreateZero(const TType &type)
size_t arraySize = type.getArraySize(); size_t arraySize = type.getArraySize();
for (size_t i = 0; i < arraySize; ++i) for (size_t i = 0; i < arraySize; ++i)
{ {
constructor->getSequence()->push_back(CreateZero(elementType)); arguments->push_back(CreateZero(elementType));
} }
} }
else else
...@@ -518,11 +553,11 @@ TIntermTyped *TIntermTyped::CreateZero(const TType &type) ...@@ -518,11 +553,11 @@ TIntermTyped *TIntermTyped::CreateZero(const TType &type)
TStructure *structure = type.getStruct(); TStructure *structure = type.getStruct();
for (const auto &field : structure->fields()) for (const auto &field : structure->fields())
{ {
constructor->getSequence()->push_back(CreateZero(*field->type())); arguments->push_back(CreateZero(*field->type()));
} }
} }
return constructor; return new TIntermAggregate(constType, sh::TypeToConstructorOperator(type), arguments);
} }
// static // static
...@@ -553,12 +588,12 @@ TIntermAggregate::TIntermAggregate(const TIntermAggregate &node) ...@@ -553,12 +588,12 @@ TIntermAggregate::TIntermAggregate(const TIntermAggregate &node)
mGotPrecisionFromChildren(node.mGotPrecisionFromChildren), mGotPrecisionFromChildren(node.mGotPrecisionFromChildren),
mFunctionInfo(node.mFunctionInfo) mFunctionInfo(node.mFunctionInfo)
{ {
for (TIntermNode *child : node.mSequence) for (TIntermNode *arg : node.mArguments)
{ {
TIntermTyped *typedChild = child->getAsTyped(); TIntermTyped *typedArg = arg->getAsTyped();
ASSERT(typedChild != nullptr); ASSERT(typedArg != nullptr);
TIntermTyped *childCopy = typedChild->deepCopy(); TIntermTyped *argCopy = typedArg->deepCopy();
mSequence.push_back(childCopy); mArguments.push_back(argCopy);
} }
} }
...@@ -1308,8 +1343,7 @@ TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics) ...@@ -1308,8 +1343,7 @@ TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics)
constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics); constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics);
// Nodes may be constant folded without being qualified as constant. // Nodes may be constant folded without being qualified as constant.
TQualifier resultQualifier = areChildrenConstQualified() ? EvqConst : EvqTemporary; return CreateFoldedNode(constArray, this, getQualifier());
return CreateFoldedNode(constArray, this, resultQualifier);
} }
// //
...@@ -2417,32 +2451,32 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg ...@@ -2417,32 +2451,32 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg
TDiagnostics *diagnostics) TDiagnostics *diagnostics)
{ {
TOperator op = aggregate->getOp(); TOperator op = aggregate->getOp();
TIntermSequence *sequence = aggregate->getSequence(); TIntermSequence *arguments = aggregate->getSequence();
unsigned int paramsCount = static_cast<unsigned int>(sequence->size()); unsigned int argsCount = static_cast<unsigned int>(arguments->size());
std::vector<const TConstantUnion *> unionArrays(paramsCount); std::vector<const TConstantUnion *> unionArrays(argsCount);
std::vector<size_t> objectSizes(paramsCount); std::vector<size_t> objectSizes(argsCount);
size_t maxObjectSize = 0; size_t maxObjectSize = 0;
TBasicType basicType = EbtVoid; TBasicType basicType = EbtVoid;
TSourceLoc loc; TSourceLoc loc;
for (unsigned int i = 0; i < paramsCount; i++) for (unsigned int i = 0; i < argsCount; i++)
{ {
TIntermConstantUnion *paramConstant = (*sequence)[i]->getAsConstantUnion(); TIntermConstantUnion *argConstant = (*arguments)[i]->getAsConstantUnion();
ASSERT(paramConstant != nullptr); // Should be checked already. ASSERT(argConstant != nullptr); // Should be checked already.
if (i == 0) if (i == 0)
{ {
basicType = paramConstant->getType().getBasicType(); basicType = argConstant->getType().getBasicType();
loc = paramConstant->getLine(); loc = argConstant->getLine();
} }
unionArrays[i] = paramConstant->getUnionArrayPointer(); unionArrays[i] = argConstant->getUnionArrayPointer();
objectSizes[i] = paramConstant->getType().getObjectSize(); objectSizes[i] = argConstant->getType().getObjectSize();
if (objectSizes[i] > maxObjectSize) if (objectSizes[i] > maxObjectSize)
maxObjectSize = objectSizes[i]; maxObjectSize = objectSizes[i];
} }
if (!(*sequence)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct) if (!(*arguments)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct)
{ {
for (unsigned int i = 0; i < paramsCount; i++) for (unsigned int i = 0; i < argsCount; i++)
if (objectSizes[i] != maxObjectSize) if (objectSizes[i] != maxObjectSize)
unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize); unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize);
} }
...@@ -2791,11 +2825,11 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg ...@@ -2791,11 +2825,11 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg
case EOpMulMatrixComponentWise: case EOpMulMatrixComponentWise:
{ {
ASSERT(basicType == EbtFloat && (*sequence)[0]->getAsTyped()->isMatrix() && ASSERT(basicType == EbtFloat && (*arguments)[0]->getAsTyped()->isMatrix() &&
(*sequence)[1]->getAsTyped()->isMatrix()); (*arguments)[1]->getAsTyped()->isMatrix());
// Perform component-wise matrix multiplication. // Perform component-wise matrix multiplication.
resultArray = new TConstantUnion[maxObjectSize]; resultArray = new TConstantUnion[maxObjectSize];
int size = (*sequence)[0]->getAsTyped()->getNominalSize(); int size = (*arguments)[0]->getAsTyped()->getNominalSize();
angle::Matrix<float> result = angle::Matrix<float> result =
GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size)); GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size));
SetUnionArrayFromMatrix(result, resultArray); SetUnionArrayFromMatrix(result, resultArray);
...@@ -2805,8 +2839,8 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg ...@@ -2805,8 +2839,8 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg
case EOpOuterProduct: case EOpOuterProduct:
{ {
ASSERT(basicType == EbtFloat); ASSERT(basicType == EbtFloat);
size_t numRows = (*sequence)[0]->getAsTyped()->getType().getObjectSize(); size_t numRows = (*arguments)[0]->getAsTyped()->getType().getObjectSize();
size_t numCols = (*sequence)[1]->getAsTyped()->getType().getObjectSize(); size_t numCols = (*arguments)[1]->getAsTyped()->getType().getObjectSize();
resultArray = new TConstantUnion[numRows * numCols]; resultArray = new TConstantUnion[numRows * numCols];
angle::Matrix<float> result = angle::Matrix<float> result =
GetMatrix(unionArrays[0], static_cast<int>(numRows), 1) GetMatrix(unionArrays[0], static_cast<int>(numRows), 1)
...@@ -2878,7 +2912,7 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg ...@@ -2878,7 +2912,7 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg
{ {
float x = unionArrays[0][i].getFConst(); float x = unionArrays[0][i].getFConst();
float y = unionArrays[1][i].getFConst(); float y = unionArrays[1][i].getFConst();
TBasicType type = (*sequence)[2]->getAsTyped()->getType().getBasicType(); TBasicType type = (*arguments)[2]->getAsTyped()->getType().getBasicType();
if (type == EbtFloat) if (type == EbtFloat)
{ {
// Returns the linear blend of x and y, i.e., x * (1 - a) + y * a. // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.
......
...@@ -136,15 +136,6 @@ struct TIntermNodePair ...@@ -136,15 +136,6 @@ struct TIntermNodePair
}; };
// //
// This is just to help yacc.
//
struct TIntermFunctionCallOrMethod
{
TIntermAggregate *argumentsNode;
TIntermNode *thisNode;
};
//
// Intermediate class for nodes that have a type. // Intermediate class for nodes that have a type.
// //
class TIntermTyped : public TIntermNode class TIntermTyped : public TIntermNode
...@@ -569,6 +560,15 @@ class TFunctionSymbolInfo ...@@ -569,6 +560,15 @@ class TFunctionSymbolInfo
typedef TVector<TIntermNode *> TIntermSequence; typedef TVector<TIntermNode *> TIntermSequence;
typedef TVector<int> TQualifierList; 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. // Interface for node classes that have an arbitrarily sized set of children.
class TIntermAggregateBase class TIntermAggregateBase
{ {
...@@ -593,19 +593,12 @@ class TIntermAggregateBase ...@@ -593,19 +593,12 @@ class TIntermAggregateBase
class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
{ {
public: public:
TIntermAggregate(TOperator op) TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments);
: TIntermOperator(op),
mUseEmulatedFunction(false),
mGotPrecisionFromChildren(false)
{
}
~TIntermAggregate() {} ~TIntermAggregate() {}
// Note: only supported for nodes that can be a part of an expression. // Note: only supported for nodes that can be a part of an expression.
TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); } TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); }
void setOp(TOperator op) { mOp = op; }
TIntermAggregate *getAsAggregate() override { return this; } TIntermAggregate *getAsAggregate() override { return this; }
void traverse(TIntermTraverser *it) override; void traverse(TIntermTraverser *it) override;
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
...@@ -614,29 +607,24 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase ...@@ -614,29 +607,24 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
bool hasSideEffects() const override { return true; } bool hasSideEffects() const override { return true; }
TIntermTyped *fold(TDiagnostics *diagnostics); TIntermTyped *fold(TDiagnostics *diagnostics);
TIntermSequence *getSequence() override { return &mSequence; } TIntermSequence *getSequence() override { return &mArguments; }
const TIntermSequence *getSequence() const override { return &mSequence; } const TIntermSequence *getSequence() const override { return &mArguments; }
void setUseEmulatedFunction() { mUseEmulatedFunction = true; } void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; } bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
bool areChildrenConstQualified();
void setPrecisionForBuiltInOp();
void setPrecisionFromChildren();
// Used for built-in functions under EOpCallBuiltInFunction.
void setBuiltInFunctionPrecision();
// Returns true if changing parameter precision may affect the return value. // Returns true if changing parameter precision may affect the return value.
bool gotPrecisionFromChildren() const { return mGotPrecisionFromChildren; } bool gotPrecisionFromChildren() const { return mGotPrecisionFromChildren; }
TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; } TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; }
const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; } const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
// Used for built-in functions under EOpCallBuiltInFunction. The function name in the symbol
// info needs to be set before calling this.
void setBuiltInFunctionPrecision();
protected: protected:
TIntermSequence mSequence; TIntermSequence mArguments;
// If set to true, replace the built-in function call with an emulated one // If set to true, replace the built-in function call with an emulated one
// to work around driver bugs. Only for calls mapped to ops other than EOpCall*. // to work around driver bugs. Only for calls mapped to ops other than EOpCall*.
...@@ -649,6 +637,14 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase ...@@ -649,6 +637,14 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
private: private:
TIntermAggregate(const TIntermAggregate &node); // note: not deleted, just private! TIntermAggregate(const TIntermAggregate &node); // note: not deleted, just private!
void setTypePrecisionAndQualifier(const TType &type);
bool areChildrenConstQualified();
void setPrecisionFromChildren();
void setPrecisionForBuiltInOp();
// Returns true if precision was set according to special rules for this built-in. // Returns true if precision was set according to special rules for this built-in.
bool setPrecisionForSpecialBuiltInOp(); bool setPrecisionForSpecialBuiltInOp();
}; };
......
...@@ -552,7 +552,7 @@ bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &id ...@@ -552,7 +552,7 @@ bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &id
// something of the type of the constructor. Also returns the type of // something of the type of the constructor. Also returns the type of
// the constructor. // the constructor.
bool TParseContext::checkConstructorArguments(const TSourceLoc &line, bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
const TIntermAggregate *argumentsNode, const TIntermSequence *arguments,
TOperator op, TOperator op,
const TType &type) const TType &type)
{ {
...@@ -585,7 +585,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, ...@@ -585,7 +585,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
bool overFull = false; bool overFull = false;
bool matrixInMatrix = false; bool matrixInMatrix = false;
bool arrayArg = false; bool arrayArg = false;
for (TIntermNode *arg : *argumentsNode->getSequence()) for (TIntermNode *arg : *arguments)
{ {
const TIntermTyped *argTyped = arg->getAsTyped(); const TIntermTyped *argTyped = arg->getAsTyped();
size += argTyped->getType().getObjectSize(); size += argTyped->getType().getObjectSize();
...@@ -604,7 +604,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, ...@@ -604,7 +604,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
{ {
// The size of an unsized constructor should already have been determined. // The size of an unsized constructor should already have been determined.
ASSERT(!type.isUnsizedArray()); ASSERT(!type.isUnsizedArray());
if (static_cast<size_t>(type.getArraySize()) != argumentsNode->getSequence()->size()) if (static_cast<size_t>(type.getArraySize()) != arguments->size())
{ {
error(line, "array constructor needs one argument per array element", "constructor"); error(line, "array constructor needs one argument per array element", "constructor");
return false; return false;
...@@ -619,7 +619,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, ...@@ -619,7 +619,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
if (matrixInMatrix && !type.isArray()) if (matrixInMatrix && !type.isArray())
{ {
if (argumentsNode->getSequence()->size() != 1) if (arguments->size() != 1)
{ {
error(line, "constructing matrix from matrix can only take one argument", error(line, "constructing matrix from matrix can only take one argument",
"constructor"); "constructor");
...@@ -634,7 +634,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, ...@@ -634,7 +634,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
} }
if (op == EOpConstructStruct && !type.isArray() && if (op == EOpConstructStruct && !type.isArray() &&
type.getStruct()->fields().size() != argumentsNode->getSequence()->size()) type.getStruct()->fields().size() != arguments->size())
{ {
error(line, error(line,
"Number of constructor parameters does not match the number of structure fields", "Number of constructor parameters does not match the number of structure fields",
...@@ -652,13 +652,13 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, ...@@ -652,13 +652,13 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
} }
} }
if (argumentsNode->getSequence()->empty()) if (arguments->empty())
{ {
error(line, "constructor does not have any arguments", "constructor"); error(line, "constructor does not have any arguments", "constructor");
return false; return false;
} }
for (TIntermNode *const &argNode : *argumentsNode->getSequence()) for (TIntermNode *const &argNode : *arguments)
{ {
TIntermTyped *argTyped = argNode->getAsTyped(); TIntermTyped *argTyped = argNode->getAsTyped();
ASSERT(argTyped != nullptr); ASSERT(argTyped != nullptr);
...@@ -683,7 +683,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, ...@@ -683,7 +683,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
{ {
// GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
// the array. // the array.
for (TIntermNode *const &argNode : *argumentsNode->getSequence()) for (TIntermNode *const &argNode : *arguments)
{ {
const TType &argType = argNode->getAsTyped()->getType(); const TType &argType = argNode->getAsTyped()->getType();
// It has already been checked that the argument is not an array. // It has already been checked that the argument is not an array.
...@@ -698,11 +698,11 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, ...@@ -698,11 +698,11 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
else if (op == EOpConstructStruct) else if (op == EOpConstructStruct)
{ {
const TFieldList &fields = type.getStruct()->fields(); const TFieldList &fields = type.getStruct()->fields();
const TIntermSequence *args = argumentsNode->getSequence();
for (size_t i = 0; i < fields.size(); i++) for (size_t i = 0; i < fields.size(); i++)
{ {
if (i >= args->size() || (*args)[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", error(line, "Structure constructor arguments do not match structure fields",
"constructor"); "constructor");
...@@ -1528,40 +1528,6 @@ TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location, ...@@ -1528,40 +1528,6 @@ TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
} }
// //
// Look up a function name in the symbol table, and make sure it is a function.
//
// Return the function symbol if found, otherwise 0.
//
const TFunction *TParseContext::findFunction(const TSourceLoc &line,
TFunction *call,
int inputShaderVersion,
bool *builtIn)
{
// 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(call->getName(), inputShaderVersion, builtIn);
if (symbol == 0 || symbol->isFunction())
{
symbol = symbolTable.find(call->getMangledName(), inputShaderVersion, builtIn);
}
if (symbol == 0)
{
error(line, "no matching overloaded function found", call->getName().c_str());
return 0;
}
if (!symbol->isFunction())
{
error(line, "function name expected", call->getName().c_str());
return 0;
}
return static_cast<const TFunction *>(symbol);
}
//
// Initializers show up in several places in the grammar. Have one set of // Initializers show up in several places in the grammar. Have one set of
// code to handle them here. // code to handle them here.
// //
...@@ -2690,61 +2656,39 @@ TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn) ...@@ -2690,61 +2656,39 @@ TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
// //
// Returns a node to add to the tree regardless of if an error was generated or not. // Returns a node to add to the tree regardless of if an error was generated or not.
// //
TIntermTyped *TParseContext::addConstructor(TIntermAggregate *arguments, TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments,
TOperator op, TOperator op,
TType type, TType type,
const TSourceLoc &line) const TSourceLoc &line)
{ {
if (type.isUnsizedArray()) if (type.isUnsizedArray())
{ {
if (arguments->getSequence()->empty()) if (arguments->empty())
{ {
error(line, "implicitly sized array constructor must have at least one argument", "[]"); error(line, "implicitly sized array constructor must have at least one argument", "[]");
type.setArraySize(1u); type.setArraySize(1u);
return TIntermTyped::CreateZero(type); return TIntermTyped::CreateZero(type);
} }
type.setArraySize(static_cast<unsigned int>(arguments->getSequence()->size())); type.setArraySize(static_cast<unsigned int>(arguments->size()));
} }
bool constType = true;
for (TIntermNode *arg : *arguments->getSequence())
{
TIntermTyped *argTyped = arg->getAsTyped();
ASSERT(argTyped);
if (argTyped->getQualifier() != EvqConst)
constType = false;
}
if (constType)
type.setQualifier(EvqConst);
if (!checkConstructorArguments(line, arguments, op, type)) if (!checkConstructorArguments(line, arguments, op, type))
{ {
return TIntermTyped::CreateZero(type); return TIntermTyped::CreateZero(type);
} }
// Turn the argument list itself into a constructor
arguments->setOp(op);
arguments->setLine(line);
ASSERT(arguments->isConstructor());
// Need to set type before setPrecisionFromChildren() because bool doesn't have precision.
arguments->setType(type);
// Structs should not be precision qualified, the individual members may be.
// Built-in types on the other hand should be precision qualified.
if (op != EOpConstructStruct)
{
arguments->setPrecisionFromChildren();
type.setPrecision(arguments->getPrecision());
}
arguments->setType(type); TIntermAggregate *constructorNode = new TIntermAggregate(type, op, arguments);
constructorNode->setLine(line);
ASSERT(constructorNode->isConstructor());
TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(arguments, mDiagnostics); TIntermTyped *constConstructor =
intermediate.foldAggregateBuiltIn(constructorNode, mDiagnostics);
if (constConstructor) if (constConstructor)
{ {
return constConstructor; return constConstructor;
} }
return arguments; return constructorNode;
} }
// //
...@@ -4320,23 +4264,37 @@ void TParseContext::checkImageMemoryAccessForUserDefinedFunctions( ...@@ -4320,23 +4264,37 @@ void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
} }
} }
TIntermAggregate *TParseContext::createEmptyArgumentsNode(const TSourceLoc &loc) TIntermSequence *TParseContext::createEmptyArgumentsList()
{ {
TIntermAggregate *argumentsNode = new TIntermAggregate(EOpNull); return new TIntermSequence();
argumentsNode->setLine(loc);
return argumentsNode;
} }
TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
TIntermAggregate *argumentsNode, TIntermSequence *arguments,
TIntermNode *thisNode, TIntermNode *thisNode,
const TSourceLoc &loc) const TSourceLoc &loc)
{ {
TOperator op = fnCall->getBuiltInOp();
TIntermTyped *callNode = nullptr;
if (thisNode != nullptr) if (thisNode != nullptr)
{ {
return addMethod(fnCall, arguments, thisNode, loc);
}
TOperator op = fnCall->getBuiltInOp();
if (op != EOpNull)
{
return addConstructor(arguments, op, fnCall->getReturnType(), loc);
}
else
{
return addNonConstructorFunctionCall(fnCall, arguments, loc);
}
}
TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
TIntermSequence *arguments,
TIntermNode *thisNode,
const TSourceLoc &loc)
{
TConstantUnion *unionArray = new TConstantUnion[1]; TConstantUnion *unionArray = new TConstantUnion[1];
int arraySize = 0; int arraySize = 0;
TIntermTyped *typedThis = thisNode->getAsTyped(); TIntermTyped *typedThis = thisNode->getAsTyped();
...@@ -4348,7 +4306,7 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, ...@@ -4348,7 +4306,7 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
{ {
error(loc, "invalid method", fnCall->getName().c_str()); error(loc, "invalid method", fnCall->getName().c_str());
} }
else if (!argumentsNode->getSequence()->empty()) else if (!arguments->empty())
{ {
error(loc, "method takes no parameters", "length"); error(loc, "method takes no parameters", "length");
} }
...@@ -4375,28 +4333,33 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, ...@@ -4375,28 +4333,33 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
} }
} }
unionArray->setIConst(arraySize); unionArray->setIConst(arraySize);
callNode = return intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc); }
}
else if (op != EOpNull) TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
TIntermSequence *arguments,
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.
bool builtIn;
const TSymbol *symbol = symbolTable.find(fnCall->getName(), mShaderVersion, &builtIn);
if (symbol != nullptr && !symbol->isFunction())
{ {
// Then this should be a constructor. error(loc, "function name expected", fnCall->getName().c_str());
callNode = addConstructor(argumentsNode, op, fnCall->getReturnType(), loc);
} }
else else
{ {
// symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->getName(), *arguments),
// Not a constructor. Find it in the symbol table. mShaderVersion, &builtIn);
// if (symbol == nullptr)
const TFunction *fnCandidate;
bool builtIn;
for (TIntermNode *arg : *argumentsNode->getSequence())
{ {
fnCall->addParameter(TConstParameter(&arg->getAsTyped()->getType())); error(loc, "no matching overloaded function found", fnCall->getName().c_str());
} }
fnCandidate = findFunction(loc, fnCall, mShaderVersion, &builtIn); else
if (fnCandidate)
{ {
const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
// //
// A declared function. // A declared function.
// //
...@@ -4404,51 +4367,42 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, ...@@ -4404,51 +4367,42 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
{ {
checkCanUseExtension(loc, fnCandidate->getExtension()); checkCanUseExtension(loc, fnCandidate->getExtension());
} }
op = fnCandidate->getBuiltInOp(); TOperator op = fnCandidate->getBuiltInOp();
if (builtIn && op != EOpNull) if (builtIn && op != EOpNull)
{ {
// A function call mapped to a built-in operation. // A function call mapped to a built-in operation.
if (fnCandidate->getParamCount() == 1) if (fnCandidate->getParamCount() == 1)
{ {
// Treat it like a built-in unary operator. // Treat it like a built-in unary operator.
TIntermNode *unaryParamNode = argumentsNode->getSequence()->front(); TIntermNode *unaryParamNode = arguments->front();
callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc); TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
ASSERT(callNode != nullptr); ASSERT(callNode != nullptr);
return callNode;
} }
else else
{ {
ASSERT(argumentsNode->getOp() == EOpNull); TIntermAggregate *callNode =
argumentsNode->setOp(op); new TIntermAggregate(fnCandidate->getReturnType(), op, arguments);
argumentsNode->setType(fnCandidate->getReturnType()); callNode->setLine(loc);
argumentsNode->setPrecisionForBuiltInOp();
if (argumentsNode->areChildrenConstQualified())
{
argumentsNode->getTypePointer()->setQualifier(EvqConst);
}
// Some built-in functions have out parameters too. // Some built-in functions have out parameters too.
functionCallLValueErrorCheck(fnCandidate, argumentsNode); functionCallLValueErrorCheck(fnCandidate, callNode);
// See if we can constant fold a built-in. Note that this may be possible even // See if we can constant fold a built-in. Note that this may be possible even
// if it is not const-qualified. // if it is not const-qualified.
TIntermTyped *foldedNode = TIntermTyped *foldedNode =
intermediate.foldAggregateBuiltIn(argumentsNode, mDiagnostics); intermediate.foldAggregateBuiltIn(callNode, mDiagnostics);
if (foldedNode) if (foldedNode)
{ {
callNode = foldedNode; return foldedNode;
}
else
{
callNode = argumentsNode;
} }
return callNode;
} }
} }
else else
{ {
// This is a real function call // This is a real function call
ASSERT(argumentsNode->getOp() == EOpNull); TIntermAggregate *callNode = nullptr;
argumentsNode->setType(fnCandidate->getReturnType());
argumentsNode->getFunctionSymbolInfo()->setFromFunction(*fnCandidate);
// If builtIn == false, the function is user defined - could be an overloaded // If builtIn == false, the function is user defined - could be an overloaded
// built-in as well. // built-in as well.
...@@ -4456,31 +4410,33 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, ...@@ -4456,31 +4410,33 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
// This needs to happen after the function info including name is set. // This needs to happen after the function info including name is set.
if (builtIn) if (builtIn)
{ {
argumentsNode->setOp(EOpCallBuiltInFunction); callNode = new TIntermAggregate(fnCandidate->getReturnType(),
argumentsNode->setBuiltInFunctionPrecision(); EOpCallBuiltInFunction, arguments);
// Note that name needs to be set before texture function type is determined.
checkTextureOffsetConst(argumentsNode); callNode->getFunctionSymbolInfo()->setFromFunction(*fnCandidate);
checkImageMemoryAccessForBuiltinFunctions(argumentsNode); callNode->setBuiltInFunctionPrecision();
checkTextureOffsetConst(callNode);
checkImageMemoryAccessForBuiltinFunctions(callNode);
} }
else else
{ {
argumentsNode->setOp(EOpCallFunctionInAST); callNode = new TIntermAggregate(fnCandidate->getReturnType(),
checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, argumentsNode); EOpCallFunctionInAST, arguments);
callNode->getFunctionSymbolInfo()->setFromFunction(*fnCandidate);
checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
} }
callNode = argumentsNode; functionCallLValueErrorCheck(fnCandidate, callNode);
functionCallLValueErrorCheck(fnCandidate, argumentsNode); callNode->setLine(loc);
}
return callNode;
} }
else
{
// error message was put out by findFunction()
// Put on a dummy node for error recovery
callNode = TIntermTyped::CreateZero(TType(EbtFloat, EbpMedium, EvqConst));
} }
} }
return callNode;
// Error message was already written. Put on a dummy node for error recovery.
return TIntermTyped::CreateZero(TType(EbtFloat, EbpMedium, EvqConst));
} }
TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond, TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
......
...@@ -112,7 +112,7 @@ class TParseContext : angle::NonCopyable ...@@ -112,7 +112,7 @@ class TParseContext : angle::NonCopyable
void checkIsScalarInteger(TIntermTyped *node, const char *token); void checkIsScalarInteger(TIntermTyped *node, const char *token);
bool checkIsAtGlobalLevel(const TSourceLoc &line, const char *token); bool checkIsAtGlobalLevel(const TSourceLoc &line, const char *token);
bool checkConstructorArguments(const TSourceLoc &line, bool checkConstructorArguments(const TSourceLoc &line,
const TIntermAggregate *argumentsNode, const TIntermSequence *arguments,
TOperator op, TOperator op,
const TType &type); const TType &type);
...@@ -167,10 +167,6 @@ class TParseContext : angle::NonCopyable ...@@ -167,10 +167,6 @@ class TParseContext : angle::NonCopyable
const char *value, const char *value,
bool stdgl); bool stdgl);
const TFunction *findFunction(const TSourceLoc &line,
TFunction *pfnCall,
int inputShaderVersion,
bool *builtIn = 0);
bool executeInitializer(const TSourceLoc &line, bool executeInitializer(const TSourceLoc &line,
const TString &identifier, const TString &identifier,
const TPublicType &pType, const TPublicType &pType,
...@@ -252,10 +248,6 @@ class TParseContext : angle::NonCopyable ...@@ -252,10 +248,6 @@ class TParseContext : angle::NonCopyable
const TString *name, const TString *name,
const TSourceLoc &location); const TSourceLoc &location);
TFunction *addConstructorFunc(const TPublicType &publicType); TFunction *addConstructorFunc(const TPublicType &publicType);
TIntermTyped *addConstructor(TIntermAggregate *arguments,
TOperator op,
TType type,
const TSourceLoc &line);
TIntermTyped *addIndexExpression(TIntermTyped *baseExpression, TIntermTyped *addIndexExpression(TIntermTyped *baseExpression,
const TSourceLoc &location, const TSourceLoc &location,
...@@ -345,12 +337,12 @@ class TParseContext : angle::NonCopyable ...@@ -345,12 +337,12 @@ class TParseContext : angle::NonCopyable
void checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall); void checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall);
void checkImageMemoryAccessForUserDefinedFunctions(const TFunction *functionDefinition, void checkImageMemoryAccessForUserDefinedFunctions(const TFunction *functionDefinition,
const TIntermAggregate *functionCall); const TIntermAggregate *functionCall);
TIntermAggregate *createEmptyArgumentsNode(const TSourceLoc &loc); TIntermSequence *createEmptyArgumentsList();
// fnCall is only storing the built-in op, and function name or constructor type. argumentsNode // fnCall is only storing the built-in op, and function name or constructor type. arguments
// has the arguments. // has the arguments.
TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall,
TIntermAggregate *argumentsNode, TIntermSequence *arguments,
TIntermNode *thisNode, TIntermNode *thisNode,
const TSourceLoc &loc); const TSourceLoc &loc);
...@@ -406,8 +398,18 @@ class TParseContext : angle::NonCopyable ...@@ -406,8 +398,18 @@ class TParseContext : angle::NonCopyable
TIntermTyped *left, TIntermTyped *left,
TIntermTyped *right, TIntermTyped *right,
const TSourceLoc &loc); const TSourceLoc &loc);
TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
TIntermTyped *child,
TIntermTyped *addMethod(TFunction *fnCall,
TIntermSequence *arguments,
TIntermNode *thisNode,
const TSourceLoc &loc);
TIntermTyped *addConstructor(TIntermSequence *arguments,
TOperator op,
TType type,
const TSourceLoc &line);
TIntermTyped *addNonConstructorFunctionCall(TFunction *fnCall,
TIntermSequence *arguments,
const TSourceLoc &loc); const TSourceLoc &loc);
// Return true if the checks pass // Return true if the checks pass
......
...@@ -113,11 +113,9 @@ TIntermTyped *EnsureSignedInt(TIntermTyped *node) ...@@ -113,11 +113,9 @@ TIntermTyped *EnsureSignedInt(TIntermTyped *node)
if (node->getBasicType() == EbtInt) if (node->getBasicType() == EbtInt)
return node; return node;
TIntermAggregate *convertedNode = new TIntermAggregate(EOpConstructInt); TIntermSequence *arguments = new TIntermSequence();
convertedNode->setType(TType(EbtInt)); arguments->push_back(node);
convertedNode->getSequence()->push_back(node); return new TIntermAggregate(TType(EbtInt), EOpConstructInt, arguments);
convertedNode->setPrecisionFromChildren();
return convertedNode;
} }
TType GetFieldType(const TType &indexedType) TType GetFieldType(const TType &indexedType)
...@@ -351,15 +349,16 @@ TIntermAggregate *CreateIndexFunctionCall(TIntermBinary *node, ...@@ -351,15 +349,16 @@ TIntermAggregate *CreateIndexFunctionCall(TIntermBinary *node,
TIntermTyped *index) TIntermTyped *index)
{ {
ASSERT(node->getOp() == EOpIndexIndirect); ASSERT(node->getOp() == EOpIndexIndirect);
TIntermAggregate *indexingCall = new TIntermAggregate(EOpCallFunctionInAST); TIntermSequence *arguments = new TIntermSequence();
arguments->push_back(indexedNode);
arguments->push_back(index);
TType fieldType = GetFieldType(indexedNode->getType());
TIntermAggregate *indexingCall =
new TIntermAggregate(fieldType, EOpCallFunctionInAST, arguments);
indexingCall->setLine(node->getLine()); indexingCall->setLine(node->getLine());
indexingCall->getFunctionSymbolInfo()->setNameObj( indexingCall->getFunctionSymbolInfo()->setNameObj(
GetIndexFunctionName(indexedNode->getType(), false)); GetIndexFunctionName(indexedNode->getType(), false));
indexingCall->getSequence()->push_back(indexedNode);
indexingCall->getSequence()->push_back(index);
TType fieldType = GetFieldType(indexedNode->getType());
indexingCall->setType(fieldType);
return indexingCall; return indexingCall;
} }
......
...@@ -94,14 +94,11 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -94,14 +94,11 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
// Create new node that represents the call of function texelFetch. // Create new node that represents the call of function texelFetch.
// Its argument list will be: texelFetch(sampler, Position+offset, lod). // Its argument list will be: texelFetch(sampler, Position+offset, lod).
TIntermAggregate *texelFetchNode = new TIntermAggregate(EOpCallBuiltInFunction);
texelFetchNode->getFunctionSymbolInfo()->setName(newName); TIntermSequence *texelFetchArguments = new TIntermSequence();
texelFetchNode->getFunctionSymbolInfo()->setId(uniqueId);
texelFetchNode->setType(node->getType());
texelFetchNode->setLine(node->getLine());
// sampler // sampler
texelFetchNode->getSequence()->push_back(sequence->at(0)); texelFetchArguments->push_back(sequence->at(0));
// Position // Position
TIntermTyped *texCoordNode = sequence->at(1)->getAsTyped(); TIntermTyped *texCoordNode = sequence->at(1)->getAsTyped();
...@@ -114,20 +111,15 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -114,20 +111,15 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
{ {
// For 2DArray samplers, Position is ivec3 and offset is ivec2; // For 2DArray samplers, Position is ivec3 and offset is ivec2;
// So offset must be converted into an ivec3 before being added to Position. // So offset must be converted into an ivec3 before being added to Position.
TIntermAggregate *constructIVec3Node = new TIntermAggregate(EOpConstructIVec3); TIntermSequence *constructOffsetIvecArguments = new TIntermSequence();
constructIVec3Node->setLine(texCoordNode->getLine()); constructOffsetIvecArguments->push_back(sequence->at(3)->getAsTyped());
constructIVec3Node->setType(texCoordNode->getType());
constructIVec3Node->getSequence()->push_back(sequence->at(3)->getAsTyped());
TConstantUnion *zero = new TConstantUnion(); TIntermTyped *zeroNode = TIntermTyped::CreateZero(TType(EbtInt));
zero->setIConst(0); constructOffsetIvecArguments->push_back(zeroNode);
TType *intType = new TType(EbtInt);
TIntermConstantUnion *zeroNode = new TIntermConstantUnion(zero, *intType); offsetNode = new TIntermAggregate(texCoordNode->getType(), EOpConstructIVec3,
constructIVec3Node->getSequence()->push_back(zeroNode); constructOffsetIvecArguments);
offsetNode->setLine(texCoordNode->getLine());
offsetNode = constructIVec3Node;
} }
else else
{ {
...@@ -137,12 +129,18 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -137,12 +129,18 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
// Position+offset // Position+offset
TIntermBinary *add = new TIntermBinary(EOpAdd, texCoordNode, offsetNode); TIntermBinary *add = new TIntermBinary(EOpAdd, texCoordNode, offsetNode);
add->setLine(texCoordNode->getLine()); add->setLine(texCoordNode->getLine());
texelFetchNode->getSequence()->push_back(add); texelFetchArguments->push_back(add);
// lod // lod
texelFetchNode->getSequence()->push_back(sequence->at(2)); texelFetchArguments->push_back(sequence->at(2));
ASSERT(texelFetchArguments->size() == 3u);
ASSERT(texelFetchNode->getSequence()->size() == 3u); TIntermAggregate *texelFetchNode =
new TIntermAggregate(node->getType(), EOpCallBuiltInFunction, texelFetchArguments);
texelFetchNode->getFunctionSymbolInfo()->setName(newName);
texelFetchNode->getFunctionSymbolInfo()->setId(uniqueId);
texelFetchNode->setLine(node->getLine());
// Replace the old node by this new node. // Replace the old node by this new node.
queueReplacement(node, texelFetchNode, OriginalNode::IS_DROPPED); queueReplacement(node, texelFetchNode, OriginalNode::IS_DROPPED);
......
...@@ -58,10 +58,9 @@ TIntermBinary *CopyAssignmentNode(TIntermBinary *node) ...@@ -58,10 +58,9 @@ TIntermBinary *CopyAssignmentNode(TIntermBinary *node)
// Performs a shallow copy of a constructor/function call node. // Performs a shallow copy of a constructor/function call node.
TIntermAggregate *CopyAggregateNode(TIntermAggregate *node) TIntermAggregate *CopyAggregateNode(TIntermAggregate *node)
{ {
TIntermAggregate *copyNode = new TIntermAggregate(node->getOp()); TIntermSequence *copySeq = new TIntermSequence();
TIntermSequence *copySeq = copyNode->getSequence();
copySeq->insert(copySeq->begin(), node->getSequence()->begin(), node->getSequence()->end()); copySeq->insert(copySeq->begin(), node->getSequence()->begin(), node->getSequence()->end());
copyNode->setType(node->getType()); TIntermAggregate *copyNode = new TIntermAggregate(node->getType(), node->getOp(), copySeq);
*copyNode->getFunctionSymbolInfo() = *node->getFunctionSymbolInfo(); *copyNode->getFunctionSymbolInfo() = *node->getFunctionSymbolInfo();
return copyNode; return copyNode;
} }
......
...@@ -67,6 +67,17 @@ const TString *TFunction::buildMangledName() const ...@@ -67,6 +67,17 @@ const TString *TFunction::buildMangledName() const
return NewPoolTString(newName.c_str()); return NewPoolTString(newName.c_str());
} }
const TString &TFunction::GetMangledNameFromCall(const TString &unmangledFunctionName,
TIntermSequence &arguments)
{
std::string newName = mangleName(unmangledFunctionName).c_str();
for (TIntermNode *argument : arguments)
{
newName += argument->getAsTyped()->getType().getMangledName().c_str();
}
return *NewPoolTString(newName.c_str());
}
// //
// Symbol table levels are a map of pointers to symbols that have to be deleted. // Symbol table levels are a map of pointers to symbols that have to be deleted.
// //
...@@ -160,22 +171,12 @@ TFunction *TSymbolTable::findBuiltInOp(TIntermAggregate *callNode, int shaderVer ...@@ -160,22 +171,12 @@ TFunction *TSymbolTable::findBuiltInOp(TIntermAggregate *callNode, int shaderVer
ASSERT(!callNode->isConstructor()); ASSERT(!callNode->isConstructor());
ASSERT(!callNode->isFunctionCall()); ASSERT(!callNode->isFunctionCall());
TString opString = GetOperatorString(callNode->getOp()); TString opString = GetOperatorString(callNode->getOp());
// The return type doesn't affect the mangled name of the function, which is used to look it up. TSymbol *sym = findBuiltIn(
TType dummyReturnType; TFunction::GetMangledNameFromCall(opString, *callNode->getSequence()), shaderVersion);
TFunction call(&opString, &dummyReturnType, callNode->getOp());
TIntermSequence *sequence = callNode->getSequence();
for (auto *child : *sequence)
{
TType *paramType = child->getAsTyped()->getTypePointer();
TConstParameter p(paramType);
call.addParameter(p);
}
TSymbol *sym = findBuiltIn(call.getMangledName(), shaderVersion);
ASSERT(sym != nullptr && sym->isFunction()); ASSERT(sym != nullptr && sym->isFunction());
TFunction *builtInFunc = static_cast<TFunction *>(sym); TFunction *builtInFunc = static_cast<TFunction *>(sym);
ASSERT(builtInFunc->getParamCount() == sequence->size()); ASSERT(builtInFunc->getParamCount() == callNode->getSequence()->size());
return builtInFunc; return builtInFunc;
} }
......
...@@ -41,8 +41,6 @@ ...@@ -41,8 +41,6 @@
namespace sh namespace sh
{ {
class TIntermAggregate;
// Symbol base class. (Can build functions or variables out of these...) // Symbol base class. (Can build functions or variables out of these...)
class TSymbol : angle::NonCopyable class TSymbol : angle::NonCopyable
{ {
...@@ -182,6 +180,10 @@ class TFunction : public TSymbol ...@@ -182,6 +180,10 @@ class TFunction : public TSymbol
} }
return *mangledName; return *mangledName;
} }
static const TString &GetMangledNameFromCall(const TString &unmangledFunctionName,
TIntermSequence &arguments);
const TType &getReturnType() const { return *returnType; } const TType &getReturnType() const { return *returnType; }
TOperator getBuiltInOp() const { return op; } TOperator getBuiltInOp() const { return op; }
......
...@@ -315,7 +315,7 @@ integer_expression ...@@ -315,7 +315,7 @@ integer_expression
function_call function_call
: function_call_or_method { : function_call_or_method {
$$ = context->addFunctionCallOrMethod($1.function, $1.callOrMethodPair.argumentsNode, $1.callOrMethodPair.thisNode, @1); $$ = context->addFunctionCallOrMethod($1.function, $1.callOrMethodPair.arguments, $1.callOrMethodPair.thisNode, @1);
} }
; ;
...@@ -343,23 +343,23 @@ function_call_generic ...@@ -343,23 +343,23 @@ function_call_generic
function_call_header_no_parameters function_call_header_no_parameters
: function_call_header VOID_TYPE { : function_call_header VOID_TYPE {
$$.function = $1; $$.function = $1;
$$.callOrMethodPair.argumentsNode = context->createEmptyArgumentsNode(@1); $$.callOrMethodPair.arguments = context->createEmptyArgumentsList();
} }
| function_call_header { | function_call_header {
$$.function = $1; $$.function = $1;
$$.callOrMethodPair.argumentsNode = context->createEmptyArgumentsNode(@1); $$.callOrMethodPair.arguments = context->createEmptyArgumentsList();
} }
; ;
function_call_header_with_parameters function_call_header_with_parameters
: function_call_header assignment_expression { : function_call_header assignment_expression {
$$.callOrMethodPair.argumentsNode = context->createEmptyArgumentsNode(@1); $$.callOrMethodPair.arguments = context->createEmptyArgumentsList();
$$.function = $1; $$.function = $1;
$$.callOrMethodPair.argumentsNode->getSequence()->push_back($2); $$.callOrMethodPair.arguments->push_back($2);
} }
| function_call_header_with_parameters COMMA assignment_expression { | function_call_header_with_parameters COMMA assignment_expression {
$$.function = $1.function; $$.function = $1.function;
$$.callOrMethodPair.argumentsNode->getSequence()->push_back($3); $$.callOrMethodPair.arguments->push_back($3);
} }
; ;
......
...@@ -2619,7 +2619,7 @@ yyreduce: ...@@ -2619,7 +2619,7 @@ yyreduce:
case 18: case 18:
{ {
(yyval.interm.intermTypedNode) = context->addFunctionCallOrMethod((yyvsp[0].interm).function, (yyvsp[0].interm).callOrMethodPair.argumentsNode, (yyvsp[0].interm).callOrMethodPair.thisNode, (yylsp[0])); (yyval.interm.intermTypedNode) = context->addFunctionCallOrMethod((yyvsp[0].interm).function, (yyvsp[0].interm).callOrMethodPair.arguments, (yyvsp[0].interm).callOrMethodPair.thisNode, (yylsp[0]));
} }
break; break;
...@@ -2663,7 +2663,7 @@ yyreduce: ...@@ -2663,7 +2663,7 @@ yyreduce:
{ {
(yyval.interm).function = (yyvsp[-1].interm.function); (yyval.interm).function = (yyvsp[-1].interm.function);
(yyval.interm).callOrMethodPair.argumentsNode = context->createEmptyArgumentsNode((yylsp[-1])); (yyval.interm).callOrMethodPair.arguments = context->createEmptyArgumentsList();
} }
break; break;
...@@ -2672,7 +2672,7 @@ yyreduce: ...@@ -2672,7 +2672,7 @@ yyreduce:
{ {
(yyval.interm).function = (yyvsp[0].interm.function); (yyval.interm).function = (yyvsp[0].interm.function);
(yyval.interm).callOrMethodPair.argumentsNode = context->createEmptyArgumentsNode((yylsp[0])); (yyval.interm).callOrMethodPair.arguments = context->createEmptyArgumentsList();
} }
break; break;
...@@ -2680,9 +2680,9 @@ yyreduce: ...@@ -2680,9 +2680,9 @@ yyreduce:
case 25: case 25:
{ {
(yyval.interm).callOrMethodPair.argumentsNode = context->createEmptyArgumentsNode((yylsp[-1])); (yyval.interm).callOrMethodPair.arguments = context->createEmptyArgumentsList();
(yyval.interm).function = (yyvsp[-1].interm.function); (yyval.interm).function = (yyvsp[-1].interm.function);
(yyval.interm).callOrMethodPair.argumentsNode->getSequence()->push_back((yyvsp[0].interm.intermTypedNode)); (yyval.interm).callOrMethodPair.arguments->push_back((yyvsp[0].interm.intermTypedNode));
} }
break; break;
...@@ -2691,7 +2691,7 @@ yyreduce: ...@@ -2691,7 +2691,7 @@ yyreduce:
{ {
(yyval.interm).function = (yyvsp[-2].interm).function; (yyval.interm).function = (yyvsp[-2].interm).function;
(yyval.interm).callOrMethodPair.argumentsNode->getSequence()->push_back((yyvsp[0].interm.intermTypedNode)); (yyval.interm).callOrMethodPair.arguments->push_back((yyvsp[0].interm.intermTypedNode));
} }
break; break;
......
...@@ -184,14 +184,14 @@ TEST_F(IntermNodeTest, DeepCopyUnaryNode) ...@@ -184,14 +184,14 @@ TEST_F(IntermNodeTest, DeepCopyUnaryNode)
// original. Child nodes also need to be copies with the same attributes as the original children. // original. Child nodes also need to be copies with the same attributes as the original children.
TEST_F(IntermNodeTest, DeepCopyAggregateNode) TEST_F(IntermNodeTest, DeepCopyAggregateNode)
{ {
TType type(EbtFloat, EbpHigh); TIntermSequence *originalSeq = new TIntermSequence();
TIntermAggregate *original = new TIntermAggregate(EOpMix);
original->setLine(getTestSourceLoc());
TIntermSequence *originalSeq = original->getSequence();
originalSeq->push_back(createTestSymbol()); originalSeq->push_back(createTestSymbol());
originalSeq->push_back(createTestSymbol()); originalSeq->push_back(createTestSymbol());
originalSeq->push_back(createTestSymbol()); originalSeq->push_back(createTestSymbol());
TIntermAggregate *original =
new TIntermAggregate(originalSeq->at(0)->getAsTyped()->getType(), EOpMix, originalSeq);
original->setLine(getTestSourceLoc());
TIntermTyped *copyTyped = original->deepCopy(); TIntermTyped *copyTyped = original->deepCopy();
TIntermAggregate *copy = copyTyped->getAsAggregate(); TIntermAggregate *copy = copyTyped->getAsAggregate();
ASSERT_NE(nullptr, copy); ASSERT_NE(nullptr, copy);
...@@ -203,7 +203,7 @@ TEST_F(IntermNodeTest, DeepCopyAggregateNode) ...@@ -203,7 +203,7 @@ TEST_F(IntermNodeTest, DeepCopyAggregateNode)
TIntermSequence::size_type i = 0; TIntermSequence::size_type i = 0;
for (auto *copyChild : *copy->getSequence()) for (auto *copyChild : *copy->getSequence())
{ {
TIntermNode *originalChild = originalSeq->at(i); TIntermNode *originalChild = original->getSequence()->at(i);
checkSymbolCopy(originalChild, copyChild); checkSymbolCopy(originalChild, copyChild);
++i; ++i;
} }
......
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