blob: a09c5058fe1843c43cbd86eee884903cd0335840 [file] [log] [blame]
alokp@chromium.org07620a52010-09-23 17:53:56 +00001//
Jamie Madill88f6e942014-02-19 10:27:53 -05002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
alokp@chromium.org07620a52010-09-23 17:53:56 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Corentin Wallez8b28a8b2016-09-15 19:47:56 -04007#include "compiler/translator/Compiler.h"
8
9#include <sstream>
10
11#include "angle_gl.h"
12#include "common/utilities.h"
Qiankun Miao09cfac62016-09-06 17:25:16 +080013#include "compiler/translator/AddAndTrueToLoopCondition.h"
Dmitry Skiba01971112015-07-10 14:54:00 -040014#include "compiler/translator/Cache.h"
Corentin Wallez71d147f2015-02-11 11:15:24 -080015#include "compiler/translator/CallDAG.h"
Olli Etuaho3d932d82016-04-12 11:10:30 +030016#include "compiler/translator/DeferGlobalInitializers.h"
Zhenyao Mo4e94fea2016-08-09 14:31:37 -070017#include "compiler/translator/EmulateGLFragColorBroadcast.h"
Jamie Madilld5696192016-10-06 11:09:24 -040018#include "compiler/translator/EmulatePrecision.h"
Geoff Lang17732822013-08-29 13:46:49 -040019#include "compiler/translator/Initialize.h"
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080020#include "compiler/translator/InitializeVariables.h"
Jamie Madill6b9cb252013-10-17 10:45:47 -040021#include "compiler/translator/ParseContext.h"
Olli Etuahoc6833112015-04-22 15:15:54 +030022#include "compiler/translator/PruneEmptyDeclarations.h"
Zhenyao Moe740add2014-07-18 17:01:01 -070023#include "compiler/translator/RegenerateStructNames.h"
Qiankun Miao705a9192016-08-29 10:05:27 +080024#include "compiler/translator/RemoveInvariantDeclaration.h"
Olli Etuaho5c407bb2015-06-01 12:20:39 +030025#include "compiler/translator/RemovePow.h"
Corentin Wallezd4b50542015-09-28 12:19:26 -070026#include "compiler/translator/RewriteDoWhile.h"
Zhenyao Mocd68fe72014-07-11 10:45:44 -070027#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
Zhenyao Mo7cab38b2013-10-15 12:59:30 -070028#include "compiler/translator/UnfoldShortCircuitAST.h"
Qin Jiajia7835b522016-10-08 11:20:17 +080029#include "compiler/translator/UseInterfaceBlockFields.h"
Geoff Lang17732822013-08-29 13:46:49 -040030#include "compiler/translator/ValidateLimitations.h"
Olli Etuaho19d1dc92016-03-08 17:18:46 +020031#include "compiler/translator/ValidateMaxParameters.h"
Olli Etuaho09b04a22016-12-15 13:30:26 +000032#include "compiler/translator/ValidateMultiviewWebGL.h"
Geoff Lang17732822013-08-29 13:46:49 -040033#include "compiler/translator/ValidateOutputs.h"
34#include "compiler/translator/VariablePacker.h"
shannon.woods@transgaming.comda1ed362013-01-25 21:54:57 +000035#include "third_party/compiler/ArrayBoundsClamper.h"
Corentin Wallez28b65282016-06-16 07:24:50 -070036
Jamie Madillacb4b812016-11-07 13:50:29 -050037namespace sh
38{
39
Corentin Wallez28b65282016-06-16 07:24:50 -070040namespace
41{
42
43#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
44void DumpFuzzerCase(char const *const *shaderStrings,
45 size_t numStrings,
46 uint32_t type,
47 uint32_t spec,
48 uint32_t output,
49 uint64_t options)
50{
51 static int fileIndex = 0;
52
53 std::ostringstream o;
54 o << "corpus/" << fileIndex++ << ".sample";
55 std::string s = o.str();
56
57 // Must match the input format of the fuzzer
58 FILE *f = fopen(s.c_str(), "w");
59 fwrite(&type, sizeof(type), 1, f);
60 fwrite(&spec, sizeof(spec), 1, f);
61 fwrite(&output, sizeof(output), 1, f);
62 fwrite(&options, sizeof(options), 1, f);
63
64 char zero[128 - 20] = {0};
65 fwrite(&zero, 128 - 20, 1, f);
66
67 for (size_t i = 0; i < numStrings; i++)
68 {
69 fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f);
70 }
71 fwrite(&zero, 1, 1, f);
72
73 fclose(f);
74}
75#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
76} // anonymous namespace
77
Jamie Madill5508f392014-02-20 13:31:36 -050078bool IsWebGLBasedSpec(ShShaderSpec spec)
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +000079{
Qiankun Miaoc2c5fc42016-08-31 15:24:22 +080080 return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC || spec == SH_WEBGL3_SPEC);
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +000081}
82
Qingqing Dengad0d0792015-04-08 14:25:06 -070083bool IsGLSL130OrNewer(ShShaderOutput output)
84{
Jamie Madillacb4b812016-11-07 13:50:29 -050085 return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
86 output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
87 output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT ||
88 output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
89 output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
Qingqing Dengad0d0792015-04-08 14:25:06 -070090}
91
Qiankun Miao705a9192016-08-29 10:05:27 +080092bool IsGLSL420OrNewer(ShShaderOutput output)
93{
Jamie Madillacb4b812016-11-07 13:50:29 -050094 return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
95 output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
Qiankun Miao705a9192016-08-29 10:05:27 +080096}
97
Zhenyao Mob7bf7422016-11-08 14:44:05 -080098bool IsGLSL410OrOlder(ShShaderOutput output)
99{
100 return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
101 output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
102 output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
103}
104
Qiankun Miao89dd8f32016-11-09 12:59:30 +0000105bool RemoveInvariant(sh::GLenum shaderType,
106 int shaderVersion,
107 ShShaderOutput outputType,
108 ShCompileOptions compileOptions)
109{
110 if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 &&
111 shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
112 return true;
113
114 if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
Qiankun Miao41f9f672016-11-16 17:04:36 +0800115 shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER)
Qiankun Miao89dd8f32016-11-09 12:59:30 +0000116 return true;
117
118 return false;
119}
120
Zhenyao Mo7faf1a12014-04-25 18:03:56 -0700121size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
Jamie Madill88f6e942014-02-19 10:27:53 -0500122{
He Yunchao29ab9ff2015-08-06 16:58:30 +0800123 // WebGL defines a max token length of 256, while ES2 leaves max token
Jamie Madill88f6e942014-02-19 10:27:53 -0500124 // size undefined. ES3 defines a max size of 1024 characters.
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700125 switch (spec)
Jamie Madill88f6e942014-02-19 10:27:53 -0500126 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500127 case SH_WEBGL_SPEC:
128 return 256;
129 default:
130 return 1024;
Jamie Madill88f6e942014-02-19 10:27:53 -0500131 }
132}
133
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500134namespace
135{
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700136
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800137class TScopedPoolAllocator
138{
139 public:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500140 TScopedPoolAllocator(TPoolAllocator *allocator) : mAllocator(allocator)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800141 {
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400142 mAllocator->push();
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000143 SetGlobalPoolAllocator(mAllocator);
144 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800145 ~TScopedPoolAllocator()
146 {
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000147 SetGlobalPoolAllocator(NULL);
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400148 mAllocator->pop();
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000149 }
150
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800151 private:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500152 TPoolAllocator *mAllocator;
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400153};
154
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800155class TScopedSymbolTableLevel
156{
157 public:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500158 TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800159 {
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400160 ASSERT(mTable->atBuiltInLevel());
161 mTable->push();
162 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800163 ~TScopedSymbolTableLevel()
164 {
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400165 while (!mTable->atBuiltInLevel())
166 mTable->pop();
167 }
168
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800169 private:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500170 TSymbolTable *mTable;
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000171};
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700172
173int MapSpecToShaderVersion(ShShaderSpec spec)
174{
175 switch (spec)
176 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500177 case SH_GLES2_SPEC:
178 case SH_WEBGL_SPEC:
179 return 100;
180 case SH_GLES3_SPEC:
181 case SH_WEBGL2_SPEC:
182 return 300;
183 case SH_GLES3_1_SPEC:
184 case SH_WEBGL3_SPEC:
185 return 310;
186 default:
187 UNREACHABLE();
188 return 0;
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700189 }
190}
191
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000192} // namespace
193
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800194TShHandleBase::TShHandleBase()
195{
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000196 allocator.push();
197 SetGlobalPoolAllocator(&allocator);
198}
199
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800200TShHandleBase::~TShHandleBase()
201{
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000202 SetGlobalPoolAllocator(NULL);
203 allocator.popAll();
204}
205
Jamie Madill183bde52014-07-02 15:31:19 -0400206TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700207 : variablesCollected(false),
208 shaderType(type),
zmo@google.comf420c422011-09-12 18:27:59 +0000209 shaderSpec(spec),
Jamie Madill68fe74a2014-05-27 12:56:01 -0400210 outputType(output),
Jamie Madilleb1a0102013-07-08 13:31:38 -0400211 maxUniformVectors(0),
212 maxExpressionComplexity(0),
213 maxCallStackDepth(0),
Olli Etuaho19d1dc92016-03-08 17:18:46 +0200214 maxFunctionParameters(0),
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +0000215 fragmentPrecisionHigh(false),
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000216 clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
Olli Etuaho8efc5ad2015-03-03 17:21:10 +0200217 builtInFunctionEmulator(),
Olli Etuaho77ba4082016-12-16 12:01:18 +0000218 mDiagnostics(infoSink.info),
Corentin Wallezd4b50542015-09-28 12:19:26 -0700219 mSourcePath(NULL),
Martin Radev802abe02016-08-04 17:48:32 +0300220 mComputeShaderLocalSizeDeclared(false),
Corentin Wallezd4b50542015-09-28 12:19:26 -0700221 mTemporaryIndex(0)
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000222{
Martin Radev802abe02016-08-04 17:48:32 +0300223 mComputeShaderLocalSize.fill(1);
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000224}
225
226TCompiler::~TCompiler()
227{
228}
229
Qiankun Miao7ebb97f2016-09-08 18:01:50 +0800230bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300231{
232 // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API,
233 // validate loop and indexing as well (to verify that the shader only uses minimal functionality
234 // of ESSL 1.00 as in Appendix A of the spec).
235 return (IsWebGLBasedSpec(shaderSpec) && shaderVersion == 100) ||
236 (compileOptions & SH_VALIDATE_LOOP_INDEXING);
237}
238
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500239bool TCompiler::Init(const ShBuiltInResources &resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000240{
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500241 shaderVersion = 100;
242 maxUniformVectors = (shaderType == GL_VERTEX_SHADER) ? resources.MaxVertexUniformVectors
243 : resources.MaxFragmentUniformVectors;
Jamie Madilleb1a0102013-07-08 13:31:38 -0400244 maxExpressionComplexity = resources.MaxExpressionComplexity;
Olli Etuaho19d1dc92016-03-08 17:18:46 +0200245 maxCallStackDepth = resources.MaxCallStackDepth;
246 maxFunctionParameters = resources.MaxFunctionParameters;
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400247
248 SetGlobalPoolAllocator(&allocator);
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000249
alokp@chromium.org07620a52010-09-23 17:53:56 +0000250 // Generate built-in symbol table.
251 if (!InitBuiltInSymbolTable(resources))
252 return false;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000253 InitExtensionBehavior(resources, extensionBehavior);
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +0000254 fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000255
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000256 arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
257 clampingStrategy = resources.ArrayIndexClampingStrategy;
258
daniel@transgaming.comc23f4612012-11-28 19:42:57 +0000259 hashFunction = resources.HashFunction;
260
alokp@chromium.org07620a52010-09-23 17:53:56 +0000261 return true;
262}
263
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100264TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],
265 size_t numStrings,
266 ShCompileOptions compileOptions)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000267{
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200268 return compileTreeImpl(shaderStrings, numStrings, compileOptions);
269}
270
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100271TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
272 size_t numStrings,
273 const ShCompileOptions compileOptions)
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200274{
alokp@chromium.org07620a52010-09-23 17:53:56 +0000275 clearResults();
276
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200277 ASSERT(numStrings > 0);
278 ASSERT(GetGlobalPoolAllocator());
alokp@chromium.org07620a52010-09-23 17:53:56 +0000279
David Yen0fbd1282015-02-02 14:46:09 -0800280 // Reset the extension behavior for each compilation unit.
281 ResetExtensionBehavior(extensionBehavior);
282
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000283 // First string is path of source file if flag is set. The actual source follows.
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000284 size_t firstSource = 0;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000285 if (compileOptions & SH_SOURCE_PATH)
286 {
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200287 mSourcePath = shaderStrings[0];
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000288 ++firstSource;
289 }
290
Olli Etuahof119a262016-08-19 15:54:22 +0300291 TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec,
Olli Etuaho77ba4082016-12-16 12:01:18 +0000292 compileOptions, true, &mDiagnostics, getResources());
Olli Etuaho853dc1a2014-11-06 17:25:48 +0200293
Olli Etuahoa6996682015-10-12 14:32:30 +0300294 parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000295
296 // We preserve symbols at the built-in level from compile-to-compile.
297 // Start pushing the user-defined symbols at global level.
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400298 TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000299
300 // Parse shader.
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500301 bool success = (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr,
302 &parseContext) == 0) &&
303 (parseContext.getTreeRoot() != nullptr);
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000304
shannon.woods%transgaming.com@gtempaccount.com5524db02013-04-13 03:38:16 +0000305 shaderVersion = parseContext.getShaderVersion();
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700306 if (success && MapSpecToShaderVersion(shaderSpec) < shaderVersion)
307 {
Olli Etuaho77ba4082016-12-16 12:01:18 +0000308 mDiagnostics.globalError("unsupported shader version");
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700309 success = false;
310 }
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000311
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100312 TIntermBlock *root = nullptr;
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200313
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800314 if (success)
315 {
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700316 mPragma = parseContext.pragma();
Kenneth Russell8bad46d2016-07-01 19:52:52 -0700317 symbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700318
Martin Radev802abe02016-08-04 17:48:32 +0300319 mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
320 mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize();
321
Olli Etuaho09b04a22016-12-15 13:30:26 +0000322 mNumViews = parseContext.getNumViews();
323
Jamie Madill6e06b1f2015-05-14 10:01:17 -0400324 root = parseContext.getTreeRoot();
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000325
Olli Etuahoa6996682015-10-12 14:32:30 +0300326 // Highp might have been auto-enabled based on shader version
327 fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh();
328
Olli Etuaho09b04a22016-12-15 13:30:26 +0000329 if (success && (IsWebGLBasedSpec(shaderSpec) &&
330 IsExtensionEnabled(extensionBehavior, "GL_OVR_multiview") &&
331 IsExtensionEnabled(extensionBehavior, "GL_OVR_multiview2")))
332 {
333 // Can't enable both extensions at the same time.
334 mDiagnostics.globalError("Can't enable both OVR_multiview and OVR_multiview2");
335 success = false;
336 }
337
Jamie Madill6654bc92014-03-26 14:01:57 -0400338 // Disallow expressions deemed too complex.
339 if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
340 success = limitExpressionComplexity(root);
341
Corentin Wallez71d147f2015-02-11 11:15:24 -0800342 // Create the function DAG and check there is no recursion
zmo@google.comb1762df2011-07-30 02:04:23 +0000343 if (success)
Corentin Wallez71d147f2015-02-11 11:15:24 -0800344 success = initCallDag(root);
345
346 if (success && (compileOptions & SH_LIMIT_CALL_STACK_DEPTH))
347 success = checkCallDepth();
348
349 // Checks which functions are used and if "main" exists
350 if (success)
351 {
352 functionMetadata.clear();
353 functionMetadata.resize(mCallDag.size());
354 success = tagUsedFunctions();
355 }
zmo@google.comb1762df2011-07-30 02:04:23 +0000356
Corentin Walleza094a8a2015-04-07 11:53:06 -0700357 if (success && !(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS))
358 success = pruneUnusedFunctions(root);
359
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500360 // Prune empty declarations to work around driver bugs and to keep declaration output
361 // simple.
Olli Etuahoc6833112015-04-22 15:15:54 +0300362 if (success)
363 PruneEmptyDeclarations(root);
364
Jamie Madill183bde52014-07-02 15:31:19 -0400365 if (success && shaderVersion == 300 && shaderType == GL_FRAGMENT_SHADER)
Jamie Madill05a80ce2013-06-20 11:55:49 -0400366 success = validateOutputs(root);
367
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300368 if (success && shouldRunLoopAndIndexingValidation(compileOptions))
Olli Etuaho9ec79392017-03-31 23:04:23 +0300369 success =
370 ValidateLimitations(root, shaderType, symbolTable, shaderVersion, &mDiagnostics);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000371
Olli Etuaho09b04a22016-12-15 13:30:26 +0000372 bool multiview2 = IsExtensionEnabled(extensionBehavior, "GL_OVR_multiview2");
373 if (success && compileResources.OVR_multiview && IsWebGLBasedSpec(shaderSpec) &&
374 (IsExtensionEnabled(extensionBehavior, "GL_OVR_multiview") || multiview2))
Olli Etuaho01d0ad02017-01-22 14:51:23 -0800375 success = ValidateMultiviewWebGL(root, shaderType, symbolTable, shaderVersion,
376 multiview2, &mDiagnostics);
Olli Etuaho09b04a22016-12-15 13:30:26 +0000377
Jamie Madilld5696192016-10-06 11:09:24 -0400378 // Fail compilation if precision emulation not supported.
379 if (success && getResources().WEBGL_debug_shader_precision &&
380 getPragma().debugShaderPrecision)
381 {
382 if (!EmulatePrecision::SupportedInLanguage(outputType))
383 {
Olli Etuaho77ba4082016-12-16 12:01:18 +0000384 mDiagnostics.globalError("Precision emulation not supported for this output type.");
Jamie Madilld5696192016-10-06 11:09:24 -0400385 success = false;
386 }
387 }
388
zmo@google.com32e97312011-08-24 01:03:11 +0000389 // Built-in function emulation needs to happen after validateLimitations pass.
Olli Etuaho8efc5ad2015-03-03 17:21:10 +0200390 if (success)
391 {
Jamie Madill438dbcf2016-06-17 14:20:05 -0400392 // TODO(jmadill): Remove global pool allocator.
393 GetGlobalPoolAllocator()->lock();
Olli Etuaho8efc5ad2015-03-03 17:21:10 +0200394 initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
Jamie Madill438dbcf2016-06-17 14:20:05 -0400395 GetGlobalPoolAllocator()->unlock();
Olli Etuahodfa75e82017-01-23 09:43:06 -0800396 builtInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
Olli Etuaho8efc5ad2015-03-03 17:21:10 +0200397 }
zmo@google.com32e97312011-08-24 01:03:11 +0000398
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000399 // Clamping uniform array bounds needs to happen after validateLimitations pass.
400 if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
401 arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
402
Ian Ewell924b7de2016-01-21 13:54:28 -0500403 // gl_Position is always written in compatibility output mode
404 if (success && shaderType == GL_VERTEX_SHADER &&
405 ((compileOptions & SH_INIT_GL_POSITION) ||
406 (outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800407 initializeGLPosition(root);
Zhenyao Moac44cd22013-09-23 14:57:09 -0400408
Corentin Wallezd4b50542015-09-28 12:19:26 -0700409 // This pass might emit short circuits so keep it before the short circuit unfolding
410 if (success && (compileOptions & SH_REWRITE_DO_WHILE_LOOPS))
411 RewriteDoWhile(root, getTemporaryIndex());
412
Qiankun Miao09cfac62016-09-06 17:25:16 +0800413 if (success && (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION))
414 sh::AddAndTrueToLoopCondition(root);
415
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800416 if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT))
417 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700418 UnfoldShortCircuitAST unfoldShortCircuit;
419 root->traverse(&unfoldShortCircuit);
420 unfoldShortCircuit.updateTree();
421 }
422
Olli Etuaho5c407bb2015-06-01 12:20:39 +0300423 if (success && (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT))
424 {
425 RemovePow(root);
426 }
427
Olli Etuaho4dfe8092015-08-21 17:44:35 +0300428 if (success && shouldCollectVariables(compileOptions))
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800429 {
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400430 collectVariables(root);
Qin Jiajia7835b522016-10-08 11:20:17 +0800431 if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
432 {
433 useAllMembersInUnusedStandardAndSharedBlocks(root);
434 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800435 if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
436 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000437 success = enforcePackingRestrictions();
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800438 if (!success)
439 {
Olli Etuaho77ba4082016-12-16 12:01:18 +0000440 mDiagnostics.globalError("too many uniforms");
gman@chromium.org8d804792012-10-17 21:33:48 +0000441 }
442 }
Zhenyao Mo72111912016-07-20 17:45:56 -0700443 if (success && (compileOptions & SH_INIT_OUTPUT_VARIABLES))
444 {
Olli Etuaho27776e32016-07-22 14:00:56 +0300445 initializeOutputVariables(root);
Zhenyao Mo72111912016-07-20 17:45:56 -0700446 }
gman@chromium.org8d804792012-10-17 21:33:48 +0000447 }
zmo@google.comfd747b82011-04-23 01:30:07 +0000448
Yuly Novikov817232e2017-02-22 18:36:10 -0500449 // Removing invariant declarations must be done after collecting variables.
450 // Otherwise, built-in invariant declarations don't apply.
451 if (success && RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions))
452 sh::RemoveInvariantDeclaration(root);
453
Zhenyao Mocd68fe72014-07-11 10:45:44 -0700454 if (success && (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS))
455 {
Olli Etuahob990b552016-10-27 12:29:17 +0100456 ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh,
457 &mTemporaryIndex);
Zhenyao Mocd68fe72014-07-11 10:45:44 -0700458 }
459
Zhenyao Moe740add2014-07-18 17:01:01 -0700460 if (success && (compileOptions & SH_REGENERATE_STRUCT_NAMES))
461 {
462 RegenerateStructNames gen(symbolTable, shaderVersion);
463 root->traverse(&gen);
464 }
Olli Etuaho3d932d82016-04-12 11:10:30 +0300465
Zhenyao Mo4e94fea2016-08-09 14:31:37 -0700466 if (success && shaderType == GL_FRAGMENT_SHADER && shaderVersion == 100 &&
467 compileResources.EXT_draw_buffers && compileResources.MaxDrawBuffers > 1 &&
468 IsExtensionEnabled(extensionBehavior, "GL_EXT_draw_buffers"))
469 {
470 EmulateGLFragColorBroadcast(root, compileResources.MaxDrawBuffers, &outputVariables);
471 }
472
Olli Etuaho3d932d82016-04-12 11:10:30 +0300473 if (success)
474 {
475 DeferGlobalInitializers(root);
476 }
alokp@chromium.org07620a52010-09-23 17:53:56 +0000477 }
478
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200479 if (success)
480 return root;
481
482 return NULL;
483}
484
Qiankun Miao7ebb97f2016-09-08 18:01:50 +0800485bool TCompiler::compile(const char *const shaderStrings[],
486 size_t numStrings,
487 ShCompileOptions compileOptionsIn)
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200488{
Corentin Wallez28b65282016-06-16 07:24:50 -0700489#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
490 DumpFuzzerCase(shaderStrings, numStrings, shaderType, shaderSpec, outputType, compileOptionsIn);
491#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
492
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200493 if (numStrings == 0)
494 return true;
495
Qiankun Miao7ebb97f2016-09-08 18:01:50 +0800496 ShCompileOptions compileOptions = compileOptionsIn;
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700497
498 // Apply key workarounds.
499 if (shouldFlattenPragmaStdglInvariantAll())
500 {
501 // This should be harmless to do in all cases, but for the moment, do it only conditionally.
502 compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;
503 }
504
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200505 TScopedPoolAllocator scopedAlloc(&allocator);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100506 TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200507
508 if (root)
509 {
510 if (compileOptions & SH_INTERMEDIATE_TREE)
511 TIntermediate::outputTree(root, infoSink.info);
512
513 if (compileOptions & SH_OBJECT_CODE)
514 translate(root, compileOptions);
515
516 // The IntermNode tree doesn't need to be deleted here, since the
517 // memory will be freed in a big chunk by the PoolAllocator.
518 return true;
519 }
520 return false;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000521}
522
Nicolas Capens49a88872013-06-20 09:54:03 -0400523bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000524{
Olli Etuaho28cb0362016-11-22 15:42:37 +0000525 if (resources.MaxDrawBuffers < 1)
526 {
527 return false;
528 }
529 if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1)
530 {
531 return false;
532 }
533
shannon.woods%transgaming.com@gtempaccount.com18b4c4b2013-04-13 03:31:40 +0000534 compileResources = resources;
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400535 setResourceString();
shannonwoods@chromium.org2ac0be92013-05-30 00:02:27 +0000536
Nicolas Capens49a88872013-06-20 09:54:03 -0400537 assert(symbolTable.isEmpty());
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500538 symbolTable.push(); // COMMON_BUILTINS
539 symbolTable.push(); // ESSL1_BUILTINS
540 symbolTable.push(); // ESSL3_BUILTINS
541 symbolTable.push(); // ESSL3_1_BUILTINS
shannonwoods@chromium.org2ac0be92013-05-30 00:02:27 +0000542
Nicolas Capens49a88872013-06-20 09:54:03 -0400543 TPublicType integer;
Martin Radev2cc85b32016-08-05 16:22:53 +0300544 integer.initializeBasicType(EbtInt);
Nicolas Capens49a88872013-06-20 09:54:03 -0400545
546 TPublicType floatingPoint;
Martin Radev2cc85b32016-08-05 16:22:53 +0300547 floatingPoint.initializeBasicType(EbtFloat);
Nicolas Capens49a88872013-06-20 09:54:03 -0400548
Jamie Madillacb4b812016-11-07 13:50:29 -0500549 switch (shaderType)
Nicolas Capens49a88872013-06-20 09:54:03 -0400550 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500551 case GL_FRAGMENT_SHADER:
552 symbolTable.setDefaultPrecision(integer, EbpMedium);
553 break;
554 case GL_VERTEX_SHADER:
555 symbolTable.setDefaultPrecision(integer, EbpHigh);
556 symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
557 break;
558 case GL_COMPUTE_SHADER:
559 symbolTable.setDefaultPrecision(integer, EbpHigh);
560 symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
561 break;
562 default:
563 assert(false && "Language not supported");
Nicolas Capens49a88872013-06-20 09:54:03 -0400564 }
Olli Etuaho183d7e22015-11-20 15:59:09 +0200565 // Set defaults for sampler types that have default precision, even those that are
Zhenyao Moa5a1dfc2013-09-23 14:57:03 -0400566 // only available if an extension exists.
Olli Etuaho183d7e22015-11-20 15:59:09 +0200567 // New sampler types in ESSL3 don't have default precision. ESSL1 types do.
568 initSamplerDefaultPrecision(EbtSampler2D);
569 initSamplerDefaultPrecision(EbtSamplerCube);
570 // SamplerExternalOES is specified in the extension to have default precision.
571 initSamplerDefaultPrecision(EbtSamplerExternalOES);
Andrei Volykhina5527072017-03-22 16:46:30 +0300572 // SamplerExternal2DY2YEXT is specified in the extension to have default precision.
573 initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT);
Olli Etuaho183d7e22015-11-20 15:59:09 +0200574 // It isn't specified whether Sampler2DRect has default precision.
575 initSamplerDefaultPrecision(EbtSampler2DRect);
Nicolas Capens49a88872013-06-20 09:54:03 -0400576
Jamie Madill1b452142013-07-12 14:51:11 -0400577 InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
Nicolas Capens49a88872013-06-20 09:54:03 -0400578
579 IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
580
581 return true;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000582}
583
Olli Etuaho183d7e22015-11-20 15:59:09 +0200584void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType)
585{
586 ASSERT(samplerType > EbtGuardSamplerBegin && samplerType < EbtGuardSamplerEnd);
587 TPublicType sampler;
Martin Radev2cc85b32016-08-05 16:22:53 +0300588 sampler.initializeBasicType(samplerType);
Olli Etuaho183d7e22015-11-20 15:59:09 +0200589 symbolTable.setDefaultPrecision(sampler, EbpLow);
590}
591
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400592void TCompiler::setResourceString()
593{
594 std::ostringstream strstream;
Geoff Langb66a9092016-05-16 15:59:14 -0400595
596 // clang-format off
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400597 strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs
Jamie Madillacb4b812016-11-07 13:50:29 -0500598 << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
599 << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
600 << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits
601 << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits
602 << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits
603 << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors
604 << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
605 << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
606 << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external
607 << ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3
608 << ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external
609 << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
610 << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
611 << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
612 << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity
613 << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
614 << ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters
615 << ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended
616 << ":EXT_frag_depth:" << compileResources.EXT_frag_depth
617 << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
618 << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch
619 << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch
620 << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch
Andrei Volykhina5527072017-03-22 16:46:30 +0300621 << ":EXT_YUV_target:" << compileResources.EXT_YUV_target
Jamie Madillacb4b812016-11-07 13:50:29 -0500622 << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
623 << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
624 << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
625 << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
626 << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers
627 << ":NV_draw_buffers:" << compileResources.NV_draw_buffers
628 << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision
629 << ":MaxImageUnits:" << compileResources.MaxImageUnits
630 << ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms
631 << ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms
632 << ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms
633 << ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms
634 << ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources
635 << ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0]
636 << ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1]
637 << ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2]
638 << ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0]
639 << ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1]
640 << ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2]
641 << ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents
642 << ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits
643 << ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters
644 << ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers
645 << ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters
646 << ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters
647 << ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters
648 << ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings
649 << ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers
650 << ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers
651 << ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers
652 << ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize;
Geoff Langb66a9092016-05-16 15:59:14 -0400653 // clang-format on
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400654
655 builtInResourcesString = strstream.str();
656}
657
alokp@chromium.org07620a52010-09-23 17:53:56 +0000658void TCompiler::clearResults()
659{
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000660 arrayBoundsClamper.Cleanup();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000661 infoSink.info.erase();
662 infoSink.obj.erase();
663 infoSink.debug.erase();
Olli Etuaho77ba4082016-12-16 12:01:18 +0000664 mDiagnostics.resetErrorCount();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000665
Jamie Madilled27c722014-07-02 15:31:23 -0400666 attributes.clear();
667 outputVariables.clear();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000668 uniforms.clear();
Jamie Madill23a8a432014-07-09 13:27:42 -0400669 expandedUniforms.clear();
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400670 varyings.clear();
Jamie Madilled27c722014-07-02 15:31:23 -0400671 interfaceBlocks.clear();
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700672 variablesCollected = false;
zmo@google.coma3b4ab42011-09-16 00:53:26 +0000673
Olli Etuaho09b04a22016-12-15 13:30:26 +0000674 mNumViews = -1;
675
Olli Etuahodfa75e82017-01-23 09:43:06 -0800676 builtInFunctionEmulator.cleanup();
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000677
678 nameMap.clear();
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200679
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500680 mSourcePath = NULL;
Corentin Wallezd4b50542015-09-28 12:19:26 -0700681 mTemporaryIndex = 0;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000682}
683
Corentin Wallez71d147f2015-02-11 11:15:24 -0800684bool TCompiler::initCallDag(TIntermNode *root)
zmo@google.comb1762df2011-07-30 02:04:23 +0000685{
Corentin Wallez71d147f2015-02-11 11:15:24 -0800686 mCallDag.clear();
687
Olli Etuaho77ba4082016-12-16 12:01:18 +0000688 switch (mCallDag.init(root, &mDiagnostics))
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800689 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500690 case CallDAG::INITDAG_SUCCESS:
691 return true;
692 case CallDAG::INITDAG_RECURSION:
Jamie Madillacb4b812016-11-07 13:50:29 -0500693 case CallDAG::INITDAG_UNDEFINED:
Olli Etuaho77ba4082016-12-16 12:01:18 +0000694 // Error message has already been written out.
695 ASSERT(mDiagnostics.numErrors() > 0);
Jamie Madillacb4b812016-11-07 13:50:29 -0500696 return false;
Corentin Wallez71d147f2015-02-11 11:15:24 -0800697 }
698
699 UNREACHABLE();
700 return true;
701}
702
703bool TCompiler::checkCallDepth()
704{
705 std::vector<int> depths(mCallDag.size());
706
707 for (size_t i = 0; i < mCallDag.size(); i++)
708 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500709 int depth = 0;
Corentin Wallez71d147f2015-02-11 11:15:24 -0800710 auto &record = mCallDag.getRecordFromIndex(i);
711
712 for (auto &calleeIndex : record.callees)
713 {
714 depth = std::max(depth, depths[calleeIndex] + 1);
715 }
716
717 depths[i] = depth;
718
719 if (depth >= maxCallStackDepth)
720 {
721 // Trace back the function chain to have a meaningful info log.
Olli Etuaho77ba4082016-12-16 12:01:18 +0000722 std::stringstream errorStream;
723 errorStream << "Call stack too deep (larger than " << maxCallStackDepth
724 << ") with the following call chain: " << record.name;
Corentin Wallez71d147f2015-02-11 11:15:24 -0800725
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700726 int currentFunction = static_cast<int>(i);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500727 int currentDepth = depth;
Corentin Wallez71d147f2015-02-11 11:15:24 -0800728
729 while (currentFunction != -1)
730 {
Olli Etuaho77ba4082016-12-16 12:01:18 +0000731 errorStream << " -> " << mCallDag.getRecordFromIndex(currentFunction).name;
Corentin Wallez71d147f2015-02-11 11:15:24 -0800732
733 int nextFunction = -1;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500734 for (auto &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
Corentin Wallez71d147f2015-02-11 11:15:24 -0800735 {
736 if (depths[calleeIndex] == currentDepth - 1)
737 {
738 currentDepth--;
739 nextFunction = calleeIndex;
740 }
741 }
742
743 currentFunction = nextFunction;
744 }
745
Olli Etuaho77ba4082016-12-16 12:01:18 +0000746 std::string errorStr = errorStream.str();
747 mDiagnostics.globalError(errorStr.c_str());
748
Corentin Wallez71d147f2015-02-11 11:15:24 -0800749 return false;
750 }
751 }
752
753 return true;
754}
755
756bool TCompiler::tagUsedFunctions()
757{
758 // Search from main, starting from the end of the DAG as it usually is the root.
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700759 for (size_t i = mCallDag.size(); i-- > 0;)
Corentin Wallez71d147f2015-02-11 11:15:24 -0800760 {
Olli Etuahoec9232b2017-03-27 17:01:37 +0300761 if (mCallDag.getRecordFromIndex(i).name == "main")
Corentin Wallez71d147f2015-02-11 11:15:24 -0800762 {
763 internalTagUsedFunction(i);
764 return true;
765 }
766 }
767
Olli Etuaho77ba4082016-12-16 12:01:18 +0000768 mDiagnostics.globalError("Missing main()");
Corentin Wallez71d147f2015-02-11 11:15:24 -0800769 return false;
770}
771
772void TCompiler::internalTagUsedFunction(size_t index)
773{
774 if (functionMetadata[index].used)
775 {
776 return;
777 }
778
779 functionMetadata[index].used = true;
780
781 for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees)
782 {
783 internalTagUsedFunction(calleeIndex);
zmo@google.comb1762df2011-07-30 02:04:23 +0000784 }
785}
786
Corentin Walleza094a8a2015-04-07 11:53:06 -0700787// A predicate for the stl that returns if a top-level node is unused
788class TCompiler::UnusedPredicate
789{
790 public:
791 UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas)
Jamie Madillacb4b812016-11-07 13:50:29 -0500792 : mCallDag(callDag), mMetadatas(metadatas)
Corentin Walleza094a8a2015-04-07 11:53:06 -0700793 {
794 }
795
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500796 bool operator()(TIntermNode *node)
Corentin Walleza094a8a2015-04-07 11:53:06 -0700797 {
Olli Etuaho16c745a2017-01-16 17:02:27 +0000798 const TIntermFunctionPrototype *asFunctionPrototype = node->getAsFunctionPrototypeNode();
799 const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition();
Corentin Walleza094a8a2015-04-07 11:53:06 -0700800
Olli Etuaho336b1472016-10-05 16:37:55 +0100801 const TFunctionSymbolInfo *functionInfo = nullptr;
802
Olli Etuaho16c745a2017-01-16 17:02:27 +0000803 if (asFunctionDefinition)
Olli Etuaho336b1472016-10-05 16:37:55 +0100804 {
Olli Etuaho16c745a2017-01-16 17:02:27 +0000805 functionInfo = asFunctionDefinition->getFunctionSymbolInfo();
Olli Etuaho336b1472016-10-05 16:37:55 +0100806 }
Olli Etuaho16c745a2017-01-16 17:02:27 +0000807 else if (asFunctionPrototype)
Olli Etuaho336b1472016-10-05 16:37:55 +0100808 {
Olli Etuaho16c745a2017-01-16 17:02:27 +0000809 functionInfo = asFunctionPrototype->getFunctionSymbolInfo();
Olli Etuaho336b1472016-10-05 16:37:55 +0100810 }
811 if (functionInfo == nullptr)
Corentin Walleza094a8a2015-04-07 11:53:06 -0700812 {
813 return false;
814 }
815
Olli Etuaho336b1472016-10-05 16:37:55 +0100816 size_t callDagIndex = mCallDag->findIndex(functionInfo);
Corentin Walleza094a8a2015-04-07 11:53:06 -0700817 if (callDagIndex == CallDAG::InvalidIndex)
818 {
819 // This happens only for unimplemented prototypes which are thus unused
Olli Etuaho16c745a2017-01-16 17:02:27 +0000820 ASSERT(asFunctionPrototype);
Corentin Walleza094a8a2015-04-07 11:53:06 -0700821 return true;
822 }
823
824 ASSERT(callDagIndex < mMetadatas->size());
825 return !(*mMetadatas)[callDagIndex].used;
826 }
827
828 private:
829 const CallDAG *mCallDag;
830 const std::vector<FunctionMetadata> *mMetadatas;
831};
832
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100833bool TCompiler::pruneUnusedFunctions(TIntermBlock *root)
Corentin Walleza094a8a2015-04-07 11:53:06 -0700834{
Corentin Walleza094a8a2015-04-07 11:53:06 -0700835 UnusedPredicate isUnused(&mCallDag, &functionMetadata);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100836 TIntermSequence *sequence = root->getSequence();
Corentin Wallezb081e782015-07-20 05:40:04 -0700837
838 if (!sequence->empty())
839 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500840 sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused),
841 sequence->end());
Corentin Wallezb081e782015-07-20 05:40:04 -0700842 }
Corentin Walleza094a8a2015-04-07 11:53:06 -0700843
844 return true;
845}
846
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500847bool TCompiler::validateOutputs(TIntermNode *root)
Jamie Madill05a80ce2013-06-20 11:55:49 -0400848{
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300849 ValidateOutputs validateOutputs(getExtensionBehavior(), compileResources.MaxDrawBuffers);
Jamie Madill05a80ce2013-06-20 11:55:49 -0400850 root->traverse(&validateOutputs);
Olli Etuaho77ba4082016-12-16 12:01:18 +0000851 validateOutputs.validate(&mDiagnostics);
852 return (mDiagnostics.numErrors() == 0);
Jamie Madill05a80ce2013-06-20 11:55:49 -0400853}
854
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500855bool TCompiler::limitExpressionComplexity(TIntermNode *root)
Jamie Madilleb1a0102013-07-08 13:31:38 -0400856{
Jamie Madillacb4b812016-11-07 13:50:29 -0500857 TMaxDepthTraverser traverser(maxExpressionComplexity + 1);
Jamie Madilleb1a0102013-07-08 13:31:38 -0400858 root->traverse(&traverser);
Jamie Madill6654bc92014-03-26 14:01:57 -0400859
860 if (traverser.getMaxDepth() > maxExpressionComplexity)
861 {
Olli Etuaho77ba4082016-12-16 12:01:18 +0000862 mDiagnostics.globalError("Expression too complex.");
Jamie Madill6654bc92014-03-26 14:01:57 -0400863 return false;
864 }
865
Olli Etuaho19d1dc92016-03-08 17:18:46 +0200866 if (!ValidateMaxParameters::validate(root, maxFunctionParameters))
867 {
Olli Etuaho77ba4082016-12-16 12:01:18 +0000868 mDiagnostics.globalError("Function has too many parameters.");
Olli Etuaho19d1dc92016-03-08 17:18:46 +0200869 return false;
870 }
871
Jamie Madilleb1a0102013-07-08 13:31:38 -0400872 return true;
873}
874
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500875void TCompiler::collectVariables(TIntermNode *root)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000876{
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700877 if (!variablesCollected)
878 {
879 sh::CollectVariables collect(&attributes, &outputVariables, &uniforms, &varyings,
Jamie Madillacb4b812016-11-07 13:50:29 -0500880 &interfaceBlocks, hashFunction, symbolTable,
881 extensionBehavior);
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700882 root->traverse(&collect);
Jamie Madill23a8a432014-07-09 13:27:42 -0400883
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700884 // This is for enforcePackingRestriction().
885 sh::ExpandUniforms(uniforms, &expandedUniforms);
886 variablesCollected = true;
887 }
alokp@chromium.org07620a52010-09-23 17:53:56 +0000888}
zmo@google.comfd747b82011-04-23 01:30:07 +0000889
Corentin Wallez1df16022016-10-27 08:16:56 -0400890bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions)
891{
892 return (compileOptions & SH_VARIABLES) != 0;
893}
894
895bool TCompiler::wereVariablesCollected() const
896{
897 return variablesCollected;
898}
899
gman@chromium.org8d804792012-10-17 21:33:48 +0000900bool TCompiler::enforcePackingRestrictions()
901{
902 VariablePacker packer;
Jamie Madill23a8a432014-07-09 13:27:42 -0400903 return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, expandedUniforms);
gman@chromium.org8d804792012-10-17 21:33:48 +0000904}
905
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500906void TCompiler::initializeGLPosition(TIntermNode *root)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800907{
Zhenyao Mo72111912016-07-20 17:45:56 -0700908 InitVariableList list;
909 sh::ShaderVariable var(GL_FLOAT_VEC4, 0);
910 var.name = "gl_Position";
911 list.push_back(var);
Zhenyao Mod7490962016-11-09 15:49:51 -0800912 InitializeVariables(root, list, symbolTable);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800913}
914
Qin Jiajia7835b522016-10-08 11:20:17 +0800915void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermNode *root)
916{
917 sh::InterfaceBlockList list;
918
919 for (auto block : interfaceBlocks)
920 {
921 if (!block.staticUse &&
922 (block.layout == sh::BLOCKLAYOUT_STANDARD || block.layout == sh::BLOCKLAYOUT_SHARED))
923 {
924 list.push_back(block);
925 }
926 }
927
Zhenyao Mod7490962016-11-09 15:49:51 -0800928 sh::UseInterfaceBlockFields(root, list, symbolTable);
Qin Jiajia7835b522016-10-08 11:20:17 +0800929}
930
Olli Etuaho27776e32016-07-22 14:00:56 +0300931void TCompiler::initializeOutputVariables(TIntermNode *root)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800932{
Zhenyao Mo72111912016-07-20 17:45:56 -0700933 InitVariableList list;
934 if (shaderType == GL_VERTEX_SHADER)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800935 {
Zhenyao Mo72111912016-07-20 17:45:56 -0700936 for (auto var : varyings)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800937 {
Zhenyao Mof9312682016-07-22 12:51:31 -0700938 list.push_back(var);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800939 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800940 }
Zhenyao Mo72111912016-07-20 17:45:56 -0700941 else
942 {
943 ASSERT(shaderType == GL_FRAGMENT_SHADER);
944 for (auto var : outputVariables)
945 {
946 list.push_back(var);
947 }
948 }
Zhenyao Mod7490962016-11-09 15:49:51 -0800949 InitializeVariables(root, list, symbolTable);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800950}
951
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500952const TExtensionBehavior &TCompiler::getExtensionBehavior() const
zmo@google.com5601ea02011-06-10 18:23:25 +0000953{
954 return extensionBehavior;
955}
zmo@google.com32e97312011-08-24 01:03:11 +0000956
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200957const char *TCompiler::getSourcePath() const
958{
959 return mSourcePath;
960}
961
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500962const ShBuiltInResources &TCompiler::getResources() const
shannon.woods%transgaming.com@gtempaccount.com18b4c4b2013-04-13 03:31:40 +0000963{
964 return compileResources;
965}
966
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500967const ArrayBoundsClamper &TCompiler::getArrayBoundsClamper() const
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000968{
969 return arrayBoundsClamper;
970}
971
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000972ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
973{
974 return clampingStrategy;
975}
976
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500977const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000978{
979 return builtInFunctionEmulator;
980}
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700981
Qiankun Miao7ebb97f2016-09-08 18:01:50 +0800982void TCompiler::writePragma(ShCompileOptions compileOptions)
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700983{
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700984 if (!(compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL))
985 {
986 TInfoSinkBase &sink = infoSink.obj;
987 if (mPragma.stdgl.invariantAll)
988 sink << "#pragma STDGL invariant(all)\n";
989 }
990}
991
992bool TCompiler::isVaryingDefined(const char *varyingName)
993{
994 ASSERT(variablesCollected);
995 for (size_t ii = 0; ii < varyings.size(); ++ii)
996 {
997 if (varyings[ii].name == varyingName)
998 {
999 return true;
1000 }
1001 }
1002
1003 return false;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001004}
Jamie Madillacb4b812016-11-07 13:50:29 -05001005
1006} // namespace sh