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