tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SymbolTable.h (13489B)


      1 //
      2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 #ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_H_
      8 #define COMPILER_TRANSLATOR_SYMBOLTABLE_H_
      9 
     10 //
     11 // Symbol table for parsing.  Has these design characteristics:
     12 //
     13 // * Same symbol table can be used to compile many shaders, to preserve
     14 //   effort of creating and loading with the large numbers of built-in
     15 //   symbols.
     16 //
     17 // * Name mangling will be used to give each function a unique name
     18 //   so that symbol table lookups are never ambiguous.  This allows
     19 //   a simpler symbol table structure.
     20 //
     21 // * Pushing and popping of scope, so symbol table will really be a stack
     22 //   of symbol tables.  Searched from the top, with new inserts going into
     23 //   the top.
     24 //
     25 // * Constants:  Compile time constant symbols will keep their values
     26 //   in the symbol table.  The parser can substitute constants at parse
     27 //   time, including doing constant folding and constant propagation.
     28 //
     29 // * No temporaries:  Temporaries made from operations (+, --, .xy, etc.)
     30 //   are tracked in the intermediate representation, not the symbol table.
     31 //
     32 
     33 #include <limits>
     34 #include <memory>
     35 #include <set>
     36 
     37 #include "common/angleutils.h"
     38 #include "compiler/translator/ExtensionBehavior.h"
     39 #include "compiler/translator/ImmutableString.h"
     40 #include "compiler/translator/InfoSink.h"
     41 #include "compiler/translator/IntermNode.h"
     42 #include "compiler/translator/Symbol.h"
     43 #include "compiler/translator/SymbolTable_autogen.h"
     44 
     45 enum class Shader : uint8_t
     46 {
     47    ALL,
     48    FRAGMENT,             // GL_FRAGMENT_SHADER
     49    VERTEX,               // GL_VERTEX_SHADER
     50    COMPUTE,              // GL_COMPUTE_SHADER
     51    GEOMETRY,             // GL_GEOMETRY_SHADER
     52    GEOMETRY_EXT,         // GL_GEOMETRY_SHADER_EXT
     53    TESS_CONTROL_EXT,     // GL_TESS_CONTROL_SHADER_EXT
     54    TESS_EVALUATION_EXT,  // GL_TESS_EVALUATION_SHADER_EXT
     55    NOT_COMPUTE
     56 };
     57 
     58 namespace sh
     59 {
     60 
     61 struct UnmangledBuiltIn
     62 {
     63    constexpr UnmangledBuiltIn(TExtension extension) : extension(extension) {}
     64 
     65    TExtension extension;
     66 };
     67 
     68 using VarPointer        = TSymbol *(TSymbolTableBase::*);
     69 using ValidateExtension = int ShBuiltInResources::*;
     70 
     71 enum class Spec : uint8_t
     72 {
     73    GLSL,
     74    ESSL
     75 };
     76 
     77 constexpr uint16_t kESSL1Only = 100;
     78 // Some built-ins from backend shader languages are made available internally to ESSL for use in
     79 // tree transformations.  This (invalid) shader version is used to select those built-ins.  This
     80 // value needs to be larger than all other shader versions.
     81 constexpr uint16_t kESSLInternalBackendBuiltIns = 0x3FFF;
     82 
     83 // The version assigned to |kESSLInternalBackendBuiltIns| should be good until OpenGL 20.0!
     84 static_assert(kESSLInternalBackendBuiltIns > 2000,
     85              "Accidentally exposing internal backend built-ins in OpenGL");
     86 
     87 static_assert(offsetof(ShBuiltInResources, OES_standard_derivatives) != 0,
     88              "Update SymbolTable extension logic");
     89 
     90 #define EXT_INDEX(Ext) (offsetof(ShBuiltInResources, Ext) / sizeof(int))
     91 
     92 class SymbolRule
     93 {
     94  public:
     95    const TSymbol *get(ShShaderSpec shaderSpec,
     96                       int shaderVersion,
     97                       sh::GLenum shaderType,
     98                       const ShBuiltInResources &resources,
     99                       const TSymbolTableBase &symbolTable) const;
    100 
    101    template <Spec spec, int version, Shader shaders, size_t extensionIndex, typename T>
    102    constexpr static SymbolRule Get(T value);
    103 
    104  private:
    105    constexpr SymbolRule(Spec spec,
    106                         int version,
    107                         Shader shaders,
    108                         size_t extensionIndex,
    109                         const TSymbol *symbol);
    110 
    111    constexpr SymbolRule(Spec spec,
    112                         int version,
    113                         Shader shaders,
    114                         size_t extensionIndex,
    115                         VarPointer resourceVar);
    116 
    117    union SymbolOrVar
    118    {
    119        constexpr SymbolOrVar(const TSymbol *symbolIn) : symbol(symbolIn) {}
    120        constexpr SymbolOrVar(VarPointer varIn) : var(varIn) {}
    121 
    122        const TSymbol *symbol;
    123        VarPointer var;
    124    };
    125 
    126    uint16_t mIsDesktop : 1;
    127    uint16_t mIsVar : 1;
    128    uint16_t mVersion : 14;
    129    uint8_t mShaders;
    130    uint8_t mExtensionIndex;
    131    SymbolOrVar mSymbolOrVar;
    132 };
    133 
    134 constexpr SymbolRule::SymbolRule(Spec spec,
    135                                 int version,
    136                                 Shader shaders,
    137                                 size_t extensionIndex,
    138                                 const TSymbol *symbol)
    139    : mIsDesktop(spec == Spec::GLSL ? 1u : 0u),
    140      mIsVar(0u),
    141      mVersion(static_cast<uint16_t>(version)),
    142      mShaders(static_cast<uint8_t>(shaders)),
    143      mExtensionIndex(extensionIndex),
    144      mSymbolOrVar(symbol)
    145 {}
    146 
    147 constexpr SymbolRule::SymbolRule(Spec spec,
    148                                 int version,
    149                                 Shader shaders,
    150                                 size_t extensionIndex,
    151                                 VarPointer resourceVar)
    152    : mIsDesktop(spec == Spec::GLSL ? 1u : 0u),
    153      mIsVar(1u),
    154      mVersion(static_cast<uint16_t>(version)),
    155      mShaders(static_cast<uint8_t>(shaders)),
    156      mExtensionIndex(extensionIndex),
    157      mSymbolOrVar(resourceVar)
    158 {}
    159 
    160 template <Spec spec, int version, Shader shaders, size_t extensionIndex, typename T>
    161 // static
    162 constexpr SymbolRule SymbolRule::Get(T value)
    163 {
    164    static_assert(version < 0x4000u, "version OOR");
    165    static_assert(static_cast<uint8_t>(shaders) < 0xFFu, "shaders OOR");
    166    static_assert(static_cast<uint8_t>(extensionIndex) < 0xFF, "extensionIndex OOR");
    167    return SymbolRule(spec, version, shaders, extensionIndex, value);
    168 }
    169 
    170 const TSymbol *FindMangledBuiltIn(ShShaderSpec shaderSpec,
    171                                  int shaderVersion,
    172                                  sh::GLenum shaderType,
    173                                  const ShBuiltInResources &resources,
    174                                  const TSymbolTableBase &symbolTable,
    175                                  const SymbolRule *rules,
    176                                  uint16_t startIndex,
    177                                  uint16_t endIndex);
    178 
    179 class UnmangledEntry
    180 {
    181  public:
    182    template <size_t ESSLExtCount>
    183    constexpr UnmangledEntry(const char *name,
    184                             const std::array<TExtension, ESSLExtCount> &esslExtensions,
    185                             TExtension glslExtension,
    186                             int esslVersion,
    187                             int glslVersion,
    188                             Shader shaderType);
    189 
    190    bool matches(const ImmutableString &name,
    191                 ShShaderSpec shaderSpec,
    192                 int shaderVersion,
    193                 sh::GLenum shaderType,
    194                 const TExtensionBehavior &extensions) const;
    195 
    196  private:
    197    const char *mName;
    198    std::array<TExtension, 2u> mESSLExtensions;
    199    TExtension mGLSLExtension;
    200    uint8_t mShaderType;
    201    uint16_t mESSLVersion;
    202    uint16_t mGLSLVersion;
    203 };
    204 
    205 template <size_t ESSLExtCount>
    206 constexpr UnmangledEntry::UnmangledEntry(const char *name,
    207                                         const std::array<TExtension, ESSLExtCount> &esslExtensions,
    208                                         TExtension glslExtension,
    209                                         int esslVersion,
    210                                         int glslVersion,
    211                                         Shader shaderType)
    212    : mName(name),
    213      mESSLExtensions{(ESSLExtCount >= 1) ? esslExtensions[0] : TExtension::UNDEFINED,
    214                      (ESSLExtCount >= 2) ? esslExtensions[1] : TExtension::UNDEFINED},
    215      mGLSLExtension(glslExtension),
    216      mShaderType(static_cast<uint8_t>(shaderType)),
    217      mESSLVersion(esslVersion < 0 ? std::numeric_limits<uint16_t>::max()
    218                                   : static_cast<uint16_t>(esslVersion)),
    219      mGLSLVersion(glslVersion < 0 ? std::numeric_limits<uint16_t>::max()
    220                                   : static_cast<uint16_t>(glslVersion))
    221 {}
    222 
    223 class TSymbolTable : angle::NonCopyable, TSymbolTableBase
    224 {
    225  public:
    226    TSymbolTable();
    227    // To start using the symbol table after construction:
    228    // * initializeBuiltIns() needs to be called.
    229    // * push() needs to be called to push the global level.
    230 
    231    ~TSymbolTable();
    232 
    233    bool isEmpty() const;
    234    bool atGlobalLevel() const;
    235 
    236    void push();
    237    void pop();
    238 
    239    // Declare a non-function symbol at the current scope. Return true in case the declaration was
    240    // successful, and false if the declaration failed due to redefinition.
    241    bool declare(TSymbol *symbol);
    242 
    243    // Only used to declare internal variables.
    244    bool declareInternal(TSymbol *symbol);
    245 
    246    // Functions are always declared at global scope.
    247    void declareUserDefinedFunction(TFunction *function, bool insertUnmangledName);
    248 
    249    // These return the TFunction pointer to keep using to refer to this function.
    250    const TFunction *markFunctionHasPrototypeDeclaration(const ImmutableString &mangledName,
    251                                                         bool *hadPrototypeDeclarationOut) const;
    252    const TFunction *setFunctionParameterNamesFromDefinition(const TFunction *function,
    253                                                             bool *wasDefinedOut) const;
    254 
    255    // Return false if the gl_in array size has already been initialized with a mismatching value.
    256    bool setGlInArraySize(unsigned int inputArraySize);
    257    TVariable *getGlInVariableWithArraySize() const;
    258 
    259    const TVariable *gl_FragData() const;
    260    const TVariable *gl_SecondaryFragDataEXT() const;
    261 
    262    void markStaticRead(const TVariable &variable);
    263    void markStaticWrite(const TVariable &variable);
    264 
    265    // Note: Should not call this for constant variables.
    266    bool isStaticallyUsed(const TVariable &variable) const;
    267 
    268    // find() is guaranteed not to retain a reference to the ImmutableString, so an ImmutableString
    269    // with a reference to a short-lived char * is fine to pass here.
    270    const TSymbol *find(const ImmutableString &name, int shaderVersion) const;
    271 
    272    const TSymbol *findUserDefined(const ImmutableString &name) const;
    273 
    274    TFunction *findUserDefinedFunction(const ImmutableString &name) const;
    275 
    276    const TSymbol *findGlobal(const ImmutableString &name) const;
    277    const TSymbol *findGlobalWithConversion(const std::vector<ImmutableString> &names) const;
    278 
    279    const TSymbol *findBuiltIn(const ImmutableString &name, int shaderVersion) const;
    280    const TSymbol *findBuiltInWithConversion(const std::vector<ImmutableString> &names,
    281                                             int shaderVersion) const;
    282 
    283    void setDefaultPrecision(TBasicType type, TPrecision prec);
    284 
    285    // Searches down the precisionStack for a precision qualifier
    286    // for the specified TBasicType
    287    TPrecision getDefaultPrecision(TBasicType type) const;
    288 
    289    // This records invariant varyings declared through "invariant varying_name;".
    290    void addInvariantVarying(const TVariable &variable);
    291 
    292    // If this returns false, the varying could still be invariant if it is set as invariant during
    293    // the varying variable declaration - this piece of information is stored in the variable's
    294    // type, not here.
    295    bool isVaryingInvariant(const TVariable &variable) const;
    296 
    297    void setGlobalInvariant(bool invariant);
    298 
    299    const TSymbolUniqueId nextUniqueId() { return TSymbolUniqueId(this); }
    300 
    301    // Gets the built-in accessible by a shader with the specified version, if any.
    302    bool isUnmangledBuiltInName(const ImmutableString &name,
    303                                int shaderVersion,
    304                                const TExtensionBehavior &extensions) const;
    305 
    306    void initializeBuiltIns(sh::GLenum type,
    307                            ShShaderSpec spec,
    308                            const ShBuiltInResources &resources);
    309    void clearCompilationResults();
    310 
    311    ShShaderSpec getShaderSpec() const { return mShaderSpec; }
    312 
    313  private:
    314    friend class TSymbolUniqueId;
    315 
    316    struct VariableMetadata
    317    {
    318        VariableMetadata();
    319        bool staticRead;
    320        bool staticWrite;
    321        bool invariant;
    322    };
    323 
    324    int nextUniqueIdValue();
    325 
    326    class TSymbolTableLevel;
    327 
    328    void initSamplerDefaultPrecision(TBasicType samplerType);
    329 
    330    void initializeBuiltInVariables(sh::GLenum shaderType,
    331                                    ShShaderSpec spec,
    332                                    const ShBuiltInResources &resources);
    333 
    334    VariableMetadata *getOrCreateVariableMetadata(const TVariable &variable);
    335 
    336    std::vector<std::unique_ptr<TSymbolTableLevel>> mTable;
    337 
    338    // There's one precision stack level for predefined precisions and then one level for each scope
    339    // in table.
    340    typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
    341    std::vector<std::unique_ptr<PrecisionStackLevel>> mPrecisionStack;
    342 
    343    bool mGlobalInvariant;
    344 
    345    int mUniqueIdCounter;
    346 
    347    static const int kLastBuiltInId;
    348 
    349    sh::GLenum mShaderType;
    350    ShShaderSpec mShaderSpec;
    351    ShBuiltInResources mResources;
    352 
    353    // Indexed by unique id. Map instead of vector since the variables are fairly sparse.
    354    std::map<int, VariableMetadata> mVariableMetadata;
    355 
    356    // Store gl_in variable with its array size once the array size can be determined. The array
    357    // size can also be checked against latter input primitive type declaration.
    358    TVariable *mGlInVariableWithArraySize;
    359 };
    360 
    361 }  // namespace sh
    362 
    363 #endif  // COMPILER_TRANSLATOR_SYMBOLTABLE_H_