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