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