| // | |
| // 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 ¶metersSource) | |
| { | |
| 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 |