1 //
2 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 #include "compiler/translator/Compiler.h"
8 
9 #include <sstream>
10 
11 #include "angle_gl.h"
12 #include "common/utilities.h"
13 #include "compiler/translator/AddAndTrueToLoopCondition.h"
14 #include "compiler/translator/Cache.h"
15 #include "compiler/translator/CallDAG.h"
16 #include "compiler/translator/ClampPointSize.h"
17 #include "compiler/translator/CollectVariables.h"
18 #include "compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h"
19 #include "compiler/translator/DeferGlobalInitializers.h"
20 #include "compiler/translator/EmulateGLFragColorBroadcast.h"
21 #include "compiler/translator/EmulatePrecision.h"
22 #include "compiler/translator/Initialize.h"
23 #include "compiler/translator/InitializeVariables.h"
24 #include "compiler/translator/IntermNodePatternMatcher.h"
25 #include "compiler/translator/IsASTDepthBelowLimit.h"
26 #include "compiler/translator/OutputTree.h"
27 #include "compiler/translator/ParseContext.h"
28 #include "compiler/translator/PruneNoOps.h"
29 #include "compiler/translator/RegenerateStructNames.h"
30 #include "compiler/translator/RemoveArrayLengthMethod.h"
31 #include "compiler/translator/RemoveEmptySwitchStatements.h"
32 #include "compiler/translator/RemoveInvariantDeclaration.h"
33 #include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h"
34 #include "compiler/translator/RemovePow.h"
35 #include "compiler/translator/RemoveUnreferencedVariables.h"
36 #include "compiler/translator/RewriteDoWhile.h"
37 #include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
38 #include "compiler/translator/SeparateDeclarations.h"
39 #include "compiler/translator/SimplifyLoopConditions.h"
40 #include "compiler/translator/SplitSequenceOperator.h"
41 #include "compiler/translator/UnfoldShortCircuitAST.h"
42 #include "compiler/translator/UseInterfaceBlockFields.h"
43 #include "compiler/translator/ValidateLimitations.h"
44 #include "compiler/translator/ValidateMaxParameters.h"
45 #include "compiler/translator/ValidateOutputs.h"
46 #include "compiler/translator/ValidateVaryingLocations.h"
47 #include "compiler/translator/VariablePacker.h"
48 #include "compiler/translator/VectorizeVectorScalarArithmetic.h"
49 #include "compiler/translator/util.h"
50 #include "third_party/compiler/ArrayBoundsClamper.h"
51 
52 namespace sh
53 {
54 
55 namespace
56 {
57 
58 #if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
DumpFuzzerCase(char const * const * shaderStrings,size_t numStrings,uint32_t type,uint32_t spec,uint32_t output,uint64_t options)59 void DumpFuzzerCase(char const *const *shaderStrings,
60                     size_t numStrings,
61                     uint32_t type,
62                     uint32_t spec,
63                     uint32_t output,
64                     uint64_t options)
65 {
66     static int fileIndex = 0;
67 
68     std::ostringstream o;
69     o << "corpus/" << fileIndex++ << ".sample";
70     std::string s = o.str();
71 
72     // Must match the input format of the fuzzer
73     FILE *f = fopen(s.c_str(), "w");
74     fwrite(&type, sizeof(type), 1, f);
75     fwrite(&spec, sizeof(spec), 1, f);
76     fwrite(&output, sizeof(output), 1, f);
77     fwrite(&options, sizeof(options), 1, f);
78 
79     char zero[128 - 20] = {0};
80     fwrite(&zero, 128 - 20, 1, f);
81 
82     for (size_t i = 0; i < numStrings; i++)
83     {
84         fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f);
85     }
86     fwrite(&zero, 1, 1, f);
87 
88     fclose(f);
89 }
90 #endif  // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
91 }  // anonymous namespace
92 
IsWebGLBasedSpec(ShShaderSpec spec)93 bool IsWebGLBasedSpec(ShShaderSpec spec)
94 {
95     return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC || spec == SH_WEBGL3_SPEC);
96 }
97 
IsGLSL130OrNewer(ShShaderOutput output)98 bool IsGLSL130OrNewer(ShShaderOutput output)
99 {
100     return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
101             output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
102             output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT ||
103             output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
104             output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
105 }
106 
IsGLSL420OrNewer(ShShaderOutput output)107 bool IsGLSL420OrNewer(ShShaderOutput output)
108 {
109     return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
110             output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
111 }
112 
IsGLSL410OrOlder(ShShaderOutput output)113 bool IsGLSL410OrOlder(ShShaderOutput output)
114 {
115     return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
116             output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
117             output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
118 }
119 
RemoveInvariant(sh::GLenum shaderType,int shaderVersion,ShShaderOutput outputType,ShCompileOptions compileOptions)120 bool RemoveInvariant(sh::GLenum shaderType,
121                      int shaderVersion,
122                      ShShaderOutput outputType,
123                      ShCompileOptions compileOptions)
124 {
125     if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 &&
126         shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
127         return true;
128 
129     if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
130         shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER)
131         return true;
132 
133     return false;
134 }
135 
GetGlobalMaxTokenSize(ShShaderSpec spec)136 size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
137 {
138     // WebGL defines a max token length of 256, while ES2 leaves max token
139     // size undefined. ES3 defines a max size of 1024 characters.
140     switch (spec)
141     {
142         case SH_WEBGL_SPEC:
143             return 256;
144         default:
145             return 1024;
146     }
147 }
148 
GetMaxUniformVectorsForShaderType(GLenum shaderType,const ShBuiltInResources & resources)149 int GetMaxUniformVectorsForShaderType(GLenum shaderType, const ShBuiltInResources &resources)
150 {
151     switch (shaderType)
152     {
153         case GL_VERTEX_SHADER:
154             return resources.MaxVertexUniformVectors;
155         case GL_FRAGMENT_SHADER:
156             return resources.MaxFragmentUniformVectors;
157 
158         // TODO (jiawei.shao@intel.com): check if we need finer-grained component counting
159         case GL_COMPUTE_SHADER:
160             return resources.MaxComputeUniformComponents / 4;
161         case GL_GEOMETRY_SHADER_OES:
162             return resources.MaxGeometryUniformComponents / 4;
163         default:
164             UNREACHABLE();
165             return -1;
166     }
167 }
168 
169 namespace
170 {
171 
172 class TScopedPoolAllocator
173 {
174   public:
TScopedPoolAllocator(TPoolAllocator * allocator)175     TScopedPoolAllocator(TPoolAllocator *allocator) : mAllocator(allocator)
176     {
177         mAllocator->push();
178         SetGlobalPoolAllocator(mAllocator);
179     }
~TScopedPoolAllocator()180     ~TScopedPoolAllocator()
181     {
182         SetGlobalPoolAllocator(nullptr);
183         mAllocator->pop();
184     }
185 
186   private:
187     TPoolAllocator *mAllocator;
188 };
189 
190 class TScopedSymbolTableLevel
191 {
192   public:
TScopedSymbolTableLevel(TSymbolTable * table)193     TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
194     {
195         ASSERT(mTable->atBuiltInLevel());
196         mTable->push();
197     }
~TScopedSymbolTableLevel()198     ~TScopedSymbolTableLevel()
199     {
200         while (!mTable->atBuiltInLevel())
201             mTable->pop();
202     }
203 
204   private:
205     TSymbolTable *mTable;
206 };
207 
MapSpecToShaderVersion(ShShaderSpec spec)208 int MapSpecToShaderVersion(ShShaderSpec spec)
209 {
210     switch (spec)
211     {
212         case SH_GLES2_SPEC:
213         case SH_WEBGL_SPEC:
214             return 100;
215         case SH_GLES3_SPEC:
216         case SH_WEBGL2_SPEC:
217             return 300;
218         case SH_GLES3_1_SPEC:
219         case SH_WEBGL3_SPEC:
220             return 310;
221         default:
222             UNREACHABLE();
223             return 0;
224     }
225 }
226 
227 }  // namespace
228 
TShHandleBase()229 TShHandleBase::TShHandleBase()
230 {
231     allocator.push();
232     SetGlobalPoolAllocator(&allocator);
233 }
234 
~TShHandleBase()235 TShHandleBase::~TShHandleBase()
236 {
237     SetGlobalPoolAllocator(nullptr);
238     allocator.popAll();
239 }
240 
TCompiler(sh::GLenum type,ShShaderSpec spec,ShShaderOutput output)241 TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
242     : variablesCollected(false),
243       mGLPositionInitialized(false),
244       shaderType(type),
245       shaderSpec(spec),
246       outputType(output),
247       maxUniformVectors(0),
248       maxExpressionComplexity(0),
249       maxCallStackDepth(0),
250       maxFunctionParameters(0),
251       fragmentPrecisionHigh(false),
252       clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
253       builtInFunctionEmulator(),
254       mDiagnostics(infoSink.info),
255       mSourcePath(nullptr),
256       mComputeShaderLocalSizeDeclared(false),
257       mComputeShaderLocalSize(1),
258       mGeometryShaderMaxVertices(-1),
259       mGeometryShaderInvocations(0),
260       mGeometryShaderInputPrimitiveType(EptUndefined),
261       mGeometryShaderOutputPrimitiveType(EptUndefined)
262 {
263 }
264 
~TCompiler()265 TCompiler::~TCompiler()
266 {
267 }
268 
shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const269 bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const
270 {
271     // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API,
272     // validate loop and indexing as well (to verify that the shader only uses minimal functionality
273     // of ESSL 1.00 as in Appendix A of the spec).
274     return (IsWebGLBasedSpec(shaderSpec) && shaderVersion == 100) ||
275            (compileOptions & SH_VALIDATE_LOOP_INDEXING);
276 }
277 
Init(const ShBuiltInResources & resources)278 bool TCompiler::Init(const ShBuiltInResources &resources)
279 {
280     shaderVersion = 100;
281 
282     maxUniformVectors = GetMaxUniformVectorsForShaderType(shaderType, resources);
283 
284     maxExpressionComplexity = resources.MaxExpressionComplexity;
285     maxCallStackDepth       = resources.MaxCallStackDepth;
286     maxFunctionParameters   = resources.MaxFunctionParameters;
287 
288     SetGlobalPoolAllocator(&allocator);
289 
290     // Generate built-in symbol table.
291     if (!InitBuiltInSymbolTable(resources))
292         return false;
293     InitExtensionBehavior(resources, extensionBehavior);
294     fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
295 
296     arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
297     clampingStrategy = resources.ArrayIndexClampingStrategy;
298 
299     hashFunction = resources.HashFunction;
300 
301     return true;
302 }
303 
compileTreeForTesting(const char * const shaderStrings[],size_t numStrings,ShCompileOptions compileOptions)304 TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],
305                                                size_t numStrings,
306                                                ShCompileOptions compileOptions)
307 {
308     return compileTreeImpl(shaderStrings, numStrings, compileOptions);
309 }
310 
compileTreeImpl(const char * const shaderStrings[],size_t numStrings,const ShCompileOptions compileOptions)311 TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
312                                          size_t numStrings,
313                                          const ShCompileOptions compileOptions)
314 {
315     clearResults();
316 
317     ASSERT(numStrings > 0);
318     ASSERT(GetGlobalPoolAllocator());
319 
320     // Reset the extension behavior for each compilation unit.
321     ResetExtensionBehavior(extensionBehavior);
322 
323     // First string is path of source file if flag is set. The actual source follows.
324     size_t firstSource = 0;
325     if (compileOptions & SH_SOURCE_PATH)
326     {
327         mSourcePath = shaderStrings[0];
328         ++firstSource;
329     }
330 
331     TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec,
332                                compileOptions, true, &mDiagnostics, getResources());
333 
334     parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh);
335 
336     // We preserve symbols at the built-in level from compile-to-compile.
337     // Start pushing the user-defined symbols at global level.
338     TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
339 
340     // Parse shader.
341     if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr,
342                        &parseContext) != 0)
343     {
344         return nullptr;
345     }
346 
347     if (parseContext.getTreeRoot() == nullptr)
348     {
349         return nullptr;
350     }
351 
352     setASTMetadata(parseContext);
353 
354     if (MapSpecToShaderVersion(shaderSpec) < shaderVersion)
355     {
356         mDiagnostics.globalError("unsupported shader version");
357         return nullptr;
358     }
359 
360     TIntermBlock *root = parseContext.getTreeRoot();
361     if (!checkAndSimplifyAST(root, parseContext, compileOptions))
362     {
363         return nullptr;
364     }
365 
366     return root;
367 }
368 
setASTMetadata(const TParseContext & parseContext)369 void TCompiler::setASTMetadata(const TParseContext &parseContext)
370 {
371     shaderVersion = parseContext.getShaderVersion();
372 
373     mPragma = parseContext.pragma();
374     symbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);
375 
376     mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
377     mComputeShaderLocalSize         = parseContext.getComputeShaderLocalSize();
378 
379     mNumViews = parseContext.getNumViews();
380 
381     // Highp might have been auto-enabled based on shader version
382     fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh();
383 
384     if (shaderType == GL_GEOMETRY_SHADER_OES)
385     {
386         mGeometryShaderInputPrimitiveType  = parseContext.getGeometryShaderInputPrimitiveType();
387         mGeometryShaderOutputPrimitiveType = parseContext.getGeometryShaderOutputPrimitiveType();
388         mGeometryShaderMaxVertices         = parseContext.getGeometryShaderMaxVertices();
389         mGeometryShaderInvocations         = parseContext.getGeometryShaderInvocations();
390     }
391 }
392 
checkAndSimplifyAST(TIntermBlock * root,const TParseContext & parseContext,ShCompileOptions compileOptions)393 bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
394                                     const TParseContext &parseContext,
395                                     ShCompileOptions compileOptions)
396 {
397     // Disallow expressions deemed too complex.
398     if ((compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY) && !limitExpressionComplexity(root))
399     {
400         return false;
401     }
402 
403     // We prune no-ops to work around driver bugs and to keep AST processing and output simple.
404     // The following kinds of no-ops are pruned:
405     //   1. Empty declarations "int;".
406     //   2. Literal statements: "1.0;". The ESSL output doesn't define a default precision
407     //      for float, so float literal statements would end up with no precision which is
408     //      invalid ESSL.
409     // After this empty declarations are not allowed in the AST.
410     PruneNoOps(root);
411 
412     // In case the last case inside a switch statement is a certain type of no-op, GLSL
413     // compilers in drivers may not accept it. In this case we clean up the dead code from the
414     // end of switch statements. This is also required because PruneNoOps may have left switch
415     // statements that only contained an empty declaration inside the final case in an invalid
416     // state. Relies on that PruneNoOps has already been run.
417     RemoveNoOpCasesFromEndOfSwitchStatements(root, &symbolTable);
418 
419     // Remove empty switch statements - this makes output simpler.
420     RemoveEmptySwitchStatements(root);
421 
422     // Create the function DAG and check there is no recursion
423     if (!initCallDag(root))
424     {
425         return false;
426     }
427 
428     if ((compileOptions & SH_LIMIT_CALL_STACK_DEPTH) && !checkCallDepth())
429     {
430         return false;
431     }
432 
433     // Checks which functions are used and if "main" exists
434     functionMetadata.clear();
435     functionMetadata.resize(mCallDag.size());
436     if (!tagUsedFunctions())
437     {
438         return false;
439     }
440 
441     if (!(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS))
442     {
443         pruneUnusedFunctions(root);
444     }
445 
446     if (shaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, shaderType))
447     {
448         return false;
449     }
450 
451     if (shaderVersion >= 300 && shaderType == GL_FRAGMENT_SHADER &&
452         !ValidateOutputs(root, getExtensionBehavior(), compileResources.MaxDrawBuffers,
453                          &mDiagnostics))
454     {
455         return false;
456     }
457 
458     if (shouldRunLoopAndIndexingValidation(compileOptions) &&
459         !ValidateLimitations(root, shaderType, &symbolTable, shaderVersion, &mDiagnostics))
460     {
461         return false;
462     }
463 
464     // Fail compilation if precision emulation not supported.
465     if (getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision &&
466         !EmulatePrecision::SupportedInLanguage(outputType))
467     {
468         mDiagnostics.globalError("Precision emulation not supported for this output type.");
469         return false;
470     }
471 
472     // Clamping uniform array bounds needs to happen after validateLimitations pass.
473     if (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)
474     {
475         arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
476     }
477 
478     if ((compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) &&
479         parseContext.isExtensionEnabled(TExtension::OVR_multiview) &&
480         getShaderType() != GL_COMPUTE_SHADER)
481     {
482         DeclareAndInitBuiltinsForInstancedMultiview(root, mNumViews, shaderType, compileOptions,
483                                                     outputType, &symbolTable);
484     }
485 
486     // This pass might emit short circuits so keep it before the short circuit unfolding
487     if (compileOptions & SH_REWRITE_DO_WHILE_LOOPS)
488         RewriteDoWhile(root, &symbolTable);
489 
490     if (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION)
491         sh::AddAndTrueToLoopCondition(root);
492 
493     if (compileOptions & SH_UNFOLD_SHORT_CIRCUIT)
494     {
495         UnfoldShortCircuitAST unfoldShortCircuit;
496         root->traverse(&unfoldShortCircuit);
497         unfoldShortCircuit.updateTree();
498     }
499 
500     if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT)
501     {
502         RemovePow(root);
503     }
504 
505     if (compileOptions & SH_REGENERATE_STRUCT_NAMES)
506     {
507         RegenerateStructNames gen(&symbolTable, shaderVersion);
508         root->traverse(&gen);
509     }
510 
511     if (shaderType == GL_FRAGMENT_SHADER && shaderVersion == 100 &&
512         compileResources.EXT_draw_buffers && compileResources.MaxDrawBuffers > 1 &&
513         IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers))
514     {
515         EmulateGLFragColorBroadcast(root, compileResources.MaxDrawBuffers, &outputVariables,
516                                     &symbolTable, shaderVersion);
517     }
518 
519     // Split multi declarations and remove calls to array length().
520     // Note that SimplifyLoopConditions needs to be run before any other AST transformations
521     // that may need to generate new statements from loop conditions or loop expressions.
522     SimplifyLoopConditions(
523         root,
524         IntermNodePatternMatcher::kMultiDeclaration | IntermNodePatternMatcher::kArrayLengthMethod,
525         &getSymbolTable(), getShaderVersion());
526 
527     // Note that separate declarations need to be run before other AST transformations that
528     // generate new statements from expressions.
529     SeparateDeclarations(root);
530 
531     SplitSequenceOperator(root, IntermNodePatternMatcher::kArrayLengthMethod, &getSymbolTable(),
532                           getShaderVersion());
533 
534     RemoveArrayLengthMethod(root);
535 
536     RemoveUnreferencedVariables(root, &symbolTable);
537 
538     // Built-in function emulation needs to happen after validateLimitations pass.
539     // TODO(jmadill): Remove global pool allocator.
540     GetGlobalPoolAllocator()->lock();
541     initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
542     GetGlobalPoolAllocator()->unlock();
543     builtInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
544 
545     if (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
546     {
547         ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh, &symbolTable);
548     }
549 
550     if (shouldCollectVariables(compileOptions))
551     {
552         ASSERT(!variablesCollected);
553         CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings,
554                          &outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks,
555                          hashFunction, &symbolTable, shaderVersion, shaderType, extensionBehavior);
556         collectInterfaceBlocks();
557         variablesCollected = true;
558         if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
559         {
560             useAllMembersInUnusedStandardAndSharedBlocks(root);
561         }
562         if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
563         {
564             // Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec
565             // Appendix A, section 7, the shader does not use too many uniforms.
566             if (!CheckVariablesInPackingLimits(maxUniformVectors, uniforms))
567             {
568                 mDiagnostics.globalError("too many uniforms");
569                 return false;
570             }
571         }
572         if (compileOptions & SH_INIT_OUTPUT_VARIABLES)
573         {
574             initializeOutputVariables(root);
575         }
576     }
577 
578     // Removing invariant declarations must be done after collecting variables.
579     // Otherwise, built-in invariant declarations don't apply.
580     if (RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions))
581     {
582         RemoveInvariantDeclaration(root);
583     }
584 
585     // gl_Position is always written in compatibility output mode.
586     // It may have been already initialized among other output variables, in that case we don't
587     // need to initialize it twice.
588     if (shaderType == GL_VERTEX_SHADER && !mGLPositionInitialized &&
589         ((compileOptions & SH_INIT_GL_POSITION) || (outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
590     {
591         initializeGLPosition(root);
592         mGLPositionInitialized = true;
593     }
594 
595     // DeferGlobalInitializers needs to be run before other AST transformations that generate new
596     // statements from expressions. But it's fine to run DeferGlobalInitializers after the above
597     // SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST
598     // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00.
599     bool initializeLocalsAndGlobals =
600         (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType());
601     bool canUseLoopsToInitialize = !(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES);
602     DeferGlobalInitializers(root, initializeLocalsAndGlobals, canUseLoopsToInitialize, &symbolTable);
603 
604     if (initializeLocalsAndGlobals)
605     {
606         // Initialize uninitialized local variables.
607         // In some cases initializing can generate extra statements in the parent block, such as
608         // when initializing nameless structs or initializing arrays in ESSL 1.00. In that case
609         // we need to first simplify loop conditions. We've already separated declarations
610         // earlier, which is also required. If we don't follow the Appendix A limitations, loop
611         // init statements can declare arrays or nameless structs and have multiple
612         // declarations.
613 
614         if (!shouldRunLoopAndIndexingValidation(compileOptions))
615         {
616             SimplifyLoopConditions(root,
617                                    IntermNodePatternMatcher::kArrayDeclaration |
618                                        IntermNodePatternMatcher::kNamelessStructDeclaration,
619                                    &getSymbolTable(), getShaderVersion());
620         }
621 
622         InitializeUninitializedLocals(root, getShaderVersion(), canUseLoopsToInitialize,
623                                       &getSymbolTable());
624     }
625 
626     if (getShaderType() == GL_VERTEX_SHADER && (compileOptions & SH_CLAMP_POINT_SIZE))
627     {
628         ClampPointSize(root, compileResources.MaxPointSize, &getSymbolTable());
629     }
630 
631     if (compileOptions & SH_REWRITE_VECTOR_SCALAR_ARITHMETIC)
632     {
633         VectorizeVectorScalarArithmetic(root, &getSymbolTable());
634     }
635 
636     return true;
637 }
638 
compile(const char * const shaderStrings[],size_t numStrings,ShCompileOptions compileOptionsIn)639 bool TCompiler::compile(const char *const shaderStrings[],
640                         size_t numStrings,
641                         ShCompileOptions compileOptionsIn)
642 {
643 #if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
644     DumpFuzzerCase(shaderStrings, numStrings, shaderType, shaderSpec, outputType, compileOptionsIn);
645 #endif  // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
646 
647     if (numStrings == 0)
648         return true;
649 
650     ShCompileOptions compileOptions = compileOptionsIn;
651 
652     // Apply key workarounds.
653     if (shouldFlattenPragmaStdglInvariantAll())
654     {
655         // This should be harmless to do in all cases, but for the moment, do it only conditionally.
656         compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;
657     }
658 
659     TScopedPoolAllocator scopedAlloc(&allocator);
660     TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
661 
662     if (root)
663     {
664         if (compileOptions & SH_INTERMEDIATE_TREE)
665             OutputTree(root, infoSink.info);
666 
667         if (compileOptions & SH_OBJECT_CODE)
668         {
669             PerformanceDiagnostics perfDiagnostics(&mDiagnostics);
670             translate(root, compileOptions, &perfDiagnostics);
671         }
672 
673         // The IntermNode tree doesn't need to be deleted here, since the
674         // memory will be freed in a big chunk by the PoolAllocator.
675         return true;
676     }
677     return false;
678 }
679 
InitBuiltInSymbolTable(const ShBuiltInResources & resources)680 bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
681 {
682     if (resources.MaxDrawBuffers < 1)
683     {
684         return false;
685     }
686     if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1)
687     {
688         return false;
689     }
690 
691     compileResources = resources;
692     setResourceString();
693 
694     ASSERT(symbolTable.isEmpty());
695     symbolTable.push();  // COMMON_BUILTINS
696     symbolTable.push();  // ESSL1_BUILTINS
697     symbolTable.push();  // ESSL3_BUILTINS
698     symbolTable.push();  // ESSL3_1_BUILTINS
699     symbolTable.push();  // GLSL_BUILTINS
700 
701     switch (shaderType)
702     {
703         case GL_FRAGMENT_SHADER:
704             symbolTable.setDefaultPrecision(EbtInt, EbpMedium);
705             break;
706         case GL_VERTEX_SHADER:
707         case GL_COMPUTE_SHADER:
708         case GL_GEOMETRY_SHADER_OES:
709             symbolTable.setDefaultPrecision(EbtInt, EbpHigh);
710             symbolTable.setDefaultPrecision(EbtFloat, EbpHigh);
711             break;
712         default:
713             UNREACHABLE();
714     }
715     // Set defaults for sampler types that have default precision, even those that are
716     // only available if an extension exists.
717     // New sampler types in ESSL3 don't have default precision. ESSL1 types do.
718     initSamplerDefaultPrecision(EbtSampler2D);
719     initSamplerDefaultPrecision(EbtSamplerCube);
720     // SamplerExternalOES is specified in the extension to have default precision.
721     initSamplerDefaultPrecision(EbtSamplerExternalOES);
722     // SamplerExternal2DY2YEXT is specified in the extension to have default precision.
723     initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT);
724     // It isn't specified whether Sampler2DRect has default precision.
725     initSamplerDefaultPrecision(EbtSampler2DRect);
726 
727     symbolTable.setDefaultPrecision(EbtAtomicCounter, EbpHigh);
728 
729     InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
730 
731     IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
732 
733     return true;
734 }
735 
initSamplerDefaultPrecision(TBasicType samplerType)736 void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType)
737 {
738     ASSERT(samplerType > EbtGuardSamplerBegin && samplerType < EbtGuardSamplerEnd);
739     symbolTable.setDefaultPrecision(samplerType, EbpLow);
740 }
741 
setResourceString()742 void TCompiler::setResourceString()
743 {
744     std::ostringstream strstream;
745 
746     // clang-format off
747     strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs
748         << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
749         << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
750         << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits
751         << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits
752         << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits
753         << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors
754         << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
755         << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
756         << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external
757         << ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3
758         << ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external
759         << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
760         << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
761         << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
762         << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity
763         << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
764         << ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters
765         << ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended
766         << ":EXT_frag_depth:" << compileResources.EXT_frag_depth
767         << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
768         << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch
769         << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch
770         << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch
771         << ":OVR_multiview:" << compileResources.OVR_multiview
772         << ":EXT_YUV_target:" << compileResources.EXT_YUV_target
773         << ":OES_geometry_shader:" << compileResources.OES_geometry_shader
774         << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
775         << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
776         << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
777         << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
778         << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers
779         << ":MaxViewsOVR:" << compileResources.MaxViewsOVR
780         << ":NV_draw_buffers:" << compileResources.NV_draw_buffers
781         << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision
782         << ":MinProgramTextureGatherOffset:" << compileResources.MinProgramTextureGatherOffset
783         << ":MaxProgramTextureGatherOffset:" << compileResources.MaxProgramTextureGatherOffset
784         << ":MaxImageUnits:" << compileResources.MaxImageUnits
785         << ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms
786         << ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms
787         << ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms
788         << ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms
789         << ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources
790         << ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0]
791         << ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1]
792         << ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2]
793         << ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0]
794         << ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1]
795         << ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2]
796         << ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents
797         << ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits
798         << ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters
799         << ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers
800         << ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters
801         << ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters
802         << ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters
803         << ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings
804         << ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers
805         << ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers
806         << ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers
807         << ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize
808         << ":MaxGeometryUniformComponents:" << compileResources.MaxGeometryUniformComponents
809         << ":MaxGeometryUniformBlocks:" << compileResources.MaxGeometryUniformBlocks
810         << ":MaxGeometryInputComponents:" << compileResources.MaxGeometryInputComponents
811         << ":MaxGeometryOutputComponents:" << compileResources.MaxGeometryOutputComponents
812         << ":MaxGeometryOutputVertices:" << compileResources.MaxGeometryOutputVertices
813         << ":MaxGeometryTotalOutputComponents:" << compileResources.MaxGeometryTotalOutputComponents
814         << ":MaxGeometryTextureImageUnits:" << compileResources.MaxGeometryTextureImageUnits
815         << ":MaxGeometryAtomicCounterBuffers:" << compileResources.MaxGeometryAtomicCounterBuffers
816         << ":MaxGeometryAtomicCounters:" << compileResources.MaxGeometryAtomicCounters
817         << ":MaxGeometryShaderStorageBlocks:" << compileResources.MaxGeometryShaderStorageBlocks
818         << ":MaxGeometryShaderInvocations:" << compileResources.MaxGeometryShaderInvocations
819         << ":MaxGeometryImageUniforms:" << compileResources.MaxGeometryImageUniforms;
820     // clang-format on
821 
822     builtInResourcesString = strstream.str();
823 }
824 
collectInterfaceBlocks()825 void TCompiler::collectInterfaceBlocks()
826 {
827     ASSERT(interfaceBlocks.empty());
828     interfaceBlocks.reserve(uniformBlocks.size() + shaderStorageBlocks.size() + inBlocks.size());
829     interfaceBlocks.insert(interfaceBlocks.end(), uniformBlocks.begin(), uniformBlocks.end());
830     interfaceBlocks.insert(interfaceBlocks.end(), shaderStorageBlocks.begin(),
831                            shaderStorageBlocks.end());
832     interfaceBlocks.insert(interfaceBlocks.end(), inBlocks.begin(), inBlocks.end());
833 }
834 
clearResults()835 void TCompiler::clearResults()
836 {
837     arrayBoundsClamper.Cleanup();
838     infoSink.info.erase();
839     infoSink.obj.erase();
840     infoSink.debug.erase();
841     mDiagnostics.resetErrorCount();
842 
843     attributes.clear();
844     outputVariables.clear();
845     uniforms.clear();
846     inputVaryings.clear();
847     outputVaryings.clear();
848     interfaceBlocks.clear();
849     uniformBlocks.clear();
850     shaderStorageBlocks.clear();
851     inBlocks.clear();
852     variablesCollected = false;
853     mGLPositionInitialized = false;
854 
855     mNumViews = -1;
856 
857     mGeometryShaderInputPrimitiveType  = EptUndefined;
858     mGeometryShaderOutputPrimitiveType = EptUndefined;
859     mGeometryShaderInvocations         = 0;
860     mGeometryShaderMaxVertices         = -1;
861 
862     builtInFunctionEmulator.cleanup();
863 
864     nameMap.clear();
865 
866     mSourcePath     = nullptr;
867 }
868 
initCallDag(TIntermNode * root)869 bool TCompiler::initCallDag(TIntermNode *root)
870 {
871     mCallDag.clear();
872 
873     switch (mCallDag.init(root, &mDiagnostics))
874     {
875         case CallDAG::INITDAG_SUCCESS:
876             return true;
877         case CallDAG::INITDAG_RECURSION:
878         case CallDAG::INITDAG_UNDEFINED:
879             // Error message has already been written out.
880             ASSERT(mDiagnostics.numErrors() > 0);
881             return false;
882     }
883 
884     UNREACHABLE();
885     return true;
886 }
887 
checkCallDepth()888 bool TCompiler::checkCallDepth()
889 {
890     std::vector<int> depths(mCallDag.size());
891 
892     for (size_t i = 0; i < mCallDag.size(); i++)
893     {
894         int depth    = 0;
895         auto &record = mCallDag.getRecordFromIndex(i);
896 
897         for (auto &calleeIndex : record.callees)
898         {
899             depth = std::max(depth, depths[calleeIndex] + 1);
900         }
901 
902         depths[i] = depth;
903 
904         if (depth >= maxCallStackDepth)
905         {
906             // Trace back the function chain to have a meaningful info log.
907             std::stringstream errorStream;
908             errorStream << "Call stack too deep (larger than " << maxCallStackDepth
909                         << ") with the following call chain: " << record.name;
910 
911             int currentFunction = static_cast<int>(i);
912             int currentDepth    = depth;
913 
914             while (currentFunction != -1)
915             {
916                 errorStream << " -> " << mCallDag.getRecordFromIndex(currentFunction).name;
917 
918                 int nextFunction = -1;
919                 for (auto &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
920                 {
921                     if (depths[calleeIndex] == currentDepth - 1)
922                     {
923                         currentDepth--;
924                         nextFunction = calleeIndex;
925                     }
926                 }
927 
928                 currentFunction = nextFunction;
929             }
930 
931             std::string errorStr = errorStream.str();
932             mDiagnostics.globalError(errorStr.c_str());
933 
934             return false;
935         }
936     }
937 
938     return true;
939 }
940 
tagUsedFunctions()941 bool TCompiler::tagUsedFunctions()
942 {
943     // Search from main, starting from the end of the DAG as it usually is the root.
944     for (size_t i = mCallDag.size(); i-- > 0;)
945     {
946         if (mCallDag.getRecordFromIndex(i).name == "main")
947         {
948             internalTagUsedFunction(i);
949             return true;
950         }
951     }
952 
953     mDiagnostics.globalError("Missing main()");
954     return false;
955 }
956 
internalTagUsedFunction(size_t index)957 void TCompiler::internalTagUsedFunction(size_t index)
958 {
959     if (functionMetadata[index].used)
960     {
961         return;
962     }
963 
964     functionMetadata[index].used = true;
965 
966     for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees)
967     {
968         internalTagUsedFunction(calleeIndex);
969     }
970 }
971 
972 // A predicate for the stl that returns if a top-level node is unused
973 class TCompiler::UnusedPredicate
974 {
975   public:
UnusedPredicate(const CallDAG * callDag,const std::vector<FunctionMetadata> * metadatas)976     UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas)
977         : mCallDag(callDag), mMetadatas(metadatas)
978     {
979     }
980 
operator ()(TIntermNode * node)981     bool operator()(TIntermNode *node)
982     {
983         const TIntermFunctionPrototype *asFunctionPrototype   = node->getAsFunctionPrototypeNode();
984         const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition();
985 
986         const TFunctionSymbolInfo *functionInfo = nullptr;
987 
988         if (asFunctionDefinition)
989         {
990             functionInfo = asFunctionDefinition->getFunctionSymbolInfo();
991         }
992         else if (asFunctionPrototype)
993         {
994             functionInfo = asFunctionPrototype->getFunctionSymbolInfo();
995         }
996         if (functionInfo == nullptr)
997         {
998             return false;
999         }
1000 
1001         size_t callDagIndex = mCallDag->findIndex(functionInfo);
1002         if (callDagIndex == CallDAG::InvalidIndex)
1003         {
1004             // This happens only for unimplemented prototypes which are thus unused
1005             ASSERT(asFunctionPrototype);
1006             return true;
1007         }
1008 
1009         ASSERT(callDagIndex < mMetadatas->size());
1010         return !(*mMetadatas)[callDagIndex].used;
1011     }
1012 
1013   private:
1014     const CallDAG *mCallDag;
1015     const std::vector<FunctionMetadata> *mMetadatas;
1016 };
1017 
pruneUnusedFunctions(TIntermBlock * root)1018 void TCompiler::pruneUnusedFunctions(TIntermBlock *root)
1019 {
1020     UnusedPredicate isUnused(&mCallDag, &functionMetadata);
1021     TIntermSequence *sequence = root->getSequence();
1022 
1023     if (!sequence->empty())
1024     {
1025         sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused),
1026                         sequence->end());
1027     }
1028 }
1029 
limitExpressionComplexity(TIntermBlock * root)1030 bool TCompiler::limitExpressionComplexity(TIntermBlock *root)
1031 {
1032     if (!IsASTDepthBelowLimit(root, maxExpressionComplexity))
1033     {
1034         mDiagnostics.globalError("Expression too complex.");
1035         return false;
1036     }
1037 
1038     if (!ValidateMaxParameters(root, maxFunctionParameters))
1039     {
1040         mDiagnostics.globalError("Function has too many parameters.");
1041         return false;
1042     }
1043 
1044     return true;
1045 }
1046 
shouldCollectVariables(ShCompileOptions compileOptions)1047 bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions)
1048 {
1049     return (compileOptions & SH_VARIABLES) != 0;
1050 }
1051 
wereVariablesCollected() const1052 bool TCompiler::wereVariablesCollected() const
1053 {
1054     return variablesCollected;
1055 }
1056 
initializeGLPosition(TIntermBlock * root)1057 void TCompiler::initializeGLPosition(TIntermBlock *root)
1058 {
1059     InitVariableList list;
1060     sh::ShaderVariable var(GL_FLOAT_VEC4);
1061     var.name = "gl_Position";
1062     list.push_back(var);
1063     InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false);
1064 }
1065 
useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock * root)1066 void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)
1067 {
1068     sh::InterfaceBlockList list;
1069 
1070     for (auto block : uniformBlocks)
1071     {
1072         if (!block.staticUse &&
1073             (block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED))
1074         {
1075             list.push_back(block);
1076         }
1077     }
1078 
1079     sh::UseInterfaceBlockFields(root, list, symbolTable);
1080 }
1081 
initializeOutputVariables(TIntermBlock * root)1082 void TCompiler::initializeOutputVariables(TIntermBlock *root)
1083 {
1084     InitVariableList list;
1085     if (shaderType == GL_VERTEX_SHADER || shaderType == GL_GEOMETRY_SHADER_OES)
1086     {
1087         for (auto var : outputVaryings)
1088         {
1089             list.push_back(var);
1090             if (var.name == "gl_Position")
1091             {
1092                 ASSERT(!mGLPositionInitialized);
1093                 mGLPositionInitialized = true;
1094             }
1095         }
1096     }
1097     else
1098     {
1099         ASSERT(shaderType == GL_FRAGMENT_SHADER);
1100         for (auto var : outputVariables)
1101         {
1102             list.push_back(var);
1103         }
1104     }
1105     InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false);
1106 }
1107 
getExtensionBehavior() const1108 const TExtensionBehavior &TCompiler::getExtensionBehavior() const
1109 {
1110     return extensionBehavior;
1111 }
1112 
getSourcePath() const1113 const char *TCompiler::getSourcePath() const
1114 {
1115     return mSourcePath;
1116 }
1117 
getResources() const1118 const ShBuiltInResources &TCompiler::getResources() const
1119 {
1120     return compileResources;
1121 }
1122 
getArrayBoundsClamper() const1123 const ArrayBoundsClamper &TCompiler::getArrayBoundsClamper() const
1124 {
1125     return arrayBoundsClamper;
1126 }
1127 
getArrayIndexClampingStrategy() const1128 ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
1129 {
1130     return clampingStrategy;
1131 }
1132 
getBuiltInFunctionEmulator() const1133 const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const
1134 {
1135     return builtInFunctionEmulator;
1136 }
1137 
writePragma(ShCompileOptions compileOptions)1138 void TCompiler::writePragma(ShCompileOptions compileOptions)
1139 {
1140     if (!(compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL))
1141     {
1142         TInfoSinkBase &sink = infoSink.obj;
1143         if (mPragma.stdgl.invariantAll)
1144             sink << "#pragma STDGL invariant(all)\n";
1145     }
1146 }
1147 
isVaryingDefined(const char * varyingName)1148 bool TCompiler::isVaryingDefined(const char *varyingName)
1149 {
1150     ASSERT(variablesCollected);
1151     for (size_t ii = 0; ii < inputVaryings.size(); ++ii)
1152     {
1153         if (inputVaryings[ii].name == varyingName)
1154         {
1155             return true;
1156         }
1157     }
1158     for (size_t ii = 0; ii < outputVaryings.size(); ++ii)
1159     {
1160         if (outputVaryings[ii].name == varyingName)
1161         {
1162             return true;
1163         }
1164     }
1165 
1166     return false;
1167 }
1168 
1169 }  // namespace sh
1170