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