Home | History | Annotate | Download | only in MachineIndependent
      1 //
      2 //Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
      3 //Copyright (C) 2013-2016 LunarG, Inc.
      4 //Copyright (C) 2015-2016 Google, Inc.
      5 //
      6 //All rights reserved.
      7 //
      8 //Redistribution and use in source and binary forms, with or without
      9 //modification, are permitted provided that the following conditions
     10 //are met:
     11 //
     12 //    Redistributions of source code must retain the above copyright
     13 //    notice, this list of conditions and the following disclaimer.
     14 //
     15 //    Redistributions in binary form must reproduce the above
     16 //    copyright notice, this list of conditions and the following
     17 //    disclaimer in the documentation and/or other materials provided
     18 //    with the distribution.
     19 //
     20 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
     21 //    contributors may be used to endorse or promote products derived
     22 //    from this software without specific prior written permission.
     23 //
     24 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     25 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     26 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     27 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     28 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     29 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     30 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     31 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     32 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     34 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35 //POSSIBILITY OF SUCH DAMAGE.
     36 //
     37 
     38 //
     39 // Implement the top-level of interface to the compiler/linker,
     40 // as defined in ShaderLang.h
     41 // This is the platform independent interface between an OGL driver
     42 // and the shading language compiler/linker.
     43 //
     44 #include <string.h>
     45 #include <iostream>
     46 #include <sstream>
     47 #include <memory>
     48 #include "SymbolTable.h"
     49 #include "ParseHelper.h"
     50 #include "../../hlsl/hlslParseHelper.h"
     51 #include "../../hlsl/hlslParseables.h"
     52 #include "Scan.h"
     53 #include "ScanContext.h"
     54 
     55 #include "../Include/ShHandle.h"
     56 #include "../../OGLCompilersDLL/InitializeDll.h"
     57 
     58 #include "preprocessor/PpContext.h"
     59 
     60 #define SH_EXPORTING
     61 #include "../Public/ShaderLang.h"
     62 #include "reflection.h"
     63 #include "Initialize.h"
     64 
     65 namespace { // anonymous namespace for file-local functions and symbols
     66 
     67 using namespace glslang;
     68 
     69 // Create a language specific version of parseables.
     70 TBuiltInParseables* CreateBuiltInParseables(TInfoSink& infoSink, EShSource source)
     71 {
     72     switch (source) {
     73     case EShSourceGlsl: return new TBuiltIns();              // GLSL builtIns
     74     case EShSourceHlsl: return new TBuiltInParseablesHlsl(); // HLSL intrinsics
     75 
     76     default:
     77         infoSink.info.message(EPrefixInternalError, "Unable to determine source language");
     78         return nullptr;
     79     }
     80 }
     81 
     82 // Local mapping functions for making arrays of symbol tables....
     83 
     84 const int VersionCount = 15;  // index range in MapVersionToIndex
     85 
     86 int MapVersionToIndex(int version)
     87 {
     88     int index = 0;
     89 
     90     switch (version) {
     91     case 100: index =  0; break;
     92     case 110: index =  1; break;
     93     case 120: index =  2; break;
     94     case 130: index =  3; break;
     95     case 140: index =  4; break;
     96     case 150: index =  5; break;
     97     case 300: index =  6; break;
     98     case 330: index =  7; break;
     99     case 400: index =  8; break;
    100     case 410: index =  9; break;
    101     case 420: index = 10; break;
    102     case 430: index = 11; break;
    103     case 440: index = 12; break;
    104     case 310: index = 13; break;
    105     case 450: index = 14; break;
    106     default:              break;
    107     }
    108 
    109     assert(index < VersionCount);
    110 
    111     return index;
    112 }
    113 
    114 const int SpvVersionCount = 3;  // index range in MapSpvVersionToIndex
    115 
    116 int MapSpvVersionToIndex(const SpvVersion& spvVersion)
    117 {
    118     int index = 0;
    119 
    120     if (spvVersion.openGl > 0)
    121         index = 1;
    122     else if (spvVersion.vulkan > 0)
    123         index = 2;
    124 
    125     assert(index < SpvVersionCount);
    126 
    127     return index;
    128 }
    129 
    130 const int ProfileCount = 4;   // index range in MapProfileToIndex
    131 
    132 int MapProfileToIndex(EProfile profile)
    133 {
    134     int index = 0;
    135 
    136     switch (profile) {
    137     case ENoProfile:            index = 0; break;
    138     case ECoreProfile:          index = 1; break;
    139     case ECompatibilityProfile: index = 2; break;
    140     case EEsProfile:            index = 3; break;
    141     default:                               break;
    142     }
    143 
    144     assert(index < ProfileCount);
    145 
    146     return index;
    147 }
    148 
    149 // only one of these needed for non-ES; ES needs 2 for different precision defaults of built-ins
    150 enum EPrecisionClass {
    151     EPcGeneral,
    152     EPcFragment,
    153     EPcCount
    154 };
    155 
    156 // A process-global symbol table per version per profile for built-ins common
    157 // to multiple stages (languages), and a process-global symbol table per version
    158 // per profile per stage for built-ins unique to each stage.  They will be sparsely
    159 // populated, so they will only be generated as needed.
    160 //
    161 // Each has a different set of built-ins, and we want to preserve that from
    162 // compile to compile.
    163 //
    164 TSymbolTable* CommonSymbolTable[VersionCount][SpvVersionCount][ProfileCount][EPcCount] = {};
    165 TSymbolTable* SharedSymbolTables[VersionCount][SpvVersionCount][ProfileCount][EShLangCount] = {};
    166 
    167 TPoolAllocator* PerProcessGPA = 0;
    168 
    169 //
    170 // Parse and add to the given symbol table the content of the given shader string.
    171 //
    172 bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink,
    173                            TSymbolTable& symbolTable)
    174 {
    175     TIntermediate intermediate(language, version, profile);
    176 
    177     TParseContext parseContext(symbolTable, intermediate, true, version, profile, spvVersion, language, infoSink);
    178     TShader::ForbidInclude includer;
    179     TPpContext ppContext(parseContext, "", includer);
    180     TScanContext scanContext(parseContext);
    181     parseContext.setScanContext(&scanContext);
    182     parseContext.setPpContext(&ppContext);
    183 
    184     //
    185     // Push the symbol table to give it an initial scope.  This
    186     // push should not have a corresponding pop, so that built-ins
    187     // are preserved, and the test for an empty table fails.
    188     //
    189 
    190     symbolTable.push();
    191 
    192     const char* builtInShaders[2];
    193     size_t builtInLengths[2];
    194     builtInShaders[0] = builtIns.c_str();
    195     builtInLengths[0] = builtIns.size();
    196 
    197     if (builtInLengths[0] == 0)
    198         return true;
    199 
    200     TInputScanner input(1, builtInShaders, builtInLengths);
    201     if (! parseContext.parseShaderStrings(ppContext, input) != 0) {
    202         infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
    203         printf("Unable to parse built-ins\n%s\n", infoSink.info.c_str());
    204         printf("%s\n", builtInShaders[0]);
    205 
    206         return false;
    207     }
    208 
    209     return true;
    210 }
    211 
    212 int CommonIndex(EProfile profile, EShLanguage language)
    213 {
    214     return (profile == EEsProfile && language == EShLangFragment) ? EPcFragment : EPcGeneral;
    215 }
    216 
    217 //
    218 // To initialize per-stage shared tables, with the common table already complete.
    219 //
    220 void InitializeStageSymbolTable(TBuiltInParseables& builtInParseables, int version, EProfile profile, const SpvVersion& spvVersion,
    221                                 EShLanguage language, TInfoSink& infoSink, TSymbolTable** commonTable, TSymbolTable** symbolTables)
    222 {
    223     (*symbolTables[language]).adoptLevels(*commonTable[CommonIndex(profile, language)]);
    224     InitializeSymbolTable(builtInParseables.getStageString(language), version, profile, spvVersion, language, infoSink, *symbolTables[language]);
    225     builtInParseables.identifyBuiltIns(version, profile, spvVersion, language, *symbolTables[language]);
    226     if (profile == EEsProfile && version >= 300)
    227         (*symbolTables[language]).setNoBuiltInRedeclarations();
    228     if (version == 110)
    229         (*symbolTables[language]).setSeparateNameSpaces();
    230 }
    231 
    232 //
    233 // Initialize the full set of shareable symbol tables;
    234 // The common (cross-stage) and those shareable per-stage.
    235 //
    236 bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable,  TSymbolTable** symbolTables, int version, EProfile profile, const SpvVersion& spvVersion, EShSource source)
    237 {
    238     std::unique_ptr<TBuiltInParseables> builtInParseables(CreateBuiltInParseables(infoSink, source));
    239 
    240     builtInParseables->initialize(version, profile, spvVersion);
    241 
    242     // do the common tables
    243     InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangVertex, infoSink, *commonTable[EPcGeneral]);
    244     if (profile == EEsProfile)
    245         InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangFragment, infoSink, *commonTable[EPcFragment]);
    246 
    247     // do the per-stage tables
    248 
    249     // always have vertex and fragment
    250     InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangVertex, infoSink, commonTable, symbolTables);
    251     InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangFragment, infoSink, commonTable, symbolTables);
    252 
    253     // check for tessellation
    254     if ((profile != EEsProfile && version >= 150) ||
    255         (profile == EEsProfile && version >= 310)) {
    256         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessControl, infoSink, commonTable, symbolTables);
    257         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessEvaluation, infoSink, commonTable, symbolTables);
    258     }
    259 
    260     // check for geometry
    261     if ((profile != EEsProfile && version >= 150) ||
    262         (profile == EEsProfile && version >= 310))
    263         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, infoSink, commonTable, symbolTables);
    264 
    265     // check for compute
    266     if ((profile != EEsProfile && version >= 420) ||
    267         (profile == EEsProfile && version >= 310))
    268         InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, infoSink, commonTable, symbolTables);
    269 
    270     return true;
    271 }
    272 
    273 bool AddContextSpecificSymbols(const TBuiltInResource* resources, TInfoSink& infoSink, TSymbolTable& symbolTable, int version,
    274                                EProfile profile, const SpvVersion& spvVersion, EShLanguage language, EShSource source)
    275 {
    276     std::unique_ptr<TBuiltInParseables> builtInParseables(CreateBuiltInParseables(infoSink, source));
    277 
    278     builtInParseables->initialize(*resources, version, profile, spvVersion, language);
    279     InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, language, infoSink, symbolTable);
    280     builtInParseables->identifyBuiltIns(version, profile, spvVersion, language, symbolTable, *resources);
    281 
    282     return true;
    283 }
    284 
    285 //
    286 // To do this on the fly, we want to leave the current state of our thread's
    287 // pool allocator intact, so:
    288 //  - Switch to a new pool for parsing the built-ins
    289 //  - Do the parsing, which builds the symbol table, using the new pool
    290 //  - Switch to the process-global pool to save a copy the resulting symbol table
    291 //  - Free up the new pool used to parse the built-ins
    292 //  - Switch back to the original thread's pool
    293 //
    294 // This only gets done the first time any thread needs a particular symbol table
    295 // (lazy evaluation).
    296 //
    297 void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& spvVersion, EShSource source)
    298 {
    299     TInfoSink infoSink;
    300 
    301     // Make sure only one thread tries to do this at a time
    302     glslang::GetGlobalLock();
    303 
    304     // See if it's already been done for this version/profile combination
    305     int versionIndex = MapVersionToIndex(version);
    306     int spvVersionIndex = MapSpvVersionToIndex(spvVersion);
    307     int profileIndex = MapProfileToIndex(profile);
    308     if (CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][EPcGeneral]) {
    309         glslang::ReleaseGlobalLock();
    310 
    311         return;
    312     }
    313 
    314     // Switch to a new pool
    315     TPoolAllocator& previousAllocator = GetThreadPoolAllocator();
    316     TPoolAllocator* builtInPoolAllocator = new TPoolAllocator();
    317     SetThreadPoolAllocator(*builtInPoolAllocator);
    318 
    319     // Dynamically allocate the local symbol tables so we can control when they are deallocated WRT when the pool is popped.
    320     TSymbolTable* commonTable[EPcCount];
    321     TSymbolTable* stageTables[EShLangCount];
    322     for (int precClass = 0; precClass < EPcCount; ++precClass)
    323         commonTable[precClass] = new TSymbolTable;
    324     for (int stage = 0; stage < EShLangCount; ++stage)
    325         stageTables[stage] = new TSymbolTable;
    326 
    327     // Generate the local symbol tables using the new pool
    328     InitializeSymbolTables(infoSink, commonTable, stageTables, version, profile, spvVersion, source);
    329 
    330     // Switch to the process-global pool
    331     SetThreadPoolAllocator(*PerProcessGPA);
    332 
    333     // Copy the local symbol tables from the new pool to the global tables using the process-global pool
    334     for (int precClass = 0; precClass < EPcCount; ++precClass) {
    335         if (! commonTable[precClass]->isEmpty()) {
    336             CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][precClass] = new TSymbolTable;
    337             CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][precClass]->copyTable(*commonTable[precClass]);
    338             CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][precClass]->readOnly();
    339         }
    340     }
    341     for (int stage = 0; stage < EShLangCount; ++stage) {
    342         if (! stageTables[stage]->isEmpty()) {
    343             SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][stage] = new TSymbolTable;
    344             SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][stage]->adoptLevels(*CommonSymbolTable
    345                               [versionIndex][spvVersionIndex][profileIndex][CommonIndex(profile, (EShLanguage)stage)]);
    346             SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][stage]->copyTable(*stageTables[stage]);
    347             SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][stage]->readOnly();
    348         }
    349     }
    350 
    351     // Clean up the local tables before deleting the pool they used.
    352     for (int precClass = 0; precClass < EPcCount; ++precClass)
    353         delete commonTable[precClass];
    354     for (int stage = 0; stage < EShLangCount; ++stage)
    355         delete stageTables[stage];
    356 
    357     delete builtInPoolAllocator;
    358     SetThreadPoolAllocator(previousAllocator);
    359 
    360     glslang::ReleaseGlobalLock();
    361 }
    362 
    363 // Return true if the shader was correctly specified for version/profile/stage.
    364 bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNotFirst, int defaultVersion,
    365                           EShSource source, int& version, EProfile& profile, const SpvVersion& spvVersion)
    366 {
    367     const int FirstProfileVersion = 150;
    368     bool correct = true;
    369 
    370     if (source == EShSourceHlsl) {
    371         version = 450;          // TODO: GLSL parser is still used for builtins.
    372         profile = ECoreProfile; // allow doubles in prototype parsing
    373         return correct;
    374     }
    375 
    376     // Get a good version...
    377     if (version == 0) {
    378         version = defaultVersion;
    379         // infoSink.info.message(EPrefixWarning, "#version: statement missing; use #version on first line of shader");
    380     }
    381 
    382     // Get a good profile...
    383     if (profile == ENoProfile) {
    384         if (version == 300 || version == 310) {
    385             correct = false;
    386             infoSink.info.message(EPrefixError, "#version: versions 300 and 310 require specifying the 'es' profile");
    387             profile = EEsProfile;
    388         } else if (version == 100)
    389             profile = EEsProfile;
    390         else if (version >= FirstProfileVersion)
    391             profile = ECoreProfile;
    392         else
    393             profile = ENoProfile;
    394     } else {
    395         // a profile was provided...
    396         if (version < 150) {
    397             correct = false;
    398             infoSink.info.message(EPrefixError, "#version: versions before 150 do not allow a profile token");
    399             if (version == 100)
    400                 profile = EEsProfile;
    401             else
    402                 profile = ENoProfile;
    403         } else if (version == 300 || version == 310) {
    404             if (profile != EEsProfile) {
    405                 correct = false;
    406                 infoSink.info.message(EPrefixError, "#version: versions 300 and 310 support only the es profile");
    407             }
    408             profile = EEsProfile;
    409         } else {
    410             if (profile == EEsProfile) {
    411                 correct = false;
    412                 infoSink.info.message(EPrefixError, "#version: only version 300 and 310 support the es profile");
    413                 if (version >= FirstProfileVersion)
    414                     profile = ECoreProfile;
    415                 else
    416                     profile = ENoProfile;
    417             }
    418             // else: typical desktop case... e.g., "#version 410 core"
    419         }
    420     }
    421 
    422     // Correct for stage type...
    423     switch (stage) {
    424     case EShLangGeometry:
    425         if ((profile == EEsProfile && version < 310) ||
    426             (profile != EEsProfile && version < 150)) {
    427             correct = false;
    428             infoSink.info.message(EPrefixError, "#version: geometry shaders require es profile with version 310 or non-es profile with version 150 or above");
    429             version = (profile == EEsProfile) ? 310 : 150;
    430             if (profile == EEsProfile || profile == ENoProfile)
    431                 profile = ECoreProfile;
    432         }
    433         break;
    434     case EShLangTessControl:
    435     case EShLangTessEvaluation:
    436         if ((profile == EEsProfile && version < 310) ||
    437             (profile != EEsProfile && version < 150)) {
    438             correct = false;
    439             infoSink.info.message(EPrefixError, "#version: tessellation shaders require es profile with version 310 or non-es profile with version 150 or above");
    440             version = (profile == EEsProfile) ? 310 : 400; // 150 supports the extension, correction is to 400 which does not
    441             if (profile == EEsProfile || profile == ENoProfile)
    442                 profile = ECoreProfile;
    443         }
    444         break;
    445     case EShLangCompute:
    446         if ((profile == EEsProfile && version < 310) ||
    447             (profile != EEsProfile && version < 420)) {
    448             correct = false;
    449             infoSink.info.message(EPrefixError, "#version: compute shaders require es profile with version 310 or above, or non-es profile with version 420 or above");
    450             version = profile == EEsProfile ? 310 : 420;
    451         }
    452         break;
    453     default:
    454         break;
    455     }
    456 
    457     if (profile == EEsProfile && version >= 300 && versionNotFirst) {
    458         correct = false;
    459         infoSink.info.message(EPrefixError, "#version: statement must appear first in es-profile shader; before comments or newlines");
    460     }
    461 
    462     // Check for SPIR-V compatibility
    463     if (spvVersion.spv != 0) {
    464         switch (profile) {
    465         case  EEsProfile:
    466             if (spvVersion.vulkan >= 100 && version < 310) {
    467                 correct = false;
    468                 infoSink.info.message(EPrefixError, "#version: ES shaders for Vulkan SPIR-V require version 310 or higher");
    469                 version = 310;
    470             }
    471             if (spvVersion.openGl >= 100) {
    472                 correct = false;
    473                 infoSink.info.message(EPrefixError, "#version: ES shaders for OpenGL SPIR-V are not supported");
    474                 version = 310;
    475             }
    476             break;
    477         case ECompatibilityProfile:
    478             infoSink.info.message(EPrefixError, "#version: compilation for SPIR-V does not support the compatibility profile");
    479             break;
    480         default:
    481             if (spvVersion.vulkan >= 100 && version < 140) {
    482                 correct = false;
    483                 infoSink.info.message(EPrefixError, "#version: Desktop shaders for Vulkan SPIR-V require version 140 or higher");
    484                 version = 140;
    485             }
    486             if (spvVersion.openGl >= 100 && version < 330) {
    487                 correct = false;
    488                 infoSink.info.message(EPrefixError, "#version: Desktop shaders for OpenGL SPIR-V require version 330 or higher");
    489                 version = 330;
    490             }
    491             break;
    492         }
    493     }
    494 
    495     // A meta check on the condition of the compiler itself...
    496     switch (version) {
    497 
    498     // ES versions
    499     case 100:
    500     case 300:
    501         // versions are complete
    502         break;
    503 
    504     // Desktop versions
    505     case 110:
    506     case 120:
    507     case 130:
    508     case 140:
    509     case 150:
    510     case 330:
    511         // versions are complete
    512         break;
    513 
    514     case 310:
    515     case 400:
    516     case 410:
    517     case 420:
    518     case 430:
    519     case 440:
    520     case 450:
    521         infoSink.info << "Warning, version " << version << " is not yet complete; most version-specific features are present, but some are missing.\n";
    522         break;
    523 
    524     default:
    525         infoSink.info << "Warning, version " << version << " is unknown.\n";
    526         break;
    527 
    528     }
    529 
    530     return correct;
    531 }
    532 
    533 // This is the common setup and cleanup code for PreprocessDeferred and
    534 // CompileDeferred.
    535 // It takes any callable with a signature of
    536 //  bool (TParseContextBase& parseContext, TPpContext& ppContext,
    537 //                  TInputScanner& input, bool versionWillBeError,
    538 //                  TSymbolTable& , TIntermediate& ,
    539 //                  EShOptimizationLevel , EShMessages );
    540 // Which returns false if a failure was detected and true otherwise.
    541 //
    542 template<typename ProcessingContext>
    543 bool ProcessDeferred(
    544     TCompiler* compiler,
    545     const char* const shaderStrings[],
    546     const int numStrings,
    547     const int* inputLengths,
    548     const char* const stringNames[],
    549     const char* customPreamble,
    550     const EShOptimizationLevel optLevel,
    551     const TBuiltInResource* resources,
    552     int defaultVersion,         // use 100 for ES environment, 110 for desktop; this is the GLSL version, not SPIR-V or Vulkan
    553     EProfile defaultProfile,
    554     // set version/profile to defaultVersion/defaultProfile regardless of the #version
    555     // directive in the source code
    556     bool forceDefaultVersionAndProfile,
    557     bool forwardCompatible,     // give errors for use of deprecated features
    558     EShMessages messages,       // warnings/errors/AST; things to print out
    559     TIntermediate& intermediate, // returned tree, etc.
    560     ProcessingContext& processingContext,
    561     bool requireNonempty,
    562     TShader::Includer& includer
    563     )
    564 {
    565     if (! InitThread())
    566         return false;
    567 
    568     // This must be undone (.pop()) by the caller, after it finishes consuming the created tree.
    569     GetThreadPoolAllocator().push();
    570 
    571     if (numStrings == 0)
    572         return true;
    573 
    574     // Move to length-based strings, rather than null-terminated strings.
    575     // Also, add strings to include the preamble and to ensure the shader is not null,
    576     // which lets the grammar accept what was a null (post preprocessing) shader.
    577     //
    578     // Shader will look like
    579     //   string 0:                system preamble
    580     //   string 1:                custom preamble
    581     //   string 2...numStrings+1: user's shader
    582     //   string numStrings+2:     "int;"
    583     const int numPre = 2;
    584     const int numPost = requireNonempty? 1 : 0;
    585     const int numTotal = numPre + numStrings + numPost;
    586     size_t* lengths = new size_t[numTotal];
    587     const char** strings = new const char*[numTotal];
    588     const char** names = new const char*[numTotal];
    589     for (int s = 0; s < numStrings; ++s) {
    590         strings[s + numPre] = shaderStrings[s];
    591         if (inputLengths == 0 || inputLengths[s] < 0)
    592             lengths[s + numPre] = strlen(shaderStrings[s]);
    593         else
    594             lengths[s + numPre] = inputLengths[s];
    595     }
    596     if (stringNames != nullptr) {
    597         for (int s = 0; s < numStrings; ++s)
    598             names[s + numPre] = stringNames[s];
    599     } else {
    600         for (int s = 0; s < numStrings; ++s)
    601             names[s + numPre] = nullptr;
    602     }
    603 
    604     // First, without using the preprocessor or parser, find the #version, so we know what
    605     // symbol tables, processing rules, etc. to set up.  This does not need the extra strings
    606     // outlined above, just the user shader.
    607     int version;
    608     EProfile profile;
    609     glslang::TInputScanner userInput(numStrings, &strings[numPre], &lengths[numPre]);  // no preamble
    610     bool versionNotFirstToken;
    611     bool versionNotFirst = userInput.scanVersion(version, profile, versionNotFirstToken);
    612     bool versionNotFound = version == 0;
    613     if (forceDefaultVersionAndProfile) {
    614         if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound &&
    615             (version != defaultVersion || profile != defaultProfile)) {
    616             compiler->infoSink.info << "Warning, (version, profile) forced to be ("
    617                                     << defaultVersion << ", " << ProfileName(defaultProfile)
    618                                     << "), while in source code it is ("
    619                                     << version << ", " << ProfileName(profile) << ")\n";
    620         }
    621 
    622         if (versionNotFound) {
    623             versionNotFirstToken = false;
    624             versionNotFirst = false;
    625             versionNotFound = false;
    626         }
    627         version = defaultVersion;
    628         profile = defaultProfile;
    629     }
    630     SpvVersion spvVersion;
    631     if (messages & EShMsgSpvRules)
    632         spvVersion.spv = 0x00010000;    // TODO: eventually have this come from the outside
    633     EShSource source = (messages & EShMsgReadHlsl) ? EShSourceHlsl : EShSourceGlsl;
    634     if (messages & EShMsgVulkanRules)
    635         spvVersion.vulkan = 100;     // TODO: eventually have this come from the outside
    636     else if (spvVersion.spv != 0)
    637         spvVersion.openGl = 100;     // TODO: eventually have this come from the outside
    638     bool goodVersion = DeduceVersionProfile(compiler->infoSink, compiler->getLanguage(), versionNotFirst, defaultVersion, source, version, profile, spvVersion);
    639     bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst));
    640     bool warnVersionNotFirst = false;
    641     if (! versionWillBeError && versionNotFirstToken) {
    642         if (messages & EShMsgRelaxedErrors)
    643             warnVersionNotFirst = true;
    644         else
    645             versionWillBeError = true;
    646     }
    647 
    648     intermediate.setSource(source);
    649     intermediate.setVersion(version);
    650     intermediate.setProfile(profile);
    651     intermediate.setSpv(spvVersion);
    652     if (spvVersion.vulkan >= 100)
    653         intermediate.setOriginUpperLeft();
    654     SetupBuiltinSymbolTable(version, profile, spvVersion, source);
    655 
    656     TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)]
    657                                                   [MapSpvVersionToIndex(spvVersion)]
    658                                                   [MapProfileToIndex(profile)]
    659                                                   [compiler->getLanguage()];
    660 
    661     // Dynamically allocate the symbol table so we can control when it is deallocated WRT the pool.
    662     TSymbolTable* symbolTableMemory = new TSymbolTable;
    663     TSymbolTable& symbolTable = *symbolTableMemory;
    664     if (cachedTable)
    665         symbolTable.adoptLevels(*cachedTable);
    666 
    667     // Add built-in symbols that are potentially context dependent;
    668     // they get popped again further down.
    669     AddContextSpecificSymbols(resources, compiler->infoSink, symbolTable, version, profile, spvVersion,
    670                               compiler->getLanguage(), source);
    671 
    672     //
    673     // Now we can process the full shader under proper symbols and rules.
    674     //
    675 
    676     TParseContextBase* parseContext;
    677     if (source == EShSourceHlsl) {
    678         parseContext = new HlslParseContext(symbolTable, intermediate, false, version, profile, spvVersion,
    679                                              compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages);
    680     }
    681     else {
    682         intermediate.setEntryPoint("main");
    683         parseContext = new TParseContext(symbolTable, intermediate, false, version, profile, spvVersion,
    684                                          compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages);
    685     }
    686     TPpContext ppContext(*parseContext, names[numPre]? names[numPre]: "", includer);
    687 
    688     // only GLSL (bison triggered, really) needs an externally set scan context
    689     glslang::TScanContext scanContext(*parseContext);
    690     if ((messages & EShMsgReadHlsl) == 0)
    691         parseContext->setScanContext(&scanContext);
    692 
    693     parseContext->setPpContext(&ppContext);
    694     parseContext->setLimits(*resources);
    695     if (! goodVersion)
    696         parseContext->addError();
    697     if (warnVersionNotFirst) {
    698         TSourceLoc loc;
    699         loc.init();
    700         parseContext->warn(loc, "Illegal to have non-comment, non-whitespace tokens before #version", "#version", "");
    701     }
    702 
    703     parseContext->initializeExtensionBehavior();
    704 
    705     // Fill in the strings as outlined above.
    706     std::string preamble;
    707     parseContext->getPreamble(preamble);
    708     strings[0] = preamble.c_str();
    709     lengths[0] = strlen(strings[0]);
    710     names[0] = nullptr;
    711     strings[1] = customPreamble;
    712     lengths[1] = strlen(strings[1]);
    713     names[1] = nullptr;
    714     assert(2 == numPre);
    715     if (requireNonempty) {
    716         const int postIndex = numStrings + numPre;
    717         strings[postIndex] = "\n int;";
    718         lengths[postIndex] = strlen(strings[numStrings + numPre]);
    719         names[postIndex] = nullptr;
    720     }
    721     TInputScanner fullInput(numStrings + numPre + numPost, strings, lengths, names, numPre, numPost);
    722 
    723     // Push a new symbol allocation scope that will get used for the shader's globals.
    724     symbolTable.push();
    725 
    726     bool success = processingContext(*parseContext, ppContext, fullInput,
    727                                      versionWillBeError, symbolTable,
    728                                      intermediate, optLevel, messages);
    729 
    730     // Clean up the symbol table. The AST is self-sufficient now.
    731     delete symbolTableMemory;
    732 
    733     delete parseContext;
    734     delete [] lengths;
    735     delete [] strings;
    736     delete [] names;
    737 
    738     return success;
    739 }
    740 
    741 // Responsible for keeping track of the most recent source string and line in
    742 // the preprocessor and outputting newlines appropriately if the source string
    743 // or line changes.
    744 class SourceLineSynchronizer {
    745 public:
    746     SourceLineSynchronizer(const std::function<int()>& lastSourceIndex,
    747                            std::stringstream* output)
    748       : getLastSourceIndex(lastSourceIndex), output(output), lastSource(-1), lastLine(0) {}
    749 //    SourceLineSynchronizer(const SourceLineSynchronizer&) = delete;
    750 //    SourceLineSynchronizer& operator=(const SourceLineSynchronizer&) = delete;
    751 
    752     // Sets the internally tracked source string index to that of the most
    753     // recently read token. If we switched to a new source string, returns
    754     // true and inserts a newline. Otherwise, returns false and outputs nothing.
    755     bool syncToMostRecentString() {
    756         if (getLastSourceIndex() != lastSource) {
    757             // After switching to a new source string, we need to reset lastLine
    758             // because line number resets every time a new source string is
    759             // used. We also need to output a newline to separate the output
    760             // from the previous source string (if there is one).
    761             if (lastSource != -1 || lastLine != 0)
    762                 *output << std::endl;
    763             lastSource = getLastSourceIndex();
    764             lastLine = -1;
    765             return true;
    766         }
    767         return false;
    768     }
    769 
    770     // Calls syncToMostRecentString() and then sets the internally tracked line
    771     // number to tokenLine. If we switched to a new line, returns true and inserts
    772     // newlines appropriately. Otherwise, returns false and outputs nothing.
    773     bool syncToLine(int tokenLine) {
    774         syncToMostRecentString();
    775         const bool newLineStarted = lastLine < tokenLine;
    776         for (; lastLine < tokenLine; ++lastLine) {
    777             if (lastLine > 0) *output << std::endl;
    778         }
    779         return newLineStarted;
    780     }
    781 
    782     // Sets the internally tracked line number to newLineNum.
    783     void setLineNum(int newLineNum) { lastLine = newLineNum; }
    784 
    785 private:
    786     SourceLineSynchronizer& operator=(const SourceLineSynchronizer&);
    787 
    788     // A function for getting the index of the last valid source string we've
    789     // read tokens from.
    790     const std::function<int()> getLastSourceIndex;
    791     // output stream for newlines.
    792     std::stringstream* output;
    793     // lastSource is the source string index (starting from 0) of the last token
    794     // processed. It is tracked in order for newlines to be inserted when a new
    795     // source string starts. -1 means we haven't started processing any source
    796     // string.
    797     int lastSource;
    798     // lastLine is the line number (starting from 1) of the last token processed.
    799     // It is tracked in order for newlines to be inserted when a token appears
    800     // on a new line. 0 means we haven't started processing any line in the
    801     // current source string.
    802     int lastLine;
    803 };
    804 
    805 // DoPreprocessing is a valid ProcessingContext template argument,
    806 // which only performs the preprocessing step of compilation.
    807 // It places the result in the "string" argument to its constructor.
    808 struct DoPreprocessing {
    809     explicit DoPreprocessing(std::string* string): outputString(string) {}
    810     bool operator()(TParseContextBase& parseContext, TPpContext& ppContext,
    811                     TInputScanner& input, bool versionWillBeError,
    812                     TSymbolTable&, TIntermediate&,
    813                     EShOptimizationLevel, EShMessages)
    814     {
    815         // This is a list of tokens that do not require a space before or after.
    816         static const std::string unNeededSpaceTokens = ";()[]";
    817         static const std::string noSpaceBeforeTokens = ",";
    818         glslang::TPpToken token;
    819 
    820         parseContext.setScanner(&input);
    821         ppContext.setInput(input, versionWillBeError);
    822 
    823         std::stringstream outputStream;
    824         SourceLineSynchronizer lineSync(
    825             std::bind(&TInputScanner::getLastValidSourceIndex, &input), &outputStream);
    826 
    827         parseContext.setExtensionCallback([&lineSync, &outputStream](
    828             int line, const char* extension, const char* behavior) {
    829                 lineSync.syncToLine(line);
    830                 outputStream << "#extension " << extension << " : " << behavior;
    831         });
    832 
    833         parseContext.setLineCallback([&lineSync, &outputStream, &parseContext](
    834             int curLineNum, int newLineNum, bool hasSource, int sourceNum, const char* sourceName) {
    835             // SourceNum is the number of the source-string that is being parsed.
    836             lineSync.syncToLine(curLineNum);
    837             outputStream << "#line " << newLineNum;
    838             if (hasSource) {
    839                 outputStream << " ";
    840                 if (sourceName != nullptr) {
    841                     outputStream << "\"" << sourceName << "\"";
    842                 } else {
    843                     outputStream << sourceNum;
    844                 }
    845             }
    846             if (parseContext.lineDirectiveShouldSetNextLine()) {
    847                 // newLineNum is the new line number for the line following the #line
    848                 // directive. So the new line number for the current line is
    849                 newLineNum -= 1;
    850             }
    851             outputStream << std::endl;
    852             // And we are at the next line of the #line directive now.
    853             lineSync.setLineNum(newLineNum + 1);
    854         });
    855 
    856         parseContext.setVersionCallback(
    857             [&lineSync, &outputStream](int line, int version, const char* str) {
    858                 lineSync.syncToLine(line);
    859                 outputStream << "#version " << version;
    860                 if (str) {
    861                     outputStream << " " << str;
    862                 }
    863             });
    864 
    865         parseContext.setPragmaCallback([&lineSync, &outputStream](
    866             int line, const glslang::TVector<glslang::TString>& ops) {
    867                 lineSync.syncToLine(line);
    868                 outputStream << "#pragma ";
    869                 for(size_t i = 0; i < ops.size(); ++i) {
    870                     outputStream << ops[i];
    871                 }
    872         });
    873 
    874         parseContext.setErrorCallback([&lineSync, &outputStream](
    875             int line, const char* errorMessage) {
    876                 lineSync.syncToLine(line);
    877                 outputStream << "#error " << errorMessage;
    878         });
    879 
    880         int lastToken = EndOfInput; // lastToken records the last token processed.
    881         while (const char* tok = ppContext.tokenize(&token)) {
    882             bool isNewString = lineSync.syncToMostRecentString();
    883             bool isNewLine = lineSync.syncToLine(token.loc.line);
    884 
    885             if (isNewLine) {
    886                 // Don't emit whitespace onto empty lines.
    887                 // Copy any whitespace characters at the start of a line
    888                 // from the input to the output.
    889                 outputStream << std::string(token.loc.column - 1, ' ');
    890             }
    891 
    892             // Output a space in between tokens, but not at the start of a line,
    893             // and also not around special tokens. This helps with readability
    894             // and consistency.
    895             if (!isNewString && !isNewLine && lastToken != EndOfInput &&
    896                 (unNeededSpaceTokens.find((char)token.token) == std::string::npos) &&
    897                 (unNeededSpaceTokens.find((char)lastToken) == std::string::npos) &&
    898                 (noSpaceBeforeTokens.find((char)token.token) == std::string::npos)) {
    899                 outputStream << " ";
    900             }
    901             lastToken = token.token;
    902             outputStream << tok;
    903         }
    904         outputStream << std::endl;
    905         *outputString = outputStream.str();
    906 
    907         bool success = true;
    908         if (parseContext.getNumErrors() > 0) {
    909             success = false;
    910             parseContext.infoSink.info.prefix(EPrefixError);
    911             parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors.  No code generated.\n\n";
    912         }
    913         return success;
    914     }
    915     std::string* outputString;
    916 };
    917 
    918 // DoFullParse is a valid ProcessingConext template argument for fully
    919 // parsing the shader.  It populates the "intermediate" with the AST.
    920 struct DoFullParse{
    921   bool operator()(TParseContextBase& parseContext, TPpContext& ppContext,
    922                   TInputScanner& fullInput, bool versionWillBeError,
    923                   TSymbolTable& symbolTable, TIntermediate& intermediate,
    924                   EShOptimizationLevel optLevel, EShMessages messages)
    925     {
    926         bool success = true;
    927         // Parse the full shader.
    928         if (! parseContext.parseShaderStrings(ppContext, fullInput, versionWillBeError))
    929             success = false;
    930         intermediate.addSymbolLinkageNodes(parseContext.getLinkage(), parseContext.getLanguage(), symbolTable);
    931 
    932         if (success && intermediate.getTreeRoot()) {
    933             if (optLevel == EShOptNoGeneration)
    934                 parseContext.infoSink.info.message(EPrefixNone, "No errors.  No code generation or linking was requested.");
    935             else
    936                 success = intermediate.postProcess(intermediate.getTreeRoot(), parseContext.getLanguage());
    937         } else if (! success) {
    938             parseContext.infoSink.info.prefix(EPrefixError);
    939             parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors.  No code generated.\n\n";
    940         }
    941 
    942         if (messages & EShMsgAST)
    943             intermediate.output(parseContext.infoSink, true);
    944 
    945         return success;
    946     }
    947 };
    948 
    949 // Take a single compilation unit, and run the preprocessor on it.
    950 // Return: True if there were no issues found in preprocessing,
    951 //         False if during preprocessing any unknown version, pragmas or
    952 //         extensions were found.
    953 bool PreprocessDeferred(
    954     TCompiler* compiler,
    955     const char* const shaderStrings[],
    956     const int numStrings,
    957     const int* inputLengths,
    958     const char* const stringNames[],
    959     const char* preamble,
    960     const EShOptimizationLevel optLevel,
    961     const TBuiltInResource* resources,
    962     int defaultVersion,         // use 100 for ES environment, 110 for desktop
    963     EProfile defaultProfile,
    964     bool forceDefaultVersionAndProfile,
    965     bool forwardCompatible,     // give errors for use of deprecated features
    966     EShMessages messages,       // warnings/errors/AST; things to print out
    967     TShader::Includer& includer,
    968     TIntermediate& intermediate, // returned tree, etc.
    969     std::string* outputString)
    970 {
    971     DoPreprocessing parser(outputString);
    972     return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
    973                            preamble, optLevel, resources, defaultVersion,
    974                            defaultProfile, forceDefaultVersionAndProfile,
    975                            forwardCompatible, messages, intermediate, parser,
    976                            false, includer);
    977 }
    978 
    979 
    980 //
    981 // do a partial compile on the given strings for a single compilation unit
    982 // for a potential deferred link into a single stage (and deferred full compile of that
    983 // stage through machine-dependent compilation).
    984 //
    985 // all preprocessing, parsing, semantic checks, etc. for a single compilation unit
    986 // are done here.
    987 //
    988 // return:  the tree and other information is filled into the intermediate argument,
    989 //          and true is returned by the function for success.
    990 //
    991 bool CompileDeferred(
    992     TCompiler* compiler,
    993     const char* const shaderStrings[],
    994     const int numStrings,
    995     const int* inputLengths,
    996     const char* const stringNames[],
    997     const char* preamble,
    998     const EShOptimizationLevel optLevel,
    999     const TBuiltInResource* resources,
   1000     int defaultVersion,         // use 100 for ES environment, 110 for desktop
   1001     EProfile defaultProfile,
   1002     bool forceDefaultVersionAndProfile,
   1003     bool forwardCompatible,     // give errors for use of deprecated features
   1004     EShMessages messages,       // warnings/errors/AST; things to print out
   1005     TIntermediate& intermediate,// returned tree, etc.
   1006     TShader::Includer& includer)
   1007 {
   1008     DoFullParse parser;
   1009     return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
   1010                            preamble, optLevel, resources, defaultVersion,
   1011                            defaultProfile, forceDefaultVersionAndProfile,
   1012                            forwardCompatible, messages, intermediate, parser,
   1013                            true, includer);
   1014 }
   1015 
   1016 } // end anonymous namespace for local functions
   1017 
   1018 
   1019 //
   1020 // ShInitialize() should be called exactly once per process, not per thread.
   1021 //
   1022 int ShInitialize()
   1023 {
   1024     glslang::InitGlobalLock();
   1025 
   1026     if (! InitProcess())
   1027         return 0;
   1028 
   1029     if (! PerProcessGPA)
   1030         PerProcessGPA = new TPoolAllocator();
   1031 
   1032     glslang::TScanContext::fillInKeywordMap();
   1033 
   1034     return 1;
   1035 }
   1036 
   1037 //
   1038 // Driver calls these to create and destroy compiler/linker
   1039 // objects.
   1040 //
   1041 
   1042 ShHandle ShConstructCompiler(const EShLanguage language, int debugOptions)
   1043 {
   1044     if (!InitThread())
   1045         return 0;
   1046 
   1047     TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(language, debugOptions));
   1048 
   1049     return reinterpret_cast<void*>(base);
   1050 }
   1051 
   1052 ShHandle ShConstructLinker(const EShExecutable executable, int debugOptions)
   1053 {
   1054     if (!InitThread())
   1055         return 0;
   1056 
   1057     TShHandleBase* base = static_cast<TShHandleBase*>(ConstructLinker(executable, debugOptions));
   1058 
   1059     return reinterpret_cast<void*>(base);
   1060 }
   1061 
   1062 ShHandle ShConstructUniformMap()
   1063 {
   1064     if (!InitThread())
   1065         return 0;
   1066 
   1067     TShHandleBase* base = static_cast<TShHandleBase*>(ConstructUniformMap());
   1068 
   1069     return reinterpret_cast<void*>(base);
   1070 }
   1071 
   1072 void ShDestruct(ShHandle handle)
   1073 {
   1074     if (handle == 0)
   1075         return;
   1076 
   1077     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
   1078 
   1079     if (base->getAsCompiler())
   1080         DeleteCompiler(base->getAsCompiler());
   1081     else if (base->getAsLinker())
   1082         DeleteLinker(base->getAsLinker());
   1083     else if (base->getAsUniformMap())
   1084         DeleteUniformMap(base->getAsUniformMap());
   1085 }
   1086 
   1087 //
   1088 // Cleanup symbol tables
   1089 //
   1090 int __fastcall ShFinalize()
   1091 {
   1092     for (int version = 0; version < VersionCount; ++version) {
   1093         for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) {
   1094             for (int p = 0; p < ProfileCount; ++p) {
   1095                 for (int lang = 0; lang < EShLangCount; ++lang) {
   1096                     delete SharedSymbolTables[version][spvVersion][p][lang];
   1097                     SharedSymbolTables[version][spvVersion][p][lang] = 0;
   1098                 }
   1099             }
   1100         }
   1101     }
   1102 
   1103     for (int version = 0; version < VersionCount; ++version) {
   1104         for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) {
   1105             for (int p = 0; p < ProfileCount; ++p) {
   1106                 for (int pc = 0; pc < EPcCount; ++pc) {
   1107                     delete CommonSymbolTable[version][spvVersion][p][pc];
   1108                     CommonSymbolTable[version][spvVersion][p][pc] = 0;
   1109                 }
   1110             }
   1111         }
   1112     }
   1113 
   1114     if (PerProcessGPA) {
   1115         PerProcessGPA->popAll();
   1116         delete PerProcessGPA;
   1117         PerProcessGPA = 0;
   1118     }
   1119 
   1120     glslang::TScanContext::deleteKeywordMap();
   1121 
   1122     return 1;
   1123 }
   1124 
   1125 //
   1126 // Do a full compile on the given strings for a single compilation unit
   1127 // forming a complete stage.  The result of the machine dependent compilation
   1128 // is left in the provided compile object.
   1129 //
   1130 // Return:  The return value is really boolean, indicating
   1131 // success (1) or failure (0).
   1132 //
   1133 int ShCompile(
   1134     const ShHandle handle,
   1135     const char* const shaderStrings[],
   1136     const int numStrings,
   1137     const int* inputLengths,
   1138     const EShOptimizationLevel optLevel,
   1139     const TBuiltInResource* resources,
   1140     int /*debugOptions*/,
   1141     int defaultVersion,        // use 100 for ES environment, 110 for desktop
   1142     bool forwardCompatible,    // give errors for use of deprecated features
   1143     EShMessages messages       // warnings/errors/AST; things to print out
   1144     )
   1145 {
   1146     // Map the generic handle to the C++ object
   1147     if (handle == 0)
   1148         return 0;
   1149 
   1150     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
   1151     TCompiler* compiler = base->getAsCompiler();
   1152     if (compiler == 0)
   1153         return 0;
   1154 
   1155     compiler->infoSink.info.erase();
   1156     compiler->infoSink.debug.erase();
   1157 
   1158     TIntermediate intermediate(compiler->getLanguage());
   1159     TShader::ForbidInclude includer;
   1160     bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr,
   1161                                    "", optLevel, resources, defaultVersion, ENoProfile, false,
   1162                                    forwardCompatible, messages, intermediate, includer);
   1163 
   1164     //
   1165     // Call the machine dependent compiler
   1166     //
   1167     if (success && intermediate.getTreeRoot() && optLevel != EShOptNoGeneration)
   1168         success = compiler->compile(intermediate.getTreeRoot(), intermediate.getVersion(), intermediate.getProfile());
   1169 
   1170     intermediate.removeTree();
   1171 
   1172     // Throw away all the temporary memory used by the compilation process.
   1173     // The push was done in the CompileDeferred() call above.
   1174     GetThreadPoolAllocator().pop();
   1175 
   1176     return success ? 1 : 0;
   1177 }
   1178 
   1179 //
   1180 // Link the given compile objects.
   1181 //
   1182 // Return:  The return value of is really boolean, indicating
   1183 // success or failure.
   1184 //
   1185 int ShLinkExt(
   1186     const ShHandle linkHandle,
   1187     const ShHandle compHandles[],
   1188     const int numHandles)
   1189 {
   1190     if (linkHandle == 0 || numHandles == 0)
   1191         return 0;
   1192 
   1193     THandleList cObjects;
   1194 
   1195     for (int i = 0; i < numHandles; ++i) {
   1196         if (compHandles[i] == 0)
   1197             return 0;
   1198         TShHandleBase* base = reinterpret_cast<TShHandleBase*>(compHandles[i]);
   1199         if (base->getAsLinker()) {
   1200             cObjects.push_back(base->getAsLinker());
   1201         }
   1202         if (base->getAsCompiler())
   1203             cObjects.push_back(base->getAsCompiler());
   1204 
   1205 
   1206         if (cObjects[i] == 0)
   1207             return 0;
   1208     }
   1209 
   1210     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(linkHandle);
   1211     TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
   1212 
   1213     if (linker == 0)
   1214         return 0;
   1215 
   1216     linker->infoSink.info.erase();
   1217 
   1218     for (int i = 0; i < numHandles; ++i) {
   1219         if (cObjects[i]->getAsCompiler()) {
   1220             if (! cObjects[i]->getAsCompiler()->linkable()) {
   1221                 linker->infoSink.info.message(EPrefixError, "Not all shaders have valid object code.");
   1222                 return 0;
   1223             }
   1224         }
   1225     }
   1226 
   1227     bool ret = linker->link(cObjects);
   1228 
   1229     return ret ? 1 : 0;
   1230 }
   1231 
   1232 //
   1233 // ShSetEncrpytionMethod is a place-holder for specifying
   1234 // how source code is encrypted.
   1235 //
   1236 void ShSetEncryptionMethod(ShHandle handle)
   1237 {
   1238     if (handle == 0)
   1239         return;
   1240 }
   1241 
   1242 //
   1243 // Return any compiler/linker/uniformmap log of messages for the application.
   1244 //
   1245 const char* ShGetInfoLog(const ShHandle handle)
   1246 {
   1247     if (!InitThread())
   1248         return 0;
   1249 
   1250     if (handle == 0)
   1251         return 0;
   1252 
   1253     TShHandleBase* base = static_cast<TShHandleBase*>(handle);
   1254     TInfoSink* infoSink;
   1255 
   1256     if (base->getAsCompiler())
   1257         infoSink = &(base->getAsCompiler()->getInfoSink());
   1258     else if (base->getAsLinker())
   1259         infoSink = &(base->getAsLinker()->getInfoSink());
   1260     else
   1261         return 0;
   1262 
   1263     infoSink->info << infoSink->debug.c_str();
   1264     return infoSink->info.c_str();
   1265 }
   1266 
   1267 //
   1268 // Return the resulting binary code from the link process.  Structure
   1269 // is machine dependent.
   1270 //
   1271 const void* ShGetExecutable(const ShHandle handle)
   1272 {
   1273     if (!InitThread())
   1274         return 0;
   1275 
   1276     if (handle == 0)
   1277         return 0;
   1278 
   1279     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
   1280 
   1281     TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
   1282     if (linker == 0)
   1283         return 0;
   1284 
   1285     return linker->getObjectCode();
   1286 }
   1287 
   1288 //
   1289 // Let the linker know where the application said it's attributes are bound.
   1290 // The linker does not use these values, they are remapped by the ICD or
   1291 // hardware.  It just needs them to know what's aliased.
   1292 //
   1293 // Return:  The return value of is really boolean, indicating
   1294 // success or failure.
   1295 //
   1296 int ShSetVirtualAttributeBindings(const ShHandle handle, const ShBindingTable* table)
   1297 {
   1298     if (!InitThread())
   1299         return 0;
   1300 
   1301     if (handle == 0)
   1302         return 0;
   1303 
   1304     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
   1305     TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
   1306 
   1307     if (linker == 0)
   1308         return 0;
   1309 
   1310     linker->setAppAttributeBindings(table);
   1311 
   1312     return 1;
   1313 }
   1314 
   1315 //
   1316 // Let the linker know where the predefined attributes have to live.
   1317 //
   1318 int ShSetFixedAttributeBindings(const ShHandle handle, const ShBindingTable* table)
   1319 {
   1320     if (!InitThread())
   1321         return 0;
   1322 
   1323     if (handle == 0)
   1324         return 0;
   1325 
   1326     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
   1327     TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
   1328 
   1329     if (linker == 0)
   1330         return 0;
   1331 
   1332     linker->setFixedAttributeBindings(table);
   1333     return 1;
   1334 }
   1335 
   1336 //
   1337 // Some attribute locations are off-limits to the linker...
   1338 //
   1339 int ShExcludeAttributes(const ShHandle handle, int *attributes, int count)
   1340 {
   1341     if (!InitThread())
   1342         return 0;
   1343 
   1344     if (handle == 0)
   1345         return 0;
   1346 
   1347     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
   1348     TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
   1349     if (linker == 0)
   1350         return 0;
   1351 
   1352     linker->setExcludedAttributes(attributes, count);
   1353 
   1354     return 1;
   1355 }
   1356 
   1357 //
   1358 // Return the index for OpenGL to use for knowing where a uniform lives.
   1359 //
   1360 // Return:  The return value of is really boolean, indicating
   1361 // success or failure.
   1362 //
   1363 int ShGetUniformLocation(const ShHandle handle, const char* name)
   1364 {
   1365     if (!InitThread())
   1366         return 0;
   1367 
   1368     if (handle == 0)
   1369         return -1;
   1370 
   1371     TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
   1372     TUniformMap* uniformMap= base->getAsUniformMap();
   1373     if (uniformMap == 0)
   1374         return -1;
   1375 
   1376     return uniformMap->getLocation(name);
   1377 }
   1378 
   1379 ////////////////////////////////////////////////////////////////////////////////////////////
   1380 //
   1381 // Deferred-Lowering C++ Interface
   1382 // -----------------------------------
   1383 //
   1384 // Below is a new alternate C++ interface that might potentially replace the above
   1385 // opaque handle-based interface.
   1386 //
   1387 // See more detailed comment in ShaderLang.h
   1388 //
   1389 
   1390 namespace glslang {
   1391 
   1392 #include "../Include/revision.h"
   1393 
   1394 const char* GetEsslVersionString()
   1395 {
   1396     return "OpenGL ES GLSL 3.00 glslang LunarG Khronos." GLSLANG_REVISION " " GLSLANG_DATE;
   1397 }
   1398 
   1399 const char* GetGlslVersionString()
   1400 {
   1401     return "4.20 glslang LunarG Khronos." GLSLANG_REVISION " " GLSLANG_DATE;
   1402 }
   1403 
   1404 int GetKhronosToolId()
   1405 {
   1406     return 8;
   1407 }
   1408 
   1409 bool InitializeProcess()
   1410 {
   1411     return ShInitialize() != 0;
   1412 }
   1413 
   1414 void FinalizeProcess()
   1415 {
   1416     ShFinalize();
   1417 }
   1418 
   1419 class TDeferredCompiler : public TCompiler {
   1420 public:
   1421     TDeferredCompiler(EShLanguage s, TInfoSink& i) : TCompiler(s, i) { }
   1422     virtual bool compile(TIntermNode*, int = 0, EProfile = ENoProfile) { return true; }
   1423 };
   1424 
   1425 TShader::TShader(EShLanguage s)
   1426     : pool(0), stage(s), lengths(nullptr), stringNames(nullptr), preamble("")
   1427 {
   1428     infoSink = new TInfoSink;
   1429     compiler = new TDeferredCompiler(stage, *infoSink);
   1430     intermediate = new TIntermediate(s);
   1431 }
   1432 
   1433 TShader::~TShader()
   1434 {
   1435     delete infoSink;
   1436     delete compiler;
   1437     delete intermediate;
   1438     delete pool;
   1439 }
   1440 
   1441 void TShader::setStrings(const char* const* s, int n)
   1442 {
   1443     strings = s;
   1444     numStrings = n;
   1445     lengths = nullptr;
   1446 }
   1447 
   1448 void TShader::setStringsWithLengths(const char* const* s, const int* l, int n)
   1449 {
   1450     strings = s;
   1451     numStrings = n;
   1452     lengths = l;
   1453 }
   1454 
   1455 void TShader::setStringsWithLengthsAndNames(
   1456     const char* const* s, const int* l, const char* const* names, int n)
   1457 {
   1458     strings = s;
   1459     numStrings = n;
   1460     lengths = l;
   1461     stringNames = names;
   1462 }
   1463 
   1464 void TShader::setEntryPoint(const char* entryPoint)
   1465 {
   1466     intermediate->setEntryPoint(entryPoint);
   1467 }
   1468 
   1469 //
   1470 // Turn the shader strings into a parse tree in the TIntermediate.
   1471 //
   1472 // Returns true for success.
   1473 //
   1474 bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
   1475                     bool forwardCompatible, EShMessages messages, Includer& includer)
   1476 {
   1477     if (! InitThread())
   1478         return false;
   1479 
   1480     pool = new TPoolAllocator();
   1481     SetThreadPoolAllocator(*pool);
   1482     if (! preamble)
   1483         preamble = "";
   1484 
   1485     return CompileDeferred(compiler, strings, numStrings, lengths, stringNames,
   1486                            preamble, EShOptNone, builtInResources, defaultVersion,
   1487                            defaultProfile, forceDefaultVersionAndProfile,
   1488                            forwardCompatible, messages, *intermediate, includer);
   1489 }
   1490 
   1491 bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages)
   1492 {
   1493     return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages);
   1494 }
   1495 
   1496 // Fill in a string with the result of preprocessing ShaderStrings
   1497 // Returns true if all extensions, pragmas and version strings were valid.
   1498 bool TShader::preprocess(const TBuiltInResource* builtInResources,
   1499                          int defaultVersion, EProfile defaultProfile,
   1500                          bool forceDefaultVersionAndProfile,
   1501                          bool forwardCompatible, EShMessages message,
   1502                          std::string* output_string,
   1503                          Includer& includer)
   1504 {
   1505     if (! InitThread())
   1506         return false;
   1507 
   1508     pool = new TPoolAllocator();
   1509     SetThreadPoolAllocator(*pool);
   1510     if (! preamble)
   1511         preamble = "";
   1512 
   1513     return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble,
   1514                               EShOptNone, builtInResources, defaultVersion,
   1515                               defaultProfile, forceDefaultVersionAndProfile,
   1516                               forwardCompatible, message, includer, *intermediate, output_string);
   1517 }
   1518 
   1519 const char* TShader::getInfoLog()
   1520 {
   1521     return infoSink->info.c_str();
   1522 }
   1523 
   1524 const char* TShader::getInfoDebugLog()
   1525 {
   1526     return infoSink->debug.c_str();
   1527 }
   1528 
   1529 TProgram::TProgram() : pool(0), reflection(0), linked(false)
   1530 {
   1531     infoSink = new TInfoSink;
   1532     for (int s = 0; s < EShLangCount; ++s) {
   1533         intermediate[s] = 0;
   1534         newedIntermediate[s] = false;
   1535     }
   1536 }
   1537 
   1538 TProgram::~TProgram()
   1539 {
   1540     delete infoSink;
   1541     delete reflection;
   1542 
   1543     for (int s = 0; s < EShLangCount; ++s)
   1544         if (newedIntermediate[s])
   1545             delete intermediate[s];
   1546 
   1547     delete pool;
   1548 }
   1549 
   1550 //
   1551 // Merge the compilation units within each stage into a single TIntermediate.
   1552 // All starting compilation units need to be the result of calling TShader::parse().
   1553 //
   1554 // Return true for success.
   1555 //
   1556 bool TProgram::link(EShMessages messages)
   1557 {
   1558     if (linked)
   1559         return false;
   1560     linked = true;
   1561 
   1562     bool error = false;
   1563 
   1564     pool = new TPoolAllocator();
   1565     SetThreadPoolAllocator(*pool);
   1566 
   1567     for (int s = 0; s < EShLangCount; ++s) {
   1568         if (! linkStage((EShLanguage)s, messages))
   1569             error = true;
   1570     }
   1571 
   1572     // TODO: Link: cross-stage error checking
   1573 
   1574     return ! error;
   1575 }
   1576 
   1577 //
   1578 // Merge the compilation units within the given stage into a single TIntermediate.
   1579 //
   1580 // Return true for success.
   1581 //
   1582 bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
   1583 {
   1584     if (stages[stage].size() == 0)
   1585         return true;
   1586 
   1587     int numEsShaders = 0, numNonEsShaders = 0;
   1588     for (auto it = stages[stage].begin(); it != stages[stage].end(); ++it) {
   1589         if ((*it)->intermediate->getProfile() == EEsProfile) {
   1590             numEsShaders++;
   1591         } else {
   1592             numNonEsShaders++;
   1593         }
   1594     }
   1595 
   1596     if (numEsShaders > 0 && numNonEsShaders > 0) {
   1597         infoSink->info.message(EPrefixError, "Cannot mix ES profile with non-ES profile shaders");
   1598         return false;
   1599     } else if (numEsShaders > 1) {
   1600         infoSink->info.message(EPrefixError, "Cannot attach multiple ES shaders of the same type to a single program");
   1601         return false;
   1602     }
   1603 
   1604     //
   1605     // Be efficient for the common single compilation unit per stage case,
   1606     // reusing it's TIntermediate instead of merging into a new one.
   1607     //
   1608     TIntermediate *firstIntermediate = stages[stage].front()->intermediate;
   1609     if (stages[stage].size() == 1)
   1610         intermediate[stage] = firstIntermediate;
   1611     else {
   1612         intermediate[stage] = new TIntermediate(stage,
   1613                                                 firstIntermediate->getVersion(),
   1614                                                 firstIntermediate->getProfile());
   1615         newedIntermediate[stage] = true;
   1616     }
   1617 
   1618     infoSink->info << "\nLinked " << StageName(stage) << " stage:\n\n";
   1619 
   1620     if (stages[stage].size() > 1) {
   1621         std::list<TShader*>::const_iterator it;
   1622         for (it = stages[stage].begin(); it != stages[stage].end(); ++it)
   1623             intermediate[stage]->merge(*infoSink, *(*it)->intermediate);
   1624     }
   1625 
   1626     intermediate[stage]->finalCheck(*infoSink);
   1627 
   1628     if (messages & EShMsgAST)
   1629         intermediate[stage]->output(*infoSink, true);
   1630 
   1631     return intermediate[stage]->getNumErrors() == 0;
   1632 }
   1633 
   1634 const char* TProgram::getInfoLog()
   1635 {
   1636     return infoSink->info.c_str();
   1637 }
   1638 
   1639 const char* TProgram::getInfoDebugLog()
   1640 {
   1641     return infoSink->debug.c_str();
   1642 }
   1643 
   1644 //
   1645 // Reflection implementation.
   1646 //
   1647 
   1648 bool TProgram::buildReflection()
   1649 {
   1650     if (! linked || reflection)
   1651         return false;
   1652 
   1653     reflection = new TReflection;
   1654 
   1655     for (int s = 0; s < EShLangCount; ++s) {
   1656         if (intermediate[s]) {
   1657             if (! reflection->addStage((EShLanguage)s, *intermediate[s]))
   1658                 return false;
   1659         }
   1660     }
   1661 
   1662     return true;
   1663 }
   1664 
   1665 int TProgram::getNumLiveUniformVariables()           { return reflection->getNumUniforms(); }
   1666 int TProgram::getNumLiveUniformBlocks()              { return reflection->getNumUniformBlocks(); }
   1667 const char* TProgram::getUniformName(int index)      { return reflection->getUniform(index).name.c_str(); }
   1668 const char* TProgram::getUniformBlockName(int index) { return reflection->getUniformBlock(index).name.c_str(); }
   1669 int TProgram::getUniformBlockSize(int index)         { return reflection->getUniformBlock(index).size; }
   1670 int TProgram::getUniformIndex(const char* name)      { return reflection->getIndex(name); }
   1671 int TProgram::getUniformBlockIndex(int index)        { return reflection->getUniform(index).index; }
   1672 int TProgram::getUniformType(int index)              { return reflection->getUniform(index).glDefineType; }
   1673 int TProgram::getUniformBufferOffset(int index)      { return reflection->getUniform(index).offset; }
   1674 int TProgram::getUniformArraySize(int index)         { return reflection->getUniform(index).size; }
   1675 int TProgram::getNumLiveAttributes()                 { return reflection->getNumAttributes(); }
   1676 const char* TProgram::getAttributeName(int index)    { return reflection->getAttribute(index).name.c_str(); }
   1677 int TProgram::getAttributeType(int index)            { return reflection->getAttribute(index).glDefineType; }
   1678 
   1679 void TProgram::dumpReflection()                      { reflection->dump(); }
   1680 
   1681 } // end namespace glslang
   1682