tor-browser

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

SymbolTable.cpp (17311B)


      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 // Symbol table for parsing. The design principles and most of the functionality are documented in
      7 // the header file.
      8 //
      9 
     10 #if defined(_MSC_VER)
     11 #    pragma warning(disable : 4718)
     12 #endif
     13 
     14 #include "compiler/translator/SymbolTable.h"
     15 
     16 #include "angle_gl.h"
     17 #include "compiler/translator/ImmutableString.h"
     18 #include "compiler/translator/IntermNode.h"
     19 #include "compiler/translator/StaticType.h"
     20 #include "compiler/translator/util.h"
     21 
     22 namespace sh
     23 {
     24 namespace
     25 {
     26 bool CheckShaderType(Shader expected, GLenum actual)
     27 {
     28    switch (expected)
     29    {
     30        case Shader::ALL:
     31            return true;
     32        case Shader::FRAGMENT:
     33            return actual == GL_FRAGMENT_SHADER;
     34        case Shader::VERTEX:
     35            return actual == GL_VERTEX_SHADER;
     36        case Shader::COMPUTE:
     37            return actual == GL_COMPUTE_SHADER;
     38        case Shader::GEOMETRY:
     39            return actual == GL_GEOMETRY_SHADER;
     40        case Shader::GEOMETRY_EXT:
     41            return actual == GL_GEOMETRY_SHADER_EXT;
     42        case Shader::TESS_CONTROL_EXT:
     43            return actual == GL_TESS_CONTROL_SHADER_EXT;
     44        case Shader::TESS_EVALUATION_EXT:
     45            return actual == GL_TESS_EVALUATION_SHADER_EXT;
     46        case Shader::NOT_COMPUTE:
     47            return actual != GL_COMPUTE_SHADER;
     48        default:
     49            UNREACHABLE();
     50            return false;
     51    }
     52 }
     53 
     54 bool CheckExtension(uint32_t extensionIndex, const ShBuiltInResources &resources)
     55 {
     56    const int *resourcePtr = reinterpret_cast<const int *>(&resources);
     57    return resourcePtr[extensionIndex] > 0;
     58 }
     59 }  // namespace
     60 
     61 class TSymbolTable::TSymbolTableLevel
     62 {
     63  public:
     64    TSymbolTableLevel() = default;
     65 
     66    bool insert(TSymbol *symbol);
     67 
     68    // Insert a function using its unmangled name as the key.
     69    void insertUnmangled(TFunction *function);
     70 
     71    TSymbol *find(const ImmutableString &name) const;
     72 
     73  private:
     74    using tLevel        = TUnorderedMap<ImmutableString,
     75                                 TSymbol *,
     76                                 ImmutableString::FowlerNollVoHash<sizeof(size_t)>>;
     77    using tLevelPair    = const tLevel::value_type;
     78    using tInsertResult = std::pair<tLevel::iterator, bool>;
     79 
     80    tLevel level;
     81 };
     82 
     83 bool TSymbolTable::TSymbolTableLevel::insert(TSymbol *symbol)
     84 {
     85    // returning true means symbol was added to the table
     86    tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
     87    return result.second;
     88 }
     89 
     90 void TSymbolTable::TSymbolTableLevel::insertUnmangled(TFunction *function)
     91 {
     92    level.insert(tLevelPair(function->name(), function));
     93 }
     94 
     95 TSymbol *TSymbolTable::TSymbolTableLevel::find(const ImmutableString &name) const
     96 {
     97    tLevel::const_iterator it = level.find(name);
     98    if (it == level.end())
     99        return nullptr;
    100    else
    101        return (*it).second;
    102 }
    103 
    104 TSymbolTable::TSymbolTable()
    105    : mGlobalInvariant(false),
    106      mUniqueIdCounter(0),
    107      mShaderType(GL_FRAGMENT_SHADER),
    108      mShaderSpec(SH_GLES2_SPEC),
    109      mGlInVariableWithArraySize(nullptr)
    110 {}
    111 
    112 TSymbolTable::~TSymbolTable() = default;
    113 
    114 bool TSymbolTable::isEmpty() const
    115 {
    116    return mTable.empty();
    117 }
    118 
    119 bool TSymbolTable::atGlobalLevel() const
    120 {
    121    return mTable.size() == 1u;
    122 }
    123 
    124 void TSymbolTable::push()
    125 {
    126    mTable.emplace_back(new TSymbolTableLevel);
    127    mPrecisionStack.emplace_back(new PrecisionStackLevel);
    128 }
    129 
    130 void TSymbolTable::pop()
    131 {
    132    mTable.pop_back();
    133    mPrecisionStack.pop_back();
    134 }
    135 
    136 const TFunction *TSymbolTable::markFunctionHasPrototypeDeclaration(
    137    const ImmutableString &mangledName,
    138    bool *hadPrototypeDeclarationOut) const
    139 {
    140    TFunction *function         = findUserDefinedFunction(mangledName);
    141    *hadPrototypeDeclarationOut = function->hasPrototypeDeclaration();
    142    function->setHasPrototypeDeclaration();
    143    return function;
    144 }
    145 
    146 const TFunction *TSymbolTable::setFunctionParameterNamesFromDefinition(const TFunction *function,
    147                                                                       bool *wasDefinedOut) const
    148 {
    149    TFunction *firstDeclaration = findUserDefinedFunction(function->getMangledName());
    150    ASSERT(firstDeclaration);
    151    // Note: 'firstDeclaration' could be 'function' if this is the first time we've seen function as
    152    // it would have just been put in the symbol table. Otherwise, we're looking up an earlier
    153    // occurance.
    154    if (function != firstDeclaration)
    155    {
    156        // The previous declaration should have the same parameters as the function definition
    157        // (parameter names may differ).
    158        firstDeclaration->shareParameters(*function);
    159    }
    160 
    161    *wasDefinedOut = firstDeclaration->isDefined();
    162    firstDeclaration->setDefined();
    163    return firstDeclaration;
    164 }
    165 
    166 bool TSymbolTable::setGlInArraySize(unsigned int inputArraySize)
    167 {
    168    if (mGlInVariableWithArraySize)
    169    {
    170        return mGlInVariableWithArraySize->getType().getOutermostArraySize() == inputArraySize;
    171    }
    172    const TInterfaceBlock *glPerVertex = static_cast<const TInterfaceBlock *>(m_gl_PerVertex);
    173    TType *glInType = new TType(glPerVertex, EvqPerVertexIn, TLayoutQualifier::Create());
    174    glInType->makeArray(inputArraySize);
    175    mGlInVariableWithArraySize =
    176        new TVariable(this, ImmutableString("gl_in"), glInType, SymbolType::BuiltIn,
    177                      TExtension::EXT_geometry_shader);
    178    return true;
    179 }
    180 
    181 TVariable *TSymbolTable::getGlInVariableWithArraySize() const
    182 {
    183    return mGlInVariableWithArraySize;
    184 }
    185 
    186 const TVariable *TSymbolTable::gl_FragData() const
    187 {
    188    return static_cast<const TVariable *>(m_gl_FragData);
    189 }
    190 
    191 const TVariable *TSymbolTable::gl_SecondaryFragDataEXT() const
    192 {
    193    return static_cast<const TVariable *>(m_gl_SecondaryFragDataEXT);
    194 }
    195 
    196 TSymbolTable::VariableMetadata *TSymbolTable::getOrCreateVariableMetadata(const TVariable &variable)
    197 {
    198    int id    = variable.uniqueId().get();
    199    auto iter = mVariableMetadata.find(id);
    200    if (iter == mVariableMetadata.end())
    201    {
    202        iter = mVariableMetadata.insert(std::make_pair(id, VariableMetadata())).first;
    203    }
    204    return &iter->second;
    205 }
    206 
    207 void TSymbolTable::markStaticWrite(const TVariable &variable)
    208 {
    209    auto metadata         = getOrCreateVariableMetadata(variable);
    210    metadata->staticWrite = true;
    211 }
    212 
    213 void TSymbolTable::markStaticRead(const TVariable &variable)
    214 {
    215    auto metadata        = getOrCreateVariableMetadata(variable);
    216    metadata->staticRead = true;
    217 }
    218 
    219 bool TSymbolTable::isStaticallyUsed(const TVariable &variable) const
    220 {
    221    ASSERT(!variable.getConstPointer());
    222    int id    = variable.uniqueId().get();
    223    auto iter = mVariableMetadata.find(id);
    224    return iter != mVariableMetadata.end() && (iter->second.staticRead || iter->second.staticWrite);
    225 }
    226 
    227 void TSymbolTable::addInvariantVarying(const TVariable &variable)
    228 {
    229    ASSERT(atGlobalLevel());
    230    auto metadata       = getOrCreateVariableMetadata(variable);
    231    metadata->invariant = true;
    232 }
    233 
    234 bool TSymbolTable::isVaryingInvariant(const TVariable &variable) const
    235 {
    236    ASSERT(atGlobalLevel());
    237    if (mGlobalInvariant && (IsShaderOutput(variable.getType().getQualifier())))
    238    {
    239        return true;
    240    }
    241    int id    = variable.uniqueId().get();
    242    auto iter = mVariableMetadata.find(id);
    243    return iter != mVariableMetadata.end() && iter->second.invariant;
    244 }
    245 
    246 void TSymbolTable::setGlobalInvariant(bool invariant)
    247 {
    248    ASSERT(atGlobalLevel());
    249    mGlobalInvariant = invariant;
    250 }
    251 
    252 const TSymbol *TSymbolTable::find(const ImmutableString &name, int shaderVersion) const
    253 {
    254    const TSymbol *userSymbol = findUserDefined(name);
    255    if (userSymbol)
    256    {
    257        return userSymbol;
    258    }
    259 
    260    return findBuiltIn(name, shaderVersion);
    261 }
    262 
    263 const TSymbol *TSymbolTable::findUserDefined(const ImmutableString &name) const
    264 {
    265    int userDefinedLevel = static_cast<int>(mTable.size()) - 1;
    266    while (userDefinedLevel >= 0)
    267    {
    268        const TSymbol *symbol = mTable[userDefinedLevel]->find(name);
    269        if (symbol)
    270        {
    271            return symbol;
    272        }
    273        userDefinedLevel--;
    274    }
    275 
    276    return nullptr;
    277 }
    278 
    279 TFunction *TSymbolTable::findUserDefinedFunction(const ImmutableString &name) const
    280 {
    281    // User-defined functions are always declared at the global level.
    282    ASSERT(!mTable.empty());
    283    return static_cast<TFunction *>(mTable[0]->find(name));
    284 }
    285 
    286 const TSymbol *TSymbolTable::findGlobal(const ImmutableString &name) const
    287 {
    288    ASSERT(!mTable.empty());
    289    return mTable[0]->find(name);
    290 }
    291 
    292 const TSymbol *TSymbolTable::findGlobalWithConversion(
    293    const std::vector<ImmutableString> &names) const
    294 {
    295    for (const ImmutableString &name : names)
    296    {
    297        const TSymbol *target = findGlobal(name);
    298        if (target != nullptr)
    299            return target;
    300    }
    301    return nullptr;
    302 }
    303 
    304 const TSymbol *TSymbolTable::findBuiltInWithConversion(const std::vector<ImmutableString> &names,
    305                                                       int shaderVersion) const
    306 {
    307    for (const ImmutableString &name : names)
    308    {
    309        const TSymbol *target = findBuiltIn(name, shaderVersion);
    310        if (target != nullptr)
    311            return target;
    312    }
    313    return nullptr;
    314 }
    315 
    316 bool TSymbolTable::declare(TSymbol *symbol)
    317 {
    318    ASSERT(!mTable.empty());
    319    // The following built-ins may be redeclared by the shader: gl_ClipDistance, gl_CullDistance and
    320    // gl_LastFragData.
    321    ASSERT(symbol->symbolType() == SymbolType::UserDefined ||
    322           (symbol->symbolType() == SymbolType::BuiltIn && IsRedeclarableBuiltIn(symbol->name())));
    323    ASSERT(!symbol->isFunction());
    324    return mTable.back()->insert(symbol);
    325 }
    326 
    327 bool TSymbolTable::declareInternal(TSymbol *symbol)
    328 {
    329    ASSERT(!mTable.empty());
    330    ASSERT(symbol->symbolType() == SymbolType::AngleInternal);
    331    ASSERT(!symbol->isFunction());
    332    return mTable.back()->insert(symbol);
    333 }
    334 
    335 void TSymbolTable::declareUserDefinedFunction(TFunction *function, bool insertUnmangledName)
    336 {
    337    ASSERT(!mTable.empty());
    338    if (insertUnmangledName)
    339    {
    340        // Insert the unmangled name to detect potential future redefinition as a variable.
    341        mTable[0]->insertUnmangled(function);
    342    }
    343    mTable[0]->insert(function);
    344 }
    345 
    346 void TSymbolTable::setDefaultPrecision(TBasicType type, TPrecision prec)
    347 {
    348    int indexOfLastElement = static_cast<int>(mPrecisionStack.size()) - 1;
    349    // Uses map operator [], overwrites the current value
    350    (*mPrecisionStack[indexOfLastElement])[type] = prec;
    351 }
    352 
    353 TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
    354 {
    355    if (!SupportsPrecision(type))
    356        return EbpUndefined;
    357 
    358    // unsigned integers use the same precision as signed
    359    TBasicType baseType = (type == EbtUInt) ? EbtInt : type;
    360 
    361    int level = static_cast<int>(mPrecisionStack.size()) - 1;
    362    ASSERT(level >= 0);  // Just to be safe. Should not happen.
    363    // If we dont find anything we return this. Some types don't have predefined default precision.
    364    TPrecision prec = EbpUndefined;
    365    while (level >= 0)
    366    {
    367        PrecisionStackLevel::iterator it = mPrecisionStack[level]->find(baseType);
    368        if (it != mPrecisionStack[level]->end())
    369        {
    370            prec = (*it).second;
    371            break;
    372        }
    373        level--;
    374    }
    375    return prec;
    376 }
    377 
    378 void TSymbolTable::clearCompilationResults()
    379 {
    380    mGlobalInvariant = false;
    381    mUniqueIdCounter = kLastBuiltInId + 1;
    382    mVariableMetadata.clear();
    383    mGlInVariableWithArraySize = nullptr;
    384 
    385    // User-defined scopes should have already been cleared when the compilation finished.
    386    ASSERT(mTable.empty());
    387 }
    388 
    389 int TSymbolTable::nextUniqueIdValue()
    390 {
    391    ASSERT(mUniqueIdCounter < std::numeric_limits<int>::max());
    392    return ++mUniqueIdCounter;
    393 }
    394 
    395 void TSymbolTable::initializeBuiltIns(sh::GLenum type,
    396                                      ShShaderSpec spec,
    397                                      const ShBuiltInResources &resources)
    398 {
    399    mShaderType = type;
    400    mShaderSpec = spec;
    401    mResources  = resources;
    402 
    403    // We need just one precision stack level for predefined precisions.
    404    mPrecisionStack.emplace_back(new PrecisionStackLevel);
    405 
    406    if (IsDesktopGLSpec(spec))
    407    {
    408        setDefaultPrecision(EbtInt, EbpUndefined);
    409        setDefaultPrecision(EbtFloat, EbpUndefined);
    410    }
    411    else
    412    {
    413        switch (type)
    414        {
    415            case GL_FRAGMENT_SHADER:
    416                setDefaultPrecision(EbtInt, EbpMedium);
    417                break;
    418            case GL_VERTEX_SHADER:
    419            case GL_COMPUTE_SHADER:
    420            case GL_GEOMETRY_SHADER_EXT:
    421            case GL_TESS_CONTROL_SHADER_EXT:
    422            case GL_TESS_EVALUATION_SHADER_EXT:
    423                setDefaultPrecision(EbtInt, EbpHigh);
    424                setDefaultPrecision(EbtFloat, EbpHigh);
    425                break;
    426            default:
    427                UNREACHABLE();
    428        }
    429    }
    430 
    431    // Set defaults for sampler types that have default precision, even those that are
    432    // only available if an extension exists.
    433    // New sampler types in ESSL3 don't have default precision. ESSL1 types do.
    434    initSamplerDefaultPrecision(EbtSampler2D);
    435    initSamplerDefaultPrecision(EbtSamplerCube);
    436    // SamplerExternalOES is specified in the extension to have default precision.
    437    initSamplerDefaultPrecision(EbtSamplerExternalOES);
    438    // SamplerExternal2DY2YEXT is specified in the extension to have default precision.
    439    initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT);
    440    // It isn't specified whether Sampler2DRect has default precision.
    441    initSamplerDefaultPrecision(EbtSampler2DRect);
    442 
    443    if (spec < SH_GLES3_SPEC)
    444    {
    445        // Only set the default precision of shadow samplers in ESLL1. They become core in ESSL3
    446        // where they do not have a defalut precision.
    447        initSamplerDefaultPrecision(EbtSampler2DShadow);
    448    }
    449 
    450    setDefaultPrecision(EbtAtomicCounter, EbpHigh);
    451 
    452    initializeBuiltInVariables(type, spec, resources);
    453    mUniqueIdCounter = kLastBuiltInId + 1;
    454 }
    455 
    456 void TSymbolTable::initSamplerDefaultPrecision(TBasicType samplerType)
    457 {
    458    ASSERT(samplerType >= EbtGuardSamplerBegin && samplerType <= EbtGuardSamplerEnd);
    459    setDefaultPrecision(samplerType, EbpLow);
    460 }
    461 
    462 TSymbolTable::VariableMetadata::VariableMetadata()
    463    : staticRead(false), staticWrite(false), invariant(false)
    464 {}
    465 
    466 const TSymbol *SymbolRule::get(ShShaderSpec shaderSpec,
    467                               int shaderVersion,
    468                               sh::GLenum shaderType,
    469                               const ShBuiltInResources &resources,
    470                               const TSymbolTableBase &symbolTable) const
    471 {
    472    if (IsDesktopGLSpec(shaderSpec) != (mIsDesktop == 1))
    473        return nullptr;
    474 
    475    if (mVersion == kESSL1Only && shaderVersion != static_cast<int>(kESSL1Only))
    476        return nullptr;
    477 
    478    if (mVersion > shaderVersion)
    479        return nullptr;
    480 
    481    if (!CheckShaderType(static_cast<Shader>(mShaders), shaderType))
    482        return nullptr;
    483 
    484    if (mExtensionIndex != 0 && !CheckExtension(mExtensionIndex, resources))
    485        return nullptr;
    486 
    487    return mIsVar > 0 ? symbolTable.*(mSymbolOrVar.var) : mSymbolOrVar.symbol;
    488 }
    489 
    490 const TSymbol *FindMangledBuiltIn(ShShaderSpec shaderSpec,
    491                                  int shaderVersion,
    492                                  sh::GLenum shaderType,
    493                                  const ShBuiltInResources &resources,
    494                                  const TSymbolTableBase &symbolTable,
    495                                  const SymbolRule *rules,
    496                                  uint16_t startIndex,
    497                                  uint16_t endIndex)
    498 {
    499    for (uint32_t ruleIndex = startIndex; ruleIndex < endIndex; ++ruleIndex)
    500    {
    501        const TSymbol *symbol =
    502            rules[ruleIndex].get(shaderSpec, shaderVersion, shaderType, resources, symbolTable);
    503        if (symbol)
    504        {
    505            return symbol;
    506        }
    507    }
    508 
    509    return nullptr;
    510 }
    511 
    512 bool UnmangledEntry::matches(const ImmutableString &name,
    513                             ShShaderSpec shaderSpec,
    514                             int shaderVersion,
    515                             sh::GLenum shaderType,
    516                             const TExtensionBehavior &extensions) const
    517 {
    518    if (name != mName)
    519        return false;
    520 
    521    if (!CheckShaderType(static_cast<Shader>(mShaderType), shaderType))
    522        return false;
    523 
    524    if (IsDesktopGLSpec(shaderSpec))
    525    {
    526        if (mGLSLVersion > shaderVersion)
    527            return false;
    528 
    529        if (mGLSLExtension == TExtension::UNDEFINED)
    530            return true;
    531 
    532        return IsExtensionEnabled(extensions, mGLSLExtension);
    533    }
    534    else
    535    {
    536        if (mESSLVersion == kESSL1Only && shaderVersion != static_cast<int>(kESSL1Only))
    537            return false;
    538 
    539        if (mESSLVersion > shaderVersion)
    540            return false;
    541 
    542        bool anyExtension        = false;
    543        bool anyExtensionEnabled = false;
    544        for (TExtension ext : mESSLExtensions)
    545        {
    546            if (ext != TExtension::UNDEFINED)
    547            {
    548                anyExtension        = true;
    549                anyExtensionEnabled = anyExtensionEnabled || IsExtensionEnabled(extensions, ext);
    550            }
    551        }
    552 
    553        if (!anyExtension)
    554            return true;
    555 
    556        return anyExtensionEnabled;
    557    }
    558 }
    559 }  // namespace sh