Commit 01d0ad08 by Olli Etuaho Committed by Commit Bot

Add symbol table function to get TFunction for a built-in op

Built-in function parameter qualifiers are stored in the symbol table. Some AST traversers need the qualifier information for ops to determine whether a node is being written to. Add an utility function that maps a TIntermAggregate node to a symbol table entry, so that the traversers can get to this information in a convenient way. This will be necessary for adding more built-ins that have out parameters from ESSL 3.10. BUG=angleproject:1730 TEST=angle_unittests Change-Id: I4bc622d70b2326a04cc858ff1258c22320c590dc Reviewed-on: https://chromium-review.googlesource.com/431109 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent ccd8c9b6
...@@ -373,7 +373,8 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], ...@@ -373,7 +373,8 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
bool multiview2 = IsExtensionEnabled(extensionBehavior, "GL_OVR_multiview2"); bool multiview2 = IsExtensionEnabled(extensionBehavior, "GL_OVR_multiview2");
if (success && compileResources.OVR_multiview && IsWebGLBasedSpec(shaderSpec) && if (success && compileResources.OVR_multiview && IsWebGLBasedSpec(shaderSpec) &&
(IsExtensionEnabled(extensionBehavior, "GL_OVR_multiview") || multiview2)) (IsExtensionEnabled(extensionBehavior, "GL_OVR_multiview") || multiview2))
success = ValidateMultiviewWebGL(root, shaderType, multiview2, &mDiagnostics); success = ValidateMultiviewWebGL(root, shaderType, symbolTable, shaderVersion,
multiview2, &mDiagnostics);
// Fail compilation if precision emulation not supported. // Fail compilation if precision emulation not supported.
if (success && getResources().WEBGL_debug_shader_precision && if (success && getResources().WEBGL_debug_shader_precision &&
......
...@@ -680,26 +680,9 @@ void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node) ...@@ -680,26 +680,9 @@ void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
// Find the built-in function corresponding to this op so that we can determine the // Find the built-in function corresponding to this op so that we can determine the
// in/out qualifiers of its parameters. // in/out qualifiers of its parameters.
TFunction *builtInFunc = nullptr; TFunction *builtInFunc = nullptr;
TString opString = GetOperatorString(node->getOp()); if (!node->isConstructor() && node->getOp() != EOpFunctionCall)
if (!node->isConstructor() && !opString.empty())
{ {
// The return type doesn't affect the mangled name of the function, which is used builtInFunc = mSymbolTable.findBuiltInOp(node, mShaderVersion);
// to look it up from the symbol table.
TType dummyReturnType;
TFunction call(&opString, &dummyReturnType, node->getOp());
for (auto *child : *sequence)
{
TType *paramType = child->getAsTyped()->getTypePointer();
TConstParameter p(paramType);
call.addParameter(p);
}
TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
if (sym != nullptr && sym->isFunction())
{
builtInFunc = static_cast<TFunction *>(sym);
ASSERT(builtInFunc->getParamCount() == sequence->size());
}
} }
size_t paramIndex = 0; size_t paramIndex = 0;
......
...@@ -14,7 +14,9 @@ ...@@ -14,7 +14,9 @@
#endif #endif
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "compiler/translator/Cache.h" #include "compiler/translator/Cache.h"
#include "compiler/translator/IntermNode.h"
#include <stdio.h> #include <stdio.h>
#include <algorithm> #include <algorithm>
...@@ -153,6 +155,30 @@ TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) const ...@@ -153,6 +155,30 @@ TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) const
return 0; return 0;
} }
TFunction *TSymbolTable::findBuiltInOp(TIntermAggregate *callNode, int shaderVersion) const
{
ASSERT(!callNode->isConstructor());
ASSERT(callNode->getOp() != EOpFunctionCall);
TString opString = GetOperatorString(callNode->getOp());
// The return type doesn't affect the mangled name of the function, which is used to look it up.
TType dummyReturnType;
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());
TFunction *builtInFunc = static_cast<TFunction *>(sym);
ASSERT(builtInFunc->getParamCount() == sequence->size());
return builtInFunc;
}
TSymbolTable::~TSymbolTable() TSymbolTable::~TSymbolTable()
{ {
while (table.size() > 0) while (table.size() > 0)
......
...@@ -41,6 +41,8 @@ ...@@ -41,6 +41,8 @@
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
{ {
...@@ -424,6 +426,10 @@ class TSymbolTable : angle::NonCopyable ...@@ -424,6 +426,10 @@ class TSymbolTable : angle::NonCopyable
TSymbol *findBuiltIn(const TString &name, int shaderVersion) const; TSymbol *findBuiltIn(const TString &name, int shaderVersion) const;
// Helper front-end for regular findBuiltIn that constructs the mangled function name from
// callNode.
TFunction *findBuiltInOp(TIntermAggregate *callNode, int shaderVersion) const;
TSymbolTableLevel *getOuterLevel() TSymbolTableLevel *getOuterLevel()
{ {
assert(currentLevel() >= 1); assert(currentLevel() >= 1);
......
...@@ -31,6 +31,8 @@ class ValidateMultiviewTraverser : public TIntermTraverser ...@@ -31,6 +31,8 @@ class ValidateMultiviewTraverser : public TIntermTraverser
// errors. // errors.
static bool validate(TIntermBlock *root, static bool validate(TIntermBlock *root,
GLenum shaderType, GLenum shaderType,
const TSymbolTable &symbolTable,
int shaderVersion,
bool multiview2, bool multiview2,
TDiagnostics *diagnostics); TDiagnostics *diagnostics);
...@@ -44,7 +46,11 @@ class ValidateMultiviewTraverser : public TIntermTraverser ...@@ -44,7 +46,11 @@ class ValidateMultiviewTraverser : public TIntermTraverser
bool visitAggregate(Visit visit, TIntermAggregate *node) override; bool visitAggregate(Visit visit, TIntermAggregate *node) override;
private: private:
ValidateMultiviewTraverser(GLenum shaderType, bool multiview2, TDiagnostics *diagnostics); ValidateMultiviewTraverser(GLenum shaderType,
const TSymbolTable &symbolTable,
int shaderVersion,
bool multiview2,
TDiagnostics *diagnostics);
static bool IsGLPosition(TIntermNode *node); static bool IsGLPosition(TIntermNode *node);
static bool IsGLViewIDOVR(TIntermNode *node); static bool IsGLViewIDOVR(TIntermNode *node);
...@@ -56,6 +62,8 @@ class ValidateMultiviewTraverser : public TIntermTraverser ...@@ -56,6 +62,8 @@ class ValidateMultiviewTraverser : public TIntermTraverser
bool mValid; bool mValid;
bool mMultiview2; bool mMultiview2;
GLenum mShaderType; GLenum mShaderType;
const TSymbolTable &mSymbolTable;
const int mShaderVersion;
bool mInsideViewIDConditional; // Only set if mMultiview2 is false. bool mInsideViewIDConditional; // Only set if mMultiview2 is false.
bool mInsideRestrictedAssignment; bool mInsideRestrictedAssignment;
...@@ -67,22 +75,29 @@ class ValidateMultiviewTraverser : public TIntermTraverser ...@@ -67,22 +75,29 @@ class ValidateMultiviewTraverser : public TIntermTraverser
bool ValidateMultiviewTraverser::validate(TIntermBlock *root, bool ValidateMultiviewTraverser::validate(TIntermBlock *root,
GLenum shaderType, GLenum shaderType,
const TSymbolTable &symbolTable,
int shaderVersion,
bool multiview2, bool multiview2,
TDiagnostics *diagnostics) TDiagnostics *diagnostics)
{ {
ValidateMultiviewTraverser validate(shaderType, multiview2, diagnostics); ValidateMultiviewTraverser validate(shaderType, symbolTable, shaderVersion, multiview2,
diagnostics);
ASSERT(root); ASSERT(root);
root->traverse(&validate); root->traverse(&validate);
return validate.isValid(); return validate.isValid();
} }
ValidateMultiviewTraverser::ValidateMultiviewTraverser(GLenum shaderType, ValidateMultiviewTraverser::ValidateMultiviewTraverser(GLenum shaderType,
const TSymbolTable &symbolTable,
int shaderVersion,
bool multiview2, bool multiview2,
TDiagnostics *diagnostics) TDiagnostics *diagnostics)
: TIntermTraverser(true, true, true), : TIntermTraverser(true, true, true),
mValid(true), mValid(true),
mMultiview2(multiview2), mMultiview2(multiview2),
mShaderType(shaderType), mShaderType(shaderType),
mSymbolTable(symbolTable),
mShaderVersion(shaderVersion),
mInsideViewIDConditional(false), mInsideViewIDConditional(false),
mInsideRestrictedAssignment(false), mInsideRestrictedAssignment(false),
mGLPositionAllowed(multiview2), mGLPositionAllowed(multiview2),
...@@ -361,17 +376,21 @@ bool ValidateMultiviewTraverser::visitAggregate(Visit visit, TIntermAggregate *n ...@@ -361,17 +376,21 @@ bool ValidateMultiviewTraverser::visitAggregate(Visit visit, TIntermAggregate *n
mValid = false; mValid = false;
} }
} }
else if (node->getOp() == EOpModf) else if (!node->isConstructor())
{ {
// TODO(oetuaho@nvidia.com): It's quite hacky to hard-code modf - should maybe refactor TFunction *builtInFunc = mSymbolTable.findBuiltInOp(node, mShaderVersion);
// out parameter detecting functionality in LValueTrackingTraverser so that it could be for (size_t paramIndex = 0u; paramIndex < builtInFunc->getParamCount(); ++paramIndex)
// used here as well? {
// LValueTrackingTraverser itself seems like a bad fit with the needs of this traverser. TQualifier qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
mDiagnostics->error(node->getLine(), if (qualifier == EvqOut || qualifier == EvqInOut)
"Disallowed use of a function with an out parameter inside " {
"assignment to gl_Position.x when using OVR_multiview", mDiagnostics->error(node->getLine(),
GetOperatorString(node->getOp())); "Disallowed use of a function with an out parameter inside "
mValid = false; "assignment to gl_Position.x when using OVR_multiview",
GetOperatorString(node->getOp()));
mValid = false;
}
}
} }
} }
return true; return true;
...@@ -381,6 +400,8 @@ bool ValidateMultiviewTraverser::visitAggregate(Visit visit, TIntermAggregate *n ...@@ -381,6 +400,8 @@ bool ValidateMultiviewTraverser::visitAggregate(Visit visit, TIntermAggregate *n
bool ValidateMultiviewWebGL(TIntermBlock *root, bool ValidateMultiviewWebGL(TIntermBlock *root,
GLenum shaderType, GLenum shaderType,
const TSymbolTable &symbolTable,
int shaderVersion,
bool multiview2, bool multiview2,
TDiagnostics *diagnostics) TDiagnostics *diagnostics)
{ {
...@@ -388,7 +409,8 @@ bool ValidateMultiviewWebGL(TIntermBlock *root, ...@@ -388,7 +409,8 @@ bool ValidateMultiviewWebGL(TIntermBlock *root,
{ {
return true; return true;
} }
return ValidateMultiviewTraverser::validate(root, shaderType, multiview2, diagnostics); return ValidateMultiviewTraverser::validate(root, shaderType, symbolTable, shaderVersion,
multiview2, diagnostics);
} }
} // namespace sh } // namespace sh
...@@ -17,11 +17,14 @@ namespace sh ...@@ -17,11 +17,14 @@ namespace sh
{ {
class TDiagnostics; class TDiagnostics;
class TIntermBlock; class TIntermBlock;
class TSymbolTable;
// Check for errors and output error messages with diagnostics. // Check for errors and output error messages with diagnostics.
// Returns true if there are no errors. // Returns true if there are no errors.
bool ValidateMultiviewWebGL(TIntermBlock *root, bool ValidateMultiviewWebGL(TIntermBlock *root,
sh::GLenum shaderType, sh::GLenum shaderType,
const TSymbolTable &symbolTable,
int shaderVersion,
bool multiview2, bool multiview2,
TDiagnostics *diagnostics); TDiagnostics *diagnostics);
......
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