• 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 #include "common/utilities.h"
13 #include "compiler/translator/CallDAG.h"
14 #include "compiler/translator/CollectVariables.h"
15 #include "compiler/translator/Initialize.h"
16 #include "compiler/translator/IsASTDepthBelowLimit.h"
17 #include "compiler/translator/OutputTree.h"
18 #include "compiler/translator/ParseContext.h"
19 #include "compiler/translator/ValidateLimitations.h"
20 #include "compiler/translator/ValidateMaxParameters.h"
21 #include "compiler/translator/ValidateOutputs.h"
22 #include "compiler/translator/ValidateVaryingLocations.h"
23 #include "compiler/translator/VariablePacker.h"
24 #include "compiler/translator/tree_ops/AddAndTrueToLoopCondition.h"
25 #include "compiler/translator/tree_ops/ClampFragDepth.h"
26 #include "compiler/translator/tree_ops/ClampPointSize.h"
27 #include "compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h"
28 #include "compiler/translator/tree_ops/DeferGlobalInitializers.h"
29 #include "compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h"
30 #include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h"
31 #include "compiler/translator/tree_ops/EmulatePrecision.h"
32 #include "compiler/translator/tree_ops/FoldExpressions.h"
33 #include "compiler/translator/tree_ops/InitializeVariables.h"
34 #include "compiler/translator/tree_ops/PruneEmptyCases.h"
35 #include "compiler/translator/tree_ops/PruneNoOps.h"
36 #include "compiler/translator/tree_ops/RegenerateStructNames.h"
37 #include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h"
38 #include "compiler/translator/tree_ops/RemoveInvariantDeclaration.h"
39 #include "compiler/translator/tree_ops/RemovePow.h"
40 #include "compiler/translator/tree_ops/RemoveUnreferencedVariables.h"
41 #include "compiler/translator/tree_ops/RewriteDoWhile.h"
42 #include "compiler/translator/tree_ops/RewriteRepeatedAssignToSwizzled.h"
43 #include "compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h"
44 #include "compiler/translator/tree_ops/SeparateDeclarations.h"
45 #include "compiler/translator/tree_ops/SimplifyLoopConditions.h"
46 #include "compiler/translator/tree_ops/SplitSequenceOperator.h"
47 #include "compiler/translator/tree_ops/UnfoldShortCircuitAST.h"
48 #include "compiler/translator/tree_ops/UseInterfaceBlockFields.h"
49 #include "compiler/translator/tree_ops/VectorizeVectorScalarArithmetic.h"
50 #include "compiler/translator/tree_util/BuiltIn_autogen.h"
51 #include "compiler/translator/tree_util/IntermNodePatternMatcher.h"
52 #include "compiler/translator/tree_util/ReplaceShadowingVariables.h"
53 #include "compiler/translator/util.h"
54 #include "third_party/compiler/ArrayBoundsClamper.h"
55 
56 namespace sh
57 {
58 
59 namespace
60 {
61 
62 #if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
DumpFuzzerCase(char const * const * shaderStrings,size_t numStrings,uint32_t type,uint32_t spec,uint32_t output,uint64_t options)63 void DumpFuzzerCase(char const *const *shaderStrings,
64                     size_t numStrings,
65                     uint32_t type,
66                     uint32_t spec,
67                     uint32_t output,
68                     uint64_t options)
69 {
70     static int fileIndex = 0;
71 
72     std::ostringstream o = sh::InitializeStream<std::ostringstream>();
73     o << "corpus/" << fileIndex++ << ".sample";
74     std::string s = o.str();
75 
76     // Must match the input format of the fuzzer
77     FILE *f = fopen(s.c_str(), "w");
78     fwrite(&type, sizeof(type), 1, f);
79     fwrite(&spec, sizeof(spec), 1, f);
80     fwrite(&output, sizeof(output), 1, f);
81     fwrite(&options, sizeof(options), 1, f);
82 
83     char zero[128 - 20] = {0};
84     fwrite(&zero, 128 - 20, 1, f);
85 
86     for (size_t i = 0; i < numStrings; i++)
87     {
88         fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f);
89     }
90     fwrite(&zero, 1, 1, f);
91 
92     fclose(f);
93 }
94 #endif  // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
95 }  // anonymous namespace
96 
IsGLSL130OrNewer(ShShaderOutput output)97 bool IsGLSL130OrNewer(ShShaderOutput output)
98 {
99     return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
100             output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
101             output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT ||
102             output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
103             output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
104 }
105 
IsGLSL420OrNewer(ShShaderOutput output)106 bool IsGLSL420OrNewer(ShShaderOutput output)
107 {
108     return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
109             output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
110 }
111 
IsGLSL410OrOlder(ShShaderOutput output)112 bool IsGLSL410OrOlder(ShShaderOutput output)
113 {
114     return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
115             output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
116             output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
117 }
118 
RemoveInvariant(sh::GLenum shaderType,int shaderVersion,ShShaderOutput outputType,ShCompileOptions compileOptions)119 bool RemoveInvariant(sh::GLenum shaderType,
120                      int shaderVersion,
121                      ShShaderOutput outputType,
122                      ShCompileOptions compileOptions)
123 {
124     if (shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
125         return true;
126 
127     if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
128         shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER)
129         return true;
130 
131     return false;
132 }
133 
GetGlobalMaxTokenSize(ShShaderSpec spec)134 size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
135 {
136     // WebGL defines a max token length of 256, while ES2 leaves max token
137     // size undefined. ES3 defines a max size of 1024 characters.
138     switch (spec)
139     {
140         case SH_WEBGL_SPEC:
141             return 256;
142         default:
143             return 1024;
144     }
145 }
146 
GetMaxUniformVectorsForShaderType(GLenum shaderType,const ShBuiltInResources & resources)147 int GetMaxUniformVectorsForShaderType(GLenum shaderType, const ShBuiltInResources &resources)
148 {
149     switch (shaderType)
150     {
151         case GL_VERTEX_SHADER:
152             return resources.MaxVertexUniformVectors;
153         case GL_FRAGMENT_SHADER:
154             return resources.MaxFragmentUniformVectors;
155 
156         // TODO (jiawei.shao@intel.com): check if we need finer-grained component counting
157         case GL_COMPUTE_SHADER:
158             return resources.MaxComputeUniformComponents / 4;
159         case GL_GEOMETRY_SHADER_EXT:
160             return resources.MaxGeometryUniformComponents / 4;
161         default:
162             UNREACHABLE();
163             return -1;
164     }
165 }
166 
167 namespace
168 {
169 
170 class TScopedPoolAllocator
171 {
172   public:
TScopedPoolAllocator(angle::PoolAllocator * allocator)173     TScopedPoolAllocator(angle::PoolAllocator *allocator) : mAllocator(allocator)
174     {
175         mAllocator->push();
176         SetGlobalPoolAllocator(mAllocator);
177     }
~TScopedPoolAllocator()178     ~TScopedPoolAllocator()
179     {
180         SetGlobalPoolAllocator(nullptr);
181         mAllocator->pop();
182     }
183 
184   private:
185     angle::PoolAllocator *mAllocator;
186 };
187 
188 class TScopedSymbolTableLevel
189 {
190   public:
TScopedSymbolTableLevel(TSymbolTable * table)191     TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
192     {
193         ASSERT(mTable->isEmpty());
194         mTable->push();
195     }
~TScopedSymbolTableLevel()196     ~TScopedSymbolTableLevel()
197     {
198         while (!mTable->isEmpty())
199             mTable->pop();
200     }
201 
202   private:
203     TSymbolTable *mTable;
204 };
205 
GetMaxShaderVersionForSpec(ShShaderSpec spec)206 int GetMaxShaderVersionForSpec(ShShaderSpec spec)
207 {
208     switch (spec)
209     {
210         case SH_GLES2_SPEC:
211         case SH_WEBGL_SPEC:
212             return 100;
213         case SH_GLES3_SPEC:
214         case SH_WEBGL2_SPEC:
215             return 300;
216         case SH_GLES3_1_SPEC:
217         case SH_WEBGL3_SPEC:
218             return 310;
219         case SH_GL_CORE_SPEC:
220         case SH_GL_COMPATIBILITY_SPEC:
221             return 460;
222         default:
223             UNREACHABLE();
224             return 0;
225     }
226 }
227 
ValidateFragColorAndFragData(GLenum shaderType,int shaderVersion,const TSymbolTable & symbolTable,TDiagnostics * diagnostics)228 bool ValidateFragColorAndFragData(GLenum shaderType,
229                                   int shaderVersion,
230                                   const TSymbolTable &symbolTable,
231                                   TDiagnostics *diagnostics)
232 {
233     if (shaderVersion > 100 || shaderType != GL_FRAGMENT_SHADER)
234     {
235         return true;
236     }
237 
238     bool usesFragColor = false;
239     bool usesFragData  = false;
240     // This validation is a bit stricter than the spec - it's only an error to write to
241     // both FragData and FragColor. But because it's better not to have reads from undefined
242     // variables, we always return an error if they are both referenced, rather than only if they
243     // are written.
244     if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_FragColor()) ||
245         symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()))
246     {
247         usesFragColor = true;
248     }
249     // Extension variables may not always be initialized (saves some time at symbol table init).
250     bool secondaryFragDataUsed =
251         symbolTable.gl_SecondaryFragDataEXT() != nullptr &&
252         symbolTable.isStaticallyUsed(*symbolTable.gl_SecondaryFragDataEXT());
253     if (symbolTable.isStaticallyUsed(*symbolTable.gl_FragData()) || secondaryFragDataUsed)
254     {
255         usesFragData = true;
256     }
257     if (usesFragColor && usesFragData)
258     {
259         const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
260         if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()) ||
261             secondaryFragDataUsed)
262         {
263             errorMessage =
264                 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
265                 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
266         }
267         diagnostics->globalError(errorMessage);
268         return false;
269     }
270     return true;
271 }
272 
273 }  // namespace
274 
TShHandleBase()275 TShHandleBase::TShHandleBase()
276 {
277     allocator.push();
278     SetGlobalPoolAllocator(&allocator);
279 }
280 
~TShHandleBase()281 TShHandleBase::~TShHandleBase()
282 {
283     SetGlobalPoolAllocator(nullptr);
284     allocator.popAll();
285 }
286 
TCompiler(sh::GLenum type,ShShaderSpec spec,ShShaderOutput output)287 TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
288     : mVariablesCollected(false),
289       mGLPositionInitialized(false),
290       mShaderType(type),
291       mShaderSpec(spec),
292       mOutputType(output),
293       mBuiltInFunctionEmulator(),
294       mDiagnostics(mInfoSink.info),
295       mSourcePath(nullptr),
296       mComputeShaderLocalSizeDeclared(false),
297       mComputeShaderLocalSize(1),
298       mGeometryShaderMaxVertices(-1),
299       mGeometryShaderInvocations(0),
300       mGeometryShaderInputPrimitiveType(EptUndefined),
301       mGeometryShaderOutputPrimitiveType(EptUndefined)
302 {}
303 
~TCompiler()304 TCompiler::~TCompiler() {}
305 
shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const306 bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const
307 {
308     // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API,
309     // validate loop and indexing as well (to verify that the shader only uses minimal functionality
310     // of ESSL 1.00 as in Appendix A of the spec).
311     return (IsWebGLBasedSpec(mShaderSpec) && mShaderVersion == 100) ||
312            (compileOptions & SH_VALIDATE_LOOP_INDEXING);
313 }
314 
Init(const ShBuiltInResources & resources)315 bool TCompiler::Init(const ShBuiltInResources &resources)
316 {
317     SetGlobalPoolAllocator(&allocator);
318 
319     // Generate built-in symbol table.
320     if (!initBuiltInSymbolTable(resources))
321         return false;
322 
323     mResources = resources;
324     setResourceString();
325 
326     InitExtensionBehavior(resources, mExtensionBehavior);
327     mArrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
328     return true;
329 }
330 
compileTreeForTesting(const char * const shaderStrings[],size_t numStrings,ShCompileOptions compileOptions)331 TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],
332                                                size_t numStrings,
333                                                ShCompileOptions compileOptions)
334 {
335     return compileTreeImpl(shaderStrings, numStrings, compileOptions);
336 }
337 
compileTreeImpl(const char * const shaderStrings[],size_t numStrings,const ShCompileOptions compileOptions)338 TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
339                                          size_t numStrings,
340                                          const ShCompileOptions compileOptions)
341 {
342     clearResults();
343 
344     ASSERT(numStrings > 0);
345     ASSERT(GetGlobalPoolAllocator());
346 
347     // Reset the extension behavior for each compilation unit.
348     ResetExtensionBehavior(mExtensionBehavior);
349 
350     // If gl_DrawID is not supported, remove it from the available extensions
351     // Currently we only allow emulation of gl_DrawID
352     const bool glDrawIDSupported = (compileOptions & SH_EMULATE_GL_DRAW_ID) != 0u;
353     if (!glDrawIDSupported)
354     {
355         auto it = mExtensionBehavior.find(TExtension::ANGLE_multi_draw);
356         if (it != mExtensionBehavior.end())
357         {
358             mExtensionBehavior.erase(it);
359         }
360     }
361 
362     const bool glBaseVertexBaseInstanceSupported =
363         (compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0u;
364     if (!glBaseVertexBaseInstanceSupported)
365     {
366         auto it = mExtensionBehavior.find(TExtension::ANGLE_base_vertex_base_instance);
367         if (it != mExtensionBehavior.end())
368         {
369             mExtensionBehavior.erase(it);
370         }
371     }
372 
373     // First string is path of source file if flag is set. The actual source follows.
374     size_t firstSource = 0;
375     if (compileOptions & SH_SOURCE_PATH)
376     {
377         mSourcePath = shaderStrings[0];
378         ++firstSource;
379     }
380 
381     TParseContext parseContext(mSymbolTable, mExtensionBehavior, mShaderType, mShaderSpec,
382                                compileOptions, !IsDesktopGLSpec(mShaderSpec), &mDiagnostics,
383                                getResources());
384 
385     parseContext.setFragmentPrecisionHighOnESSL1(mResources.FragmentPrecisionHigh == 1);
386 
387     // We preserve symbols at the built-in level from compile-to-compile.
388     // Start pushing the user-defined symbols at global level.
389     TScopedSymbolTableLevel globalLevel(&mSymbolTable);
390     ASSERT(mSymbolTable.atGlobalLevel());
391 
392     // Parse shader.
393     if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr,
394                        &parseContext) != 0)
395     {
396         return nullptr;
397     }
398 
399     if (parseContext.getTreeRoot() == nullptr)
400     {
401         return nullptr;
402     }
403 
404     setASTMetadata(parseContext);
405 
406     if (!checkShaderVersion(&parseContext))
407     {
408         return nullptr;
409     }
410 
411     TIntermBlock *root = parseContext.getTreeRoot();
412     if (!checkAndSimplifyAST(root, parseContext, compileOptions))
413     {
414         return nullptr;
415     }
416 
417     return root;
418 }
419 
checkShaderVersion(TParseContext * parseContext)420 bool TCompiler::checkShaderVersion(TParseContext *parseContext)
421 {
422     if (GetMaxShaderVersionForSpec(mShaderSpec) < mShaderVersion)
423     {
424         mDiagnostics.globalError("unsupported shader version");
425         return false;
426     }
427 
428     ASSERT(parseContext);
429     switch (mShaderType)
430     {
431         case GL_COMPUTE_SHADER:
432             if (mShaderVersion < 310)
433             {
434                 mDiagnostics.globalError("Compute shader is not supported in this shader version.");
435                 return false;
436             }
437             break;
438 
439         case GL_GEOMETRY_SHADER_EXT:
440             if (mShaderVersion < 310)
441             {
442                 mDiagnostics.globalError(
443                     "Geometry shader is not supported in this shader version.");
444                 return false;
445             }
446             else
447             {
448                 ASSERT(mShaderVersion == 310);
449                 if (!parseContext->checkCanUseExtension(sh::TSourceLoc(),
450                                                         TExtension::EXT_geometry_shader))
451                 {
452                     return false;
453                 }
454             }
455             break;
456 
457         default:
458             break;
459     }
460 
461     return true;
462 }
463 
setASTMetadata(const TParseContext & parseContext)464 void TCompiler::setASTMetadata(const TParseContext &parseContext)
465 {
466     mShaderVersion = parseContext.getShaderVersion();
467 
468     mPragma = parseContext.pragma();
469     mSymbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);
470 
471     mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
472     mComputeShaderLocalSize         = parseContext.getComputeShaderLocalSize();
473 
474     mNumViews = parseContext.getNumViews();
475 
476     if (mShaderType == GL_GEOMETRY_SHADER_EXT)
477     {
478         mGeometryShaderInputPrimitiveType  = parseContext.getGeometryShaderInputPrimitiveType();
479         mGeometryShaderOutputPrimitiveType = parseContext.getGeometryShaderOutputPrimitiveType();
480         mGeometryShaderMaxVertices         = parseContext.getGeometryShaderMaxVertices();
481         mGeometryShaderInvocations         = parseContext.getGeometryShaderInvocations();
482     }
483 }
484 
checkAndSimplifyAST(TIntermBlock * root,const TParseContext & parseContext,ShCompileOptions compileOptions)485 bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
486                                     const TParseContext &parseContext,
487                                     ShCompileOptions compileOptions)
488 {
489     // Disallow expressions deemed too complex.
490     if ((compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY) && !limitExpressionComplexity(root))
491     {
492         return false;
493     }
494 
495     if (shouldRunLoopAndIndexingValidation(compileOptions) &&
496         !ValidateLimitations(root, mShaderType, &mSymbolTable, &mDiagnostics))
497     {
498         return false;
499     }
500 
501     if (!ValidateFragColorAndFragData(mShaderType, mShaderVersion, mSymbolTable, &mDiagnostics))
502     {
503         return false;
504     }
505 
506     // Fold expressions that could not be folded before validation that was done as a part of
507     // parsing.
508     FoldExpressions(root, &mDiagnostics);
509     // Folding should only be able to generate warnings.
510     ASSERT(mDiagnostics.numErrors() == 0);
511     if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
512     {
513         return false;
514     }
515 
516     // We prune no-ops to work around driver bugs and to keep AST processing and output simple.
517     // The following kinds of no-ops are pruned:
518     //   1. Empty declarations "int;".
519     //   2. Literal statements: "1.0;". The ESSL output doesn't define a default precision
520     //      for float, so float literal statements would end up with no precision which is
521     //      invalid ESSL.
522     // After this empty declarations are not allowed in the AST.
523     PruneNoOps(root, &mSymbolTable);
524     if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
525     {
526         return false;
527     }
528 
529     // Create the function DAG and check there is no recursion
530     if (!initCallDag(root))
531     {
532         return false;
533     }
534 
535     if ((compileOptions & SH_LIMIT_CALL_STACK_DEPTH) && !checkCallDepth())
536     {
537         return false;
538     }
539 
540     // Checks which functions are used and if "main" exists
541     mFunctionMetadata.clear();
542     mFunctionMetadata.resize(mCallDag.size());
543     if (!tagUsedFunctions())
544     {
545         return false;
546     }
547 
548     if (!(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS))
549     {
550         pruneUnusedFunctions(root);
551         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
552         {
553             return false;
554         }
555     }
556     if (IsSpecWithFunctionBodyNewScope(mShaderSpec, mShaderVersion))
557     {
558         ReplaceShadowingVariables(root, &mSymbolTable);
559     }
560 
561     if (mShaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, mShaderType))
562     {
563         return false;
564     }
565 
566     if (mShaderVersion >= 300 && mShaderType == GL_FRAGMENT_SHADER &&
567         !ValidateOutputs(root, getExtensionBehavior(), mResources.MaxDrawBuffers, &mDiagnostics))
568     {
569         return false;
570     }
571 
572     // Fail compilation if precision emulation not supported.
573     if (getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision &&
574         !EmulatePrecision::SupportedInLanguage(mOutputType))
575     {
576         mDiagnostics.globalError("Precision emulation not supported for this output type.");
577         return false;
578     }
579 
580     // Clamping uniform array bounds needs to happen after validateLimitations pass.
581     if (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)
582     {
583         mArrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
584     }
585 
586     if ((compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) &&
587         (parseContext.isExtensionEnabled(TExtension::OVR_multiview2) ||
588          parseContext.isExtensionEnabled(TExtension::OVR_multiview)) &&
589         getShaderType() != GL_COMPUTE_SHADER)
590     {
591         DeclareAndInitBuiltinsForInstancedMultiview(root, mNumViews, mShaderType, compileOptions,
592                                                     mOutputType, &mSymbolTable);
593         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
594         {
595             return false;
596         }
597     }
598 
599     // This pass might emit short circuits so keep it before the short circuit unfolding
600     if (compileOptions & SH_REWRITE_DO_WHILE_LOOPS)
601     {
602         RewriteDoWhile(root, &mSymbolTable);
603         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
604         {
605             return false;
606         }
607     }
608 
609     if (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION)
610     {
611         AddAndTrueToLoopCondition(root);
612         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
613         {
614             return false;
615         }
616     }
617 
618     if (compileOptions & SH_UNFOLD_SHORT_CIRCUIT)
619     {
620         UnfoldShortCircuitAST(root);
621         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
622         {
623             return false;
624         }
625     }
626 
627     if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT)
628     {
629         RemovePow(root, &mSymbolTable);
630         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
631         {
632             return false;
633         }
634     }
635 
636     if (compileOptions & SH_REGENERATE_STRUCT_NAMES)
637     {
638         RegenerateStructNames gen(&mSymbolTable);
639         root->traverse(&gen);
640         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
641         {
642             return false;
643         }
644     }
645 
646     if (mShaderType == GL_VERTEX_SHADER &&
647         IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_multi_draw))
648     {
649         if ((compileOptions & SH_EMULATE_GL_DRAW_ID) != 0u)
650         {
651             EmulateGLDrawID(root, &mSymbolTable, &mUniforms,
652                             shouldCollectVariables(compileOptions));
653             if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
654             {
655                 return false;
656             }
657         }
658     }
659 
660     if (mShaderType == GL_VERTEX_SHADER &&
661         IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_base_vertex_base_instance))
662     {
663         if ((compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0u)
664         {
665             EmulateGLBaseVertex(root, &mSymbolTable, &mUniforms,
666                                 shouldCollectVariables(compileOptions));
667             EmulateGLBaseInstance(root, &mSymbolTable, &mUniforms,
668                                   shouldCollectVariables(compileOptions));
669             if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
670             {
671                 return false;
672             }
673         }
674     }
675 
676     if (mShaderType == GL_FRAGMENT_SHADER && mShaderVersion == 100 && mResources.EXT_draw_buffers &&
677         mResources.MaxDrawBuffers > 1 &&
678         IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
679     {
680         EmulateGLFragColorBroadcast(root, mResources.MaxDrawBuffers, &mOutputVariables,
681                                     &mSymbolTable, mShaderVersion);
682         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
683         {
684             return false;
685         }
686     }
687 
688     int simplifyScalarized = (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
689                                  ? IntermNodePatternMatcher::kScalarizedVecOrMatConstructor
690                                  : 0;
691 
692     // Split multi declarations and remove calls to array length().
693     // Note that SimplifyLoopConditions needs to be run before any other AST transformations
694     // that may need to generate new statements from loop conditions or loop expressions.
695     SimplifyLoopConditions(root,
696                            IntermNodePatternMatcher::kMultiDeclaration |
697                                IntermNodePatternMatcher::kArrayLengthMethod | simplifyScalarized,
698                            &getSymbolTable());
699     if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
700     {
701         return false;
702     }
703 
704     // Note that separate declarations need to be run before other AST transformations that
705     // generate new statements from expressions.
706     SeparateDeclarations(root);
707     mValidateASTOptions.validateMultiDeclarations = true;
708     if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
709     {
710         return false;
711     }
712 
713     SplitSequenceOperator(root, IntermNodePatternMatcher::kArrayLengthMethod | simplifyScalarized,
714                           &getSymbolTable());
715     if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
716     {
717         return false;
718     }
719 
720     RemoveArrayLengthMethod(root);
721     if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
722     {
723         return false;
724     }
725 
726     RemoveUnreferencedVariables(root, &mSymbolTable);
727     if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
728     {
729         return false;
730     }
731 
732     // In case the last case inside a switch statement is a certain type of no-op, GLSL compilers in
733     // drivers may not accept it. In this case we clean up the dead code from the end of switch
734     // statements. This is also required because PruneNoOps or RemoveUnreferencedVariables may have
735     // left switch statements that only contained an empty declaration inside the final case in an
736     // invalid state. Relies on that PruneNoOps and RemoveUnreferencedVariables have already been
737     // run.
738     PruneEmptyCases(root);
739     if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
740     {
741         return false;
742     }
743 
744     // Built-in function emulation needs to happen after validateLimitations pass.
745     // TODO(jmadill): Remove global pool allocator.
746     GetGlobalPoolAllocator()->lock();
747     initBuiltInFunctionEmulator(&mBuiltInFunctionEmulator, compileOptions);
748     GetGlobalPoolAllocator()->unlock();
749     mBuiltInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
750 
751     bool highPrecisionSupported = mShaderVersion > 100 || mShaderType != GL_FRAGMENT_SHADER ||
752                                   mResources.FragmentPrecisionHigh == 1;
753     if (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
754     {
755         ScalarizeVecAndMatConstructorArgs(root, mShaderType, highPrecisionSupported, &mSymbolTable);
756         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
757         {
758             return false;
759         }
760     }
761 
762     if (shouldCollectVariables(compileOptions))
763     {
764         ASSERT(!mVariablesCollected);
765         CollectVariables(root, &mAttributes, &mOutputVariables, &mUniforms, &mInputVaryings,
766                          &mOutputVaryings, &mUniformBlocks, &mShaderStorageBlocks, &mInBlocks,
767                          mResources.HashFunction, &mSymbolTable, mShaderType, mExtensionBehavior);
768         collectInterfaceBlocks();
769         mVariablesCollected = true;
770         if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
771         {
772             useAllMembersInUnusedStandardAndSharedBlocks(root);
773         }
774         if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
775         {
776             int maxUniformVectors = GetMaxUniformVectorsForShaderType(mShaderType, mResources);
777             // Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec
778             // Appendix A, section 7, the shader does not use too many uniforms.
779             if (!CheckVariablesInPackingLimits(maxUniformVectors, mUniforms))
780             {
781                 mDiagnostics.globalError("too many uniforms");
782                 return false;
783             }
784         }
785         if ((compileOptions & SH_INIT_OUTPUT_VARIABLES) && (mShaderType != GL_COMPUTE_SHADER))
786         {
787             initializeOutputVariables(root);
788             if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
789             {
790                 return false;
791             }
792         }
793     }
794 
795     // Removing invariant declarations must be done after collecting variables.
796     // Otherwise, built-in invariant declarations don't apply.
797     if (RemoveInvariant(mShaderType, mShaderVersion, mOutputType, compileOptions))
798     {
799         RemoveInvariantDeclaration(root);
800         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
801         {
802             return false;
803         }
804     }
805 
806     // gl_Position is always written in compatibility output mode.
807     // It may have been already initialized among other output variables, in that case we don't
808     // need to initialize it twice.
809     if (mShaderType == GL_VERTEX_SHADER && !mGLPositionInitialized &&
810         ((compileOptions & SH_INIT_GL_POSITION) || (mOutputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
811     {
812         initializeGLPosition(root);
813         mGLPositionInitialized = true;
814         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
815         {
816             return false;
817         }
818     }
819 
820     // DeferGlobalInitializers needs to be run before other AST transformations that generate new
821     // statements from expressions. But it's fine to run DeferGlobalInitializers after the above
822     // SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST
823     // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00.
824     bool initializeLocalsAndGlobals =
825         (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType());
826     bool canUseLoopsToInitialize = !(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES);
827     DeferGlobalInitializers(root, initializeLocalsAndGlobals, canUseLoopsToInitialize,
828                             highPrecisionSupported, &mSymbolTable);
829     if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
830     {
831         return false;
832     }
833 
834     if (initializeLocalsAndGlobals)
835     {
836         // Initialize uninitialized local variables.
837         // In some cases initializing can generate extra statements in the parent block, such as
838         // when initializing nameless structs or initializing arrays in ESSL 1.00. In that case
839         // we need to first simplify loop conditions. We've already separated declarations
840         // earlier, which is also required. If we don't follow the Appendix A limitations, loop
841         // init statements can declare arrays or nameless structs and have multiple
842         // declarations.
843 
844         if (!shouldRunLoopAndIndexingValidation(compileOptions))
845         {
846             SimplifyLoopConditions(root,
847                                    IntermNodePatternMatcher::kArrayDeclaration |
848                                        IntermNodePatternMatcher::kNamelessStructDeclaration,
849                                    &getSymbolTable());
850             if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
851             {
852                 return false;
853             }
854         }
855 
856         InitializeUninitializedLocals(root, getShaderVersion(), canUseLoopsToInitialize,
857                                       highPrecisionSupported, &getSymbolTable());
858         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
859         {
860             return false;
861         }
862     }
863 
864     if (getShaderType() == GL_VERTEX_SHADER && (compileOptions & SH_CLAMP_POINT_SIZE))
865     {
866         ClampPointSize(root, mResources.MaxPointSize, &getSymbolTable());
867         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
868         {
869             return false;
870         }
871     }
872 
873     if (getShaderType() == GL_FRAGMENT_SHADER && (compileOptions & SH_CLAMP_FRAG_DEPTH))
874     {
875         ClampFragDepth(root, &getSymbolTable());
876         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
877         {
878             return false;
879         }
880     }
881 
882     if (compileOptions & SH_REWRITE_REPEATED_ASSIGN_TO_SWIZZLED)
883     {
884         sh::RewriteRepeatedAssignToSwizzled(root);
885         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
886         {
887             return false;
888         }
889     }
890 
891     if (compileOptions & SH_REWRITE_VECTOR_SCALAR_ARITHMETIC)
892     {
893         VectorizeVectorScalarArithmetic(root, &getSymbolTable());
894         if (!ValidateAST(root, &mDiagnostics, mValidateASTOptions))
895         {
896             return false;
897         }
898     }
899 
900     return true;
901 }
902 
compile(const char * const shaderStrings[],size_t numStrings,ShCompileOptions compileOptionsIn)903 bool TCompiler::compile(const char *const shaderStrings[],
904                         size_t numStrings,
905                         ShCompileOptions compileOptionsIn)
906 {
907 #if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
908     DumpFuzzerCase(shaderStrings, numStrings, mShaderType, mShaderSpec, mOutputType,
909                    compileOptionsIn);
910 #endif  // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
911 
912     if (numStrings == 0)
913         return true;
914 
915     ShCompileOptions compileOptions = compileOptionsIn;
916 
917     // Apply key workarounds.
918     if (shouldFlattenPragmaStdglInvariantAll())
919     {
920         // This should be harmless to do in all cases, but for the moment, do it only conditionally.
921         compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;
922     }
923 
924     TScopedPoolAllocator scopedAlloc(&allocator);
925     TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
926 
927     if (root)
928     {
929         if (compileOptions & SH_INTERMEDIATE_TREE)
930             OutputTree(root, mInfoSink.info);
931 
932         if (compileOptions & SH_OBJECT_CODE)
933         {
934             PerformanceDiagnostics perfDiagnostics(&mDiagnostics);
935             translate(root, compileOptions, &perfDiagnostics);
936         }
937 
938         if (mShaderType == GL_VERTEX_SHADER)
939         {
940             bool lookForDrawID =
941                 IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_multi_draw) &&
942                 ((compileOptions & SH_EMULATE_GL_DRAW_ID) != 0u);
943             bool lookForBaseVertexBaseInstance =
944                 IsExtensionEnabled(mExtensionBehavior,
945                                    TExtension::ANGLE_base_vertex_base_instance) &&
946                 ((compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0u);
947 
948             if (lookForDrawID || lookForBaseVertexBaseInstance)
949             {
950                 for (auto &uniform : mUniforms)
951                 {
952                     if (lookForDrawID && uniform.name == "angle_DrawID" &&
953                         uniform.mappedName == "angle_DrawID")
954                     {
955                         uniform.name = "gl_DrawID";
956                     }
957                     else if (lookForBaseVertexBaseInstance && uniform.name == "angle_BaseVertex" &&
958                              uniform.mappedName == "angle_BaseVertex")
959                     {
960                         uniform.name = "gl_BaseVertex";
961                     }
962                     else if (lookForBaseVertexBaseInstance &&
963                              uniform.name == "angle_BaseInstance" &&
964                              uniform.mappedName == "angle_BaseInstance")
965                     {
966                         uniform.name = "gl_BaseInstance";
967                     }
968                 }
969             }
970         }
971 
972         // The IntermNode tree doesn't need to be deleted here, since the
973         // memory will be freed in a big chunk by the PoolAllocator.
974         return true;
975     }
976     return false;
977 }
978 
initBuiltInSymbolTable(const ShBuiltInResources & resources)979 bool TCompiler::initBuiltInSymbolTable(const ShBuiltInResources &resources)
980 {
981     if (resources.MaxDrawBuffers < 1)
982     {
983         return false;
984     }
985     if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1)
986     {
987         return false;
988     }
989 
990     mSymbolTable.initializeBuiltIns(mShaderType, mShaderSpec, resources);
991 
992     return true;
993 }
994 
setResourceString()995 void TCompiler::setResourceString()
996 {
997     std::ostringstream strstream = sh::InitializeStream<std::ostringstream>();
998 
999     // clang-format off
1000     strstream << ":MaxVertexAttribs:" << mResources.MaxVertexAttribs
1001         << ":MaxVertexUniformVectors:" << mResources.MaxVertexUniformVectors
1002         << ":MaxVaryingVectors:" << mResources.MaxVaryingVectors
1003         << ":MaxVertexTextureImageUnits:" << mResources.MaxVertexTextureImageUnits
1004         << ":MaxCombinedTextureImageUnits:" << mResources.MaxCombinedTextureImageUnits
1005         << ":MaxTextureImageUnits:" << mResources.MaxTextureImageUnits
1006         << ":MaxFragmentUniformVectors:" << mResources.MaxFragmentUniformVectors
1007         << ":MaxDrawBuffers:" << mResources.MaxDrawBuffers
1008         << ":OES_standard_derivatives:" << mResources.OES_standard_derivatives
1009         << ":OES_EGL_image_external:" << mResources.OES_EGL_image_external
1010         << ":OES_EGL_image_external_essl3:" << mResources.OES_EGL_image_external_essl3
1011         << ":NV_EGL_stream_consumer_external:" << mResources.NV_EGL_stream_consumer_external
1012         << ":ARB_texture_rectangle:" << mResources.ARB_texture_rectangle
1013         << ":EXT_draw_buffers:" << mResources.EXT_draw_buffers
1014         << ":FragmentPrecisionHigh:" << mResources.FragmentPrecisionHigh
1015         << ":MaxExpressionComplexity:" << mResources.MaxExpressionComplexity
1016         << ":MaxCallStackDepth:" << mResources.MaxCallStackDepth
1017         << ":MaxFunctionParameters:" << mResources.MaxFunctionParameters
1018         << ":EXT_blend_func_extended:" << mResources.EXT_blend_func_extended
1019         << ":EXT_frag_depth:" << mResources.EXT_frag_depth
1020         << ":EXT_shader_texture_lod:" << mResources.EXT_shader_texture_lod
1021         << ":EXT_shader_framebuffer_fetch:" << mResources.EXT_shader_framebuffer_fetch
1022         << ":NV_shader_framebuffer_fetch:" << mResources.NV_shader_framebuffer_fetch
1023         << ":ARM_shader_framebuffer_fetch:" << mResources.ARM_shader_framebuffer_fetch
1024         << ":OVR_multiview2:" << mResources.OVR_multiview2
1025         << ":OVR_multiview:" << mResources.OVR_multiview
1026         << ":EXT_YUV_target:" << mResources.EXT_YUV_target
1027         << ":EXT_geometry_shader:" << mResources.EXT_geometry_shader
1028         << ":OES_texture_3D:" << mResources.OES_texture_3D
1029         << ":MaxVertexOutputVectors:" << mResources.MaxVertexOutputVectors
1030         << ":MaxFragmentInputVectors:" << mResources.MaxFragmentInputVectors
1031         << ":MinProgramTexelOffset:" << mResources.MinProgramTexelOffset
1032         << ":MaxProgramTexelOffset:" << mResources.MaxProgramTexelOffset
1033         << ":MaxDualSourceDrawBuffers:" << mResources.MaxDualSourceDrawBuffers
1034         << ":MaxViewsOVR:" << mResources.MaxViewsOVR
1035         << ":NV_draw_buffers:" << mResources.NV_draw_buffers
1036         << ":WEBGL_debug_shader_precision:" << mResources.WEBGL_debug_shader_precision
1037         << ":ANGLE_multi_draw:" << mResources.ANGLE_multi_draw
1038         << ":ANGLE_base_vertex_base_instance:" << mResources.ANGLE_base_vertex_base_instance
1039         << ":MinProgramTextureGatherOffset:" << mResources.MinProgramTextureGatherOffset
1040         << ":MaxProgramTextureGatherOffset:" << mResources.MaxProgramTextureGatherOffset
1041         << ":MaxImageUnits:" << mResources.MaxImageUnits
1042         << ":MaxVertexImageUniforms:" << mResources.MaxVertexImageUniforms
1043         << ":MaxFragmentImageUniforms:" << mResources.MaxFragmentImageUniforms
1044         << ":MaxComputeImageUniforms:" << mResources.MaxComputeImageUniforms
1045         << ":MaxCombinedImageUniforms:" << mResources.MaxCombinedImageUniforms
1046         << ":MaxCombinedShaderOutputResources:" << mResources.MaxCombinedShaderOutputResources
1047         << ":MaxComputeWorkGroupCountX:" << mResources.MaxComputeWorkGroupCount[0]
1048         << ":MaxComputeWorkGroupCountY:" << mResources.MaxComputeWorkGroupCount[1]
1049         << ":MaxComputeWorkGroupCountZ:" << mResources.MaxComputeWorkGroupCount[2]
1050         << ":MaxComputeWorkGroupSizeX:" << mResources.MaxComputeWorkGroupSize[0]
1051         << ":MaxComputeWorkGroupSizeY:" << mResources.MaxComputeWorkGroupSize[1]
1052         << ":MaxComputeWorkGroupSizeZ:" << mResources.MaxComputeWorkGroupSize[2]
1053         << ":MaxComputeUniformComponents:" << mResources.MaxComputeUniformComponents
1054         << ":MaxComputeTextureImageUnits:" << mResources.MaxComputeTextureImageUnits
1055         << ":MaxComputeAtomicCounters:" << mResources.MaxComputeAtomicCounters
1056         << ":MaxComputeAtomicCounterBuffers:" << mResources.MaxComputeAtomicCounterBuffers
1057         << ":MaxVertexAtomicCounters:" << mResources.MaxVertexAtomicCounters
1058         << ":MaxFragmentAtomicCounters:" << mResources.MaxFragmentAtomicCounters
1059         << ":MaxCombinedAtomicCounters:" << mResources.MaxCombinedAtomicCounters
1060         << ":MaxAtomicCounterBindings:" << mResources.MaxAtomicCounterBindings
1061         << ":MaxVertexAtomicCounterBuffers:" << mResources.MaxVertexAtomicCounterBuffers
1062         << ":MaxFragmentAtomicCounterBuffers:" << mResources.MaxFragmentAtomicCounterBuffers
1063         << ":MaxCombinedAtomicCounterBuffers:" << mResources.MaxCombinedAtomicCounterBuffers
1064         << ":MaxAtomicCounterBufferSize:" << mResources.MaxAtomicCounterBufferSize
1065         << ":MaxGeometryUniformComponents:" << mResources.MaxGeometryUniformComponents
1066         << ":MaxGeometryUniformBlocks:" << mResources.MaxGeometryUniformBlocks
1067         << ":MaxGeometryInputComponents:" << mResources.MaxGeometryInputComponents
1068         << ":MaxGeometryOutputComponents:" << mResources.MaxGeometryOutputComponents
1069         << ":MaxGeometryOutputVertices:" << mResources.MaxGeometryOutputVertices
1070         << ":MaxGeometryTotalOutputComponents:" << mResources.MaxGeometryTotalOutputComponents
1071         << ":MaxGeometryTextureImageUnits:" << mResources.MaxGeometryTextureImageUnits
1072         << ":MaxGeometryAtomicCounterBuffers:" << mResources.MaxGeometryAtomicCounterBuffers
1073         << ":MaxGeometryAtomicCounters:" << mResources.MaxGeometryAtomicCounters
1074         << ":MaxGeometryShaderStorageBlocks:" << mResources.MaxGeometryShaderStorageBlocks
1075         << ":MaxGeometryShaderInvocations:" << mResources.MaxGeometryShaderInvocations
1076         << ":MaxGeometryImageUniforms:" << mResources.MaxGeometryImageUniforms;
1077     // clang-format on
1078 
1079     mBuiltInResourcesString = strstream.str();
1080 }
1081 
collectInterfaceBlocks()1082 void TCompiler::collectInterfaceBlocks()
1083 {
1084     ASSERT(mInterfaceBlocks.empty());
1085     mInterfaceBlocks.reserve(mUniformBlocks.size() + mShaderStorageBlocks.size() +
1086                              mInBlocks.size());
1087     mInterfaceBlocks.insert(mInterfaceBlocks.end(), mUniformBlocks.begin(), mUniformBlocks.end());
1088     mInterfaceBlocks.insert(mInterfaceBlocks.end(), mShaderStorageBlocks.begin(),
1089                             mShaderStorageBlocks.end());
1090     mInterfaceBlocks.insert(mInterfaceBlocks.end(), mInBlocks.begin(), mInBlocks.end());
1091 }
1092 
clearResults()1093 void TCompiler::clearResults()
1094 {
1095     mArrayBoundsClamper.Cleanup();
1096     mInfoSink.info.erase();
1097     mInfoSink.obj.erase();
1098     mInfoSink.debug.erase();
1099     mDiagnostics.resetErrorCount();
1100 
1101     mAttributes.clear();
1102     mOutputVariables.clear();
1103     mUniforms.clear();
1104     mInputVaryings.clear();
1105     mOutputVaryings.clear();
1106     mInterfaceBlocks.clear();
1107     mUniformBlocks.clear();
1108     mShaderStorageBlocks.clear();
1109     mInBlocks.clear();
1110     mVariablesCollected    = false;
1111     mGLPositionInitialized = false;
1112 
1113     mNumViews = -1;
1114 
1115     mGeometryShaderInputPrimitiveType  = EptUndefined;
1116     mGeometryShaderOutputPrimitiveType = EptUndefined;
1117     mGeometryShaderInvocations         = 0;
1118     mGeometryShaderMaxVertices         = -1;
1119 
1120     mBuiltInFunctionEmulator.cleanup();
1121 
1122     mNameMap.clear();
1123 
1124     mSourcePath = nullptr;
1125 
1126     mSymbolTable.clearCompilationResults();
1127 }
1128 
initCallDag(TIntermNode * root)1129 bool TCompiler::initCallDag(TIntermNode *root)
1130 {
1131     mCallDag.clear();
1132 
1133     switch (mCallDag.init(root, &mDiagnostics))
1134     {
1135         case CallDAG::INITDAG_SUCCESS:
1136             return true;
1137         case CallDAG::INITDAG_RECURSION:
1138         case CallDAG::INITDAG_UNDEFINED:
1139             // Error message has already been written out.
1140             ASSERT(mDiagnostics.numErrors() > 0);
1141             return false;
1142     }
1143 
1144     UNREACHABLE();
1145     return true;
1146 }
1147 
checkCallDepth()1148 bool TCompiler::checkCallDepth()
1149 {
1150     std::vector<int> depths(mCallDag.size());
1151 
1152     for (size_t i = 0; i < mCallDag.size(); i++)
1153     {
1154         int depth                     = 0;
1155         const CallDAG::Record &record = mCallDag.getRecordFromIndex(i);
1156 
1157         for (const int &calleeIndex : record.callees)
1158         {
1159             depth = std::max(depth, depths[calleeIndex] + 1);
1160         }
1161 
1162         depths[i] = depth;
1163 
1164         if (depth >= mResources.MaxCallStackDepth)
1165         {
1166             // Trace back the function chain to have a meaningful info log.
1167             std::stringstream errorStream = sh::InitializeStream<std::stringstream>();
1168             errorStream << "Call stack too deep (larger than " << mResources.MaxCallStackDepth
1169                         << ") with the following call chain: "
1170                         << record.node->getFunction()->name();
1171 
1172             int currentFunction = static_cast<int>(i);
1173             int currentDepth    = depth;
1174 
1175             while (currentFunction != -1)
1176             {
1177                 errorStream
1178                     << " -> "
1179                     << mCallDag.getRecordFromIndex(currentFunction).node->getFunction()->name();
1180 
1181                 int nextFunction = -1;
1182                 for (const int &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
1183                 {
1184                     if (depths[calleeIndex] == currentDepth - 1)
1185                     {
1186                         currentDepth--;
1187                         nextFunction = calleeIndex;
1188                     }
1189                 }
1190 
1191                 currentFunction = nextFunction;
1192             }
1193 
1194             std::string errorStr = errorStream.str();
1195             mDiagnostics.globalError(errorStr.c_str());
1196 
1197             return false;
1198         }
1199     }
1200 
1201     return true;
1202 }
1203 
tagUsedFunctions()1204 bool TCompiler::tagUsedFunctions()
1205 {
1206     // Search from main, starting from the end of the DAG as it usually is the root.
1207     for (size_t i = mCallDag.size(); i-- > 0;)
1208     {
1209         if (mCallDag.getRecordFromIndex(i).node->getFunction()->isMain())
1210         {
1211             internalTagUsedFunction(i);
1212             return true;
1213         }
1214     }
1215 
1216     mDiagnostics.globalError("Missing main()");
1217     return false;
1218 }
1219 
internalTagUsedFunction(size_t index)1220 void TCompiler::internalTagUsedFunction(size_t index)
1221 {
1222     if (mFunctionMetadata[index].used)
1223     {
1224         return;
1225     }
1226 
1227     mFunctionMetadata[index].used = true;
1228 
1229     for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees)
1230     {
1231         internalTagUsedFunction(calleeIndex);
1232     }
1233 }
1234 
1235 // A predicate for the stl that returns if a top-level node is unused
1236 class TCompiler::UnusedPredicate
1237 {
1238   public:
UnusedPredicate(const CallDAG * callDag,const std::vector<FunctionMetadata> * metadatas)1239     UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas)
1240         : mCallDag(callDag), mMetadatas(metadatas)
1241     {}
1242 
operator ()(TIntermNode * node)1243     bool operator()(TIntermNode *node)
1244     {
1245         const TIntermFunctionPrototype *asFunctionPrototype   = node->getAsFunctionPrototypeNode();
1246         const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition();
1247 
1248         const TFunction *func = nullptr;
1249 
1250         if (asFunctionDefinition)
1251         {
1252             func = asFunctionDefinition->getFunction();
1253         }
1254         else if (asFunctionPrototype)
1255         {
1256             func = asFunctionPrototype->getFunction();
1257         }
1258         if (func == nullptr)
1259         {
1260             return false;
1261         }
1262 
1263         size_t callDagIndex = mCallDag->findIndex(func->uniqueId());
1264         if (callDagIndex == CallDAG::InvalidIndex)
1265         {
1266             // This happens only for unimplemented prototypes which are thus unused
1267             ASSERT(asFunctionPrototype);
1268             return true;
1269         }
1270 
1271         ASSERT(callDagIndex < mMetadatas->size());
1272         return !(*mMetadatas)[callDagIndex].used;
1273     }
1274 
1275   private:
1276     const CallDAG *mCallDag;
1277     const std::vector<FunctionMetadata> *mMetadatas;
1278 };
1279 
pruneUnusedFunctions(TIntermBlock * root)1280 void TCompiler::pruneUnusedFunctions(TIntermBlock *root)
1281 {
1282     UnusedPredicate isUnused(&mCallDag, &mFunctionMetadata);
1283     TIntermSequence *sequence = root->getSequence();
1284 
1285     if (!sequence->empty())
1286     {
1287         sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused),
1288                         sequence->end());
1289     }
1290 }
1291 
limitExpressionComplexity(TIntermBlock * root)1292 bool TCompiler::limitExpressionComplexity(TIntermBlock *root)
1293 {
1294     if (!IsASTDepthBelowLimit(root, mResources.MaxExpressionComplexity))
1295     {
1296         mDiagnostics.globalError("Expression too complex.");
1297         return false;
1298     }
1299 
1300     if (!ValidateMaxParameters(root, mResources.MaxFunctionParameters))
1301     {
1302         mDiagnostics.globalError("Function has too many parameters.");
1303         return false;
1304     }
1305 
1306     return true;
1307 }
1308 
shouldCollectVariables(ShCompileOptions compileOptions)1309 bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions)
1310 {
1311     return (compileOptions & SH_VARIABLES) != 0;
1312 }
1313 
wereVariablesCollected() const1314 bool TCompiler::wereVariablesCollected() const
1315 {
1316     return mVariablesCollected;
1317 }
1318 
initializeGLPosition(TIntermBlock * root)1319 void TCompiler::initializeGLPosition(TIntermBlock *root)
1320 {
1321     InitVariableList list;
1322     sh::ShaderVariable var(GL_FLOAT_VEC4);
1323     var.name = "gl_Position";
1324     list.push_back(var);
1325     InitializeVariables(root, list, &mSymbolTable, mShaderVersion, mExtensionBehavior, false,
1326                         false);
1327 }
1328 
useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock * root)1329 void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)
1330 {
1331     sh::InterfaceBlockList list;
1332 
1333     for (const sh::InterfaceBlock &block : mUniformBlocks)
1334     {
1335         if (!block.staticUse &&
1336             (block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED))
1337         {
1338             list.push_back(block);
1339         }
1340     }
1341 
1342     sh::UseInterfaceBlockFields(root, list, mSymbolTable);
1343 }
1344 
initializeOutputVariables(TIntermBlock * root)1345 void TCompiler::initializeOutputVariables(TIntermBlock *root)
1346 {
1347     InitVariableList list;
1348     if (mShaderType == GL_VERTEX_SHADER || mShaderType == GL_GEOMETRY_SHADER_EXT)
1349     {
1350         for (const sh::Varying &var : mOutputVaryings)
1351         {
1352             list.push_back(var);
1353             if (var.name == "gl_Position")
1354             {
1355                 ASSERT(!mGLPositionInitialized);
1356                 mGLPositionInitialized = true;
1357             }
1358         }
1359     }
1360     else
1361     {
1362         ASSERT(mShaderType == GL_FRAGMENT_SHADER);
1363         for (const sh::OutputVariable &var : mOutputVariables)
1364         {
1365             list.push_back(var);
1366         }
1367     }
1368     InitializeVariables(root, list, &mSymbolTable, mShaderVersion, mExtensionBehavior, false,
1369                         false);
1370 }
1371 
getExtensionBehavior() const1372 const TExtensionBehavior &TCompiler::getExtensionBehavior() const
1373 {
1374     return mExtensionBehavior;
1375 }
1376 
getSourcePath() const1377 const char *TCompiler::getSourcePath() const
1378 {
1379     return mSourcePath;
1380 }
1381 
getResources() const1382 const ShBuiltInResources &TCompiler::getResources() const
1383 {
1384     return mResources;
1385 }
1386 
getArrayBoundsClamper() const1387 const ArrayBoundsClamper &TCompiler::getArrayBoundsClamper() const
1388 {
1389     return mArrayBoundsClamper;
1390 }
1391 
getArrayIndexClampingStrategy() const1392 ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
1393 {
1394     return mResources.ArrayIndexClampingStrategy;
1395 }
1396 
getBuiltInFunctionEmulator() const1397 const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const
1398 {
1399     return mBuiltInFunctionEmulator;
1400 }
1401 
writePragma(ShCompileOptions compileOptions)1402 void TCompiler::writePragma(ShCompileOptions compileOptions)
1403 {
1404     if (!(compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL))
1405     {
1406         TInfoSinkBase &sink = mInfoSink.obj;
1407         if (mPragma.stdgl.invariantAll)
1408             sink << "#pragma STDGL invariant(all)\n";
1409     }
1410 }
1411 
isVaryingDefined(const char * varyingName)1412 bool TCompiler::isVaryingDefined(const char *varyingName)
1413 {
1414     ASSERT(mVariablesCollected);
1415     for (size_t ii = 0; ii < mInputVaryings.size(); ++ii)
1416     {
1417         if (mInputVaryings[ii].name == varyingName)
1418         {
1419             return true;
1420         }
1421     }
1422     for (size_t ii = 0; ii < mOutputVaryings.size(); ++ii)
1423     {
1424         if (mOutputVaryings[ii].name == varyingName)
1425         {
1426             return true;
1427         }
1428     }
1429 
1430     return false;
1431 }
1432 
EmitWorkGroupSizeGLSL(const TCompiler & compiler,TInfoSinkBase & sink)1433 void EmitWorkGroupSizeGLSL(const TCompiler &compiler, TInfoSinkBase &sink)
1434 {
1435     if (compiler.isComputeShaderLocalSizeDeclared())
1436     {
1437         const sh::WorkGroupSize &localSize = compiler.getComputeShaderLocalSize();
1438         sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1]
1439              << ", local_size_z=" << localSize[2] << ") in;\n";
1440     }
1441 }
1442 
EmitMultiviewGLSL(const TCompiler & compiler,const ShCompileOptions & compileOptions,const TBehavior behavior,TInfoSinkBase & sink)1443 void EmitMultiviewGLSL(const TCompiler &compiler,
1444                        const ShCompileOptions &compileOptions,
1445                        const TBehavior behavior,
1446                        TInfoSinkBase &sink)
1447 {
1448     ASSERT(behavior != EBhUndefined);
1449     if (behavior == EBhDisable)
1450         return;
1451 
1452     const bool isVertexShader = (compiler.getShaderType() == GL_VERTEX_SHADER);
1453     if (compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW)
1454     {
1455         // Emit ARB_shader_viewport_layer_array/NV_viewport_array2 in a vertex shader if the
1456         // SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set and the
1457         // OVR_multiview(2) extension is requested.
1458         if (isVertexShader && (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER))
1459         {
1460             sink << "#if defined(GL_ARB_shader_viewport_layer_array)\n"
1461                  << "#extension GL_ARB_shader_viewport_layer_array : require\n"
1462                  << "#elif defined(GL_NV_viewport_array2)\n"
1463                  << "#extension GL_NV_viewport_array2 : require\n"
1464                  << "#endif\n";
1465         }
1466     }
1467     else
1468     {
1469         sink << "#extension GL_OVR_multiview2 : " << GetBehaviorString(behavior) << "\n";
1470 
1471         const auto &numViews = compiler.getNumViews();
1472         if (isVertexShader && numViews != -1)
1473         {
1474             sink << "layout(num_views=" << numViews << ") in;\n";
1475         }
1476     }
1477 }
1478 
1479 }  // namespace sh
1480