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