blob: 7861acf95f41613008b8fe08a03d001a2cd33e47 [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;
Nicolas Capens6407fe82015-02-10 16:27:49 -050069
70 MaxCallStackDepth = UINT_MAX;
71}
72
Nicolas Capens08ca3c62015-02-13 16:06:45 -050073TCompiler::TCompiler(GLenum type)
Nicolas Capens0bac2852016-05-07 06:09:58 -040074 : shaderType(type),
75 maxCallStackDepth(UINT_MAX)
John Bauman66b8ab22014-05-06 15:57:45 -040076{
Nicolas Capens7a8ccc42015-02-10 15:42:31 -050077 allocator.push();
Nicolas Capens0bac2852016-05-07 06:09:58 -040078 SetGlobalPoolAllocator(&allocator);
John Bauman66b8ab22014-05-06 15:57:45 -040079}
80
81TCompiler::~TCompiler()
82{
Nicolas Capens0bac2852016-05-07 06:09:58 -040083 SetGlobalPoolAllocator(nullptr);
84 allocator.popAll();
John Bauman66b8ab22014-05-06 15:57:45 -040085}
86
87bool TCompiler::Init(const ShBuiltInResources& resources)
88{
Nicolas Capens0bac2852016-05-07 06:09:58 -040089 shaderVersion = 100;
90 maxCallStackDepth = resources.MaxCallStackDepth;
91 TScopedPoolAllocator scopedAlloc(&allocator, false);
John Bauman66b8ab22014-05-06 15:57:45 -040092
Nicolas Capens0bac2852016-05-07 06:09:58 -040093 // Generate built-in symbol table.
94 if (!InitBuiltInSymbolTable(resources))
95 return false;
96 InitExtensionBehavior(resources, extensionBehavior);
John Bauman66b8ab22014-05-06 15:57:45 -040097
Nicolas Capens0bac2852016-05-07 06:09:58 -040098 return true;
John Bauman66b8ab22014-05-06 15:57:45 -040099}
100
101bool TCompiler::compile(const char* const shaderStrings[],
102 const int numStrings,
103 int compileOptions)
104{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400105 TScopedPoolAllocator scopedAlloc(&allocator, true);
106 clearResults();
John Bauman66b8ab22014-05-06 15:57:45 -0400107
Nicolas Capens0bac2852016-05-07 06:09:58 -0400108 if (numStrings == 0)
109 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400110
Nicolas Capens0bac2852016-05-07 06:09:58 -0400111 // First string is path of source file if flag is set. The actual source follows.
112 const char* sourcePath = nullptr;
113 int firstSource = 0;
114 if (compileOptions & SH_SOURCE_PATH)
115 {
116 sourcePath = shaderStrings[0];
117 ++firstSource;
118 }
John Bauman66b8ab22014-05-06 15:57:45 -0400119
Nicolas Capens0bac2852016-05-07 06:09:58 -0400120 TIntermediate intermediate(infoSink);
121 TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
122 shaderType, compileOptions, true,
123 sourcePath, infoSink);
124 SetGlobalParseContext(&parseContext);
John Bauman66b8ab22014-05-06 15:57:45 -0400125
Nicolas Capens0bac2852016-05-07 06:09:58 -0400126 // We preserve symbols at the built-in level from compile-to-compile.
127 // Start pushing the user-defined symbols at global level.
128 symbolTable.push();
129 if (!symbolTable.atGlobalLevel())
130 infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
John Bauman66b8ab22014-05-06 15:57:45 -0400131
Nicolas Capens0bac2852016-05-07 06:09:58 -0400132 // Parse shader.
133 bool success =
134 (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr, &parseContext) == 0) &&
135 (parseContext.getTreeRoot() != nullptr);
Nicolas Capensb28964b2015-02-10 15:23:06 -0500136
Nicolas Capens0bac2852016-05-07 06:09:58 -0400137 shaderVersion = parseContext.getShaderVersion();
Nicolas Capensb28964b2015-02-10 15:23:06 -0500138
Nicolas Capens0bac2852016-05-07 06:09:58 -0400139 if (success) {
140 TIntermNode* root = parseContext.getTreeRoot();
141 success = intermediate.postProcess(root);
John Bauman66b8ab22014-05-06 15:57:45 -0400142
Nicolas Capens0bac2852016-05-07 06:09:58 -0400143 if (success)
144 success = validateCallDepth(root, infoSink);
John Bauman66b8ab22014-05-06 15:57:45 -0400145
Nicolas Capens0bac2852016-05-07 06:09:58 -0400146 if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
147 success = validateLimitations(root);
John Bauman66b8ab22014-05-06 15:57:45 -0400148
Nicolas Capens0bac2852016-05-07 06:09:58 -0400149 if (success && (compileOptions & SH_INTERMEDIATE_TREE))
150 intermediate.outputTree(root);
John Bauman66b8ab22014-05-06 15:57:45 -0400151
Nicolas Capens0bac2852016-05-07 06:09:58 -0400152 if (success && (compileOptions & SH_OBJECT_CODE))
153 success = translate(root);
154 }
John Bauman66b8ab22014-05-06 15:57:45 -0400155
Nicolas Capens0bac2852016-05-07 06:09:58 -0400156 // Ensure symbol table is returned to the built-in level,
157 // throwing away all but the built-ins.
158 while (!symbolTable.atBuiltInLevel())
159 symbolTable.pop();
John Bauman66b8ab22014-05-06 15:57:45 -0400160
Nicolas Capens0bac2852016-05-07 06:09:58 -0400161 return success;
John Bauman66b8ab22014-05-06 15:57:45 -0400162}
163
John Baumand4ae8632014-05-06 16:18:33 -0400164bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
John Bauman66b8ab22014-05-06 15:57:45 -0400165{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400166 assert(symbolTable.isEmpty());
167 symbolTable.push(); // COMMON_BUILTINS
168 symbolTable.push(); // ESSL1_BUILTINS
169 symbolTable.push(); // ESSL3_BUILTINS
John Bauman66b8ab22014-05-06 15:57:45 -0400170
John Baumand4ae8632014-05-06 16:18:33 -0400171 TPublicType integer;
172 integer.type = EbtInt;
Alexis Hetub14178b2015-04-13 13:23:20 -0400173 integer.primarySize = 1;
174 integer.secondarySize = 1;
John Baumand4ae8632014-05-06 16:18:33 -0400175 integer.array = false;
176
177 TPublicType floatingPoint;
178 floatingPoint.type = EbtFloat;
Alexis Hetub14178b2015-04-13 13:23:20 -0400179 floatingPoint.primarySize = 1;
180 floatingPoint.secondarySize = 1;
John Baumand4ae8632014-05-06 16:18:33 -0400181 floatingPoint.array = false;
182
183 switch(shaderType)
184 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400185 case GL_FRAGMENT_SHADER:
John Baumand4ae8632014-05-06 16:18:33 -0400186 symbolTable.setDefaultPrecision(integer, EbpMedium);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400187 break;
188 case GL_VERTEX_SHADER:
John Baumand4ae8632014-05-06 16:18:33 -0400189 symbolTable.setDefaultPrecision(integer, EbpHigh);
190 symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400191 break;
192 default: assert(false && "Language not supported");
193 }
John Baumand4ae8632014-05-06 16:18:33 -0400194
195 InsertBuiltInFunctions(shaderType, resources, symbolTable);
196
Nicolas Capens0bac2852016-05-07 06:09:58 -0400197 IdentifyBuiltIns(shaderType, resources, symbolTable);
John Baumand4ae8632014-05-06 16:18:33 -0400198
Nicolas Capens0bac2852016-05-07 06:09:58 -0400199 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400200}
201
202void TCompiler::clearResults()
203{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400204 infoSink.info.erase();
205 infoSink.obj.erase();
206 infoSink.debug.erase();
John Bauman66b8ab22014-05-06 15:57:45 -0400207}
208
John Baumand4ae8632014-05-06 16:18:33 -0400209bool TCompiler::validateCallDepth(TIntermNode *root, TInfoSink &infoSink)
John Bauman66b8ab22014-05-06 15:57:45 -0400210{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400211 AnalyzeCallDepth validator(root);
212
John Baumand4ae8632014-05-06 16:18:33 -0400213 unsigned int depth = validator.analyzeCallDepth();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400214
John Baumand4ae8632014-05-06 16:18:33 -0400215 if(depth == 0)
216 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400217 infoSink.info.prefix(EPrefixError);
218 infoSink.info << "Missing main()";
219 return false;
John Baumand4ae8632014-05-06 16:18:33 -0400220 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400221 else if(depth == UINT_MAX)
John Baumand4ae8632014-05-06 16:18:33 -0400222 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400223 infoSink.info.prefix(EPrefixError);
224 infoSink.info << "Function recursion detected";
225 return false;
John Baumand4ae8632014-05-06 16:18:33 -0400226 }
227 else if(depth > maxCallStackDepth)
228 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400229 infoSink.info.prefix(EPrefixError);
230 infoSink.info << "Function call stack too deep";
231 return false;
John Baumand4ae8632014-05-06 16:18:33 -0400232 }
233
Nicolas Capens0bac2852016-05-07 06:09:58 -0400234 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400235}
236
237bool TCompiler::validateLimitations(TIntermNode* root) {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400238 ValidateLimitations validate(shaderType, infoSink.info);
239 root->traverse(&validate);
240 return validate.numErrors() == 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400241}
242
John Bauman66b8ab22014-05-06 15:57:45 -0400243const TExtensionBehavior& TCompiler::getExtensionBehavior() const
244{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400245 return extensionBehavior;
John Bauman66b8ab22014-05-06 15:57:45 -0400246}
Nicolas Capens6407fe82015-02-10 16:27:49 -0500247
248bool InitCompilerGlobals()
249{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400250 if(!InitializePoolIndex())
Nicolas Capens6407fe82015-02-10 16:27:49 -0500251 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400252 assert(0 && "InitCompilerGlobals(): Failed to initalize global pool");
253 return false;
254 }
Nicolas Capens6407fe82015-02-10 16:27:49 -0500255
Nicolas Capens0bac2852016-05-07 06:09:58 -0400256 if(!InitializeParseContextIndex())
Nicolas Capens6407fe82015-02-10 16:27:49 -0500257 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400258 assert(0 && "InitCompilerGlobals(): Failed to initalize parse context");
259 return false;
260 }
Nicolas Capens6407fe82015-02-10 16:27:49 -0500261
Nicolas Capens0bac2852016-05-07 06:09:58 -0400262 return true;
Nicolas Capens6407fe82015-02-10 16:27:49 -0500263}
264
265void FreeCompilerGlobals()
266{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400267 FreeParseContextIndex();
268 FreePoolIndex();
Nicolas Capensb28964b2015-02-10 15:23:06 -0500269}