Commit 72d1020e by Olli Etuaho Committed by Commit Bot

Refactor function call node creation

This makes function call node creation code simpler and more type safe. It also prepares for further simplification by removing usage of TFunction in places where the arguments node is sufficient. BUG=angleproject:1490 TEST=angle_unittests Change-Id: I75d9e059bb32c475487f0be24e40ac0d78012d86 Reviewed-on: https://chromium-review.googlesource.com/433217Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 9250cb24
...@@ -429,8 +429,7 @@ bool canRoundFloat(const TType &type) ...@@ -429,8 +429,7 @@ bool canRoundFloat(const TType &type)
TIntermAggregate *createInternalFunctionCallNode(TString name, TIntermNode *child) TIntermAggregate *createInternalFunctionCallNode(TString name, TIntermNode *child)
{ {
TIntermAggregate *callNode = new TIntermAggregate(); TIntermAggregate *callNode = new TIntermAggregate(EOpFunctionCall);
callNode->setOp(EOpFunctionCall);
TName nameObj(TFunction::mangleName(name)); TName nameObj(TFunction::mangleName(name));
nameObj.setInternal(true); nameObj.setInternal(true);
callNode->getFunctionSymbolInfo()->setNameObj(nameObj); callNode->getFunctionSymbolInfo()->setNameObj(nameObj);
......
...@@ -136,6 +136,15 @@ struct TIntermNodePair ...@@ -136,6 +136,15 @@ 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
...@@ -579,13 +588,6 @@ class TIntermAggregateBase ...@@ -579,13 +588,6 @@ class TIntermAggregateBase
class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
{ {
public: public:
TIntermAggregate()
: TIntermOperator(EOpNull),
mUserDefined(false),
mUseEmulatedFunction(false),
mGotPrecisionFromChildren(false)
{
}
TIntermAggregate(TOperator op) TIntermAggregate(TOperator op)
: TIntermOperator(op), : TIntermOperator(op),
mUserDefined(false), mUserDefined(false),
......
...@@ -67,97 +67,6 @@ TIntermTyped *TIntermediate::addIndex(TOperator op, ...@@ -67,97 +67,6 @@ TIntermTyped *TIntermediate::addIndex(TOperator op,
return node; return node;
} }
// This is the safe way to change the operator on an aggregate, as it
// does lots of error checking and fixing. Especially for establishing
// a function call's operation on it's set of parameters.
//
// Returns an aggregate node, which could be the one passed in if
// it was already an aggregate but no operator was set.
TIntermAggregate *TIntermediate::setAggregateOperator(TIntermNode *node,
TOperator op,
const TSourceLoc &line)
{
TIntermAggregate *aggNode;
//
// Make sure we have an aggregate. If not turn it into one.
//
if (node)
{
aggNode = node->getAsAggregate();
if (aggNode == NULL || aggNode->getOp() != EOpNull)
{
//
// Make an aggregate containing this node.
//
aggNode = new TIntermAggregate();
aggNode->getSequence()->push_back(node);
}
}
else
{
aggNode = new TIntermAggregate();
}
//
// Set the operator.
//
aggNode->setOp(op);
aggNode->setLine(line);
return aggNode;
}
//
// Safe way to combine two nodes into an aggregate. Works with null pointers,
// a node that's not a aggregate yet, etc.
//
// Returns the resulting aggregate, unless 0 was passed in for
// both existing nodes.
//
TIntermAggregate *TIntermediate::growAggregate(TIntermNode *left,
TIntermNode *right,
const TSourceLoc &line)
{
if (left == NULL && right == NULL)
return NULL;
TIntermAggregate *aggNode = NULL;
if (left)
aggNode = left->getAsAggregate();
if (!aggNode || aggNode->getOp() != EOpNull)
{
aggNode = new TIntermAggregate;
if (left)
aggNode->getSequence()->push_back(left);
}
if (right)
aggNode->getSequence()->push_back(right);
aggNode->setLine(line);
return aggNode;
}
//
// Turn an existing node into an aggregate.
//
// Returns an aggregate, unless NULL was passed in for the existing node.
//
TIntermAggregate *TIntermediate::MakeAggregate(TIntermNode *node, const TSourceLoc &line)
{
if (node == nullptr)
return nullptr;
TIntermAggregate *aggNode = new TIntermAggregate;
aggNode->getSequence()->push_back(node);
aggNode->setLine(line);
return aggNode;
}
// If the input node is nullptr, return nullptr. // If the input node is nullptr, return nullptr.
// If the input node is a block node, return it. // If the input node is a block node, return it.
// If the input node is not a block node, put it inside a block node and return that. // If the input node is not a block node, put it inside a block node and return that.
......
...@@ -33,14 +33,7 @@ class TIntermediate ...@@ -33,14 +33,7 @@ class TIntermediate
TIntermTyped *index, TIntermTyped *index,
const TSourceLoc &line, const TSourceLoc &line,
TDiagnostics *diagnostics); TDiagnostics *diagnostics);
TIntermTyped *addUnaryMath(TOperator op,
TIntermTyped *child,
const TSourceLoc &line,
const TType *funcReturnType);
TIntermAggregate *growAggregate(TIntermNode *left, TIntermNode *right, const TSourceLoc &);
static TIntermAggregate *MakeAggregate(TIntermNode *node, const TSourceLoc &line);
static TIntermBlock *EnsureBlock(TIntermNode *node); static TIntermBlock *EnsureBlock(TIntermNode *node);
TIntermAggregate *setAggregateOperator(TIntermNode *, TOperator, const TSourceLoc &);
TIntermNode *addIfElse(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &line); TIntermNode *addIfElse(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &line);
static TIntermTyped *AddTernarySelection(TIntermTyped *cond, static TIntermTyped *AddTernarySelection(TIntermTyped *cond,
TIntermTyped *trueExpression, TIntermTyped *trueExpression,
......
...@@ -552,8 +552,7 @@ bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &id ...@@ -552,8 +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,
TIntermNode *argumentsNode, const TIntermAggregate *argumentsNode,
const TFunction &function,
TOperator op, TOperator op,
const TType &type) const TType &type)
{ {
...@@ -586,18 +585,18 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, ...@@ -586,18 +585,18 @@ 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 (size_t i = 0; i < function.getParamCount(); ++i) for (TIntermNode *arg : *argumentsNode->getSequence())
{ {
const TConstParameter &param = function.getParam(i); const TIntermTyped *argTyped = arg->getAsTyped();
size += param.type->getObjectSize(); size += argTyped->getType().getObjectSize();
if (constructingMatrix && param.type->isMatrix()) if (constructingMatrix && argTyped->getType().isMatrix())
matrixInMatrix = true; matrixInMatrix = true;
if (full) if (full)
overFull = true; overFull = true;
if (op != EOpConstructStruct && !type.isArray() && size >= type.getObjectSize()) if (op != EOpConstructStruct && !type.isArray() && size >= type.getObjectSize())
full = true; full = true;
if (param.type->isArray()) if (argTyped->getType().isArray())
arrayArg = true; arrayArg = true;
} }
...@@ -605,7 +604,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, ...@@ -605,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()) != function.getParamCount()) if (static_cast<size_t>(type.getArraySize()) != argumentsNode->getSequence()->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;
...@@ -620,7 +619,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, ...@@ -620,7 +619,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
if (matrixInMatrix && !type.isArray()) if (matrixInMatrix && !type.isArray())
{ {
if (function.getParamCount() != 1) if (argumentsNode->getSequence()->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");
...@@ -635,7 +634,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, ...@@ -635,7 +634,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
} }
if (op == EOpConstructStruct && !type.isArray() && if (op == EOpConstructStruct && !type.isArray() &&
type.getStruct()->fields().size() != function.getParamCount()) type.getStruct()->fields().size() != argumentsNode->getSequence()->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",
...@@ -653,14 +652,13 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, ...@@ -653,14 +652,13 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
} }
} }
if (argumentsNode == nullptr) if (argumentsNode->getSequence()->empty())
{ {
error(line, "constructor does not have any arguments", "constructor"); error(line, "constructor does not have any arguments", "constructor");
return false; return false;
} }
TIntermAggregate *argumentsAgg = argumentsNode->getAsAggregate(); for (TIntermNode *const &argNode : *argumentsNode->getSequence())
for (TIntermNode *&argNode : *argumentsAgg->getSequence())
{ {
TIntermTyped *argTyped = argNode->getAsTyped(); TIntermTyped *argTyped = argNode->getAsTyped();
ASSERT(argTyped != nullptr); ASSERT(argTyped != nullptr);
...@@ -685,7 +683,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, ...@@ -685,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 *&argNode : *argumentsAgg->getSequence()) for (TIntermNode *const &argNode : *argumentsNode->getSequence())
{ {
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.
...@@ -700,7 +698,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, ...@@ -700,7 +698,7 @@ 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();
TIntermSequence *args = argumentsAgg->getSequence(); const TIntermSequence *args = argumentsNode->getSequence();
for (size_t i = 0; i < fields.size(); i++) for (size_t i = 0; i < fields.size(); i++)
{ {
...@@ -2683,9 +2681,8 @@ TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn) ...@@ -2683,9 +2681,8 @@ TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
} }
} }
TString tempString;
const TType *type = new TType(publicType); const TType *type = new TType(publicType);
return new TFunction(&tempString, type, op); return new TFunction(nullptr, type, op);
} }
// This function is used to test for the correctness of the parameters passed to various constructor // This function is used to test for the correctness of the parameters passed to various constructor
...@@ -2693,66 +2690,61 @@ TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn) ...@@ -2693,66 +2690,61 @@ 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(TIntermNode *arguments, TIntermTyped *TParseContext::addConstructor(TIntermAggregate *arguments,
TOperator op, TOperator op,
TFunction *fnCall, TType type,
const TSourceLoc &line) const TSourceLoc &line)
{ {
TType type = fnCall->getReturnType();
if (type.isUnsizedArray()) if (type.isUnsizedArray())
{ {
if (fnCall->getParamCount() == 0) if (arguments->getSequence()->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>(fnCall->getParamCount())); type.setArraySize(static_cast<unsigned int>(arguments->getSequence()->size()));
} }
bool constType = true; bool constType = true;
for (size_t i = 0; i < fnCall->getParamCount(); ++i) for (TIntermNode *arg : *arguments->getSequence())
{ {
const TConstParameter &param = fnCall->getParam(i); TIntermTyped *argTyped = arg->getAsTyped();
if (param.type->getQualifier() != EvqConst) ASSERT(argTyped);
if (argTyped->getQualifier() != EvqConst)
constType = false; constType = false;
} }
if (constType) if (constType)
type.setQualifier(EvqConst); type.setQualifier(EvqConst);
if (!checkConstructorArguments(line, arguments, *fnCall, op, type)) if (!checkConstructorArguments(line, arguments, op, type))
{ {
TIntermTyped *dummyNode = intermediate.setAggregateOperator(nullptr, op, line); return TIntermTyped::CreateZero(type);
dummyNode->setType(type);
return dummyNode;
} }
TIntermAggregate *constructor = arguments->getAsAggregate();
ASSERT(constructor != nullptr);
// Turn the argument list itself into a constructor // Turn the argument list itself into a constructor
constructor->setOp(op); arguments->setOp(op);
constructor->setLine(line); arguments->setLine(line);
ASSERT(constructor->isConstructor()); ASSERT(arguments->isConstructor());
// Need to set type before setPrecisionFromChildren() because bool doesn't have precision. // Need to set type before setPrecisionFromChildren() because bool doesn't have precision.
constructor->setType(type); arguments->setType(type);
// Structs should not be precision qualified, the individual members may be. // Structs should not be precision qualified, the individual members may be.
// Built-in types on the other hand should be precision qualified. // Built-in types on the other hand should be precision qualified.
if (op != EOpConstructStruct) if (op != EOpConstructStruct)
{ {
constructor->setPrecisionFromChildren(); arguments->setPrecisionFromChildren();
type.setPrecision(constructor->getPrecision()); type.setPrecision(arguments->getPrecision());
} }
constructor->setType(type); arguments->setType(type);
TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor, mDiagnostics); TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(arguments, mDiagnostics);
if (constConstructor) if (constConstructor)
{ {
return constConstructor; return constConstructor;
} }
return constructor; return arguments;
} }
// //
...@@ -4330,13 +4322,18 @@ void TParseContext::checkImageMemoryAccessForUserDefinedFunctions( ...@@ -4330,13 +4322,18 @@ void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
} }
} }
TIntermAggregate *TParseContext::createEmptyArgumentsNode(const TSourceLoc &loc)
{
TIntermAggregate *argumentsNode = new TIntermAggregate(EOpNull);
argumentsNode->setLine(loc);
return argumentsNode;
}
TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
TIntermNode *paramNode, TIntermAggregate *argumentsNode,
TIntermNode *thisNode, TIntermNode *thisNode,
const TSourceLoc &loc, const TSourceLoc &loc)
bool *fatalError)
{ {
*fatalError = false;
TOperator op = fnCall->getBuiltInOp(); TOperator op = fnCall->getBuiltInOp();
TIntermTyped *callNode = nullptr; TIntermTyped *callNode = nullptr;
...@@ -4345,11 +4342,15 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, ...@@ -4345,11 +4342,15 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
TConstantUnion *unionArray = new TConstantUnion[1]; TConstantUnion *unionArray = new TConstantUnion[1];
int arraySize = 0; int arraySize = 0;
TIntermTyped *typedThis = thisNode->getAsTyped(); TIntermTyped *typedThis = thisNode->getAsTyped();
// 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->getName() below is safe.
if (fnCall->getName() != "length") if (fnCall->getName() != "length")
{ {
error(loc, "invalid method", fnCall->getName().c_str()); error(loc, "invalid method", fnCall->getName().c_str());
} }
else if (paramNode != nullptr) else if (!argumentsNode->getSequence()->empty())
{ {
error(loc, "method takes no parameters", "length"); error(loc, "method takes no parameters", "length");
} }
...@@ -4382,7 +4383,7 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, ...@@ -4382,7 +4383,7 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
else if (op != EOpNull) else if (op != EOpNull)
{ {
// Then this should be a constructor. // Then this should be a constructor.
callNode = addConstructor(paramNode, op, fnCall, loc); callNode = addConstructor(argumentsNode, op, fnCall->getReturnType(), loc);
} }
else else
{ {
...@@ -4391,6 +4392,10 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, ...@@ -4391,6 +4392,10 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
// //
const TFunction *fnCandidate; const TFunction *fnCandidate;
bool builtIn; bool builtIn;
for (TIntermNode *arg : *argumentsNode->getSequence())
{
fnCall->addParameter(TConstParameter(&arg->getAsTyped()->getType()));
}
fnCandidate = findFunction(loc, fnCall, mShaderVersion, &builtIn); fnCandidate = findFunction(loc, fnCall, mShaderVersion, &builtIn);
if (fnCandidate) if (fnCandidate)
{ {
...@@ -4412,55 +4417,54 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, ...@@ -4412,55 +4417,54 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
// //
// Treat it like a built-in unary operator. // Treat it like a built-in unary operator.
// //
TIntermAggregate *paramAgg = paramNode->getAsAggregate(); TIntermNode *unaryParamNode = argumentsNode->getSequence()->front();
paramNode = paramAgg->getSequence()->front(); callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc,
callNode = createUnaryMath(op, paramNode->getAsTyped(), loc,
&fnCandidate->getReturnType()); &fnCandidate->getReturnType());
if (callNode == nullptr) if (callNode == nullptr)
{ {
std::stringstream reasonStream; std::stringstream reasonStream;
reasonStream << "wrong operand type for built in unary function: " reasonStream
<< static_cast<TIntermTyped *>(paramNode)->getCompleteString(); << "wrong operand type for built in unary function: "
<< static_cast<TIntermTyped *>(argumentsNode)->getCompleteString();
std::string reason = reasonStream.str(); std::string reason = reasonStream.str();
error(paramNode->getLine(), reason.c_str(), "Internal Error"); error(argumentsNode->getLine(), reason.c_str(), "Internal Error");
*fatalError = true; return TIntermTyped::CreateZero(TType(EbtFloat, EbpMedium, EvqConst));
return nullptr;
} }
} }
else else
{ {
TIntermAggregate *aggregate = ASSERT(argumentsNode->getOp() == EOpNull);
intermediate.setAggregateOperator(paramNode, op, loc); argumentsNode->setOp(op);
aggregate->setType(fnCandidate->getReturnType()); argumentsNode->setType(fnCandidate->getReturnType());
aggregate->setPrecisionForBuiltInOp(); argumentsNode->setPrecisionForBuiltInOp();
if (aggregate->areChildrenConstQualified()) if (argumentsNode->areChildrenConstQualified())
{ {
aggregate->getTypePointer()->setQualifier(EvqConst); argumentsNode->getTypePointer()->setQualifier(EvqConst);
} }
// Some built-in functions have out parameters too. // Some built-in functions have out parameters too.
functionCallLValueErrorCheck(fnCandidate, aggregate); functionCallLValueErrorCheck(fnCandidate, argumentsNode);
// 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(aggregate, mDiagnostics); intermediate.foldAggregateBuiltIn(argumentsNode, mDiagnostics);
if (foldedNode) if (foldedNode)
{ {
callNode = foldedNode; callNode = foldedNode;
} }
else else
{ {
callNode = aggregate; callNode = argumentsNode;
} }
} }
} }
else else
{ {
// This is a real function call // This is a real function call
TIntermAggregate *aggregate = ASSERT(argumentsNode->getOp() == EOpNull);
intermediate.setAggregateOperator(paramNode, EOpFunctionCall, loc); argumentsNode->setOp(EOpFunctionCall);
aggregate->setType(fnCandidate->getReturnType()); argumentsNode->setType(fnCandidate->getReturnType());
// this is how we know whether the given function is a builtIn function or a user // this is how we know whether the given function is a builtIn function or a user
// defined function // defined function
...@@ -4468,36 +4472,33 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, ...@@ -4468,36 +4472,33 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
// builtIn function also // builtIn function also
// if builtIn == true, it's definitely a builtIn function with EOpNull // if builtIn == true, it's definitely a builtIn function with EOpNull
if (!builtIn) if (!builtIn)
aggregate->setUserDefined(); argumentsNode->setUserDefined();
aggregate->getFunctionSymbolInfo()->setFromFunction(*fnCandidate); argumentsNode->getFunctionSymbolInfo()->setFromFunction(*fnCandidate);
// 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)
{ {
aggregate->setBuiltInFunctionPrecision(); argumentsNode->setBuiltInFunctionPrecision();
checkTextureOffsetConst(aggregate); checkTextureOffsetConst(argumentsNode);
checkImageMemoryAccessForBuiltinFunctions(aggregate); checkImageMemoryAccessForBuiltinFunctions(argumentsNode);
} }
else else
{ {
checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, aggregate); checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, argumentsNode);
} }
callNode = aggregate; callNode = argumentsNode;
functionCallLValueErrorCheck(fnCandidate, aggregate); functionCallLValueErrorCheck(fnCandidate, argumentsNode);
} }
} }
else else
{ {
// error message was put out by findFunction() // error message was put out by findFunction()
// Put on a dummy node for error recovery // Put on a dummy node for error recovery
TConstantUnion *unionArray = new TConstantUnion[1]; callNode = TIntermTyped::CreateZero(TType(EbtFloat, EbpMedium, EvqConst));
unionArray->setFConst(0.0f);
callNode = intermediate.addConstantUnion(unionArray,
TType(EbtFloat, EbpUndefined, EvqConst), loc);
} }
} }
return callNode; return callNode;
......
...@@ -112,8 +112,7 @@ class TParseContext : angle::NonCopyable ...@@ -112,8 +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,
TIntermNode *argumentsNode, const TIntermAggregate *argumentsNode,
const TFunction &function,
TOperator op, TOperator op,
const TType &type); const TType &type);
...@@ -253,9 +252,9 @@ class TParseContext : angle::NonCopyable ...@@ -253,9 +252,9 @@ 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(TIntermNode *arguments, TIntermTyped *addConstructor(TIntermAggregate *arguments,
TOperator op, TOperator op,
TFunction *fnCall, TType type,
const TSourceLoc &line); const TSourceLoc &line);
TIntermTyped *addIndexExpression(TIntermTyped *baseExpression, TIntermTyped *addIndexExpression(TIntermTyped *baseExpression,
...@@ -346,11 +345,14 @@ class TParseContext : angle::NonCopyable ...@@ -346,11 +345,14 @@ 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);
// fnCall is only storing the built-in op, and function name or constructor type. argumentsNode
// has the arguments.
TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall,
TIntermNode *paramNode, TIntermAggregate *argumentsNode,
TIntermNode *thisNode, TIntermNode *thisNode,
const TSourceLoc &loc, const TSourceLoc &loc);
bool *fatalError);
TIntermTyped *addTernarySelection(TIntermTyped *cond, TIntermTyped *addTernarySelection(TIntermTyped *cond,
TIntermTyped *trueExpression, TIntermTyped *trueExpression,
......
...@@ -484,7 +484,6 @@ class TType ...@@ -484,7 +484,6 @@ class TType
private: private:
void invalidateMangledName() { mangled = ""; } void invalidateMangledName() { mangled = ""; }
TString buildMangledName() const; TString buildMangledName() const;
size_t getStructSize() const;
TBasicType type; TBasicType type;
TPrecision precision; TPrecision precision;
......
...@@ -76,6 +76,7 @@ using namespace sh; ...@@ -76,6 +76,7 @@ using namespace sh;
union { union {
TIntermNode *intermNode; TIntermNode *intermNode;
TIntermNodePair nodePair; TIntermNodePair nodePair;
TIntermFunctionCallOrMethod callOrMethodPair;
TIntermTyped *intermTypedNode; TIntermTyped *intermTypedNode;
TIntermAggregate *intermAggregate; TIntermAggregate *intermAggregate;
TIntermBlock *intermBlock; TIntermBlock *intermBlock;
...@@ -314,24 +315,19 @@ integer_expression ...@@ -314,24 +315,19 @@ integer_expression
function_call function_call
: function_call_or_method { : function_call_or_method {
bool fatalError = false; $$ = context->addFunctionCallOrMethod($1.function, $1.callOrMethodPair.argumentsNode, $1.callOrMethodPair.thisNode, @1);
$$ = context->addFunctionCallOrMethod($1.function, $1.nodePair.node1, $1.nodePair.node2, @1, &fatalError);
if (fatalError)
{
YYERROR;
}
} }
; ;
function_call_or_method function_call_or_method
: function_call_generic { : function_call_generic {
$$ = $1; $$ = $1;
$$.nodePair.node2 = nullptr; $$.callOrMethodPair.thisNode = nullptr;
} }
| postfix_expression DOT function_call_generic { | postfix_expression DOT function_call_generic {
ES3_OR_NEWER("", @3, "methods"); ES3_OR_NEWER("", @3, "methods");
$$ = $3; $$ = $3;
$$.nodePair.node2 = $1; $$.callOrMethodPair.thisNode = $1;
} }
; ;
...@@ -347,26 +343,23 @@ function_call_generic ...@@ -347,26 +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;
$$.nodePair.node1 = nullptr; $$.callOrMethodPair.argumentsNode = context->createEmptyArgumentsNode(@1);
} }
| function_call_header { | function_call_header {
$$.function = $1; $$.function = $1;
$$.nodePair.node1 = nullptr; $$.callOrMethodPair.argumentsNode = context->createEmptyArgumentsNode(@1);
} }
; ;
function_call_header_with_parameters function_call_header_with_parameters
: function_call_header assignment_expression { : function_call_header assignment_expression {
const TType *type = new TType($2->getType()); $$.callOrMethodPair.argumentsNode = context->createEmptyArgumentsNode(@1);
$1->addParameter(TConstParameter(type));
$$.function = $1; $$.function = $1;
$$.nodePair.node1 = TIntermediate::MakeAggregate($2, @2); $$.callOrMethodPair.argumentsNode->getSequence()->push_back($2);
} }
| function_call_header_with_parameters COMMA assignment_expression { | function_call_header_with_parameters COMMA assignment_expression {
const TType *type = new TType($3->getType());
$1.function->addParameter(TConstParameter(type));
$$.function = $1.function; $$.function = $1.function;
$$.nodePair.node1 = context->intermediate.growAggregate($1.intermNode, $3, @2); $$.callOrMethodPair.argumentsNode->getSequence()->push_back($3);
} }
; ;
......
...@@ -308,6 +308,7 @@ union YYSTYPE ...@@ -308,6 +308,7 @@ union YYSTYPE
union { union {
TIntermNode *intermNode; TIntermNode *intermNode;
TIntermNodePair nodePair; TIntermNodePair nodePair;
TIntermFunctionCallOrMethod callOrMethodPair;
TIntermTyped *intermTypedNode; TIntermTyped *intermTypedNode;
TIntermAggregate *intermAggregate; TIntermAggregate *intermAggregate;
TIntermBlock *intermBlock; TIntermBlock *intermBlock;
...@@ -737,36 +738,36 @@ static const yytype_uint8 yytranslate[] = ...@@ -737,36 +738,36 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] = static const yytype_uint16 yyrline[] =
{ {
0, 245, 245, 246, 249, 259, 262, 267, 272, 277, 0, 246, 246, 247, 250, 260, 263, 268, 273, 278,
282, 288, 291, 294, 297, 300, 303, 309, 316, 327, 283, 289, 292, 295, 298, 301, 304, 310, 317, 323,
331, 339, 342, 348, 352, 359, 365, 374, 382, 388, 327, 335, 338, 344, 348, 355, 360, 367, 375, 381,
394, 403, 406, 409, 412, 422, 423, 424, 425, 433, 387, 396, 399, 402, 405, 415, 416, 417, 418, 426,
434, 437, 440, 447, 448, 451, 457, 458, 462, 469, 427, 430, 433, 440, 441, 444, 450, 451, 455, 462,
470, 473, 476, 479, 485, 486, 489, 495, 496, 503, 463, 466, 469, 472, 478, 479, 482, 488, 489, 496,
504, 511, 512, 519, 520, 526, 527, 533, 534, 540, 497, 504, 505, 512, 513, 519, 520, 526, 527, 533,
541, 547, 548, 555, 556, 557, 558, 562, 563, 564, 534, 540, 541, 548, 549, 550, 551, 555, 556, 557,
568, 572, 576, 580, 587, 590, 596, 603, 610, 613, 561, 565, 569, 573, 580, 583, 589, 596, 603, 606,
616, 625, 629, 633, 637, 641, 648, 655, 658, 665, 609, 618, 622, 626, 630, 634, 641, 648, 651, 658,
673, 693, 703, 711, 736, 740, 744, 748, 755, 762, 666, 686, 696, 704, 729, 733, 737, 741, 748, 755,
765, 769, 773, 778, 783, 790, 794, 798, 802, 807, 758, 762, 766, 771, 776, 783, 787, 791, 795, 800,
812, 819, 823, 829, 832, 838, 842, 849, 855, 859, 805, 812, 816, 822, 825, 831, 835, 842, 848, 852,
863, 866, 869, 878, 884, 892, 895, 915, 934, 941, 856, 859, 862, 871, 877, 885, 888, 908, 927, 934,
945, 949, 952, 955, 958, 961, 964, 972, 979, 982, 938, 942, 945, 948, 951, 954, 957, 965, 972, 975,
985, 991, 998, 1001, 1007, 1010, 1013, 1016, 1022, 1025, 978, 984, 991, 994, 1000, 1003, 1006, 1009, 1015, 1018,
1030, 1041, 1044, 1047, 1050, 1053, 1056, 1060, 1064, 1068, 1023, 1034, 1037, 1040, 1043, 1046, 1049, 1053, 1057, 1061,
1072, 1076, 1080, 1084, 1088, 1092, 1096, 1100, 1104, 1108, 1065, 1069, 1073, 1077, 1081, 1085, 1089, 1093, 1097, 1101,
1112, 1116, 1120, 1124, 1128, 1132, 1136, 1140, 1143, 1146, 1105, 1109, 1113, 1117, 1121, 1125, 1129, 1133, 1136, 1139,
1149, 1152, 1155, 1158, 1161, 1164, 1167, 1170, 1173, 1176, 1142, 1145, 1148, 1151, 1154, 1157, 1160, 1163, 1166, 1169,
1179, 1182, 1185, 1188, 1191, 1194, 1201, 1207, 1210, 1213, 1172, 1175, 1178, 1181, 1184, 1187, 1194, 1200, 1203, 1206,
1216, 1219, 1222, 1225, 1228, 1231, 1234, 1237, 1240, 1243, 1209, 1212, 1215, 1218, 1221, 1224, 1227, 1230, 1233, 1236,
1246, 1258, 1258, 1261, 1261, 1267, 1270, 1276, 1279, 1286, 1239, 1251, 1251, 1254, 1254, 1260, 1263, 1269, 1272, 1279,
1290, 1296, 1302, 1314, 1318, 1322, 1323, 1329, 1330, 1331, 1283, 1289, 1295, 1307, 1311, 1315, 1316, 1322, 1323, 1324,
1332, 1333, 1334, 1335, 1339, 1340, 1340, 1340, 1349, 1350, 1325, 1326, 1327, 1328, 1332, 1333, 1333, 1333, 1342, 1343,
1354, 1354, 1355, 1355, 1360, 1363, 1372, 1377, 1384, 1385, 1347, 1347, 1348, 1348, 1353, 1356, 1365, 1370, 1377, 1378,
1389, 1396, 1400, 1407, 1407, 1414, 1417, 1424, 1428, 1441, 1382, 1389, 1393, 1400, 1400, 1407, 1410, 1417, 1421, 1434,
1441, 1446, 1446, 1452, 1452, 1460, 1463, 1469, 1472, 1478, 1434, 1439, 1439, 1445, 1445, 1453, 1456, 1462, 1465, 1471,
1482, 1489, 1492, 1495, 1498, 1501, 1510, 1516, 1522, 1525, 1475, 1482, 1485, 1488, 1491, 1494, 1503, 1509, 1515, 1518,
1531, 1531 1524, 1524
}; };
#endif #endif
...@@ -2618,12 +2619,7 @@ yyreduce: ...@@ -2618,12 +2619,7 @@ yyreduce:
case 18: case 18:
{ {
bool fatalError = false; (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).nodePair.node1, (yyvsp[0].interm).nodePair.node2, (yylsp[0]), &fatalError);
if (fatalError)
{
YYERROR;
}
} }
break; break;
...@@ -2632,7 +2628,7 @@ yyreduce: ...@@ -2632,7 +2628,7 @@ yyreduce:
{ {
(yyval.interm) = (yyvsp[0].interm); (yyval.interm) = (yyvsp[0].interm);
(yyval.interm).nodePair.node2 = nullptr; (yyval.interm).callOrMethodPair.thisNode = nullptr;
} }
break; break;
...@@ -2642,7 +2638,7 @@ yyreduce: ...@@ -2642,7 +2638,7 @@ yyreduce:
{ {
ES3_OR_NEWER("", (yylsp[0]), "methods"); ES3_OR_NEWER("", (yylsp[0]), "methods");
(yyval.interm) = (yyvsp[0].interm); (yyval.interm) = (yyvsp[0].interm);
(yyval.interm).nodePair.node2 = (yyvsp[-2].interm.intermTypedNode); (yyval.interm).callOrMethodPair.thisNode = (yyvsp[-2].interm.intermTypedNode);
} }
break; break;
...@@ -2667,7 +2663,7 @@ yyreduce: ...@@ -2667,7 +2663,7 @@ yyreduce:
{ {
(yyval.interm).function = (yyvsp[-1].interm.function); (yyval.interm).function = (yyvsp[-1].interm.function);
(yyval.interm).nodePair.node1 = nullptr; (yyval.interm).callOrMethodPair.argumentsNode = context->createEmptyArgumentsNode((yylsp[-1]));
} }
break; break;
...@@ -2676,7 +2672,7 @@ yyreduce: ...@@ -2676,7 +2672,7 @@ yyreduce:
{ {
(yyval.interm).function = (yyvsp[0].interm.function); (yyval.interm).function = (yyvsp[0].interm.function);
(yyval.interm).nodePair.node1 = nullptr; (yyval.interm).callOrMethodPair.argumentsNode = context->createEmptyArgumentsNode((yylsp[0]));
} }
break; break;
...@@ -2684,10 +2680,9 @@ yyreduce: ...@@ -2684,10 +2680,9 @@ yyreduce:
case 25: case 25:
{ {
const TType *type = new TType((yyvsp[0].interm.intermTypedNode)->getType()); (yyval.interm).callOrMethodPair.argumentsNode = context->createEmptyArgumentsNode((yylsp[-1]));
(yyvsp[-1].interm.function)->addParameter(TConstParameter(type));
(yyval.interm).function = (yyvsp[-1].interm.function); (yyval.interm).function = (yyvsp[-1].interm.function);
(yyval.interm).nodePair.node1 = TIntermediate::MakeAggregate((yyvsp[0].interm.intermTypedNode), (yylsp[0])); (yyval.interm).callOrMethodPair.argumentsNode->getSequence()->push_back((yyvsp[0].interm.intermTypedNode));
} }
break; break;
...@@ -2695,10 +2690,8 @@ yyreduce: ...@@ -2695,10 +2690,8 @@ yyreduce:
case 26: case 26:
{ {
const TType *type = new TType((yyvsp[0].interm.intermTypedNode)->getType());
(yyvsp[-2].interm).function->addParameter(TConstParameter(type));
(yyval.interm).function = (yyvsp[-2].interm).function; (yyval.interm).function = (yyvsp[-2].interm).function;
(yyval.interm).nodePair.node1 = context->intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); (yyval.interm).callOrMethodPair.argumentsNode->getSequence()->push_back((yyvsp[0].interm.intermTypedNode));
} }
break; break;
......
...@@ -220,6 +220,7 @@ union YYSTYPE { ...@@ -220,6 +220,7 @@ union YYSTYPE {
union { union {
TIntermNode *intermNode; TIntermNode *intermNode;
TIntermNodePair nodePair; TIntermNodePair nodePair;
TIntermFunctionCallOrMethod callOrMethodPair;
TIntermTyped *intermTypedNode; TIntermTyped *intermTypedNode;
TIntermAggregate *intermAggregate; TIntermAggregate *intermAggregate;
TIntermBlock *intermBlock; TIntermBlock *intermBlock;
......
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