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