Home | History | Annotate | Download | only in MachineIndependent
      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