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