blob: 38446dcbdb29c2a34cccde9413d161d7d997a2ab [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman66b8ab22014-05-06 15:57:45 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
John Bauman66b8ab22014-05-06 15:57:45 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
John Bauman66b8ab22014-05-06 15:57:45 -040014
Nicolas Capens6407fe82015-02-10 16:27:49 -050015#include "Compiler.h"
16
Nicolas Capenscc863da2015-01-21 15:50:55 -050017#include "AnalyzeCallDepth.h"
18#include "Initialize.h"
19#include "InitializeParseContext.h"
Nicolas Capens6407fe82015-02-10 16:27:49 -050020#include "InitializeGlobals.h"
Nicolas Capenscc863da2015-01-21 15:50:55 -050021#include "ParseHelper.h"
Nicolas Capenscc863da2015-01-21 15:50:55 -050022#include "ValidateLimitations.h"
John Bauman66b8ab22014-05-06 15:57:45 -040023
Nicolas Capens0bac2852016-05-07 06:09:58 -040024namespace
John Bauman66b8ab22014-05-06 15:57:45 -040025{
John Bauman66b8ab22014-05-06 15:57:45 -040026class TScopedPoolAllocator {
27public:
Nicolas Capens0bac2852016-05-07 06:09:58 -040028 TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
29 : mAllocator(allocator), mPushPopAllocator(pushPop)
30 {
31 if (mPushPopAllocator) mAllocator->push();
32 SetGlobalPoolAllocator(mAllocator);
33 }
34 ~TScopedPoolAllocator()
35 {
36 SetGlobalPoolAllocator(nullptr);
37 if (mPushPopAllocator) mAllocator->pop();
38 }
John Bauman66b8ab22014-05-06 15:57:45 -040039
40private:
Nicolas Capens0bac2852016-05-07 06:09:58 -040041 TPoolAllocator* mAllocator;
42 bool mPushPopAllocator;
John Bauman66b8ab22014-05-06 15:57:45 -040043};
44} // namespace
45
Nicolas Capens6407fe82015-02-10 16:27:49 -050046//
47// Initialize built-in resources with minimum expected values.
48//
49ShBuiltInResources::ShBuiltInResources()
50{
Nicolas Capens0bac2852016-05-07 06:09:58 -040051 // Constants.
52 MaxVertexAttribs = 8;
53 MaxVertexUniformVectors = 128;
54 MaxVaryingVectors = 8;
55 MaxVertexTextureImageUnits = 0;
56 MaxCombinedTextureImageUnits = 8;
57 MaxTextureImageUnits = 8;
58 MaxFragmentUniformVectors = 16;
59 MaxDrawBuffers = 1;
60 MaxVertexOutputVectors = 16;
61 MaxFragmentInputVectors = 15;
62 MinProgramTexelOffset = -8;
63 MaxProgramTexelOffset = 7;
Nicolas Capens6407fe82015-02-10 16:27:49 -050064
Nicolas Capens0bac2852016-05-07 06:09:58 -040065 // Extensions.
66 OES_standard_derivatives = 0;
Nicolas Capens6407fe82015-02-10 16:27:49 -050067 OES_fragment_precision_high = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -040068 OES_EGL_image_external = 0;
Lingfeng Yang4806a9b2019-01-19 14:40:08 -080069 OES_EGL_image_external_essl3 = 0;
Nicolas Capens6407fe82015-02-10 16:27:49 -050070
71 MaxCallStackDepth = UINT_MAX;
72}
73
Nicolas Capens08ca3c62015-02-13 16:06:45 -050074TCompiler::TCompiler(GLenum type)
Nicolas Capens0bac2852016-05-07 06:09:58 -040075 : shaderType(type),
76 maxCallStackDepth(UINT_MAX)
John Bauman66b8ab22014-05-06 15:57:45 -040077{
Nicolas Capens7a8ccc42015-02-10 15:42:31 -050078 allocator.push();
Nicolas Capens0bac2852016-05-07 06:09:58 -040079 SetGlobalPoolAllocator(&allocator);
John Bauman66b8ab22014-05-06 15:57:45 -040080}
81
82TCompiler::~TCompiler()
83{
Nicolas Capens0bac2852016-05-07 06:09:58 -040084 SetGlobalPoolAllocator(nullptr);
85 allocator.popAll();
John Bauman66b8ab22014-05-06 15:57:45 -040086}
87
88bool TCompiler::Init(const ShBuiltInResources& resources)
89{
Nicolas Capens0bac2852016-05-07 06:09:58 -040090 shaderVersion = 100;
91 maxCallStackDepth = resources.MaxCallStackDepth;
92 TScopedPoolAllocator scopedAlloc(&allocator, false);
John Bauman66b8ab22014-05-06 15:57:45 -040093
Nicolas Capens0bac2852016-05-07 06:09:58 -040094 // Generate built-in symbol table.
95 if (!InitBuiltInSymbolTable(resources))
96 return false;
97 InitExtensionBehavior(resources, extensionBehavior);
John Bauman66b8ab22014-05-06 15:57:45 -040098
Nicolas Capens0bac2852016-05-07 06:09:58 -040099 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400100}
101
102bool TCompiler::compile(const char* const shaderStrings[],
103 const int numStrings,
104 int compileOptions)
105{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400106 TScopedPoolAllocator scopedAlloc(&allocator, true);
107 clearResults();
John Bauman66b8ab22014-05-06 15:57:45 -0400108
Nicolas Capens0bac2852016-05-07 06:09:58 -0400109 if (numStrings == 0)
110 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400111
Nicolas Capens0bac2852016-05-07 06:09:58 -0400112 // First string is path of source file if flag is set. The actual source follows.
113 const char* sourcePath = nullptr;
114 int firstSource = 0;
115 if (compileOptions & SH_SOURCE_PATH)
116 {
117 sourcePath = shaderStrings[0];
118 ++firstSource;
119 }
John Bauman66b8ab22014-05-06 15:57:45 -0400120
Nicolas Capens0bac2852016-05-07 06:09:58 -0400121 TIntermediate intermediate(infoSink);
122 TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
123 shaderType, compileOptions, true,
124 sourcePath, infoSink);
125 SetGlobalParseContext(&parseContext);
John Bauman66b8ab22014-05-06 15:57:45 -0400126
Nicolas Capens0bac2852016-05-07 06:09:58 -0400127 // We preserve symbols at the built-in level from compile-to-compile.
128 // Start pushing the user-defined symbols at global level.
129 symbolTable.push();
130 if (!symbolTable.atGlobalLevel())
131 infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
John Bauman66b8ab22014-05-06 15:57:45 -0400132
Nicolas Capens0bac2852016-05-07 06:09:58 -0400133 // Parse shader.
134 bool success =
135 (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr, &parseContext) == 0) &&
136 (parseContext.getTreeRoot() != nullptr);
Nicolas Capensb28964b2015-02-10 15:23:06 -0500137
Nicolas Capens0bac2852016-05-07 06:09:58 -0400138 shaderVersion = parseContext.getShaderVersion();
Nicolas Capensb28964b2015-02-10 15:23:06 -0500139
Nicolas Capens0bac2852016-05-07 06:09:58 -0400140 if (success) {
141 TIntermNode* root = parseContext.getTreeRoot();
142 success = intermediate.postProcess(root);
John Bauman66b8ab22014-05-06 15:57:45 -0400143
Nicolas Capens0bac2852016-05-07 06:09:58 -0400144 if (success)
145 success = validateCallDepth(root, infoSink);
John Bauman66b8ab22014-05-06 15:57:45 -0400146
Nicolas Capens0bac2852016-05-07 06:09:58 -0400147 if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
148 success = validateLimitations(root);
John Bauman66b8ab22014-05-06 15:57:45 -0400149
Nicolas Capens0bac2852016-05-07 06:09:58 -0400150 if (success && (compileOptions & SH_INTERMEDIATE_TREE))
151 intermediate.outputTree(root);
John Bauman66b8ab22014-05-06 15:57:45 -0400152
Nicolas Capens0bac2852016-05-07 06:09:58 -0400153 if (success && (compileOptions & SH_OBJECT_CODE))
154 success = translate(root);
155 }
John Bauman66b8ab22014-05-06 15:57:45 -0400156
Nicolas Capens0bac2852016-05-07 06:09:58 -0400157 // Ensure symbol table is returned to the built-in level,
158 // throwing away all but the built-ins.
159 while (!symbolTable.atBuiltInLevel())
160 symbolTable.pop();
John Bauman66b8ab22014-05-06 15:57:45 -0400161
Nicolas Capens0bac2852016-05-07 06:09:58 -0400162 return success;
John Bauman66b8ab22014-05-06 15:57:45 -0400163}
164
John Baumand4ae8632014-05-06 16:18:33 -0400165bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
John Bauman66b8ab22014-05-06 15:57:45 -0400166{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400167 assert(symbolTable.isEmpty());
168 symbolTable.push(); // COMMON_BUILTINS
169 symbolTable.push(); // ESSL1_BUILTINS
170 symbolTable.push(); // ESSL3_BUILTINS
John Bauman66b8ab22014-05-06 15:57:45 -0400171
John Baumand4ae8632014-05-06 16:18:33 -0400172 TPublicType integer;
173 integer.type = EbtInt;
Alexis Hetub14178b2015-04-13 13:23:20 -0400174 integer.primarySize = 1;
175 integer.secondarySize = 1;
John Baumand4ae8632014-05-06 16:18:33 -0400176 integer.array = false;
177
178 TPublicType floatingPoint;
179 floatingPoint.type = EbtFloat;
Alexis Hetub14178b2015-04-13 13:23:20 -0400180 floatingPoint.primarySize = 1;
181 floatingPoint.secondarySize = 1;
John Baumand4ae8632014-05-06 16:18:33 -0400182 floatingPoint.array = false;
183
184 switch(shaderType)
185 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400186 case GL_FRAGMENT_SHADER:
John Baumand4ae8632014-05-06 16:18:33 -0400187 symbolTable.setDefaultPrecision(integer, EbpMedium);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400188 break;
189 case GL_VERTEX_SHADER:
John Baumand4ae8632014-05-06 16:18:33 -0400190 symbolTable.setDefaultPrecision(integer, EbpHigh);
191 symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400192 break;
193 default: assert(false && "Language not supported");
194 }
John Baumand4ae8632014-05-06 16:18:33 -0400195
196 InsertBuiltInFunctions(shaderType, resources, symbolTable);
197
Nicolas Capens0bac2852016-05-07 06:09:58 -0400198 IdentifyBuiltIns(shaderType, resources, symbolTable);
John Baumand4ae8632014-05-06 16:18:33 -0400199
Nicolas Capens0bac2852016-05-07 06:09:58 -0400200 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400201}
202
203void TCompiler::clearResults()
204{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400205 infoSink.info.erase();
206 infoSink.obj.erase();
207 infoSink.debug.erase();
John Bauman66b8ab22014-05-06 15:57:45 -0400208}
209
John Baumand4ae8632014-05-06 16:18:33 -0400210bool TCompiler::validateCallDepth(TIntermNode *root, TInfoSink &infoSink)
John Bauman66b8ab22014-05-06 15:57:45 -0400211{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400212 AnalyzeCallDepth validator(root);
213
John Baumand4ae8632014-05-06 16:18:33 -0400214 unsigned int depth = validator.analyzeCallDepth();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400215
John Baumand4ae8632014-05-06 16:18:33 -0400216 if(depth == 0)
217 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400218 infoSink.info.prefix(EPrefixError);
219 infoSink.info << "Missing main()";
220 return false;
John Baumand4ae8632014-05-06 16:18:33 -0400221 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400222 else if(depth == UINT_MAX)
John Baumand4ae8632014-05-06 16:18:33 -0400223 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400224 infoSink.info.prefix(EPrefixError);
225 infoSink.info << "Function recursion detected";
226 return false;
John Baumand4ae8632014-05-06 16:18:33 -0400227 }
228 else if(depth > maxCallStackDepth)
229 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400230 infoSink.info.prefix(EPrefixError);
Alexis Hetu2e4c0692018-01-15 16:16:27 -0500231 infoSink.info << "Function call stack too deep (depth was ";
232 infoSink.info << depth;
233 infoSink.info << " while maximum call stack depth is ";
234 infoSink.info << maxCallStackDepth;
235 infoSink.info << ")";
Nicolas Capens0bac2852016-05-07 06:09:58 -0400236 return false;
John Baumand4ae8632014-05-06 16:18:33 -0400237 }
238
Nicolas Capens0bac2852016-05-07 06:09:58 -0400239 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400240}
241
242bool TCompiler::validateLimitations(TIntermNode* root) {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400243 ValidateLimitations validate(shaderType, infoSink.info);
244 root->traverse(&validate);
245 return validate.numErrors() == 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400246}
247
John Bauman66b8ab22014-05-06 15:57:45 -0400248const TExtensionBehavior& TCompiler::getExtensionBehavior() const
249{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400250 return extensionBehavior;
John Bauman66b8ab22014-05-06 15:57:45 -0400251}
Nicolas Capens6407fe82015-02-10 16:27:49 -0500252
253bool InitCompilerGlobals()
254{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400255 if(!InitializePoolIndex())
Nicolas Capens6407fe82015-02-10 16:27:49 -0500256 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400257 assert(0 && "InitCompilerGlobals(): Failed to initalize global pool");
258 return false;
259 }
Nicolas Capens6407fe82015-02-10 16:27:49 -0500260
Nicolas Capens0bac2852016-05-07 06:09:58 -0400261 if(!InitializeParseContextIndex())
Nicolas Capens6407fe82015-02-10 16:27:49 -0500262 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400263 assert(0 && "InitCompilerGlobals(): Failed to initalize parse context");
264 return false;
265 }
Nicolas Capens6407fe82015-02-10 16:27:49 -0500266
Nicolas Capens0bac2852016-05-07 06:09:58 -0400267 return true;
Nicolas Capens6407fe82015-02-10 16:27:49 -0500268}
269
270void FreeCompilerGlobals()
271{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400272 FreeParseContextIndex();
273 FreePoolIndex();
Nicolas Capensb28964b2015-02-10 15:23:06 -0500274}