Commit e80825ef by Olli Etuaho Committed by Commit Bot

Simplify built-in function node initialization

Built-ins with no math op associated with them now have the op code EOpCallBuiltInFunction set. This makes initializing built-in function nodes simpler, since they can always get the op code from the function symbol. We also no longer look for functions in inner scopes, only from the global scope and from built-in functions. BUG=angleproject:2267 TEST=angle_unittests Change-Id: I55a2642f34bb3c8b8f13183c95fa509ec3b9cfdb Reviewed-on: https://chromium-review.googlesource.com/923724Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 17448956
...@@ -352,11 +352,9 @@ TIntermAggregate *TIntermAggregate::CreateRawFunctionCall(const TFunction &func, ...@@ -352,11 +352,9 @@ TIntermAggregate *TIntermAggregate::CreateRawFunctionCall(const TFunction &func,
TIntermAggregate *TIntermAggregate::CreateBuiltInFunctionCall(const TFunction &func, TIntermAggregate *TIntermAggregate::CreateBuiltInFunctionCall(const TFunction &func,
TIntermSequence *arguments) TIntermSequence *arguments)
{ {
TIntermAggregate *callNode = // op should be either EOpCallBuiltInFunction or a specific math op.
new TIntermAggregate(&func, func.getReturnType(), EOpCallBuiltInFunction, arguments); ASSERT(func.getBuiltInOp() != EOpNull);
// Note that name needs to be set before texture function type is determined. return new TIntermAggregate(&func, func.getReturnType(), func.getBuiltInOp(), arguments);
callNode->setBuiltInFunctionPrecision();
return callNode;
} }
TIntermAggregate *TIntermAggregate::CreateConstructor(const TType &type, TIntermAggregate *TIntermAggregate::CreateConstructor(const TType &type,
...@@ -365,22 +363,11 @@ TIntermAggregate *TIntermAggregate::CreateConstructor(const TType &type, ...@@ -365,22 +363,11 @@ TIntermAggregate *TIntermAggregate::CreateConstructor(const TType &type,
return new TIntermAggregate(nullptr, type, EOpConstruct, arguments); return new TIntermAggregate(nullptr, type, EOpConstruct, arguments);
} }
TIntermAggregate *TIntermAggregate::Create(const TFunction &func,
TOperator op,
TIntermSequence *arguments)
{
ASSERT(op != EOpCallFunctionInAST); // Should use CreateFunctionCall
ASSERT(op != EOpCallInternalRawFunction); // Should use CreateRawFunctionCall
ASSERT(op != EOpCallBuiltInFunction); // Should use CreateBuiltInFunctionCall
ASSERT(op != EOpConstruct); // Should use CreateConstructor
return new TIntermAggregate(&func, func.getReturnType(), op, arguments);
}
TIntermAggregate::TIntermAggregate(const TFunction *func, TIntermAggregate::TIntermAggregate(const TFunction *func,
const TType &type, const TType &type,
TOperator op, TOperator op,
TIntermSequence *arguments) TIntermSequence *arguments)
: TIntermOperator(op), : TIntermOperator(op, type),
mUseEmulatedFunction(false), mUseEmulatedFunction(false),
mGotPrecisionFromChildren(false), mGotPrecisionFromChildren(false),
mFunction(func) mFunction(func)
...@@ -390,14 +377,17 @@ TIntermAggregate::TIntermAggregate(const TFunction *func, ...@@ -390,14 +377,17 @@ TIntermAggregate::TIntermAggregate(const TFunction *func,
mArguments.swap(*arguments); mArguments.swap(*arguments);
} }
ASSERT(mFunction == nullptr || mFunction->symbolType() != SymbolType::Empty); ASSERT(mFunction == nullptr || mFunction->symbolType() != SymbolType::Empty);
setTypePrecisionAndQualifier(type); setPrecisionAndQualifier();
} }
void TIntermAggregate::setTypePrecisionAndQualifier(const TType &type) void TIntermAggregate::setPrecisionAndQualifier()
{ {
setType(type);
mType.setQualifier(EvqTemporary); mType.setQualifier(EvqTemporary);
if (!isFunctionCall()) if (mOp == EOpCallBuiltInFunction)
{
setBuiltInFunctionPrecision();
}
else if (!isFunctionCall())
{ {
if (isConstructor()) if (isConstructor())
{ {
......
...@@ -564,13 +564,11 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase ...@@ -564,13 +564,11 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
static TIntermAggregate *CreateRawFunctionCall(const TFunction &func, static TIntermAggregate *CreateRawFunctionCall(const TFunction &func,
TIntermSequence *arguments); TIntermSequence *arguments);
// This covers all built-in function calls - whether they are associated with an op or not.
static TIntermAggregate *CreateBuiltInFunctionCall(const TFunction &func, static TIntermAggregate *CreateBuiltInFunctionCall(const TFunction &func,
TIntermSequence *arguments); TIntermSequence *arguments);
static TIntermAggregate *CreateConstructor(const TType &type, static TIntermAggregate *CreateConstructor(const TType &type,
TIntermSequence *arguments); TIntermSequence *arguments);
static TIntermAggregate *Create(const TFunction &func,
TOperator op,
TIntermSequence *arguments);
~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.
...@@ -622,7 +620,7 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase ...@@ -622,7 +620,7 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
TIntermAggregate(const TIntermAggregate &node); // note: not deleted, just private! TIntermAggregate(const TIntermAggregate &node); // note: not deleted, just private!
void setTypePrecisionAndQualifier(const TType &type); void setPrecisionAndQualifier();
bool areChildrenConstQualified(); bool areChildrenConstQualified();
......
...@@ -259,13 +259,9 @@ TIntermTyped *CreateBuiltInFunctionCallNode(const char *name, ...@@ -259,13 +259,9 @@ TIntermTyped *CreateBuiltInFunctionCallNode(const char *name,
const TFunction *fn = LookUpBuiltInFunction(name, arguments, symbolTable, shaderVersion); const TFunction *fn = LookUpBuiltInFunction(name, arguments, symbolTable, shaderVersion);
ASSERT(fn); ASSERT(fn);
TOperator op = fn->getBuiltInOp(); TOperator op = fn->getBuiltInOp();
if (op != EOpNull) if (op != EOpCallBuiltInFunction && arguments->size() == 1)
{ {
if (arguments->size() == 1) return new TIntermUnary(op, arguments->at(0)->getAsTyped());
{
return new TIntermUnary(op, arguments->at(0)->getAsTyped());
}
return TIntermAggregate::Create(*fn, op, arguments);
} }
return TIntermAggregate::CreateBuiltInFunctionCall(*fn, arguments); return TIntermAggregate::CreateBuiltInFunctionCall(*fn, arguments);
} }
......
...@@ -5808,23 +5808,39 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCa ...@@ -5808,23 +5808,39 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCa
} }
else else
{ {
symbol = symbolTable.find(fnCall->getMangledName(), mShaderVersion); // There are no inner functions, so it's enough to look for user-defined functions in the
// global scope.
symbol = symbolTable.findGlobal(fnCall->getMangledName());
if (symbol != nullptr)
{
// A user-defined function - could be an overloaded built-in as well.
ASSERT(symbol->symbolType() == SymbolType::UserDefined);
const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
TIntermAggregate *callNode =
TIntermAggregate::CreateFunctionCall(*fnCandidate, &fnCall->arguments());
callNode->setLine(loc);
checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
functionCallRValueLValueErrorCheck(fnCandidate, callNode);
return callNode;
}
symbol = symbolTable.findBuiltIn(fnCall->getMangledName(), mShaderVersion);
if (symbol == nullptr) if (symbol == nullptr)
{ {
error(loc, "no matching overloaded function found", fnCall->name()); error(loc, "no matching overloaded function found", fnCall->name());
} }
else else
{ {
// A built-in function.
ASSERT(symbol->symbolType() == SymbolType::BuiltIn);
const TFunction *fnCandidate = static_cast<const TFunction *>(symbol); const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
//
// A declared function.
//
if (fnCandidate->extension() != TExtension::UNDEFINED) if (fnCandidate->extension() != TExtension::UNDEFINED)
{ {
checkCanUseExtension(loc, fnCandidate->extension()); checkCanUseExtension(loc, fnCandidate->extension());
} }
TOperator op = fnCandidate->getBuiltInOp(); TOperator op = fnCandidate->getBuiltInOp();
if (op != EOpNull) if (op != EOpCallBuiltInFunction)
{ {
// 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)
...@@ -5835,50 +5851,28 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCa ...@@ -5835,50 +5851,28 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCa
ASSERT(callNode != nullptr); ASSERT(callNode != nullptr);
return callNode; return callNode;
} }
else TIntermAggregate *callNode =
{ TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, &fnCall->arguments());
TIntermAggregate *callNode = callNode->setLine(loc);
TIntermAggregate::Create(*fnCandidate, op, &fnCall->arguments());
callNode->setLine(loc);
// Some built-in functions have out parameters too.
functionCallRValueLValueErrorCheck(fnCandidate, callNode);
// See if we can constant fold a built-in. Note that this may be possible
// even if it is not const-qualified.
return callNode->fold(mDiagnostics);
}
}
else
{
// This is a real function call.
TIntermAggregate *callNode = nullptr;
// If the symbol type is not BuiltIn, the function is user defined - could be an
// overloaded built-in as well. if the symbol type is BuiltIn, it's a built-in
// function with no op associated with it.
if (fnCandidate->symbolType() == SymbolType::BuiltIn)
{
callNode = TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate,
&fnCall->arguments());
checkTextureOffsetConst(callNode);
checkTextureGather(callNode);
checkImageMemoryAccessForBuiltinFunctions(callNode);
checkAtomicMemoryBuiltinFunctions(callNode);
}
else
{
callNode =
TIntermAggregate::CreateFunctionCall(*fnCandidate, &fnCall->arguments());
checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
}
// Some built-in functions have out parameters too.
functionCallRValueLValueErrorCheck(fnCandidate, callNode); functionCallRValueLValueErrorCheck(fnCandidate, callNode);
callNode->setLine(loc); // See if we can constant fold a built-in. Note that this may be possible
// even if it is not const-qualified.
return callNode; return callNode->fold(mDiagnostics);
} }
// This is a built-in function with no op associated with it.
TIntermAggregate *callNode =
TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, &fnCall->arguments());
callNode->setLine(loc);
checkTextureOffsetConst(callNode);
checkTextureGather(callNode);
checkImageMemoryAccessForBuiltinFunctions(callNode);
checkAtomicMemoryBuiltinFunctions(callNode);
functionCallRValueLValueErrorCheck(fnCandidate, callNode);
return callNode;
} }
} }
......
...@@ -196,8 +196,8 @@ class TSymbolTable : angle::NonCopyable ...@@ -196,8 +196,8 @@ class TSymbolTable : angle::NonCopyable
const TType *ptype5 = 0) const TType *ptype5 = 0)
{ {
insertUnmangledBuiltInName(name, level); insertUnmangledBuiltInName(name, level);
insertBuiltIn(level, EOpNull, TExtension::UNDEFINED, rvalue, name, ptype1, ptype2, ptype3, insertBuiltIn(level, EOpCallBuiltInFunction, TExtension::UNDEFINED, rvalue, name, ptype1,
ptype4, ptype5); ptype2, ptype3, ptype4, ptype5);
} }
void insertBuiltIn(ESymbolLevel level, void insertBuiltIn(ESymbolLevel level,
...@@ -211,7 +211,8 @@ class TSymbolTable : angle::NonCopyable ...@@ -211,7 +211,8 @@ class TSymbolTable : angle::NonCopyable
const TType *ptype5 = 0) const TType *ptype5 = 0)
{ {
insertUnmangledBuiltInName(name, level); insertUnmangledBuiltInName(name, level);
insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); insertBuiltIn(level, EOpCallBuiltInFunction, ext, rvalue, name, ptype1, ptype2, ptype3,
ptype4, ptype5);
} }
void insertBuiltInOp(ESymbolLevel level, void insertBuiltInOp(ESymbolLevel level,
......
...@@ -60,13 +60,18 @@ class IntermNodeTest : public testing::Test ...@@ -60,13 +60,18 @@ class IntermNodeTest : public testing::Test
return createTestSymbol(type); return createTestSymbol(type);
} }
TFunction *createTestBuiltInFunction(const TType &returnType, const TIntermSequence &args) TFunction *createTestFunction(const TType &returnType, const TIntermSequence &args)
{ {
// We're using a dummy symbol table similarly as for creating symbol nodes. // We're using a dummy symbol table similarly as for creating symbol nodes.
const ImmutableString name("testFunc"); const ImmutableString name("testFunc");
TSymbolTable symbolTable; TSymbolTable symbolTable;
TFunction *func = TFunction *func = new TFunction(&symbolTable, name, new TType(returnType),
new TFunction(&symbolTable, name, new TType(returnType), SymbolType::BuiltIn, true); SymbolType::UserDefined, false);
for (TIntermNode *arg : args)
{
const TType *type = new TType(arg->getAsTyped()->getType());
func->addParameter(TConstParameter(type));
}
return func; return func;
} }
...@@ -211,10 +216,10 @@ TEST_F(IntermNodeTest, DeepCopyAggregateNode) ...@@ -211,10 +216,10 @@ TEST_F(IntermNodeTest, DeepCopyAggregateNode)
originalSeq->push_back(createTestSymbol()); originalSeq->push_back(createTestSymbol());
originalSeq->push_back(createTestSymbol()); originalSeq->push_back(createTestSymbol());
TFunction *mix = TFunction *testFunc =
createTestBuiltInFunction(originalSeq->back()->getAsTyped()->getType(), *originalSeq); createTestFunction(originalSeq->back()->getAsTyped()->getType(), *originalSeq);
TIntermAggregate *original = TIntermAggregate::Create(*mix, EOpMix, originalSeq); TIntermAggregate *original = TIntermAggregate::CreateFunctionCall(*testFunc, originalSeq);
original->setLine(getTestSourceLoc()); original->setLine(getTestSourceLoc());
TIntermTyped *copyTyped = original->deepCopy(); TIntermTyped *copyTyped = original->deepCopy();
......
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