tor-browser

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

SeparateDeclarations.cpp (7628B)


      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 // The SeparateDeclarations function processes declarations, so that in the end each declaration
      7 // contains only one declarator.
      8 // This is useful as an intermediate step when initialization needs to be separated from
      9 // declaration, or when things need to be unfolded out of the initializer.
     10 // Example:
     11 //     int a[1] = int[1](1), b[1] = int[1](2);
     12 // gets transformed when run through this class into the AST equivalent of:
     13 //     int a[1] = int[1](1);
     14 //     int b[1] = int[1](2);
     15 
     16 #include "compiler/translator/tree_ops/SeparateDeclarations.h"
     17 
     18 #include "compiler/translator/SymbolTable.h"
     19 #include "compiler/translator/tree_util/IntermTraverse.h"
     20 #include "compiler/translator/tree_util/ReplaceVariable.h"
     21 
     22 namespace sh
     23 {
     24 
     25 namespace
     26 {
     27 
     28 class SeparateDeclarationsTraverser : private TIntermTraverser
     29 {
     30  public:
     31    [[nodiscard]] static bool apply(TCompiler *compiler,
     32                                    TIntermNode *root,
     33                                    TSymbolTable *symbolTable);
     34 
     35  private:
     36    SeparateDeclarationsTraverser(TSymbolTable *symbolTable);
     37    bool visitDeclaration(Visit, TIntermDeclaration *node) override;
     38    void visitSymbol(TIntermSymbol *symbol) override;
     39 
     40    void separateDeclarator(TIntermSequence *sequence,
     41                            size_t index,
     42                            TIntermSequence *replacementDeclarations,
     43                            const TStructure **replacementStructure);
     44 
     45    VariableReplacementMap mVariableMap;
     46 };
     47 
     48 bool SeparateDeclarationsTraverser::apply(TCompiler *compiler,
     49                                          TIntermNode *root,
     50                                          TSymbolTable *symbolTable)
     51 {
     52    SeparateDeclarationsTraverser separateDecl(symbolTable);
     53    root->traverse(&separateDecl);
     54    return separateDecl.updateTree(compiler, root);
     55 }
     56 
     57 SeparateDeclarationsTraverser::SeparateDeclarationsTraverser(TSymbolTable *symbolTable)
     58    : TIntermTraverser(true, false, false, symbolTable)
     59 {}
     60 
     61 bool SeparateDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
     62 {
     63    TIntermSequence *sequence = node->getSequence();
     64    if (sequence->size() <= 1)
     65    {
     66        return true;
     67    }
     68 
     69    TIntermBlock *parentBlock = getParentNode()->getAsBlock();
     70    ASSERT(parentBlock != nullptr);
     71 
     72    TIntermSequence replacementDeclarations;
     73    const TStructure *replacementStructure = nullptr;
     74    for (size_t ii = 0; ii < sequence->size(); ++ii)
     75    {
     76        separateDeclarator(sequence, ii, &replacementDeclarations, &replacementStructure);
     77    }
     78 
     79    mMultiReplacements.emplace_back(parentBlock, node, std::move(replacementDeclarations));
     80    return false;
     81 }
     82 
     83 void SeparateDeclarationsTraverser::visitSymbol(TIntermSymbol *symbol)
     84 {
     85    const TVariable *variable = &symbol->variable();
     86    if (mVariableMap.count(variable) > 0)
     87    {
     88        queueAccessChainReplacement(mVariableMap[variable]->deepCopy());
     89    }
     90 }
     91 
     92 void SeparateDeclarationsTraverser::separateDeclarator(TIntermSequence *sequence,
     93                                                       size_t index,
     94                                                       TIntermSequence *replacementDeclarations,
     95                                                       const TStructure **replacementStructure)
     96 {
     97    TIntermTyped *declarator    = sequence->at(index)->getAsTyped();
     98    const TType &declaratorType = declarator->getType();
     99 
    100    // If the declaration is not simultaneously declaring a struct, can use the same declarator.
    101    // Otherwise, the first declarator is taken as-is if the struct has a name.
    102    const TStructure *structure  = declaratorType.getStruct();
    103    const bool isStructSpecifier = declaratorType.isStructSpecifier();
    104    if (!isStructSpecifier || (index == 0 && structure->symbolType() != SymbolType::Empty))
    105    {
    106        TIntermDeclaration *replacementDeclaration = new TIntermDeclaration;
    107 
    108        // Make sure to update the declarator's initializers if any.
    109        declarator->traverse(this);
    110 
    111        replacementDeclaration->appendDeclarator(declarator);
    112        replacementDeclaration->setLine(declarator->getLine());
    113        replacementDeclarations->push_back(replacementDeclaration);
    114        return;
    115    }
    116 
    117    // If the struct is nameless, split it out first.
    118    if (structure->symbolType() == SymbolType::Empty)
    119    {
    120        if (*replacementStructure == nullptr)
    121        {
    122            TStructure *newStructure =
    123                new TStructure(mSymbolTable, kEmptyImmutableString, &structure->fields(),
    124                               SymbolType::AngleInternal);
    125            newStructure->setAtGlobalScope(structure->atGlobalScope());
    126            *replacementStructure = structure = newStructure;
    127 
    128            TType *namedType = new TType(structure, true);
    129            namedType->setQualifier(EvqGlobal);
    130 
    131            TVariable *structVariable =
    132                new TVariable(mSymbolTable, kEmptyImmutableString, namedType, SymbolType::Empty);
    133 
    134            TIntermDeclaration *structDeclaration = new TIntermDeclaration;
    135            structDeclaration->appendDeclarator(new TIntermSymbol(structVariable));
    136            structDeclaration->setLine(declarator->getLine());
    137            replacementDeclarations->push_back(structDeclaration);
    138        }
    139        else
    140        {
    141            structure = *replacementStructure;
    142        }
    143    }
    144 
    145    // Redeclare the declarator but not as a struct specifier.
    146    TIntermSymbol *asSymbol   = declarator->getAsSymbolNode();
    147    TIntermTyped *initializer = nullptr;
    148    if (asSymbol == nullptr)
    149    {
    150        TIntermBinary *asBinary = declarator->getAsBinaryNode();
    151        ASSERT(asBinary->getOp() == EOpInitialize);
    152        asSymbol    = asBinary->getLeft()->getAsSymbolNode();
    153        initializer = asBinary->getRight();
    154 
    155        // Make sure the initializer itself has its variables replaced if necessary.
    156        if (initializer->getAsSymbolNode())
    157        {
    158            const TVariable *initializerVariable = &initializer->getAsSymbolNode()->variable();
    159            if (mVariableMap.count(initializerVariable) > 0)
    160            {
    161                initializer = mVariableMap[initializerVariable]->deepCopy();
    162            }
    163        }
    164        else
    165        {
    166            initializer->traverse(this);
    167        }
    168    }
    169 
    170    ASSERT(asSymbol && asSymbol->variable().symbolType() != SymbolType::Empty);
    171 
    172    TType *newType = new TType(structure, false);
    173    newType->setQualifier(asSymbol->getType().getQualifier());
    174    newType->makeArrays(asSymbol->getType().getArraySizes());
    175 
    176    TVariable *replacementVar        = new TVariable(mSymbolTable, asSymbol->getName(), newType,
    177                                                     asSymbol->variable().symbolType());
    178    TIntermSymbol *replacementSymbol = new TIntermSymbol(replacementVar);
    179    TIntermTyped *replacement        = replacementSymbol;
    180    if (initializer)
    181    {
    182        replacement = new TIntermBinary(EOpInitialize, replacement, initializer);
    183    }
    184 
    185    TIntermDeclaration *replacementDeclaration = new TIntermDeclaration;
    186    replacementDeclaration->appendDeclarator(replacement);
    187    replacementDeclaration->setLine(declarator->getLine());
    188    replacementDeclarations->push_back(replacementDeclaration);
    189 
    190    mVariableMap[&asSymbol->variable()] = replacementSymbol;
    191 }
    192 }  // namespace
    193 
    194 bool SeparateDeclarations(TCompiler *compiler, TIntermNode *root, TSymbolTable *symbolTable)
    195 {
    196    return SeparateDeclarationsTraverser::apply(compiler, root, symbolTable);
    197 }
    198 
    199 }  // namespace sh