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