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