diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /gfx/angle/checkout/src/compiler/translator/SymbolTable.h | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/angle/checkout/src/compiler/translator/SymbolTable.h')
-rw-r--r-- | gfx/angle/checkout/src/compiler/translator/SymbolTable.h | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/compiler/translator/SymbolTable.h b/gfx/angle/checkout/src/compiler/translator/SymbolTable.h new file mode 100644 index 0000000000..fb05729981 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/SymbolTable.h @@ -0,0 +1,363 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_H_ +#define COMPILER_TRANSLATOR_SYMBOLTABLE_H_ + +// +// Symbol table for parsing. Has these design characteristics: +// +// * Same symbol table can be used to compile many shaders, to preserve +// effort of creating and loading with the large numbers of built-in +// symbols. +// +// * Name mangling will be used to give each function a unique name +// so that symbol table lookups are never ambiguous. This allows +// a simpler symbol table structure. +// +// * Pushing and popping of scope, so symbol table will really be a stack +// of symbol tables. Searched from the top, with new inserts going into +// the top. +// +// * Constants: Compile time constant symbols will keep their values +// in the symbol table. The parser can substitute constants at parse +// time, including doing constant folding and constant propagation. +// +// * No temporaries: Temporaries made from operations (+, --, .xy, etc.) +// are tracked in the intermediate representation, not the symbol table. +// + +#include <limits> +#include <memory> +#include <set> + +#include "common/angleutils.h" +#include "compiler/translator/ExtensionBehavior.h" +#include "compiler/translator/ImmutableString.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/SymbolTable_autogen.h" + +enum class Shader : uint8_t +{ + ALL, + FRAGMENT, // GL_FRAGMENT_SHADER + VERTEX, // GL_VERTEX_SHADER + COMPUTE, // GL_COMPUTE_SHADER + GEOMETRY, // GL_GEOMETRY_SHADER + GEOMETRY_EXT, // GL_GEOMETRY_SHADER_EXT + TESS_CONTROL_EXT, // GL_TESS_CONTROL_SHADER_EXT + TESS_EVALUATION_EXT, // GL_TESS_EVALUATION_SHADER_EXT + NOT_COMPUTE +}; + +namespace sh +{ + +struct UnmangledBuiltIn +{ + constexpr UnmangledBuiltIn(TExtension extension) : extension(extension) {} + + TExtension extension; +}; + +using VarPointer = TSymbol *(TSymbolTableBase::*); +using ValidateExtension = int ShBuiltInResources::*; + +enum class Spec : uint8_t +{ + GLSL, + ESSL +}; + +constexpr uint16_t kESSL1Only = 100; +// Some built-ins from backend shader languages are made available internally to ESSL for use in +// tree transformations. This (invalid) shader version is used to select those built-ins. This +// value needs to be larger than all other shader versions. +constexpr uint16_t kESSLInternalBackendBuiltIns = 0x3FFF; + +// The version assigned to |kESSLInternalBackendBuiltIns| should be good until OpenGL 20.0! +static_assert(kESSLInternalBackendBuiltIns > 2000, + "Accidentally exposing internal backend built-ins in OpenGL"); + +static_assert(offsetof(ShBuiltInResources, OES_standard_derivatives) != 0, + "Update SymbolTable extension logic"); + +#define EXT_INDEX(Ext) (offsetof(ShBuiltInResources, Ext) / sizeof(int)) + +class SymbolRule +{ + public: + const TSymbol *get(ShShaderSpec shaderSpec, + int shaderVersion, + sh::GLenum shaderType, + const ShBuiltInResources &resources, + const TSymbolTableBase &symbolTable) const; + + template <Spec spec, int version, Shader shaders, size_t extensionIndex, typename T> + constexpr static SymbolRule Get(T value); + + private: + constexpr SymbolRule(Spec spec, + int version, + Shader shaders, + size_t extensionIndex, + const TSymbol *symbol); + + constexpr SymbolRule(Spec spec, + int version, + Shader shaders, + size_t extensionIndex, + VarPointer resourceVar); + + union SymbolOrVar + { + constexpr SymbolOrVar(const TSymbol *symbolIn) : symbol(symbolIn) {} + constexpr SymbolOrVar(VarPointer varIn) : var(varIn) {} + + const TSymbol *symbol; + VarPointer var; + }; + + uint16_t mIsDesktop : 1; + uint16_t mIsVar : 1; + uint16_t mVersion : 14; + uint8_t mShaders; + uint8_t mExtensionIndex; + SymbolOrVar mSymbolOrVar; +}; + +constexpr SymbolRule::SymbolRule(Spec spec, + int version, + Shader shaders, + size_t extensionIndex, + const TSymbol *symbol) + : mIsDesktop(spec == Spec::GLSL ? 1u : 0u), + mIsVar(0u), + mVersion(static_cast<uint16_t>(version)), + mShaders(static_cast<uint8_t>(shaders)), + mExtensionIndex(extensionIndex), + mSymbolOrVar(symbol) +{} + +constexpr SymbolRule::SymbolRule(Spec spec, + int version, + Shader shaders, + size_t extensionIndex, + VarPointer resourceVar) + : mIsDesktop(spec == Spec::GLSL ? 1u : 0u), + mIsVar(1u), + mVersion(static_cast<uint16_t>(version)), + mShaders(static_cast<uint8_t>(shaders)), + mExtensionIndex(extensionIndex), + mSymbolOrVar(resourceVar) +{} + +template <Spec spec, int version, Shader shaders, size_t extensionIndex, typename T> +// static +constexpr SymbolRule SymbolRule::Get(T value) +{ + static_assert(version < 0x4000u, "version OOR"); + static_assert(static_cast<uint8_t>(shaders) < 0xFFu, "shaders OOR"); + static_assert(static_cast<uint8_t>(extensionIndex) < 0xFF, "extensionIndex OOR"); + return SymbolRule(spec, version, shaders, extensionIndex, value); +} + +const TSymbol *FindMangledBuiltIn(ShShaderSpec shaderSpec, + int shaderVersion, + sh::GLenum shaderType, + const ShBuiltInResources &resources, + const TSymbolTableBase &symbolTable, + const SymbolRule *rules, + uint16_t startIndex, + uint16_t endIndex); + +class UnmangledEntry +{ + public: + template <size_t ESSLExtCount> + constexpr UnmangledEntry(const char *name, + const std::array<TExtension, ESSLExtCount> &esslExtensions, + TExtension glslExtension, + int esslVersion, + int glslVersion, + Shader shaderType); + + bool matches(const ImmutableString &name, + ShShaderSpec shaderSpec, + int shaderVersion, + sh::GLenum shaderType, + const TExtensionBehavior &extensions) const; + + private: + const char *mName; + std::array<TExtension, 2u> mESSLExtensions; + TExtension mGLSLExtension; + uint8_t mShaderType; + uint16_t mESSLVersion; + uint16_t mGLSLVersion; +}; + +template <size_t ESSLExtCount> +constexpr UnmangledEntry::UnmangledEntry(const char *name, + const std::array<TExtension, ESSLExtCount> &esslExtensions, + TExtension glslExtension, + int esslVersion, + int glslVersion, + Shader shaderType) + : mName(name), + mESSLExtensions{(ESSLExtCount >= 1) ? esslExtensions[0] : TExtension::UNDEFINED, + (ESSLExtCount >= 2) ? esslExtensions[1] : TExtension::UNDEFINED}, + mGLSLExtension(glslExtension), + mShaderType(static_cast<uint8_t>(shaderType)), + mESSLVersion(esslVersion < 0 ? std::numeric_limits<uint16_t>::max() + : static_cast<uint16_t>(esslVersion)), + mGLSLVersion(glslVersion < 0 ? std::numeric_limits<uint16_t>::max() + : static_cast<uint16_t>(glslVersion)) +{} + +class TSymbolTable : angle::NonCopyable, TSymbolTableBase +{ + public: + TSymbolTable(); + // To start using the symbol table after construction: + // * initializeBuiltIns() needs to be called. + // * push() needs to be called to push the global level. + + ~TSymbolTable(); + + bool isEmpty() const; + bool atGlobalLevel() const; + + void push(); + void pop(); + + // Declare a non-function symbol at the current scope. Return true in case the declaration was + // successful, and false if the declaration failed due to redefinition. + bool declare(TSymbol *symbol); + + // Only used to declare internal variables. + bool declareInternal(TSymbol *symbol); + + // Functions are always declared at global scope. + void declareUserDefinedFunction(TFunction *function, bool insertUnmangledName); + + // These return the TFunction pointer to keep using to refer to this function. + const TFunction *markFunctionHasPrototypeDeclaration(const ImmutableString &mangledName, + bool *hadPrototypeDeclarationOut) const; + const TFunction *setFunctionParameterNamesFromDefinition(const TFunction *function, + bool *wasDefinedOut) const; + + // Return false if the gl_in array size has already been initialized with a mismatching value. + bool setGlInArraySize(unsigned int inputArraySize); + TVariable *getGlInVariableWithArraySize() const; + + const TVariable *gl_FragData() const; + const TVariable *gl_SecondaryFragDataEXT() const; + + void markStaticRead(const TVariable &variable); + void markStaticWrite(const TVariable &variable); + + // Note: Should not call this for constant variables. + bool isStaticallyUsed(const TVariable &variable) const; + + // find() is guaranteed not to retain a reference to the ImmutableString, so an ImmutableString + // with a reference to a short-lived char * is fine to pass here. + const TSymbol *find(const ImmutableString &name, int shaderVersion) const; + + const TSymbol *findUserDefined(const ImmutableString &name) const; + + TFunction *findUserDefinedFunction(const ImmutableString &name) const; + + const TSymbol *findGlobal(const ImmutableString &name) const; + const TSymbol *findGlobalWithConversion(const std::vector<ImmutableString> &names) const; + + const TSymbol *findBuiltIn(const ImmutableString &name, int shaderVersion) const; + const TSymbol *findBuiltInWithConversion(const std::vector<ImmutableString> &names, + int shaderVersion) const; + + void setDefaultPrecision(TBasicType type, TPrecision prec); + + // Searches down the precisionStack for a precision qualifier + // for the specified TBasicType + TPrecision getDefaultPrecision(TBasicType type) const; + + // This records invariant varyings declared through "invariant varying_name;". + void addInvariantVarying(const TVariable &variable); + + // If this returns false, the varying could still be invariant if it is set as invariant during + // the varying variable declaration - this piece of information is stored in the variable's + // type, not here. + bool isVaryingInvariant(const TVariable &variable) const; + + void setGlobalInvariant(bool invariant); + + const TSymbolUniqueId nextUniqueId() { return TSymbolUniqueId(this); } + + // Gets the built-in accessible by a shader with the specified version, if any. + bool isUnmangledBuiltInName(const ImmutableString &name, + int shaderVersion, + const TExtensionBehavior &extensions) const; + + void initializeBuiltIns(sh::GLenum type, + ShShaderSpec spec, + const ShBuiltInResources &resources); + void clearCompilationResults(); + + ShShaderSpec getShaderSpec() const { return mShaderSpec; } + + private: + friend class TSymbolUniqueId; + + struct VariableMetadata + { + VariableMetadata(); + bool staticRead; + bool staticWrite; + bool invariant; + }; + + int nextUniqueIdValue(); + + class TSymbolTableLevel; + + void initSamplerDefaultPrecision(TBasicType samplerType); + + void initializeBuiltInVariables(sh::GLenum shaderType, + ShShaderSpec spec, + const ShBuiltInResources &resources); + + VariableMetadata *getOrCreateVariableMetadata(const TVariable &variable); + + std::vector<std::unique_ptr<TSymbolTableLevel>> mTable; + + // There's one precision stack level for predefined precisions and then one level for each scope + // in table. + typedef TMap<TBasicType, TPrecision> PrecisionStackLevel; + std::vector<std::unique_ptr<PrecisionStackLevel>> mPrecisionStack; + + bool mGlobalInvariant; + + int mUniqueIdCounter; + + static const int kLastBuiltInId; + + sh::GLenum mShaderType; + ShShaderSpec mShaderSpec; + ShBuiltInResources mResources; + + // Indexed by unique id. Map instead of vector since the variables are fairly sparse. + std::map<int, VariableMetadata> mVariableMetadata; + + // Store gl_in variable with its array size once the array size can be determined. The array + // size can also be checked against latter input primitive type declaration. + TVariable *mGlInVariableWithArraySize; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_ |