Edit

kc3-lang/angle/src/compiler/translator/Symbol.cpp

Branch :

  • Show log

    Commit

  • Author : James Dong
    Date : 2019-08-06 11:20:13
    Hash : 1d5aaa6c
    Message : Vulkan: support dynamic indices in array of arrays Expands existing struct-sampler rewrite to flatten arrays of arrays. This allows us to support dynamically-uniform array indexing, which is core in ES 3.2. Samplers inside (possibly nested) structs are broken apart as before, and then if the type resulting from merging the array sizes of the field and its containing structs is an array of array, the array is flattened. Also adds an offset parameter to functions taking in arrays to account for this translation. As a result of outer array sizes leaking into function signatures, functions taking arrays of different sizes are duplicated according to how the function is invoked. Bug: angleproject:3604 Change-Id: Ic9373fd12a38f19bd811eac92e281055a63c1901 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1744177 Commit-Queue: James Dong <dongja@google.com> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>

  • src/compiler/translator/Symbol.cpp
  • //
    // Copyright 2017 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.
    //
    // Symbol.cpp: Symbols representing variables, functions, structures and interface blocks.
    //
    
    #if defined(_MSC_VER)
    #    pragma warning(disable : 4718)
    #endif
    
    #include "compiler/translator/Symbol.h"
    
    #include "compiler/translator/ImmutableStringBuilder.h"
    #include "compiler/translator/SymbolTable.h"
    
    namespace sh
    {
    
    namespace
    {
    
    constexpr const ImmutableString kMainName("main");
    constexpr const ImmutableString kImageLoadName("imageLoad");
    constexpr const ImmutableString kImageStoreName("imageStore");
    constexpr const ImmutableString kImageSizeName("imageSize");
    constexpr const ImmutableString kAtomicCounterName("atomicCounter");
    
    static const char kFunctionMangledNameSeparator = '(';
    
    }  // anonymous namespace
    
    TSymbol::TSymbol(TSymbolTable *symbolTable,
                     const ImmutableString &name,
                     SymbolType symbolType,
                     SymbolClass symbolClass,
                     TExtension extension)
        : mName(name),
          mUniqueId(symbolTable->nextUniqueId()),
          mSymbolType(symbolType),
          mExtension(extension),
          mSymbolClass(symbolClass)
    {
        ASSERT(mSymbolType == SymbolType::BuiltIn || mExtension == TExtension::UNDEFINED);
        ASSERT(mName != "" || mSymbolType == SymbolType::AngleInternal ||
               mSymbolType == SymbolType::Empty);
    }
    
    ImmutableString TSymbol::name() const
    {
        if (!mName.empty())
        {
            return mName;
        }
        // This can be called for nameless function parameters in HLSL.
        ASSERT(mSymbolType == SymbolType::AngleInternal ||
               (mSymbolType == SymbolType::Empty && isVariable()));
        int uniqueId = mUniqueId.get();
        ImmutableStringBuilder symbolNameOut(sizeof(uniqueId) * 2u + 1u);
        symbolNameOut << 's';
        symbolNameOut.appendHex(mUniqueId.get());
        return symbolNameOut;
    }
    
    ImmutableString TSymbol::getMangledName() const
    {
        if (mSymbolClass == SymbolClass::Function)
        {
            // We do this instead of using proper virtual functions so that we can better support
            // constexpr symbols.
            return static_cast<const TFunction *>(this)->getFunctionMangledName();
        }
        ASSERT(mSymbolType != SymbolType::Empty);
        return name();
    }
    
    TVariable::TVariable(TSymbolTable *symbolTable,
                         const ImmutableString &name,
                         const TType *type,
                         SymbolType symbolType,
                         TExtension extension)
        : TSymbol(symbolTable, name, symbolType, SymbolClass::Variable, extension),
          mType(type),
          unionArray(nullptr)
    {
        ASSERT(mType);
        ASSERT(name.empty() || symbolType != SymbolType::Empty);
    }
    
    TStructure::TStructure(TSymbolTable *symbolTable,
                           const ImmutableString &name,
                           const TFieldList *fields,
                           SymbolType symbolType)
        : TSymbol(symbolTable, name, symbolType, SymbolClass::Struct), TFieldListCollection(fields)
    {}
    
    TStructure::TStructure(const TSymbolUniqueId &id,
                           const ImmutableString &name,
                           TExtension extension,
                           const TFieldList *fields)
        : TSymbol(id, name, SymbolType::BuiltIn, extension, SymbolClass::Struct),
          TFieldListCollection(fields)
    {}
    
    void TStructure::createSamplerSymbols(const char *namePrefix,
                                          const TString &apiNamePrefix,
                                          TVector<const TVariable *> *outputSymbols,
                                          TMap<const TVariable *, TString> *outputSymbolsToAPINames,
                                          TSymbolTable *symbolTable) const
    {
        ASSERT(containsSamplers());
        for (const auto *field : *mFields)
        {
            const TType *fieldType = field->type();
            if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
            {
                std::stringstream fieldName = sh::InitializeStream<std::stringstream>();
                fieldName << namePrefix << "_" << field->name();
                TString fieldApiName = apiNamePrefix + ".";
                fieldApiName += field->name().data();
                fieldType->createSamplerSymbols(ImmutableString(fieldName.str()), fieldApiName,
                                                outputSymbols, outputSymbolsToAPINames, symbolTable);
            }
        }
    }
    
    void TStructure::setName(const ImmutableString &name)
    {
        ImmutableString *mutableName = const_cast<ImmutableString *>(&mName);
        *mutableName                 = name;
    }
    
    TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable,
                                     const ImmutableString &name,
                                     const TFieldList *fields,
                                     const TLayoutQualifier &layoutQualifier,
                                     SymbolType symbolType,
                                     TExtension extension)
        : TSymbol(symbolTable, name, symbolType, SymbolClass::InterfaceBlock, extension),
          TFieldListCollection(fields),
          mBlockStorage(layoutQualifier.blockStorage),
          mBinding(layoutQualifier.binding)
    {
        ASSERT(name != nullptr);
    }
    
    TInterfaceBlock::TInterfaceBlock(const TSymbolUniqueId &id,
                                     const ImmutableString &name,
                                     TExtension extension,
                                     const TFieldList *fields)
        : TSymbol(id, name, SymbolType::BuiltIn, extension, SymbolClass::InterfaceBlock),
          TFieldListCollection(fields),
          mBlockStorage(EbsUnspecified),
          mBinding(0)
    {}
    
    TFunction::TFunction(TSymbolTable *symbolTable,
                         const ImmutableString &name,
                         SymbolType symbolType,
                         const TType *retType,
                         bool knownToNotHaveSideEffects)
        : TSymbol(symbolTable, name, symbolType, SymbolClass::Function, TExtension::UNDEFINED),
          mParametersVector(new TParamVector()),
          mParameters(nullptr),
          mParamCount(0u),
          returnType(retType),
          mMangledName(""),
          mOp(EOpNull),
          defined(false),
          mHasPrototypeDeclaration(false),
          mKnownToNotHaveSideEffects(knownToNotHaveSideEffects)
    {
        // Functions with an empty name are not allowed.
        ASSERT(symbolType != SymbolType::Empty);
        ASSERT(name != nullptr || symbolType == SymbolType::AngleInternal);
    }
    
    void TFunction::addParameter(const TVariable *p)
    {
        ASSERT(mParametersVector);
        mParametersVector->push_back(p);
        mParameters  = mParametersVector->data();
        mParamCount  = mParametersVector->size();
        mMangledName = kEmptyImmutableString;
    }
    
    void TFunction::shareParameters(const TFunction &parametersSource)
    {
        mParametersVector = nullptr;
        mParameters       = parametersSource.mParameters;
        mParamCount       = parametersSource.mParamCount;
        ASSERT(parametersSource.name() == name());
        mMangledName = parametersSource.mMangledName;
    }
    
    ImmutableString TFunction::buildMangledName() const
    {
        std::string newName(name().data(), name().length());
        newName += kFunctionMangledNameSeparator;
    
        for (size_t i = 0u; i < mParamCount; ++i)
        {
            newName += mParameters[i]->getType().getMangledName();
        }
        return ImmutableString(newName);
    }
    
    bool TFunction::isMain() const
    {
        return symbolType() == SymbolType::UserDefined && name() == kMainName;
    }
    
    bool TFunction::isImageFunction() const
    {
        return symbolType() == SymbolType::BuiltIn &&
               (name() == kImageSizeName || name() == kImageLoadName || name() == kImageStoreName);
    }
    
    bool TFunction::isAtomicCounterFunction() const
    {
        return SymbolType() == SymbolType::BuiltIn && name().beginsWith(kAtomicCounterName);
    }
    
    bool TFunction::hasSamplerInStructOrArrayParams() const
    {
        for (size_t paramIndex = 0; paramIndex < mParamCount; ++paramIndex)
        {
            const TVariable *param = getParam(paramIndex);
            if (param->getType().isStructureContainingSamplers() ||
                (param->getType().isArray() && param->getType().isSampler()))
            {
                return true;
            }
        }
    
        return false;
    }
    
    bool TFunction::hasSamplerInStructOrArrayOfArrayParams() const
    {
        for (size_t paramIndex = 0; paramIndex < mParamCount; ++paramIndex)
        {
            const TVariable *param = getParam(paramIndex);
            if (param->getType().isStructureContainingSamplers() ||
                (param->getType().isArrayOfArrays() && param->getType().isSampler()))
            {
                return true;
            }
        }
    
        return false;
    }
    }  // namespace sh