1 // 2 // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. 3 // Copyright (C) 2012-2013 LunarG, Inc. 4 // Copyright (C) 2017 ARM Limited. 5 // Copyright (C) 2015-2018 Google, Inc. 6 // 7 // All rights reserved. 8 // 9 // Redistribution and use in source and binary forms, with or without 10 // modification, are permitted provided that the following conditions 11 // are met: 12 // 13 // Redistributions of source code must retain the above copyright 14 // notice, this list of conditions and the following disclaimer. 15 // 16 // Redistributions in binary form must reproduce the above 17 // copyright notice, this list of conditions and the following 18 // disclaimer in the documentation and/or other materials provided 19 // with the distribution. 20 // 21 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its 22 // contributors may be used to endorse or promote products derived 23 // from this software without specific prior written permission. 24 // 25 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 28 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 29 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 30 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 31 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 32 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 33 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 35 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 // POSSIBILITY OF SUCH DAMAGE. 37 // 38 39 // 40 // Symbol table for parsing. Most functionality and main ideas 41 // are documented in the header file. 42 // 43 44 #include "SymbolTable.h" 45 46 namespace glslang { 47 48 // 49 // TType helper function needs a place to live. 50 // 51 52 // 53 // Recursively generate mangled names. 54 // 55 void TType::buildMangledName(TString& mangledName) const 56 { 57 if (isMatrix()) 58 mangledName += 'm'; 59 else if (isVector()) 60 mangledName += 'v'; 61 62 switch (basicType) { 63 case EbtFloat: mangledName += 'f'; break; 64 case EbtDouble: mangledName += 'd'; break; 65 case EbtFloat16: mangledName += "f16"; break; 66 case EbtInt: mangledName += 'i'; break; 67 case EbtUint: mangledName += 'u'; break; 68 case EbtInt8: mangledName += "i8"; break; 69 case EbtUint8: mangledName += "u8"; break; 70 case EbtInt16: mangledName += "i16"; break; 71 case EbtUint16: mangledName += "u16"; break; 72 case EbtInt64: mangledName += "i64"; break; 73 case EbtUint64: mangledName += "u64"; break; 74 case EbtBool: mangledName += 'b'; break; 75 case EbtAtomicUint: mangledName += "au"; break; 76 #ifdef NV_EXTENSIONS 77 case EbtAccStructNV: mangledName += "asnv"; break; 78 #endif 79 case EbtSampler: 80 switch (sampler.type) { 81 #ifdef AMD_EXTENSIONS 82 case EbtFloat16: mangledName += "f16"; break; 83 #endif 84 case EbtInt: mangledName += "i"; break; 85 case EbtUint: mangledName += "u"; break; 86 default: break; // some compilers want this 87 } 88 if (sampler.image) 89 mangledName += "I"; // a normal image 90 else if (sampler.sampler) 91 mangledName += "p"; // a "pure" sampler 92 else if (!sampler.combined) 93 mangledName += "t"; // a "pure" texture 94 else 95 mangledName += "s"; // traditional combined sampler 96 if (sampler.arrayed) 97 mangledName += "A"; 98 if (sampler.shadow) 99 mangledName += "S"; 100 if (sampler.external) 101 mangledName += "E"; 102 switch (sampler.dim) { 103 case Esd1D: mangledName += "1"; break; 104 case Esd2D: mangledName += "2"; break; 105 case Esd3D: mangledName += "3"; break; 106 case EsdCube: mangledName += "C"; break; 107 case EsdRect: mangledName += "R2"; break; 108 case EsdBuffer: mangledName += "B"; break; 109 case EsdSubpass: mangledName += "P"; break; 110 default: break; // some compilers want this 111 } 112 113 if (sampler.hasReturnStruct()) { 114 // Name mangle for sampler return struct uses struct table index. 115 mangledName += "-tx-struct"; 116 117 char text[16]; // plenty enough space for the small integers. 118 snprintf(text, sizeof(text), "%d-", sampler.structReturnIndex); 119 mangledName += text; 120 } else { 121 switch (sampler.getVectorSize()) { 122 case 1: mangledName += "1"; break; 123 case 2: mangledName += "2"; break; 124 case 3: mangledName += "3"; break; 125 case 4: break; // default to prior name mangle behavior 126 } 127 } 128 129 if (sampler.ms) 130 mangledName += "M"; 131 break; 132 case EbtStruct: 133 case EbtBlock: 134 if (basicType == EbtStruct) 135 mangledName += "struct-"; 136 else 137 mangledName += "block-"; 138 if (typeName) 139 mangledName += *typeName; 140 for (unsigned int i = 0; i < structure->size(); ++i) { 141 mangledName += '-'; 142 (*structure)[i].type->buildMangledName(mangledName); 143 } 144 default: 145 break; 146 } 147 148 if (getVectorSize() > 0) 149 mangledName += static_cast<char>('0' + getVectorSize()); 150 else { 151 mangledName += static_cast<char>('0' + getMatrixCols()); 152 mangledName += static_cast<char>('0' + getMatrixRows()); 153 } 154 155 if (arraySizes) { 156 const int maxSize = 11; 157 char buf[maxSize]; 158 for (int i = 0; i < arraySizes->getNumDims(); ++i) { 159 if (arraySizes->getDimNode(i)) { 160 if (arraySizes->getDimNode(i)->getAsSymbolNode()) 161 snprintf(buf, maxSize, "s%d", arraySizes->getDimNode(i)->getAsSymbolNode()->getId()); 162 else 163 snprintf(buf, maxSize, "s%p", arraySizes->getDimNode(i)); 164 } else 165 snprintf(buf, maxSize, "%d", arraySizes->getDimSize(i)); 166 mangledName += '['; 167 mangledName += buf; 168 mangledName += ']'; 169 } 170 } 171 } 172 173 // 174 // Dump functions. 175 // 176 177 void TVariable::dump(TInfoSink& infoSink) const 178 { 179 infoSink.debug << getName().c_str() << ": " << type.getStorageQualifierString() << " " << type.getBasicTypeString(); 180 if (type.isArray()) { 181 infoSink.debug << "[0]"; 182 } 183 infoSink.debug << "\n"; 184 } 185 186 void TFunction::dump(TInfoSink& infoSink) const 187 { 188 infoSink.debug << getName().c_str() << ": " << returnType.getBasicTypeString() << " " << getMangledName().c_str() << "\n"; 189 } 190 191 void TAnonMember::dump(TInfoSink& TInfoSink) const 192 { 193 TInfoSink.debug << "anonymous member " << getMemberNumber() << " of " << getAnonContainer().getName().c_str() << "\n"; 194 } 195 196 void TSymbolTableLevel::dump(TInfoSink &infoSink) const 197 { 198 tLevel::const_iterator it; 199 for (it = level.begin(); it != level.end(); ++it) 200 (*it).second->dump(infoSink); 201 } 202 203 void TSymbolTable::dump(TInfoSink &infoSink) const 204 { 205 for (int level = currentLevel(); level >= 0; --level) { 206 infoSink.debug << "LEVEL " << level << "\n"; 207 table[level]->dump(infoSink); 208 } 209 } 210 211 // 212 // Functions have buried pointers to delete. 213 // 214 TFunction::~TFunction() 215 { 216 for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i) 217 delete (*i).type; 218 } 219 220 // 221 // Symbol table levels are a map of pointers to symbols that have to be deleted. 222 // 223 TSymbolTableLevel::~TSymbolTableLevel() 224 { 225 for (tLevel::iterator it = level.begin(); it != level.end(); ++it) 226 delete (*it).second; 227 228 delete [] defaultPrecision; 229 } 230 231 // 232 // Change all function entries in the table with the non-mangled name 233 // to be related to the provided built-in operation. 234 // 235 void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) 236 { 237 tLevel::const_iterator candidate = level.lower_bound(name); 238 while (candidate != level.end()) { 239 const TString& candidateName = (*candidate).first; 240 TString::size_type parenAt = candidateName.find_first_of('('); 241 if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) { 242 TFunction* function = (*candidate).second->getAsFunction(); 243 function->relateToOperator(op); 244 } else 245 break; 246 ++candidate; 247 } 248 } 249 250 // Make all function overloads of the given name require an extension(s). 251 // Should only be used for a version/profile that actually needs the extension(s). 252 void TSymbolTableLevel::setFunctionExtensions(const char* name, int num, const char* const extensions[]) 253 { 254 tLevel::const_iterator candidate = level.lower_bound(name); 255 while (candidate != level.end()) { 256 const TString& candidateName = (*candidate).first; 257 TString::size_type parenAt = candidateName.find_first_of('('); 258 if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) { 259 TSymbol* symbol = candidate->second; 260 symbol->setExtensions(num, extensions); 261 } else 262 break; 263 ++candidate; 264 } 265 } 266 267 // 268 // Make all symbols in this table level read only. 269 // 270 void TSymbolTableLevel::readOnly() 271 { 272 for (tLevel::iterator it = level.begin(); it != level.end(); ++it) 273 (*it).second->makeReadOnly(); 274 } 275 276 // 277 // Copy a symbol, but the copy is writable; call readOnly() afterward if that's not desired. 278 // 279 TSymbol::TSymbol(const TSymbol& copyOf) 280 { 281 name = NewPoolTString(copyOf.name->c_str()); 282 uniqueId = copyOf.uniqueId; 283 writable = true; 284 } 285 286 TVariable::TVariable(const TVariable& copyOf) : TSymbol(copyOf) 287 { 288 type.deepCopy(copyOf.type); 289 userType = copyOf.userType; 290 numExtensions = 0; 291 extensions = 0; 292 if (copyOf.numExtensions != 0) 293 setExtensions(copyOf.numExtensions, copyOf.extensions); 294 295 if (! copyOf.constArray.empty()) { 296 assert(! copyOf.type.isStruct()); 297 TConstUnionArray newArray(copyOf.constArray, 0, copyOf.constArray.size()); 298 constArray = newArray; 299 } 300 301 // don't support specialization-constant subtrees in cloned tables 302 constSubtree = nullptr; 303 } 304 305 TVariable* TVariable::clone() const 306 { 307 TVariable *variable = new TVariable(*this); 308 309 return variable; 310 } 311 312 TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf) 313 { 314 for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) { 315 TParameter param; 316 parameters.push_back(param); 317 parameters.back().copyParam(copyOf.parameters[i]); 318 } 319 320 numExtensions = 0; 321 extensions = 0; 322 if (copyOf.extensions != 0) 323 setExtensions(copyOf.numExtensions, copyOf.extensions); 324 returnType.deepCopy(copyOf.returnType); 325 mangledName = copyOf.mangledName; 326 op = copyOf.op; 327 defined = copyOf.defined; 328 prototyped = copyOf.prototyped; 329 implicitThis = copyOf.implicitThis; 330 illegalImplicitThis = copyOf.illegalImplicitThis; 331 defaultParamCount = copyOf.defaultParamCount; 332 } 333 334 TFunction* TFunction::clone() const 335 { 336 TFunction *function = new TFunction(*this); 337 338 return function; 339 } 340 341 TAnonMember* TAnonMember::clone() const 342 { 343 // Anonymous members of a given block should be cloned at a higher level, 344 // where they can all be assured to still end up pointing to a single 345 // copy of the original container. 346 assert(0); 347 348 return 0; 349 } 350 351 TSymbolTableLevel* TSymbolTableLevel::clone() const 352 { 353 TSymbolTableLevel *symTableLevel = new TSymbolTableLevel(); 354 symTableLevel->anonId = anonId; 355 symTableLevel->thisLevel = thisLevel; 356 std::vector<bool> containerCopied(anonId, false); 357 tLevel::const_iterator iter; 358 for (iter = level.begin(); iter != level.end(); ++iter) { 359 const TAnonMember* anon = iter->second->getAsAnonMember(); 360 if (anon) { 361 // Insert all the anonymous members of this same container at once, 362 // avoid inserting the other members in the future, once this has been done, 363 // allowing them to all be part of the same new container. 364 if (! containerCopied[anon->getAnonId()]) { 365 TVariable* container = anon->getAnonContainer().clone(); 366 container->changeName(NewPoolTString("")); 367 // insert the whole container 368 symTableLevel->insert(*container, false); 369 containerCopied[anon->getAnonId()] = true; 370 } 371 } else 372 symTableLevel->insert(*iter->second->clone(), false); 373 } 374 375 return symTableLevel; 376 } 377 378 void TSymbolTable::copyTable(const TSymbolTable& copyOf) 379 { 380 assert(adoptedLevels == copyOf.adoptedLevels); 381 382 uniqueId = copyOf.uniqueId; 383 noBuiltInRedeclarations = copyOf.noBuiltInRedeclarations; 384 separateNameSpaces = copyOf.separateNameSpaces; 385 for (unsigned int i = copyOf.adoptedLevels; i < copyOf.table.size(); ++i) 386 table.push_back(copyOf.table[i]->clone()); 387 } 388 389 } // end namespace glslang 390