• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 #include "compiler/translator/Compiler.h"
8 
9 #include <sstream>
10 
11 #include "angle_gl.h"
12 
13 #include "common/BinaryStream.h"
14 #include "common/CompiledShaderState.h"
15 #include "common/PackedEnums.h"
16 #include "common/angle_version_info.h"
17 
18 #include "compiler/translator/CallDAG.h"
19 #include "compiler/translator/CollectVariables.h"
20 #include "compiler/translator/Initialize.h"
21 #include "compiler/translator/IsASTDepthBelowLimit.h"
22 #include "compiler/translator/OutputTree.h"
23 #include "compiler/translator/ParseContext.h"
24 #include "compiler/translator/ValidateBarrierFunctionCall.h"
25 #include "compiler/translator/ValidateClipCullDistance.h"
26 #include "compiler/translator/ValidateLimitations.h"
27 #include "compiler/translator/ValidateMaxParameters.h"
28 #include "compiler/translator/ValidateOutputs.h"
29 #include "compiler/translator/ValidateTypeSizeLimitations.h"
30 #include "compiler/translator/ValidateVaryingLocations.h"
31 #include "compiler/translator/VariablePacker.h"
32 #include "compiler/translator/tree_ops/ClampFragDepth.h"
33 #include "compiler/translator/tree_ops/ClampIndirectIndices.h"
34 #include "compiler/translator/tree_ops/ClampPointSize.h"
35 #include "compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h"
36 #include "compiler/translator/tree_ops/DeferGlobalInitializers.h"
37 #include "compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h"
38 #include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h"
39 #include "compiler/translator/tree_ops/FoldExpressions.h"
40 #include "compiler/translator/tree_ops/ForcePrecisionQualifier.h"
41 #include "compiler/translator/tree_ops/InitializeVariables.h"
42 #include "compiler/translator/tree_ops/MonomorphizeUnsupportedFunctions.h"
43 #include "compiler/translator/tree_ops/PruneEmptyCases.h"
44 #include "compiler/translator/tree_ops/PruneInfiniteLoops.h"
45 #include "compiler/translator/tree_ops/PruneNoOps.h"
46 #include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h"
47 #include "compiler/translator/tree_ops/RemoveDynamicIndexing.h"
48 #include "compiler/translator/tree_ops/RemoveInvariantDeclaration.h"
49 #include "compiler/translator/tree_ops/RemoveUnreferencedVariables.h"
50 #include "compiler/translator/tree_ops/RemoveUnusedFramebufferFetch.h"
51 #include "compiler/translator/tree_ops/RescopeGlobalVariables.h"
52 #include "compiler/translator/tree_ops/RewritePixelLocalStorage.h"
53 #include "compiler/translator/tree_ops/SeparateDeclarations.h"
54 #include "compiler/translator/tree_ops/SimplifyLoopConditions.h"
55 #include "compiler/translator/tree_ops/SplitSequenceOperator.h"
56 #include "compiler/translator/tree_ops/glsl/RegenerateStructNames.h"
57 #include "compiler/translator/tree_ops/glsl/RewriteRepeatedAssignToSwizzled.h"
58 #include "compiler/translator/tree_ops/glsl/ScalarizeVecAndMatConstructorArgs.h"
59 #include "compiler/translator/tree_ops/glsl/UseInterfaceBlockFields.h"
60 #include "compiler/translator/tree_ops/glsl/apple/AddAndTrueToLoopCondition.h"
61 #include "compiler/translator/tree_ops/glsl/apple/RewriteDoWhile.h"
62 #include "compiler/translator/tree_ops/glsl/apple/UnfoldShortCircuitAST.h"
63 #include "compiler/translator/tree_util/BuiltIn.h"
64 #include "compiler/translator/tree_util/FindSymbolNode.h"
65 #include "compiler/translator/tree_util/IntermNodePatternMatcher.h"
66 #include "compiler/translator/tree_util/ReplaceShadowingVariables.h"
67 #include "compiler/translator/tree_util/ReplaceVariable.h"
68 #include "compiler/translator/util.h"
69 
70 // #define ANGLE_FUZZER_CORPUS_OUTPUT_DIR "corpus/"
71 
72 #if defined(ANGLE_FUZZER_CORPUS_OUTPUT_DIR)
73 #    include "common/hash_utils.h"
74 #    include "common/mathutil.h"
75 #endif
76 
77 namespace sh
78 {
79 
80 namespace
81 {
82 // Helper that returns if a top-level node is unused.  If it's a function, the function prototype is
83 // returned as well.
IsTopLevelNodeUnusedFunction(const CallDAG & callDag,const std::vector<TFunctionMetadata> & metadata,TIntermNode * node,const TFunction ** functionOut)84 bool IsTopLevelNodeUnusedFunction(const CallDAG &callDag,
85                                   const std::vector<TFunctionMetadata> &metadata,
86                                   TIntermNode *node,
87                                   const TFunction **functionOut)
88 {
89     const TIntermFunctionPrototype *asFunctionPrototype   = node->getAsFunctionPrototypeNode();
90     const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition();
91 
92     *functionOut = nullptr;
93 
94     if (asFunctionDefinition)
95     {
96         *functionOut = asFunctionDefinition->getFunction();
97     }
98     else if (asFunctionPrototype)
99     {
100         *functionOut = asFunctionPrototype->getFunction();
101     }
102     if (*functionOut == nullptr)
103     {
104         return false;
105     }
106 
107     size_t callDagIndex = callDag.findIndex((*functionOut)->uniqueId());
108     if (callDagIndex == CallDAG::InvalidIndex)
109     {
110         // This happens only for unimplemented prototypes which are thus unused
111         ASSERT(asFunctionPrototype);
112         return true;
113     }
114 
115     ASSERT(callDagIndex < metadata.size());
116     return !metadata[callDagIndex].used;
117 }
118 
AddBuiltInToInitList(TSymbolTable * symbolTable,int shaderVersion,TIntermBlock * root,const char * name,InitVariableList * list)119 void AddBuiltInToInitList(TSymbolTable *symbolTable,
120                           int shaderVersion,
121                           TIntermBlock *root,
122                           const char *name,
123                           InitVariableList *list)
124 {
125     const TIntermSymbol *builtin = FindSymbolNode(root, ImmutableString(name));
126     const TVariable *builtinVar  = nullptr;
127     if (builtin != nullptr)
128     {
129         builtinVar = &builtin->variable();
130     }
131     else
132     {
133         builtinVar = static_cast<const TVariable *>(
134             symbolTable->findBuiltIn(ImmutableString(name), shaderVersion));
135     }
136 
137     if (builtinVar != nullptr)
138     {
139         list->push_back(builtinVar);
140     }
141 }
142 
143 #if defined(ANGLE_FUZZER_CORPUS_OUTPUT_DIR)
DumpFuzzerCase(char const * const * shaderStrings,size_t numStrings,uint32_t type,uint32_t spec,uint32_t output,const ShCompileOptions & options)144 void DumpFuzzerCase(char const *const *shaderStrings,
145                     size_t numStrings,
146                     uint32_t type,
147                     uint32_t spec,
148                     uint32_t output,
149                     const ShCompileOptions &options)
150 {
151     ShaderDumpHeader header{};
152     header.type   = type;
153     header.spec   = spec;
154     header.output = output;
155     memcpy(&header.basicCompileOptions, &options, offsetof(ShCompileOptions, metal));
156     static_assert(offsetof(ShCompileOptions, metal) <= sizeof(header.basicCompileOptions));
157     memcpy(&header.metalCompileOptions, &options.metal, sizeof(options.metal));
158     static_assert(sizeof(options.metal) <= sizeof(header.metalCompileOptions));
159     memcpy(&header.plsCompileOptions, &options.pls, sizeof(options.pls));
160     static_assert(sizeof(options.pls) <= sizeof(header.plsCompileOptions));
161     size_t contentsLength = sizeof(header) + 1;  // Extra: header + nul terminator.
162     for (size_t i = 0; i < numStrings; i++)
163     {
164         contentsLength += strlen(shaderStrings[i]);
165     }
166     std::vector<uint8_t> contents(rx::roundUp<size_t>(contentsLength, 4), 0);
167     memcpy(&contents[0], &header, sizeof(header));
168     uint8_t *data = &contents[sizeof(header)];
169     for (size_t i = 0; i < numStrings; i++)
170     {
171         auto length = strlen(shaderStrings[i]);
172         memcpy(data, shaderStrings[i], length);
173         data += length;
174     }
175     auto hash = angle::ComputeGenericHash(contents.data(), contents.size());
176 
177     std::ostringstream o = sh::InitializeStream<std::ostringstream>();
178     o << ANGLE_FUZZER_CORPUS_OUTPUT_DIR << std::hex << std::setw(16) << std::setfill('0') << hash
179       << ".sample";
180     std::string s = o.str();
181 
182     // Must match the input format of the fuzzer
183     FILE *f = fopen(s.c_str(), "w");
184     fwrite(contents.data(), sizeof(char), contentsLength, f);
185     fclose(f);
186 }
187 #endif  // defined(ANGLE_FUZZER_CORPUS_OUTPUT_DIR)
188 }  // anonymous namespace
189 
IsGLSL130OrNewer(ShShaderOutput output)190 bool IsGLSL130OrNewer(ShShaderOutput output)
191 {
192     return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
193             output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
194             output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT ||
195             output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
196             output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
197 }
198 
IsGLSL420OrNewer(ShShaderOutput output)199 bool IsGLSL420OrNewer(ShShaderOutput output)
200 {
201     return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
202             output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
203 }
204 
IsGLSL410OrOlder(ShShaderOutput output)205 bool IsGLSL410OrOlder(ShShaderOutput output)
206 {
207     return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
208             output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
209             output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
210 }
211 
RemoveInvariant(sh::GLenum shaderType,int shaderVersion,ShShaderOutput outputType,const ShCompileOptions & compileOptions)212 bool RemoveInvariant(sh::GLenum shaderType,
213                      int shaderVersion,
214                      ShShaderOutput outputType,
215                      const ShCompileOptions &compileOptions)
216 {
217     if (shaderType == GL_FRAGMENT_SHADER &&
218         (IsGLSL420OrNewer(outputType) || IsOutputSPIRV(outputType)))
219         return true;
220 
221     if (compileOptions.removeInvariantAndCentroidForESSL3 && shaderVersion >= 300 &&
222         shaderType == GL_VERTEX_SHADER)
223         return true;
224 
225     return false;
226 }
227 
GetGlobalMaxTokenSize(ShShaderSpec spec)228 size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
229 {
230     // WebGL defines a max token length of 256, while ES2 leaves max token
231     // size undefined. ES3 defines a max size of 1024 characters.
232     switch (spec)
233     {
234         case SH_WEBGL_SPEC:
235             return 256;
236         default:
237             return 1024;
238     }
239 }
240 
GetMaxUniformVectorsForShaderType(GLenum shaderType,const ShBuiltInResources & resources)241 int GetMaxUniformVectorsForShaderType(GLenum shaderType, const ShBuiltInResources &resources)
242 {
243     switch (shaderType)
244     {
245         case GL_VERTEX_SHADER:
246             return resources.MaxVertexUniformVectors;
247         case GL_FRAGMENT_SHADER:
248             return resources.MaxFragmentUniformVectors;
249 
250         // TODO (jiawei.shao@intel.com): check if we need finer-grained component counting
251         case GL_COMPUTE_SHADER:
252             return resources.MaxComputeUniformComponents / 4;
253         case GL_GEOMETRY_SHADER_EXT:
254             return resources.MaxGeometryUniformComponents / 4;
255         default:
256             UNREACHABLE();
257             return -1;
258     }
259 }
260 
261 namespace
262 {
263 
264 class [[nodiscard]] TScopedPoolAllocator
265 {
266   public:
TScopedPoolAllocator(angle::PoolAllocator * allocator)267     TScopedPoolAllocator(angle::PoolAllocator *allocator) : mAllocator(allocator)
268     {
269         mAllocator->push();
270         SetGlobalPoolAllocator(mAllocator);
271     }
~TScopedPoolAllocator()272     ~TScopedPoolAllocator()
273     {
274         SetGlobalPoolAllocator(nullptr);
275         mAllocator->pop(angle::PoolAllocator::ReleaseStrategy::All);
276     }
277 
278   private:
279     angle::PoolAllocator *mAllocator;
280 };
281 
282 class [[nodiscard]] TScopedSymbolTableLevel
283 {
284   public:
TScopedSymbolTableLevel(TSymbolTable * table)285     TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
286     {
287         ASSERT(mTable->isEmpty());
288         mTable->push();
289     }
~TScopedSymbolTableLevel()290     ~TScopedSymbolTableLevel()
291     {
292         while (!mTable->isEmpty())
293             mTable->pop();
294     }
295 
296   private:
297     TSymbolTable *mTable;
298 };
299 
GetMaxShaderVersionForSpec(ShShaderSpec spec)300 int GetMaxShaderVersionForSpec(ShShaderSpec spec)
301 {
302     switch (spec)
303     {
304         case SH_GLES2_SPEC:
305         case SH_WEBGL_SPEC:
306             return 100;
307         case SH_GLES3_SPEC:
308         case SH_WEBGL2_SPEC:
309             return 300;
310         case SH_GLES3_1_SPEC:
311         case SH_WEBGL3_SPEC:
312             return 310;
313         case SH_GLES3_2_SPEC:
314             return 320;
315         default:
316             UNREACHABLE();
317             return 0;
318     }
319 }
320 
ValidateFragColorAndFragData(GLenum shaderType,int shaderVersion,const TSymbolTable & symbolTable,TDiagnostics * diagnostics)321 bool ValidateFragColorAndFragData(GLenum shaderType,
322                                   int shaderVersion,
323                                   const TSymbolTable &symbolTable,
324                                   TDiagnostics *diagnostics)
325 {
326     if (shaderVersion > 100 || shaderType != GL_FRAGMENT_SHADER)
327     {
328         return true;
329     }
330 
331     bool usesFragColor = false;
332     bool usesFragData  = false;
333     // This validation is a bit stricter than the spec - it's only an error to write to
334     // both FragData and FragColor. But because it's better not to have reads from undefined
335     // variables, we always return an error if they are both referenced, rather than only if they
336     // are written.
337     if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_FragColor()) ||
338         symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()))
339     {
340         usesFragColor = true;
341     }
342     // Extension variables may not always be initialized (saves some time at symbol table init).
343     bool secondaryFragDataUsed =
344         symbolTable.gl_SecondaryFragDataEXT() != nullptr &&
345         symbolTable.isStaticallyUsed(*symbolTable.gl_SecondaryFragDataEXT());
346     if (symbolTable.isStaticallyUsed(*symbolTable.gl_FragData()) || secondaryFragDataUsed)
347     {
348         usesFragData = true;
349     }
350     if (usesFragColor && usesFragData)
351     {
352         const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
353         if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()) ||
354             secondaryFragDataUsed)
355         {
356             errorMessage =
357                 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
358                 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
359         }
360         diagnostics->globalError(errorMessage);
361         return false;
362     }
363     return true;
364 }
365 
366 }  // namespace
367 
TShHandleBase()368 TShHandleBase::TShHandleBase()
369 {
370     allocator.push();
371     SetGlobalPoolAllocator(&allocator);
372 }
373 
~TShHandleBase()374 TShHandleBase::~TShHandleBase()
375 {
376     SetGlobalPoolAllocator(nullptr);
377     allocator.popAll();
378 }
379 
TCompiler(sh::GLenum type,ShShaderSpec spec,ShShaderOutput output)380 TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
381     : mVariablesCollected(false),
382       mGLPositionInitialized(false),
383       mShaderType(type),
384       mShaderSpec(spec),
385       mOutputType(output),
386       mBuiltInFunctionEmulator(),
387       mDiagnostics(mInfoSink.info),
388       mSourcePath(nullptr),
389       mComputeShaderLocalSizeDeclared(false),
390       mComputeShaderLocalSize(1),
391       mGeometryShaderMaxVertices(-1),
392       mGeometryShaderInvocations(0),
393       mGeometryShaderInputPrimitiveType(EptUndefined),
394       mGeometryShaderOutputPrimitiveType(EptUndefined),
395       mTessControlShaderOutputVertices(0),
396       mTessEvaluationShaderInputPrimitiveType(EtetUndefined),
397       mTessEvaluationShaderInputVertexSpacingType(EtetUndefined),
398       mTessEvaluationShaderInputOrderingType(EtetUndefined),
399       mTessEvaluationShaderInputPointType(EtetUndefined),
400       mHasAnyPreciseType(false),
401       mAdvancedBlendEquations(0),
402       mUsesDerivatives(false),
403       mCompileOptions{}
404 {}
405 
~TCompiler()406 TCompiler::~TCompiler() {}
407 
isHighPrecisionSupported() const408 bool TCompiler::isHighPrecisionSupported() const
409 {
410     return mShaderVersion > 100 || mShaderType != GL_FRAGMENT_SHADER ||
411            mResources.FragmentPrecisionHigh == 1;
412 }
413 
shouldRunLoopAndIndexingValidation(const ShCompileOptions & compileOptions) const414 bool TCompiler::shouldRunLoopAndIndexingValidation(const ShCompileOptions &compileOptions) const
415 {
416     // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API,
417     // validate loop and indexing as well (to verify that the shader only uses minimal functionality
418     // of ESSL 1.00 as in Appendix A of the spec).
419     return (IsWebGLBasedSpec(mShaderSpec) && mShaderVersion == 100) ||
420            compileOptions.validateLoopIndexing;
421 }
422 
shouldLimitTypeSizes() const423 bool TCompiler::shouldLimitTypeSizes() const
424 {
425     // Prevent unrealistically large variable sizes in shaders.  This works around driver bugs
426     // around int-size limits (such as 2GB).  The limits are generously large enough that no real
427     // shader should ever hit it.
428     //
429     // The size check does not take std430 into account, so this is limited to WebGL and shaders
430     // up to ES3.
431     return mShaderVersion <= 300;
432 }
433 
Init(const ShBuiltInResources & resources)434 bool TCompiler::Init(const ShBuiltInResources &resources)
435 {
436     SetGlobalPoolAllocator(&allocator);
437 
438     // Generate built-in symbol table.
439     if (!initBuiltInSymbolTable(resources))
440         return false;
441 
442     mResources = resources;
443     setResourceString();
444 
445     InitExtensionBehavior(resources, mExtensionBehavior);
446     return true;
447 }
448 
compileTreeForTesting(const char * const shaderStrings[],size_t numStrings,const ShCompileOptions & compileOptions)449 TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],
450                                                size_t numStrings,
451                                                const ShCompileOptions &compileOptions)
452 {
453     return compileTreeImpl(shaderStrings, numStrings, compileOptions);
454 }
455 
compileTreeImpl(const char * const shaderStrings[],size_t numStrings,const ShCompileOptions & compileOptions)456 TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
457                                          size_t numStrings,
458                                          const ShCompileOptions &compileOptions)
459 {
460     // Remember the compile options for helper functions such as validateAST.
461     mCompileOptions = compileOptions;
462 
463     clearResults();
464 
465     ASSERT(numStrings > 0);
466     ASSERT(GetGlobalPoolAllocator());
467 
468     // Reset the extension behavior for each compilation unit.
469     ResetExtensionBehavior(mResources, mExtensionBehavior, compileOptions);
470 
471     // If gl_DrawID is not supported, remove it from the available extensions
472     // Currently we only allow emulation of gl_DrawID
473     const bool glDrawIDSupported = compileOptions.emulateGLDrawID;
474     if (!glDrawIDSupported)
475     {
476         auto it = mExtensionBehavior.find(TExtension::ANGLE_multi_draw);
477         if (it != mExtensionBehavior.end())
478         {
479             mExtensionBehavior.erase(it);
480         }
481     }
482 
483     const bool glBaseVertexBaseInstanceSupported = compileOptions.emulateGLBaseVertexBaseInstance;
484     if (!glBaseVertexBaseInstanceSupported)
485     {
486         auto it =
487             mExtensionBehavior.find(TExtension::ANGLE_base_vertex_base_instance_shader_builtin);
488         if (it != mExtensionBehavior.end())
489         {
490             mExtensionBehavior.erase(it);
491         }
492     }
493 
494     // First string is path of source file if flag is set. The actual source follows.
495     size_t firstSource = 0;
496     if (compileOptions.sourcePath)
497     {
498         mSourcePath = shaderStrings[0];
499         ++firstSource;
500     }
501 
502     TParseContext parseContext(mSymbolTable, mExtensionBehavior, mShaderType, mShaderSpec,
503                                compileOptions, &mDiagnostics, getResources(), getOutputType());
504 
505     parseContext.setFragmentPrecisionHighOnESSL1(mResources.FragmentPrecisionHigh == 1);
506 
507     // We preserve symbols at the built-in level from compile-to-compile.
508     // Start pushing the user-defined symbols at global level.
509     TScopedSymbolTableLevel globalLevel(&mSymbolTable);
510     ASSERT(mSymbolTable.atGlobalLevel());
511 
512     // Parse shader.
513     if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr,
514                        &parseContext) != 0)
515     {
516         return nullptr;
517     }
518 
519     if (!postParseChecks(parseContext))
520     {
521         return nullptr;
522     }
523 
524     setASTMetadata(parseContext);
525 
526     if (!checkShaderVersion(&parseContext))
527     {
528         return nullptr;
529     }
530 
531     TIntermBlock *root = parseContext.getTreeRoot();
532     if (!checkAndSimplifyAST(root, parseContext, compileOptions))
533     {
534         return nullptr;
535     }
536 
537     return root;
538 }
539 
checkShaderVersion(TParseContext * parseContext)540 bool TCompiler::checkShaderVersion(TParseContext *parseContext)
541 {
542     if (GetMaxShaderVersionForSpec(mShaderSpec) < mShaderVersion)
543     {
544         mDiagnostics.globalError("unsupported shader version");
545         return false;
546     }
547 
548     ASSERT(parseContext);
549     switch (mShaderType)
550     {
551         case GL_COMPUTE_SHADER:
552             if (mShaderVersion < 310)
553             {
554                 mDiagnostics.globalError("Compute shader is not supported in this shader version.");
555                 return false;
556             }
557             break;
558 
559         case GL_GEOMETRY_SHADER_EXT:
560             if (mShaderVersion < 310)
561             {
562                 mDiagnostics.globalError(
563                     "Geometry shader is not supported in this shader version.");
564                 return false;
565             }
566             else if (mShaderVersion == 310)
567             {
568                 if (!parseContext->checkCanUseOneOfExtensions(
569                         sh::TSourceLoc(),
570                         std::array<TExtension, 2u>{
571                             {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}))
572                 {
573                     return false;
574                 }
575             }
576             break;
577 
578         case GL_TESS_CONTROL_SHADER_EXT:
579         case GL_TESS_EVALUATION_SHADER_EXT:
580             if (mShaderVersion < 310)
581             {
582                 mDiagnostics.globalError(
583                     "Tessellation shaders are not supported in this shader version.");
584                 return false;
585             }
586             else if (mShaderVersion == 310)
587             {
588                 if (!parseContext->checkCanUseOneOfExtensions(
589                         sh::TSourceLoc(),
590                         std::array<TExtension, 2u>{{TExtension::EXT_tessellation_shader,
591                                                     TExtension::OES_tessellation_shader}}))
592                 {
593                     return false;
594                 }
595             }
596             break;
597 
598         default:
599             break;
600     }
601 
602     return true;
603 }
604 
setASTMetadata(const TParseContext & parseContext)605 void TCompiler::setASTMetadata(const TParseContext &parseContext)
606 {
607     mShaderVersion = parseContext.getShaderVersion();
608 
609     mPragma = parseContext.pragma();
610     mSymbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);
611 
612     mEarlyFragmentTestsSpecified = parseContext.isEarlyFragmentTestsSpecified();
613 
614     mMetadataFlags[MetadataFlags::HasDiscard] = parseContext.hasDiscard();
615     mMetadataFlags[MetadataFlags::EnablesPerSampleShading] =
616         parseContext.isSampleQualifierSpecified();
617 
618     mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
619     mComputeShaderLocalSize         = parseContext.getComputeShaderLocalSize();
620 
621     mNumViews = parseContext.getNumViews();
622 
623     mHasAnyPreciseType = parseContext.hasAnyPreciseType();
624 
625     mUsesDerivatives = parseContext.usesDerivatives();
626 
627     if (mShaderType == GL_FRAGMENT_SHADER)
628     {
629         mAdvancedBlendEquations = parseContext.getAdvancedBlendEquations();
630         const std::map<int, ShPixelLocalStorageFormat> &plsFormats =
631             parseContext.pixelLocalStorageFormats();
632         // std::map keys are in sorted order, so the PLS uniform with the largest binding will be at
633         // rbegin().
634         mPixelLocalStorageFormats.resize(plsFormats.empty() ? 0 : plsFormats.rbegin()->first + 1,
635                                          ShPixelLocalStorageFormat::NotPLS);
636         for (auto [binding, format] : parseContext.pixelLocalStorageFormats())
637         {
638             mPixelLocalStorageFormats[binding] = format;
639         }
640     }
641     if (mShaderType == GL_GEOMETRY_SHADER_EXT)
642     {
643         mGeometryShaderInputPrimitiveType  = parseContext.getGeometryShaderInputPrimitiveType();
644         mGeometryShaderOutputPrimitiveType = parseContext.getGeometryShaderOutputPrimitiveType();
645         mGeometryShaderMaxVertices         = parseContext.getGeometryShaderMaxVertices();
646         mGeometryShaderInvocations         = parseContext.getGeometryShaderInvocations();
647 
648         mMetadataFlags[MetadataFlags::HasValidGeometryShaderInputPrimitiveType] =
649             mGeometryShaderInputPrimitiveType != EptUndefined;
650         mMetadataFlags[MetadataFlags::HasValidGeometryShaderOutputPrimitiveType] =
651             mGeometryShaderOutputPrimitiveType != EptUndefined;
652         mMetadataFlags[MetadataFlags::HasValidGeometryShaderMaxVertices] =
653             mGeometryShaderMaxVertices >= 0;
654     }
655     if (mShaderType == GL_TESS_CONTROL_SHADER_EXT)
656     {
657         mTessControlShaderOutputVertices = parseContext.getTessControlShaderOutputVertices();
658     }
659     if (mShaderType == GL_TESS_EVALUATION_SHADER_EXT)
660     {
661         mTessEvaluationShaderInputPrimitiveType =
662             parseContext.getTessEvaluationShaderInputPrimitiveType();
663         mTessEvaluationShaderInputVertexSpacingType =
664             parseContext.getTessEvaluationShaderInputVertexSpacingType();
665         mTessEvaluationShaderInputOrderingType =
666             parseContext.getTessEvaluationShaderInputOrderingType();
667         mTessEvaluationShaderInputPointType = parseContext.getTessEvaluationShaderInputPointType();
668 
669         mMetadataFlags[MetadataFlags::HasValidTessGenMode] =
670             mTessEvaluationShaderInputPrimitiveType != EtetUndefined;
671         mMetadataFlags[MetadataFlags::HasValidTessGenSpacing] =
672             mTessEvaluationShaderInputVertexSpacingType != EtetUndefined;
673         mMetadataFlags[MetadataFlags::HasValidTessGenVertexOrder] =
674             mTessEvaluationShaderInputOrderingType != EtetUndefined;
675         mMetadataFlags[MetadataFlags::HasValidTessGenPointMode] =
676             mTessEvaluationShaderInputPointType != EtetUndefined;
677     }
678 }
679 
getSharedMemorySize() const680 unsigned int TCompiler::getSharedMemorySize() const
681 {
682     unsigned int sharedMemSize = 0;
683     for (const sh::ShaderVariable &var : mSharedVariables)
684     {
685         sharedMemSize += var.getExternalSize();
686     }
687 
688     return sharedMemSize;
689 }
690 
getShaderBinary(const ShHandle compilerHandle,const char * const shaderStrings[],size_t numStrings,const ShCompileOptions & compileOptions,ShaderBinaryBlob * const binaryOut)691 bool TCompiler::getShaderBinary(const ShHandle compilerHandle,
692                                 const char *const shaderStrings[],
693                                 size_t numStrings,
694                                 const ShCompileOptions &compileOptions,
695                                 ShaderBinaryBlob *const binaryOut)
696 {
697     if (!compile(shaderStrings, numStrings, compileOptions))
698     {
699         return false;
700     }
701 
702     gl::BinaryOutputStream stream;
703     gl::ShaderType shaderType = gl::FromGLenum<gl::ShaderType>(mShaderType);
704     gl::CompiledShaderState state(shaderType);
705     state.buildCompiledShaderState(compilerHandle, IsOutputSPIRV(mOutputType));
706 
707     stream.writeBytes(
708         reinterpret_cast<const unsigned char *>(angle::GetANGLEShaderProgramVersion()),
709         angle::GetANGLEShaderProgramVersionHashSize());
710     stream.writeEnum(shaderType);
711     stream.writeEnum(mOutputType);
712 
713     // Serialize the full source string for the shader. Ignore the source path if it is provided.
714     std::string sourceString;
715     size_t startingIndex = compileOptions.sourcePath ? 1 : 0;
716     for (size_t i = startingIndex; i < numStrings; ++i)
717     {
718         sourceString.append(shaderStrings[i]);
719     }
720     stream.writeString(sourceString);
721 
722     stream.writeBytes(reinterpret_cast<const uint8_t *>(&compileOptions), sizeof(compileOptions));
723     stream.writeBytes(reinterpret_cast<const uint8_t *>(&mResources), sizeof(mResources));
724 
725     state.serialize(stream);
726 
727     ASSERT(binaryOut);
728     *binaryOut = std::move(stream.getData());
729     return true;
730 }
731 
validateAST(TIntermNode * root)732 bool TCompiler::validateAST(TIntermNode *root)
733 {
734     if (mCompileOptions.validateAST)
735     {
736         bool valid = ValidateAST(root, &mDiagnostics, mValidateASTOptions);
737 
738 #if defined(ANGLE_ENABLE_ASSERTS)
739         if (!valid)
740         {
741             OutputTree(root, mInfoSink.info);
742             fprintf(stderr, "AST validation error(s):\n%s\n", mInfoSink.info.c_str());
743         }
744 #endif
745         // In debug, assert validation.  In release, validation errors will be returned back to the
746         // application as internal ANGLE errors.
747         ASSERT(valid);
748 
749         return valid;
750     }
751     return true;
752 }
753 
disableValidateFunctionCall()754 bool TCompiler::disableValidateFunctionCall()
755 {
756     bool wasEnabled                          = mValidateASTOptions.validateFunctionCall;
757     mValidateASTOptions.validateFunctionCall = false;
758     return wasEnabled;
759 }
760 
restoreValidateFunctionCall(bool enable)761 void TCompiler::restoreValidateFunctionCall(bool enable)
762 {
763     ASSERT(!mValidateASTOptions.validateFunctionCall);
764     mValidateASTOptions.validateFunctionCall = enable;
765 }
766 
disableValidateVariableReferences()767 bool TCompiler::disableValidateVariableReferences()
768 {
769     bool wasEnabled                                = mValidateASTOptions.validateVariableReferences;
770     mValidateASTOptions.validateVariableReferences = false;
771     return wasEnabled;
772 }
773 
restoreValidateVariableReferences(bool enable)774 void TCompiler::restoreValidateVariableReferences(bool enable)
775 {
776     ASSERT(!mValidateASTOptions.validateVariableReferences);
777     mValidateASTOptions.validateVariableReferences = enable;
778 }
779 
enableValidateNoMoreTransformations()780 void TCompiler::enableValidateNoMoreTransformations()
781 {
782     mValidateASTOptions.validateNoMoreTransformations = true;
783 }
784 
checkAndSimplifyAST(TIntermBlock * root,const TParseContext & parseContext,const ShCompileOptions & compileOptions)785 bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
786                                     const TParseContext &parseContext,
787                                     const ShCompileOptions &compileOptions)
788 {
789     mValidateASTOptions = {};
790 
791     // Disallow expressions deemed too complex.
792     // This needs to be checked before other functions that will traverse the AST
793     // to prevent potential stack overflow crashes.
794     if (compileOptions.limitExpressionComplexity && !limitExpressionComplexity(root))
795     {
796         return false;
797     }
798 
799     if (!validateAST(root))
800     {
801         return false;
802     }
803 
804     // Turn |inout| variables that are never read from into |out| before collecting variables and
805     // before PLS uses them.
806     if (mShaderVersion >= 300 &&
807         (IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_shader_framebuffer_fetch) ||
808          IsExtensionEnabled(mExtensionBehavior,
809                             TExtension::EXT_shader_framebuffer_fetch_non_coherent)))
810     {
811         if (!RemoveUnusedFramebufferFetch(this, root, &mSymbolTable))
812         {
813             return false;
814         }
815     }
816 
817     // For now, rewrite pixel local storage before collecting variables or any operations on images.
818     //
819     // TODO(anglebug.com/40096838):
820     //   Should this actually run after collecting variables?
821     //   Do we need more introspection?
822     //   Do we want to hide rewritten shader image uniforms from glGetActiveUniform?
823     if (hasPixelLocalStorageUniforms())
824     {
825         ASSERT(
826             IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_shader_pixel_local_storage));
827         if (!RewritePixelLocalStorage(this, root, getSymbolTable(), compileOptions,
828                                       getShaderVersion()))
829         {
830             mDiagnostics.globalError("internal compiler error translating pixel local storage");
831             return false;
832         }
833     }
834 
835     if (shouldRunLoopAndIndexingValidation(compileOptions) &&
836         !ValidateLimitations(root, mShaderType, &mSymbolTable, &mDiagnostics))
837     {
838         return false;
839     }
840 
841     if (!ValidateFragColorAndFragData(mShaderType, mShaderVersion, mSymbolTable, &mDiagnostics))
842     {
843         return false;
844     }
845 
846     // Fold expressions that could not be folded before validation that was done as a part of
847     // parsing.
848     if (!FoldExpressions(this, root, &mDiagnostics))
849     {
850         return false;
851     }
852     // Folding should only be able to generate warnings.
853     ASSERT(mDiagnostics.numErrors() == 0);
854 
855     // gl_ClipDistance and gl_CullDistance built-in arrays have unique semantics.
856     // They are pre-declared as unsized and must be sized by the shader either
857     // redeclaring them or indexing them only with integral constant expressions.
858     // The translator treats them as having the maximum allowed size and this pass
859     // detects the actual sizes resizing the variables if needed.
860     if (parseContext.isExtensionEnabled(TExtension::ANGLE_clip_cull_distance) ||
861         parseContext.isExtensionEnabled(TExtension::EXT_clip_cull_distance) ||
862         parseContext.isExtensionEnabled(TExtension::APPLE_clip_distance))
863     {
864         bool isClipDistanceUsed = false;
865         if (!ValidateClipCullDistance(this, root, &mDiagnostics,
866                                       mResources.MaxCombinedClipAndCullDistances,
867                                       &mClipDistanceSize, &mCullDistanceSize, &isClipDistanceUsed))
868         {
869             return false;
870         }
871         mMetadataFlags[MetadataFlags::HasClipDistance] = isClipDistanceUsed;
872     }
873 
874     // Validate no barrier() after return before prunning it in |PruneNoOps()| below.
875     if (mShaderType == GL_TESS_CONTROL_SHADER && !ValidateBarrierFunctionCall(root, &mDiagnostics))
876     {
877         return false;
878     }
879 
880     // We prune no-ops to work around driver bugs and to keep AST processing and output simple.
881     // The following kinds of no-ops are pruned:
882     //   1. Empty declarations "int;".
883     //   2. Literal statements: "1.0;". The ESSL output doesn't define a default precision
884     //      for float, so float literal statements would end up with no precision which is
885     //      invalid ESSL.
886     //   3. Any unreachable statement after a discard, return, break or continue.
887     // After this empty declarations are not allowed in the AST.
888     if (!PruneNoOps(this, root, &mSymbolTable))
889     {
890         return false;
891     }
892     mValidateASTOptions.validateNoStatementsAfterBranch = true;
893 
894     // We need to generate globals early if we have non constant initializers enabled
895     bool initializeLocalsAndGlobals =
896         compileOptions.initializeUninitializedLocals && !IsOutputHLSL(getOutputType());
897     bool canUseLoopsToInitialize       = !compileOptions.dontUseLoopsToInitializeVariables;
898     bool highPrecisionSupported        = isHighPrecisionSupported();
899     bool enableNonConstantInitializers = IsExtensionEnabled(
900         mExtensionBehavior, TExtension::EXT_shader_non_constant_global_initializers);
901     // forceDeferNonConstGlobalInitializers is needed for MSL
902     // to convert a non-const global. For example:
903     //
904     //    int someGlobal = 123;
905     //
906     // to
907     //
908     //    int someGlobal;
909     //    void main() {
910     //        someGlobal = 123;
911     //
912     // This is because MSL doesn't allow statically initialized non-const globals.
913     bool forceDeferNonConstGlobalInitializers = getOutputType() == SH_MSL_METAL_OUTPUT;
914 
915     if (enableNonConstantInitializers &&
916         !DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize,
917                                  highPrecisionSupported, forceDeferNonConstGlobalInitializers,
918                                  &mSymbolTable))
919     {
920         return false;
921     }
922 
923     // Create the function DAG and check there is no recursion
924     if (!initCallDag(root))
925     {
926         return false;
927     }
928 
929     if (compileOptions.limitCallStackDepth && !checkCallDepth())
930     {
931         return false;
932     }
933 
934     // Checks which functions are used and if "main" exists
935     mFunctionMetadata.clear();
936     mFunctionMetadata.resize(mCallDag.size());
937     if (!tagUsedFunctions())
938     {
939         return false;
940     }
941 
942     if (!pruneUnusedFunctions(root))
943     {
944         return false;
945     }
946 
947     if (IsSpecWithFunctionBodyNewScope(mShaderSpec, mShaderVersion))
948     {
949         if (!ReplaceShadowingVariables(this, root, &mSymbolTable))
950         {
951             return false;
952         }
953     }
954 
955     if (mShaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, mShaderType))
956     {
957         return false;
958     }
959 
960     // anglebug.com/42265954: The ESSL spec has a bug with images as function arguments. The
961     // recommended workaround is to inline functions that accept image arguments.
962     if (mShaderVersion >= 310 && !MonomorphizeUnsupportedFunctions(
963                                      this, root, &mSymbolTable,
964                                      UnsupportedFunctionArgsBitSet{UnsupportedFunctionArgs::Image}))
965     {
966         return false;
967     }
968 
969     if (mShaderVersion >= 300 && mShaderType == GL_FRAGMENT_SHADER &&
970         !ValidateOutputs(root, getExtensionBehavior(), mResources, hasPixelLocalStorageUniforms(),
971                          IsWebGLBasedSpec(mShaderSpec), &mDiagnostics))
972     {
973         return false;
974     }
975 
976     // Clamping uniform array bounds needs to happen after validateLimitations pass.
977     if (compileOptions.clampIndirectArrayBounds)
978     {
979         if (!ClampIndirectIndices(this, root, &mSymbolTable))
980         {
981             return false;
982         }
983     }
984 
985     if (compileOptions.initializeBuiltinsForInstancedMultiview &&
986         (parseContext.isExtensionEnabled(TExtension::OVR_multiview2) ||
987          parseContext.isExtensionEnabled(TExtension::OVR_multiview)) &&
988         getShaderType() != GL_COMPUTE_SHADER)
989     {
990         if (!DeclareAndInitBuiltinsForInstancedMultiview(
991                 this, root, mNumViews, mShaderType, compileOptions, mOutputType, &mSymbolTable))
992         {
993             return false;
994         }
995     }
996 
997     // This pass might emit short circuits so keep it before the short circuit unfolding
998     if (compileOptions.rewriteDoWhileLoops)
999     {
1000         if (!RewriteDoWhile(this, root, &mSymbolTable))
1001         {
1002             return false;
1003         }
1004     }
1005 
1006     if (compileOptions.addAndTrueToLoopCondition)
1007     {
1008         if (!AddAndTrueToLoopCondition(this, root))
1009         {
1010             return false;
1011         }
1012     }
1013 
1014     if (compileOptions.unfoldShortCircuit)
1015     {
1016         if (!UnfoldShortCircuitAST(this, root))
1017         {
1018             return false;
1019         }
1020     }
1021 
1022     if (compileOptions.regenerateStructNames)
1023     {
1024         if (!RegenerateStructNames(this, root, &mSymbolTable))
1025         {
1026             return false;
1027         }
1028     }
1029 
1030     if (mShaderType == GL_VERTEX_SHADER &&
1031         IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_multi_draw))
1032     {
1033         if (compileOptions.emulateGLDrawID)
1034         {
1035             if (!EmulateGLDrawID(this, root, &mSymbolTable, &mUniforms))
1036             {
1037                 return false;
1038             }
1039         }
1040     }
1041 
1042     if (mShaderType == GL_VERTEX_SHADER &&
1043         IsExtensionEnabled(mExtensionBehavior,
1044                            TExtension::ANGLE_base_vertex_base_instance_shader_builtin))
1045     {
1046         if (compileOptions.emulateGLBaseVertexBaseInstance)
1047         {
1048             if (!EmulateGLBaseVertexBaseInstance(this, root, &mSymbolTable, &mUniforms,
1049                                                  compileOptions.addBaseVertexToVertexID))
1050             {
1051                 return false;
1052             }
1053         }
1054     }
1055 
1056     if (mShaderType == GL_FRAGMENT_SHADER && mShaderVersion == 100 && mResources.EXT_draw_buffers &&
1057         mResources.MaxDrawBuffers > 1 &&
1058         IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
1059     {
1060         if (!EmulateGLFragColorBroadcast(this, root, mResources.MaxDrawBuffers,
1061                                          mResources.MaxDualSourceDrawBuffers, &mOutputVariables,
1062                                          &mSymbolTable, mShaderVersion))
1063         {
1064             return false;
1065         }
1066     }
1067 
1068     if (compileOptions.simplifyLoopConditions)
1069     {
1070         if (!SimplifyLoopConditions(this, root, &getSymbolTable()))
1071         {
1072             return false;
1073         }
1074     }
1075     else
1076     {
1077         // Split multi declarations and remove calls to array length().
1078         // Note that SimplifyLoopConditions needs to be run before any other AST transformations
1079         // that may need to generate new statements from loop conditions or loop expressions.
1080         if (!SimplifyLoopConditions(this, root,
1081                                     IntermNodePatternMatcher::kMultiDeclaration |
1082                                         IntermNodePatternMatcher::kArrayLengthMethod,
1083                                     &getSymbolTable()))
1084         {
1085             return false;
1086         }
1087     }
1088 
1089     // Note that separate declarations need to be run before other AST transformations that
1090     // generate new statements from expressions.
1091     if (!SeparateDeclarations(*this, *root, mCompileOptions.separateCompoundStructDeclarations))
1092     {
1093         return false;
1094     }
1095 
1096     if (IsWebGLBasedSpec(mShaderSpec))
1097     {
1098         // Remove infinite loops, they are not supposed to exist in shaders.
1099         bool anyInfiniteLoops = false;
1100         if (!PruneInfiniteLoops(this, root, &mSymbolTable, &anyInfiniteLoops))
1101         {
1102             return false;
1103         }
1104 
1105         // If requested, reject shaders with infinite loops.  If not requested, the same loops are
1106         // removed from the shader as a fallback.
1107         if (anyInfiniteLoops && mCompileOptions.rejectWebglShadersWithUndefinedBehavior)
1108         {
1109             mDiagnostics.globalError("Infinite loop detected in the shader");
1110             return false;
1111         }
1112     }
1113 
1114     if (compileOptions.rescopeGlobalVariables)
1115     {
1116         if (!RescopeGlobalVariables(*this, *root))
1117         {
1118             return false;
1119         }
1120     }
1121 
1122     mValidateASTOptions.validateMultiDeclarations = true;
1123 
1124     if (!SplitSequenceOperator(this, root, IntermNodePatternMatcher::kArrayLengthMethod,
1125                                &getSymbolTable()))
1126     {
1127         return false;
1128     }
1129 
1130     if (!RemoveArrayLengthMethod(this, root))
1131     {
1132         return false;
1133     }
1134     // Fold the expressions again, because |RemoveArrayLengthMethod| can introduce new constants.
1135     if (!FoldExpressions(this, root, &mDiagnostics))
1136     {
1137         return false;
1138     }
1139 
1140     if (!RemoveUnreferencedVariables(this, root, &mSymbolTable))
1141     {
1142         return false;
1143     }
1144 
1145     // In case the last case inside a switch statement is a certain type of no-op, GLSL compilers in
1146     // drivers may not accept it. In this case we clean up the dead code from the end of switch
1147     // statements. This is also required because PruneNoOps or RemoveUnreferencedVariables may have
1148     // left switch statements that only contained an empty declaration inside the final case in an
1149     // invalid state. Relies on that PruneNoOps and RemoveUnreferencedVariables have already been
1150     // run.
1151     if (!PruneEmptyCases(this, root))
1152     {
1153         return false;
1154     }
1155 
1156     // Run after RemoveUnreferencedVariables, validate that the shader does not have excessively
1157     // large variables.
1158     if (shouldLimitTypeSizes() && !ValidateTypeSizeLimitations(root, &mSymbolTable, &mDiagnostics))
1159     {
1160         return false;
1161     }
1162 
1163     // Built-in function emulation needs to happen after validateLimitations pass.
1164     GetGlobalPoolAllocator()->lock();
1165     initBuiltInFunctionEmulator(&mBuiltInFunctionEmulator, compileOptions);
1166     GetGlobalPoolAllocator()->unlock();
1167     mBuiltInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
1168 
1169     if (compileOptions.scalarizeVecAndMatConstructorArgs)
1170     {
1171         if (!ScalarizeVecAndMatConstructorArgs(this, root, &mSymbolTable))
1172         {
1173             return false;
1174         }
1175     }
1176 
1177     if (compileOptions.forceShaderPrecisionHighpToMediump)
1178     {
1179         if (!ForceShaderPrecisionToMediump(root, &mSymbolTable, mShaderType))
1180         {
1181             return false;
1182         }
1183     }
1184 
1185     ASSERT(!mVariablesCollected);
1186     CollectVariables(root, &mAttributes, &mOutputVariables, &mUniforms, &mInputVaryings,
1187                      &mOutputVaryings, &mSharedVariables, &mUniformBlocks, &mShaderStorageBlocks,
1188                      mResources.HashFunction, &mSymbolTable, mShaderType, mExtensionBehavior,
1189                      mResources, mTessControlShaderOutputVertices);
1190     collectInterfaceBlocks();
1191     mVariablesCollected = true;
1192     if (compileOptions.useUnusedStandardSharedBlocks)
1193     {
1194         if (!useAllMembersInUnusedStandardAndSharedBlocks(root))
1195         {
1196             return false;
1197         }
1198     }
1199     if (compileOptions.enforcePackingRestrictions)
1200     {
1201         int maxUniformVectors = GetMaxUniformVectorsForShaderType(mShaderType, mResources);
1202         if (mShaderType == GL_VERTEX_SHADER && compileOptions.emulateClipOrigin)
1203         {
1204             --maxUniformVectors;
1205         }
1206         // Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec
1207         // Appendix A, section 7, the shader does not use too many uniforms.
1208         if (!CheckVariablesInPackingLimits(maxUniformVectors, mUniforms))
1209         {
1210             mDiagnostics.globalError("too many uniforms");
1211             return false;
1212         }
1213     }
1214     bool needInitializeOutputVariables =
1215         compileOptions.initOutputVariables && mShaderType != GL_COMPUTE_SHADER;
1216     needInitializeOutputVariables |=
1217         compileOptions.initFragmentOutputVariables && mShaderType == GL_FRAGMENT_SHADER;
1218     if (needInitializeOutputVariables)
1219     {
1220         if (!initializeOutputVariables(root))
1221         {
1222             return false;
1223         }
1224     }
1225 
1226     // Removing invariant declarations must be done after collecting variables.
1227     // Otherwise, built-in invariant declarations don't apply.
1228     if (RemoveInvariant(mShaderType, mShaderVersion, mOutputType, compileOptions))
1229     {
1230         if (!RemoveInvariantDeclaration(this, root))
1231         {
1232             return false;
1233         }
1234     }
1235 
1236     // gl_Position is always written in compatibility output mode.
1237     // It may have been already initialized among other output variables, in that case we don't
1238     // need to initialize it twice.
1239     if (mShaderType == GL_VERTEX_SHADER && !mGLPositionInitialized &&
1240         (compileOptions.initGLPosition || mOutputType == SH_GLSL_COMPATIBILITY_OUTPUT))
1241     {
1242         if (!initializeGLPosition(root))
1243         {
1244             return false;
1245         }
1246         mGLPositionInitialized = true;
1247     }
1248 
1249     // DeferGlobalInitializers needs to be run before other AST transformations that generate new
1250     // statements from expressions. But it's fine to run DeferGlobalInitializers after the above
1251     // SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST
1252     // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00.
1253     // Exception: if EXT_shader_non_constant_global_initializers is enabled, we must generate global
1254     // initializers before we generate the DAG, since initializers may call functions which must not
1255     // be optimized out
1256     if (!enableNonConstantInitializers &&
1257         !DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize,
1258                                  highPrecisionSupported, forceDeferNonConstGlobalInitializers,
1259                                  &mSymbolTable))
1260     {
1261         return false;
1262     }
1263 
1264     if (initializeLocalsAndGlobals)
1265     {
1266         // Initialize uninitialized local variables.
1267         // In some cases initializing can generate extra statements in the parent block, such as
1268         // when initializing nameless structs or initializing arrays in ESSL 1.00. In that case
1269         // we need to first simplify loop conditions. We've already separated declarations
1270         // earlier, which is also required. If we don't follow the Appendix A limitations, loop
1271         // init statements can declare arrays or nameless structs and have multiple
1272         // declarations.
1273 
1274         if (!shouldRunLoopAndIndexingValidation(compileOptions))
1275         {
1276             if (!SimplifyLoopConditions(this, root,
1277                                         IntermNodePatternMatcher::kArrayDeclaration |
1278                                             IntermNodePatternMatcher::kNamelessStructDeclaration,
1279                                         &getSymbolTable()))
1280             {
1281                 return false;
1282             }
1283         }
1284 
1285         if (!InitializeUninitializedLocals(this, root, getShaderVersion(), canUseLoopsToInitialize,
1286                                            highPrecisionSupported, &getSymbolTable()))
1287         {
1288             return false;
1289         }
1290     }
1291 
1292     if (getShaderType() == GL_VERTEX_SHADER && compileOptions.clampPointSize)
1293     {
1294         if (!ClampPointSize(this, root, mResources.MinPointSize, mResources.MaxPointSize,
1295                             &getSymbolTable()))
1296         {
1297             return false;
1298         }
1299     }
1300 
1301     if (getShaderType() == GL_FRAGMENT_SHADER && compileOptions.clampFragDepth)
1302     {
1303         if (!ClampFragDepth(this, root, &getSymbolTable()))
1304         {
1305             return false;
1306         }
1307     }
1308 
1309     if (compileOptions.rewriteRepeatedAssignToSwizzled)
1310     {
1311         if (!sh::RewriteRepeatedAssignToSwizzled(this, root))
1312         {
1313             return false;
1314         }
1315     }
1316 
1317     if (compileOptions.removeDynamicIndexingOfSwizzledVector)
1318     {
1319         if (!sh::RemoveDynamicIndexingOfSwizzledVector(this, root, &getSymbolTable(), nullptr))
1320         {
1321             return false;
1322         }
1323     }
1324 
1325     return true;
1326 }
1327 
postParseChecks(const TParseContext & parseContext)1328 bool TCompiler::postParseChecks(const TParseContext &parseContext)
1329 {
1330     std::stringstream errorMessage;
1331 
1332     if (parseContext.getTreeRoot() == nullptr)
1333     {
1334         errorMessage << "Shader parsing failed (mTreeRoot == nullptr)";
1335     }
1336 
1337     for (TType *type : parseContext.getDeferredArrayTypesToSize())
1338     {
1339         errorMessage << "Unsized global array type: " << type->getBasicString();
1340     }
1341 
1342     if (!errorMessage.str().empty())
1343     {
1344         mDiagnostics.globalError(errorMessage.str().c_str());
1345         return false;
1346     }
1347 
1348     return true;
1349 }
1350 
compile(const char * const shaderStrings[],size_t numStrings,const ShCompileOptions & compileOptionsIn)1351 bool TCompiler::compile(const char *const shaderStrings[],
1352                         size_t numStrings,
1353                         const ShCompileOptions &compileOptionsIn)
1354 {
1355 #if defined(ANGLE_FUZZER_CORPUS_OUTPUT_DIR)
1356     DumpFuzzerCase(shaderStrings, numStrings, mShaderType, mShaderSpec, mOutputType,
1357                    compileOptionsIn);
1358 #endif  // defined(ANGLE_FUZZER_CORPUS_OUTPUT_DIR)
1359 
1360     if (numStrings == 0)
1361         return true;
1362 
1363     ShCompileOptions compileOptions = compileOptionsIn;
1364 
1365     // Apply key workarounds.
1366     if (shouldFlattenPragmaStdglInvariantAll())
1367     {
1368         // This should be harmless to do in all cases, but for the moment, do it only conditionally.
1369         compileOptions.flattenPragmaSTDGLInvariantAll = true;
1370     }
1371 
1372     TScopedPoolAllocator scopedAlloc(&allocator);
1373     TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
1374 
1375     if (root)
1376     {
1377         if (compileOptions.intermediateTree)
1378         {
1379             OutputTree(root, mInfoSink.info);
1380         }
1381 
1382         if (compileOptions.objectCode)
1383         {
1384             PerformanceDiagnostics perfDiagnostics(&mDiagnostics);
1385             if (!translate(root, compileOptions, &perfDiagnostics))
1386             {
1387                 return false;
1388             }
1389         }
1390 
1391         if (mShaderType == GL_VERTEX_SHADER)
1392         {
1393             bool lookForDrawID =
1394                 IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_multi_draw) &&
1395                 compileOptions.emulateGLDrawID;
1396             bool lookForBaseVertexBaseInstance =
1397                 IsExtensionEnabled(mExtensionBehavior,
1398                                    TExtension::ANGLE_base_vertex_base_instance_shader_builtin) &&
1399                 compileOptions.emulateGLBaseVertexBaseInstance;
1400 
1401             if (lookForDrawID || lookForBaseVertexBaseInstance)
1402             {
1403                 for (auto &uniform : mUniforms)
1404                 {
1405                     if (lookForDrawID && uniform.name == "angle_DrawID" &&
1406                         uniform.mappedName == "angle_DrawID")
1407                     {
1408                         uniform.name = "gl_DrawID";
1409                     }
1410                     else if (lookForBaseVertexBaseInstance && uniform.name == "angle_BaseVertex" &&
1411                              uniform.mappedName == "angle_BaseVertex")
1412                     {
1413                         uniform.name = "gl_BaseVertex";
1414                     }
1415                     else if (lookForBaseVertexBaseInstance &&
1416                              uniform.name == "angle_BaseInstance" &&
1417                              uniform.mappedName == "angle_BaseInstance")
1418                     {
1419                         uniform.name = "gl_BaseInstance";
1420                     }
1421                 }
1422             }
1423         }
1424 
1425         // The IntermNode tree doesn't need to be deleted here, since the
1426         // memory will be freed in a big chunk by the PoolAllocator.
1427         return true;
1428     }
1429     return false;
1430 }
1431 
initBuiltInSymbolTable(const ShBuiltInResources & resources)1432 bool TCompiler::initBuiltInSymbolTable(const ShBuiltInResources &resources)
1433 {
1434     if (resources.MaxDrawBuffers < 1)
1435     {
1436         return false;
1437     }
1438     if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1)
1439     {
1440         return false;
1441     }
1442 
1443     mSymbolTable.initializeBuiltIns(mShaderType, mShaderSpec, resources);
1444 
1445     return true;
1446 }
1447 
setResourceString()1448 void TCompiler::setResourceString()
1449 {
1450     std::ostringstream strstream = sh::InitializeStream<std::ostringstream>();
1451 
1452     // clang-format off
1453     strstream << ":MaxVertexAttribs:" << mResources.MaxVertexAttribs
1454         << ":MaxVertexUniformVectors:" << mResources.MaxVertexUniformVectors
1455         << ":MaxVaryingVectors:" << mResources.MaxVaryingVectors
1456         << ":MaxVertexTextureImageUnits:" << mResources.MaxVertexTextureImageUnits
1457         << ":MaxCombinedTextureImageUnits:" << mResources.MaxCombinedTextureImageUnits
1458         << ":MaxTextureImageUnits:" << mResources.MaxTextureImageUnits
1459         << ":MaxFragmentUniformVectors:" << mResources.MaxFragmentUniformVectors
1460         << ":MaxDrawBuffers:" << mResources.MaxDrawBuffers
1461         << ":OES_standard_derivatives:" << mResources.OES_standard_derivatives
1462         << ":OES_EGL_image_external:" << mResources.OES_EGL_image_external
1463         << ":OES_EGL_image_external_essl3:" << mResources.OES_EGL_image_external_essl3
1464         << ":NV_EGL_stream_consumer_external:" << mResources.NV_EGL_stream_consumer_external
1465         << ":ARB_texture_rectangle:" << mResources.ARB_texture_rectangle
1466         << ":EXT_draw_buffers:" << mResources.EXT_draw_buffers
1467         << ":FragmentPrecisionHigh:" << mResources.FragmentPrecisionHigh
1468         << ":MaxExpressionComplexity:" << mResources.MaxExpressionComplexity
1469         << ":MaxStatementDepth:" << mResources.MaxStatementDepth
1470         << ":MaxCallStackDepth:" << mResources.MaxCallStackDepth
1471         << ":MaxFunctionParameters:" << mResources.MaxFunctionParameters
1472         << ":EXT_blend_func_extended:" << mResources.EXT_blend_func_extended
1473         << ":EXT_conservative_depth:" << mResources.EXT_conservative_depth
1474         << ":EXT_frag_depth:" << mResources.EXT_frag_depth
1475         << ":EXT_primitive_bounding_box:" << mResources.EXT_primitive_bounding_box
1476         << ":OES_primitive_bounding_box:" << mResources.OES_primitive_bounding_box
1477         << ":EXT_separate_shader_objects:" << mResources.EXT_separate_shader_objects
1478         << ":EXT_shader_texture_lod:" << mResources.EXT_shader_texture_lod
1479         << ":EXT_shader_framebuffer_fetch:" << mResources.EXT_shader_framebuffer_fetch
1480         << ":EXT_shader_framebuffer_fetch_non_coherent:" << mResources.EXT_shader_framebuffer_fetch_non_coherent
1481         << ":NV_shader_framebuffer_fetch:" << mResources.NV_shader_framebuffer_fetch
1482         << ":ARM_shader_framebuffer_fetch:" << mResources.ARM_shader_framebuffer_fetch
1483         << ":ARM_shader_framebuffer_fetch_depth_stencil:" << mResources.ARM_shader_framebuffer_fetch_depth_stencil
1484         << ":OVR_multiview2:" << mResources.OVR_multiview2
1485         << ":OVR_multiview:" << mResources.OVR_multiview
1486         << ":EXT_YUV_target:" << mResources.EXT_YUV_target
1487         << ":EXT_geometry_shader:" << mResources.EXT_geometry_shader
1488         << ":OES_geometry_shader:" << mResources.OES_geometry_shader
1489         << ":OES_shader_io_blocks:" << mResources.OES_shader_io_blocks
1490         << ":EXT_shader_io_blocks:" << mResources.EXT_shader_io_blocks
1491         << ":EXT_gpu_shader5:" << mResources.EXT_gpu_shader5
1492         << ":OES_texture_3D:" << mResources.OES_texture_3D
1493         << ":MaxVertexOutputVectors:" << mResources.MaxVertexOutputVectors
1494         << ":MaxFragmentInputVectors:" << mResources.MaxFragmentInputVectors
1495         << ":MinProgramTexelOffset:" << mResources.MinProgramTexelOffset
1496         << ":MaxProgramTexelOffset:" << mResources.MaxProgramTexelOffset
1497         << ":MaxDualSourceDrawBuffers:" << mResources.MaxDualSourceDrawBuffers
1498         << ":MaxViewsOVR:" << mResources.MaxViewsOVR
1499         << ":NV_draw_buffers:" << mResources.NV_draw_buffers
1500         << ":ANGLE_multi_draw:" << mResources.ANGLE_multi_draw
1501         << ":ANGLE_base_vertex_base_instance_shader_builtin:" << mResources.ANGLE_base_vertex_base_instance_shader_builtin
1502         << ":APPLE_clip_distance:" << mResources.APPLE_clip_distance
1503         << ":OES_texture_cube_map_array:" << mResources.OES_texture_cube_map_array
1504         << ":EXT_texture_cube_map_array:" << mResources.EXT_texture_cube_map_array
1505         << ":EXT_texture_query_lod:" << mResources.EXT_texture_query_lod
1506         << ":EXT_texture_shadow_lod:" << mResources.EXT_texture_shadow_lod
1507         << ":EXT_shadow_samplers:" << mResources.EXT_shadow_samplers
1508         << ":OES_shader_multisample_interpolation:" << mResources.OES_shader_multisample_interpolation
1509         << ":OES_shader_image_atomic:" << mResources.OES_shader_image_atomic
1510         << ":EXT_tessellation_shader:" << mResources.EXT_tessellation_shader
1511         << ":OES_tessellation_shader:" << mResources.OES_tessellation_shader
1512         << ":OES_texture_buffer:" << mResources.OES_texture_buffer
1513         << ":EXT_texture_buffer:" << mResources.EXT_texture_buffer
1514         << ":OES_sample_variables:" << mResources.OES_sample_variables
1515         << ":EXT_clip_cull_distance:" << mResources.EXT_clip_cull_distance
1516         << ":ANGLE_clip_cull_distance:" << mResources.ANGLE_clip_cull_distance
1517         << ":MinProgramTextureGatherOffset:" << mResources.MinProgramTextureGatherOffset
1518         << ":MaxProgramTextureGatherOffset:" << mResources.MaxProgramTextureGatherOffset
1519         << ":MaxImageUnits:" << mResources.MaxImageUnits
1520         << ":MaxSamples:" << mResources.MaxSamples
1521         << ":MaxVertexImageUniforms:" << mResources.MaxVertexImageUniforms
1522         << ":MaxFragmentImageUniforms:" << mResources.MaxFragmentImageUniforms
1523         << ":MaxComputeImageUniforms:" << mResources.MaxComputeImageUniforms
1524         << ":MaxCombinedImageUniforms:" << mResources.MaxCombinedImageUniforms
1525         << ":MaxCombinedShaderOutputResources:" << mResources.MaxCombinedShaderOutputResources
1526         << ":MaxComputeWorkGroupCountX:" << mResources.MaxComputeWorkGroupCount[0]
1527         << ":MaxComputeWorkGroupCountY:" << mResources.MaxComputeWorkGroupCount[1]
1528         << ":MaxComputeWorkGroupCountZ:" << mResources.MaxComputeWorkGroupCount[2]
1529         << ":MaxComputeWorkGroupSizeX:" << mResources.MaxComputeWorkGroupSize[0]
1530         << ":MaxComputeWorkGroupSizeY:" << mResources.MaxComputeWorkGroupSize[1]
1531         << ":MaxComputeWorkGroupSizeZ:" << mResources.MaxComputeWorkGroupSize[2]
1532         << ":MaxComputeUniformComponents:" << mResources.MaxComputeUniformComponents
1533         << ":MaxComputeTextureImageUnits:" << mResources.MaxComputeTextureImageUnits
1534         << ":MaxComputeAtomicCounters:" << mResources.MaxComputeAtomicCounters
1535         << ":MaxComputeAtomicCounterBuffers:" << mResources.MaxComputeAtomicCounterBuffers
1536         << ":MaxVertexAtomicCounters:" << mResources.MaxVertexAtomicCounters
1537         << ":MaxFragmentAtomicCounters:" << mResources.MaxFragmentAtomicCounters
1538         << ":MaxCombinedAtomicCounters:" << mResources.MaxCombinedAtomicCounters
1539         << ":MaxAtomicCounterBindings:" << mResources.MaxAtomicCounterBindings
1540         << ":MaxVertexAtomicCounterBuffers:" << mResources.MaxVertexAtomicCounterBuffers
1541         << ":MaxFragmentAtomicCounterBuffers:" << mResources.MaxFragmentAtomicCounterBuffers
1542         << ":MaxCombinedAtomicCounterBuffers:" << mResources.MaxCombinedAtomicCounterBuffers
1543         << ":MaxAtomicCounterBufferSize:" << mResources.MaxAtomicCounterBufferSize
1544         << ":MaxGeometryUniformComponents:" << mResources.MaxGeometryUniformComponents
1545         << ":MaxGeometryUniformBlocks:" << mResources.MaxGeometryUniformBlocks
1546         << ":MaxGeometryInputComponents:" << mResources.MaxGeometryInputComponents
1547         << ":MaxGeometryOutputComponents:" << mResources.MaxGeometryOutputComponents
1548         << ":MaxGeometryOutputVertices:" << mResources.MaxGeometryOutputVertices
1549         << ":MaxGeometryTotalOutputComponents:" << mResources.MaxGeometryTotalOutputComponents
1550         << ":MaxGeometryTextureImageUnits:" << mResources.MaxGeometryTextureImageUnits
1551         << ":MaxGeometryAtomicCounterBuffers:" << mResources.MaxGeometryAtomicCounterBuffers
1552         << ":MaxGeometryAtomicCounters:" << mResources.MaxGeometryAtomicCounters
1553         << ":MaxGeometryShaderStorageBlocks:" << mResources.MaxGeometryShaderStorageBlocks
1554         << ":MaxGeometryShaderInvocations:" << mResources.MaxGeometryShaderInvocations
1555         << ":MaxGeometryImageUniforms:" << mResources.MaxGeometryImageUniforms
1556         << ":MaxClipDistances" << mResources.MaxClipDistances
1557         << ":MaxCullDistances" << mResources.MaxCullDistances
1558         << ":MaxCombinedClipAndCullDistances" << mResources.MaxCombinedClipAndCullDistances
1559         << ":MaxTessControlInputComponents:" << mResources.MaxTessControlInputComponents
1560         << ":MaxTessControlOutputComponents:" << mResources.MaxTessControlOutputComponents
1561         << ":MaxTessControlTextureImageUnits:" << mResources.MaxTessControlTextureImageUnits
1562         << ":MaxTessControlUniformComponents:" << mResources.MaxTessControlUniformComponents
1563         << ":MaxTessControlTotalOutputComponents:" << mResources.MaxTessControlTotalOutputComponents
1564         << ":MaxTessControlImageUniforms:" << mResources.MaxTessControlImageUniforms
1565         << ":MaxTessControlAtomicCounters:" << mResources.MaxTessControlAtomicCounters
1566         << ":MaxTessControlAtomicCounterBuffers:" << mResources.MaxTessControlAtomicCounterBuffers
1567         << ":MaxTessPatchComponents:" << mResources.MaxTessPatchComponents
1568         << ":MaxPatchVertices:" << mResources.MaxPatchVertices
1569         << ":MaxTessGenLevel:" << mResources.MaxTessGenLevel
1570         << ":MaxTessEvaluationInputComponents:" << mResources.MaxTessEvaluationInputComponents
1571         << ":MaxTessEvaluationOutputComponents:" << mResources.MaxTessEvaluationOutputComponents
1572         << ":MaxTessEvaluationTextureImageUnits:" << mResources.MaxTessEvaluationTextureImageUnits
1573         << ":MaxTessEvaluationUniformComponents:" << mResources.MaxTessEvaluationUniformComponents
1574         << ":MaxTessEvaluationImageUniforms:" << mResources.MaxTessEvaluationImageUniforms
1575         << ":MaxTessEvaluationAtomicCounters:" << mResources.MaxTessEvaluationAtomicCounters
1576         << ":MaxTessEvaluationAtomicCounterBuffers:" << mResources.MaxTessEvaluationAtomicCounterBuffers;
1577     // clang-format on
1578 
1579     mBuiltInResourcesString = strstream.str();
1580 }
1581 
collectInterfaceBlocks()1582 void TCompiler::collectInterfaceBlocks()
1583 {
1584     ASSERT(mInterfaceBlocks.empty());
1585     mInterfaceBlocks.reserve(mUniformBlocks.size() + mShaderStorageBlocks.size());
1586     mInterfaceBlocks.insert(mInterfaceBlocks.end(), mUniformBlocks.begin(), mUniformBlocks.end());
1587     mInterfaceBlocks.insert(mInterfaceBlocks.end(), mShaderStorageBlocks.begin(),
1588                             mShaderStorageBlocks.end());
1589 }
1590 
clearResults()1591 void TCompiler::clearResults()
1592 {
1593     mInfoSink.info.erase();
1594     mInfoSink.obj.erase();
1595     mInfoSink.debug.erase();
1596     mDiagnostics.resetErrorCount();
1597 
1598     mMetadataFlags.reset();
1599     mSpecConstUsageBits.reset();
1600 
1601     mAttributes.clear();
1602     mOutputVariables.clear();
1603     mUniforms.clear();
1604     mInputVaryings.clear();
1605     mOutputVaryings.clear();
1606     mSharedVariables.clear();
1607     mInterfaceBlocks.clear();
1608     mUniformBlocks.clear();
1609     mShaderStorageBlocks.clear();
1610     mVariablesCollected    = false;
1611     mGLPositionInitialized = false;
1612 
1613     mNumViews = -1;
1614 
1615     mClipDistanceSize = 0;
1616     mCullDistanceSize = 0;
1617 
1618     mGeometryShaderInputPrimitiveType  = EptUndefined;
1619     mGeometryShaderOutputPrimitiveType = EptUndefined;
1620     mGeometryShaderInvocations         = 0;
1621     mGeometryShaderMaxVertices         = -1;
1622 
1623     mTessControlShaderOutputVertices            = 0;
1624     mTessEvaluationShaderInputPrimitiveType     = EtetUndefined;
1625     mTessEvaluationShaderInputVertexSpacingType = EtetUndefined;
1626     mTessEvaluationShaderInputOrderingType      = EtetUndefined;
1627     mTessEvaluationShaderInputPointType         = EtetUndefined;
1628 
1629     mBuiltInFunctionEmulator.cleanup();
1630 
1631     mNameMap.clear();
1632 
1633     mSourcePath = nullptr;
1634 
1635     mSymbolTable.clearCompilationResults();
1636 }
1637 
initCallDag(TIntermNode * root)1638 bool TCompiler::initCallDag(TIntermNode *root)
1639 {
1640     mCallDag.clear();
1641 
1642     switch (mCallDag.init(root, &mDiagnostics))
1643     {
1644         case CallDAG::INITDAG_SUCCESS:
1645             return true;
1646         case CallDAG::INITDAG_RECURSION:
1647         case CallDAG::INITDAG_UNDEFINED:
1648             // Error message has already been written out.
1649             ASSERT(mDiagnostics.numErrors() > 0);
1650             return false;
1651     }
1652 
1653     UNREACHABLE();
1654     return true;
1655 }
1656 
checkCallDepth()1657 bool TCompiler::checkCallDepth()
1658 {
1659     std::vector<int> depths(mCallDag.size());
1660 
1661     for (size_t i = 0; i < mCallDag.size(); i++)
1662     {
1663         int depth                     = 0;
1664         const CallDAG::Record &record = mCallDag.getRecordFromIndex(i);
1665 
1666         for (int calleeIndex : record.callees)
1667         {
1668             depth = std::max(depth, depths[calleeIndex] + 1);
1669         }
1670 
1671         depths[i] = depth;
1672 
1673         if (depth >= mResources.MaxCallStackDepth)
1674         {
1675             // Trace back the function chain to have a meaningful info log.
1676             std::stringstream errorStream = sh::InitializeStream<std::stringstream>();
1677             errorStream << "Call stack too deep (larger than " << mResources.MaxCallStackDepth
1678                         << ") with the following call chain: "
1679                         << record.node->getFunction()->name();
1680 
1681             int currentFunction = static_cast<int>(i);
1682             int currentDepth    = depth;
1683 
1684             while (currentFunction != -1)
1685             {
1686                 errorStream
1687                     << " -> "
1688                     << mCallDag.getRecordFromIndex(currentFunction).node->getFunction()->name();
1689 
1690                 int nextFunction = -1;
1691                 for (const int &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
1692                 {
1693                     if (depths[calleeIndex] == currentDepth - 1)
1694                     {
1695                         currentDepth--;
1696                         nextFunction = calleeIndex;
1697                     }
1698                 }
1699 
1700                 currentFunction = nextFunction;
1701             }
1702 
1703             std::string errorStr = errorStream.str();
1704             mDiagnostics.globalError(errorStr.c_str());
1705 
1706             return false;
1707         }
1708     }
1709 
1710     return true;
1711 }
1712 
tagUsedFunctions()1713 bool TCompiler::tagUsedFunctions()
1714 {
1715     // Search from main, starting from the end of the DAG as it usually is the root.
1716     for (size_t i = mCallDag.size(); i-- > 0;)
1717     {
1718         if (mCallDag.getRecordFromIndex(i).node->getFunction()->isMain())
1719         {
1720             internalTagUsedFunction(i);
1721             return true;
1722         }
1723     }
1724 
1725     mDiagnostics.globalError("Missing main()");
1726     return false;
1727 }
1728 
internalTagUsedFunction(size_t index)1729 void TCompiler::internalTagUsedFunction(size_t index)
1730 {
1731     if (mFunctionMetadata[index].used)
1732     {
1733         return;
1734     }
1735 
1736     mFunctionMetadata[index].used = true;
1737 
1738     for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees)
1739     {
1740         internalTagUsedFunction(calleeIndex);
1741     }
1742 }
1743 
pruneUnusedFunctions(TIntermBlock * root)1744 bool TCompiler::pruneUnusedFunctions(TIntermBlock *root)
1745 {
1746     TIntermSequence *sequence = root->getSequence();
1747 
1748     size_t writeIndex = 0;
1749     for (size_t readIndex = 0; readIndex < sequence->size(); ++readIndex)
1750     {
1751         TIntermNode *node = sequence->at(readIndex);
1752 
1753         // Keep anything that's not unused.
1754         const TFunction *function = nullptr;
1755         const bool shouldPrune =
1756             IsTopLevelNodeUnusedFunction(mCallDag, mFunctionMetadata, node, &function);
1757         if (!shouldPrune)
1758         {
1759             (*sequence)[writeIndex++] = node;
1760             continue;
1761         }
1762 
1763         // If a function is unused, it may have a struct declaration in its return value which
1764         // shouldn't be pruned.  In that case, replace the function definition with the struct
1765         // definition.
1766         ASSERT(function != nullptr);
1767         const TType &returnType = function->getReturnType();
1768         if (!returnType.isStructSpecifier())
1769         {
1770             continue;
1771         }
1772 
1773         TVariable *structVariable =
1774             new TVariable(&mSymbolTable, kEmptyImmutableString, &returnType, SymbolType::Empty);
1775         TIntermSymbol *structSymbol           = new TIntermSymbol(structVariable);
1776         TIntermDeclaration *structDeclaration = new TIntermDeclaration;
1777         structDeclaration->appendDeclarator(structSymbol);
1778 
1779         structSymbol->setLine(node->getLine());
1780         structDeclaration->setLine(node->getLine());
1781 
1782         (*sequence)[writeIndex++] = structDeclaration;
1783     }
1784 
1785     sequence->resize(writeIndex);
1786 
1787     return validateAST(root);
1788 }
1789 
limitExpressionComplexity(TIntermBlock * root)1790 bool TCompiler::limitExpressionComplexity(TIntermBlock *root)
1791 {
1792     if (!IsASTDepthBelowLimit(root, mResources.MaxExpressionComplexity))
1793     {
1794         mDiagnostics.globalError("Expression too complex.");
1795         return false;
1796     }
1797 
1798     if (!ValidateMaxParameters(root, mResources.MaxFunctionParameters))
1799     {
1800         mDiagnostics.globalError("Function has too many parameters.");
1801         return false;
1802     }
1803 
1804     return true;
1805 }
1806 
initializeGLPosition(TIntermBlock * root)1807 bool TCompiler::initializeGLPosition(TIntermBlock *root)
1808 {
1809     InitVariableList list;
1810     AddBuiltInToInitList(&mSymbolTable, mShaderVersion, root, "gl_Position", &list);
1811 
1812     if (!list.empty())
1813     {
1814         return InitializeVariables(this, root, list, &mSymbolTable, mShaderVersion,
1815                                    mExtensionBehavior, false, false);
1816     }
1817 
1818     return true;
1819 }
1820 
useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock * root)1821 bool TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)
1822 {
1823     sh::InterfaceBlockList list;
1824 
1825     for (const sh::InterfaceBlock &block : mUniformBlocks)
1826     {
1827         if (!block.staticUse &&
1828             (block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED))
1829         {
1830             list.push_back(block);
1831         }
1832     }
1833 
1834     return sh::UseInterfaceBlockFields(this, root, list, mSymbolTable);
1835 }
1836 
initializeOutputVariables(TIntermBlock * root)1837 bool TCompiler::initializeOutputVariables(TIntermBlock *root)
1838 {
1839     InitVariableList list;
1840 
1841     for (TIntermNode *node : *root->getSequence())
1842     {
1843         TIntermDeclaration *asDecl = node->getAsDeclarationNode();
1844         if (asDecl == nullptr)
1845         {
1846             continue;
1847         }
1848 
1849         TIntermSymbol *symbol = asDecl->getSequence()->front()->getAsSymbolNode();
1850         if (symbol == nullptr)
1851         {
1852             TIntermBinary *initNode = asDecl->getSequence()->front()->getAsBinaryNode();
1853             ASSERT(initNode->getOp() == EOpInitialize);
1854             symbol = initNode->getLeft()->getAsSymbolNode();
1855         }
1856         ASSERT(symbol);
1857 
1858         // inout variables represent the context of the framebuffer when the draw call starts, so
1859         // they have to be considered as already initialized.
1860         const TQualifier qualifier = symbol->getType().getQualifier();
1861         if (qualifier != EvqFragmentInOut && IsShaderOut(symbol->getType().getQualifier()))
1862         {
1863             list.push_back(&symbol->variable());
1864         }
1865     }
1866 
1867     // Initialize built-in outputs as well.
1868     const std::vector<ShaderVariable> &outputVariables =
1869         mShaderType == GL_FRAGMENT_SHADER ? mOutputVariables : mOutputVaryings;
1870 
1871     for (const ShaderVariable &var : outputVariables)
1872     {
1873         if (var.isFragmentInOut || !var.isBuiltIn())
1874         {
1875             continue;
1876         }
1877 
1878         AddBuiltInToInitList(&mSymbolTable, mShaderVersion, root, var.name.c_str(), &list);
1879         if (var.name == "gl_Position")
1880         {
1881             ASSERT(!mGLPositionInitialized);
1882             mGLPositionInitialized = true;
1883         }
1884     }
1885 
1886     return InitializeVariables(this, root, list, &mSymbolTable, mShaderVersion, mExtensionBehavior,
1887                                false, false);
1888 }
1889 
getExtensionBehavior() const1890 const TExtensionBehavior &TCompiler::getExtensionBehavior() const
1891 {
1892     return mExtensionBehavior;
1893 }
1894 
getSourcePath() const1895 const char *TCompiler::getSourcePath() const
1896 {
1897     return mSourcePath;
1898 }
1899 
getResources() const1900 const ShBuiltInResources &TCompiler::getResources() const
1901 {
1902     return mResources;
1903 }
1904 
getBuiltInFunctionEmulator() const1905 const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const
1906 {
1907     return mBuiltInFunctionEmulator;
1908 }
1909 
isVaryingDefined(const char * varyingName)1910 bool TCompiler::isVaryingDefined(const char *varyingName)
1911 {
1912     ASSERT(mVariablesCollected);
1913     for (size_t ii = 0; ii < mInputVaryings.size(); ++ii)
1914     {
1915         if (mInputVaryings[ii].name == varyingName)
1916         {
1917             return true;
1918         }
1919     }
1920     for (size_t ii = 0; ii < mOutputVaryings.size(); ++ii)
1921     {
1922         if (mOutputVaryings[ii].name == varyingName)
1923         {
1924             return true;
1925         }
1926     }
1927 
1928     return false;
1929 }
1930 
1931 }  // namespace sh
1932