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