Symbol.cpp (9068B)
1 // 2 // Copyright 2017 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.cpp: Symbols representing variables, functions, structures and interface blocks. 7 // 8 9 #if defined(_MSC_VER) 10 # pragma warning(disable : 4718) 11 #endif 12 13 #include "compiler/translator/Symbol.h" 14 15 #include "compiler/translator/ImmutableStringBuilder.h" 16 #include "compiler/translator/SymbolTable.h" 17 18 namespace sh 19 { 20 21 namespace 22 { 23 24 constexpr const ImmutableString kMainName("main"); 25 constexpr const ImmutableString kImageLoadName("imageLoad"); 26 constexpr const ImmutableString kImageStoreName("imageStore"); 27 constexpr const ImmutableString kImageSizeName("imageSize"); 28 constexpr const ImmutableString kImageAtomicExchangeName("imageAtomicExchange"); 29 constexpr const ImmutableString kAtomicCounterName("atomicCounter"); 30 31 static const char kFunctionMangledNameSeparator = '('; 32 33 } // anonymous namespace 34 35 TSymbol::TSymbol(TSymbolTable *symbolTable, 36 const ImmutableString &name, 37 SymbolType symbolType, 38 SymbolClass symbolClass, 39 TExtension extension) 40 : mName(name), 41 mUniqueId(symbolTable->nextUniqueId()), 42 mExtensions( 43 std::array<TExtension, 3u>{{extension, TExtension::UNDEFINED, TExtension::UNDEFINED}}), 44 mSymbolType(symbolType), 45 mSymbolClass(symbolClass) 46 { 47 ASSERT(mSymbolType == SymbolType::BuiltIn || extension == TExtension::UNDEFINED); 48 ASSERT(mName != "" || mSymbolType == SymbolType::AngleInternal || 49 mSymbolType == SymbolType::Empty); 50 } 51 52 TSymbol::TSymbol(TSymbolTable *symbolTable, 53 const ImmutableString &name, 54 SymbolType symbolType, 55 SymbolClass symbolClass, 56 const std::array<TExtension, 3u> &extensions) 57 : mName(name), 58 mUniqueId(symbolTable->nextUniqueId()), 59 mExtensions(extensions), 60 mSymbolType(symbolType), 61 mSymbolClass(symbolClass) 62 { 63 ASSERT(mSymbolType == SymbolType::BuiltIn || extensions[0] == TExtension::UNDEFINED); 64 ASSERT(mName != "" || mSymbolType == SymbolType::AngleInternal || 65 mSymbolType == SymbolType::Empty); 66 } 67 68 ImmutableString TSymbol::name() const 69 { 70 if (!mName.empty()) 71 { 72 return mName; 73 } 74 // This can be called for nameless function parameters in HLSL. 75 ASSERT(mSymbolType == SymbolType::AngleInternal || 76 (mSymbolType == SymbolType::Empty && isVariable())); 77 int uniqueId = mUniqueId.get(); 78 ImmutableStringBuilder symbolNameOut(sizeof(uniqueId) * 2u + 1u); 79 symbolNameOut << 's'; 80 symbolNameOut.appendHex(mUniqueId.get()); 81 return symbolNameOut; 82 } 83 84 ImmutableString TSymbol::getMangledName() const 85 { 86 if (mSymbolClass == SymbolClass::Function) 87 { 88 // We do this instead of using proper virtual functions so that we can better support 89 // constexpr symbols. 90 return static_cast<const TFunction *>(this)->getFunctionMangledName(); 91 } 92 ASSERT(mSymbolType != SymbolType::Empty); 93 return name(); 94 } 95 96 TVariable::TVariable(TSymbolTable *symbolTable, 97 const ImmutableString &name, 98 const TType *type, 99 SymbolType symbolType, 100 TExtension extension) 101 : TSymbol(symbolTable, name, symbolType, SymbolClass::Variable, extension), 102 mType(type), 103 unionArray(nullptr) 104 { 105 ASSERT(mType); 106 ASSERT(name.empty() || symbolType != SymbolType::Empty); 107 } 108 109 TVariable::TVariable(TSymbolTable *symbolTable, 110 const ImmutableString &name, 111 const TType *type, 112 SymbolType symbolType, 113 const std::array<TExtension, 3u> &extensions) 114 : TSymbol(symbolTable, name, symbolType, SymbolClass::Variable, extensions), 115 mType(type), 116 unionArray(nullptr) 117 { 118 ASSERT(mType); 119 ASSERT(name.empty() || symbolType != SymbolType::Empty); 120 } 121 122 TStructure::TStructure(TSymbolTable *symbolTable, 123 const ImmutableString &name, 124 const TFieldList *fields, 125 SymbolType symbolType) 126 : TSymbol(symbolTable, name, symbolType, SymbolClass::Struct), TFieldListCollection(fields) 127 {} 128 129 void TStructure::createSamplerSymbols(const char *namePrefix, 130 const TString &apiNamePrefix, 131 TVector<const TVariable *> *outputSymbols, 132 TMap<const TVariable *, TString> *outputSymbolsToAPINames, 133 TSymbolTable *symbolTable) const 134 { 135 ASSERT(containsSamplers()); 136 for (const auto *field : *mFields) 137 { 138 const TType *fieldType = field->type(); 139 if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers()) 140 { 141 std::stringstream fieldName = sh::InitializeStream<std::stringstream>(); 142 fieldName << namePrefix << "_" << field->name(); 143 TString fieldApiName = apiNamePrefix + "."; 144 fieldApiName += field->name().data(); 145 fieldType->createSamplerSymbols(ImmutableString(fieldName.str()), fieldApiName, 146 outputSymbols, outputSymbolsToAPINames, symbolTable); 147 } 148 } 149 } 150 151 void TStructure::setName(const ImmutableString &name) 152 { 153 ImmutableString *mutableName = const_cast<ImmutableString *>(&mName); 154 *mutableName = name; 155 } 156 157 TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable, 158 const ImmutableString &name, 159 const TFieldList *fields, 160 const TLayoutQualifier &layoutQualifier, 161 SymbolType symbolType, 162 TExtension extension) 163 : TSymbol(symbolTable, name, symbolType, SymbolClass::InterfaceBlock, extension), 164 TFieldListCollection(fields), 165 mBlockStorage(layoutQualifier.blockStorage), 166 mBinding(layoutQualifier.binding) 167 { 168 ASSERT(name != nullptr); 169 } 170 171 TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable, 172 const ImmutableString &name, 173 const TFieldList *fields, 174 const TLayoutQualifier &layoutQualifier, 175 SymbolType symbolType, 176 const std::array<TExtension, 3u> &extensions) 177 : TSymbol(symbolTable, name, symbolType, SymbolClass::InterfaceBlock, extensions), 178 TFieldListCollection(fields), 179 mBlockStorage(layoutQualifier.blockStorage), 180 mBinding(layoutQualifier.binding) 181 { 182 ASSERT(name != nullptr); 183 } 184 185 TFunction::TFunction(TSymbolTable *symbolTable, 186 const ImmutableString &name, 187 SymbolType symbolType, 188 const TType *retType, 189 bool knownToNotHaveSideEffects) 190 : TSymbol(symbolTable, name, symbolType, SymbolClass::Function, TExtension::UNDEFINED), 191 mParametersVector(new TParamVector()), 192 mParameters(nullptr), 193 returnType(retType), 194 mMangledName(""), 195 mParamCount(0u), 196 mOp(EOpNull), 197 defined(false), 198 mHasPrototypeDeclaration(false), 199 mKnownToNotHaveSideEffects(knownToNotHaveSideEffects), 200 mHasVoidParameter(false) 201 { 202 // Functions with an empty name are not allowed. 203 ASSERT(symbolType != SymbolType::Empty); 204 ASSERT(name != nullptr || symbolType == SymbolType::AngleInternal); 205 } 206 207 void TFunction::addParameter(const TVariable *p) 208 { 209 ASSERT(mParametersVector); 210 mParametersVector->push_back(p); 211 mParameters = mParametersVector->data(); 212 mParamCount = mParametersVector->size(); 213 mMangledName = kEmptyImmutableString; 214 } 215 216 void TFunction::shareParameters(const TFunction ¶metersSource) 217 { 218 mParametersVector = nullptr; 219 mParameters = parametersSource.mParameters; 220 mParamCount = parametersSource.mParamCount; 221 ASSERT(parametersSource.name() == name()); 222 mMangledName = parametersSource.mMangledName; 223 } 224 225 ImmutableString TFunction::buildMangledName() const 226 { 227 ImmutableString name = this->name(); 228 std::string newName(name.data(), name.length()); 229 newName += kFunctionMangledNameSeparator; 230 231 for (size_t i = 0u; i < mParamCount; ++i) 232 { 233 newName += mParameters[i]->getType().getMangledName(); 234 } 235 return ImmutableString(newName); 236 } 237 238 bool TFunction::isMain() const 239 { 240 return symbolType() == SymbolType::UserDefined && name() == kMainName; 241 } 242 243 bool TFunction::isImageFunction() const 244 { 245 return symbolType() == SymbolType::BuiltIn && 246 (name() == kImageSizeName || name() == kImageLoadName || name() == kImageStoreName || 247 name() == kImageAtomicExchangeName); 248 } 249 250 bool TFunction::isAtomicCounterFunction() const 251 { 252 return SymbolType() == SymbolType::BuiltIn && name().beginsWith(kAtomicCounterName); 253 } 254 } // namespace sh