• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // 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
6 //
7 //    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.
14 
15 #include "Compiler.h"
16 
17 #include "AnalyzeCallDepth.h"
18 #include "Initialize.h"
19 #include "InitializeParseContext.h"
20 #include "InitializeGlobals.h"
21 #include "ParseHelper.h"
22 #include "ValidateLimitations.h"
23 
24 namespace
25 {
26 class TScopedPoolAllocator {
27 public:
TScopedPoolAllocator(TPoolAllocator * allocator,bool pushPop)28 	TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
29 		: mAllocator(allocator), mPushPopAllocator(pushPop)
30 	{
31 		if (mPushPopAllocator) mAllocator->push();
32 		SetGlobalPoolAllocator(mAllocator);
33 	}
~TScopedPoolAllocator()34 	~TScopedPoolAllocator()
35 	{
36 		SetGlobalPoolAllocator(nullptr);
37 		if (mPushPopAllocator) mAllocator->pop();
38 	}
39 
40 private:
41 	TPoolAllocator* mAllocator;
42 	bool mPushPopAllocator;
43 };
44 }  // namespace
45 
46 //
47 // Initialize built-in resources with minimum expected values.
48 //
ShBuiltInResources()49 ShBuiltInResources::ShBuiltInResources()
50 {
51 	// 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;
64 
65 	// Extensions.
66 	OES_standard_derivatives = 0;
67 	OES_fragment_precision_high = 0;
68 	OES_EGL_image_external = 0;
69 
70 	MaxCallStackDepth = UINT_MAX;
71 }
72 
TCompiler(GLenum type)73 TCompiler::TCompiler(GLenum type)
74 	: shaderType(type),
75 	  maxCallStackDepth(UINT_MAX)
76 {
77 	allocator.push();
78 	SetGlobalPoolAllocator(&allocator);
79 }
80 
~TCompiler()81 TCompiler::~TCompiler()
82 {
83 	SetGlobalPoolAllocator(nullptr);
84 	allocator.popAll();
85 }
86 
Init(const ShBuiltInResources & resources)87 bool TCompiler::Init(const ShBuiltInResources& resources)
88 {
89 	shaderVersion = 100;
90 	maxCallStackDepth = resources.MaxCallStackDepth;
91 	TScopedPoolAllocator scopedAlloc(&allocator, false);
92 
93 	// Generate built-in symbol table.
94 	if (!InitBuiltInSymbolTable(resources))
95 		return false;
96 	InitExtensionBehavior(resources, extensionBehavior);
97 
98 	return true;
99 }
100 
compile(const char * const shaderStrings[],const int numStrings,int compileOptions)101 bool TCompiler::compile(const char* const shaderStrings[],
102                         const int numStrings,
103                         int compileOptions)
104 {
105 	TScopedPoolAllocator scopedAlloc(&allocator, true);
106 	clearResults();
107 
108 	if (numStrings == 0)
109 		return true;
110 
111 	// 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 	}
119 
120 	TIntermediate intermediate(infoSink);
121 	TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
122 	                           shaderType, compileOptions, true,
123 	                           sourcePath, infoSink);
124 	SetGlobalParseContext(&parseContext);
125 
126 	// 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");
131 
132 	// Parse shader.
133 	bool success =
134 		(PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr, &parseContext) == 0) &&
135 		(parseContext.getTreeRoot() != nullptr);
136 
137 	shaderVersion = parseContext.getShaderVersion();
138 
139 	if (success) {
140 		TIntermNode* root = parseContext.getTreeRoot();
141 		success = intermediate.postProcess(root);
142 
143 		if (success)
144 			success = validateCallDepth(root, infoSink);
145 
146 		if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
147 			success = validateLimitations(root);
148 
149 		if (success && (compileOptions & SH_INTERMEDIATE_TREE))
150 			intermediate.outputTree(root);
151 
152 		if (success && (compileOptions & SH_OBJECT_CODE))
153 			success = translate(root);
154 	}
155 
156 	// 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();
160 
161 	return success;
162 }
163 
InitBuiltInSymbolTable(const ShBuiltInResources & resources)164 bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
165 {
166 	assert(symbolTable.isEmpty());
167 	symbolTable.push();   // COMMON_BUILTINS
168 	symbolTable.push();   // ESSL1_BUILTINS
169 	symbolTable.push();   // ESSL3_BUILTINS
170 
171 	TPublicType integer;
172 	integer.type = EbtInt;
173 	integer.primarySize = 1;
174 	integer.secondarySize = 1;
175 	integer.array = false;
176 
177 	TPublicType floatingPoint;
178 	floatingPoint.type = EbtFloat;
179 	floatingPoint.primarySize = 1;
180 	floatingPoint.secondarySize = 1;
181 	floatingPoint.array = false;
182 
183 	switch(shaderType)
184 	{
185 	case GL_FRAGMENT_SHADER:
186 		symbolTable.setDefaultPrecision(integer, EbpMedium);
187 		break;
188 	case GL_VERTEX_SHADER:
189 		symbolTable.setDefaultPrecision(integer, EbpHigh);
190 		symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
191 		break;
192 	default: assert(false && "Language not supported");
193 	}
194 
195 	InsertBuiltInFunctions(shaderType, resources, symbolTable);
196 
197 	IdentifyBuiltIns(shaderType, resources, symbolTable);
198 
199 	return true;
200 }
201 
clearResults()202 void TCompiler::clearResults()
203 {
204 	infoSink.info.erase();
205 	infoSink.obj.erase();
206 	infoSink.debug.erase();
207 }
208 
validateCallDepth(TIntermNode * root,TInfoSink & infoSink)209 bool TCompiler::validateCallDepth(TIntermNode *root, TInfoSink &infoSink)
210 {
211 	AnalyzeCallDepth validator(root);
212 
213 	unsigned int depth = validator.analyzeCallDepth();
214 
215 	if(depth == 0)
216 	{
217 		infoSink.info.prefix(EPrefixError);
218 		infoSink.info << "Missing main()";
219 		return false;
220 	}
221 	else if(depth == UINT_MAX)
222 	{
223 		infoSink.info.prefix(EPrefixError);
224 		infoSink.info << "Function recursion detected";
225 		return false;
226 	}
227 	else if(depth > maxCallStackDepth)
228 	{
229 		infoSink.info.prefix(EPrefixError);
230 		infoSink.info << "Function call stack too deep";
231 		return false;
232 	}
233 
234 	return true;
235 }
236 
validateLimitations(TIntermNode * root)237 bool TCompiler::validateLimitations(TIntermNode* root) {
238 	ValidateLimitations validate(shaderType, infoSink.info);
239 	root->traverse(&validate);
240 	return validate.numErrors() == 0;
241 }
242 
getExtensionBehavior() const243 const TExtensionBehavior& TCompiler::getExtensionBehavior() const
244 {
245 	return extensionBehavior;
246 }
247 
InitCompilerGlobals()248 bool InitCompilerGlobals()
249 {
250 	if(!InitializePoolIndex())
251 	{
252 		assert(0 && "InitCompilerGlobals(): Failed to initalize global pool");
253 		return false;
254 	}
255 
256 	if(!InitializeParseContextIndex())
257 	{
258 		assert(0 && "InitCompilerGlobals(): Failed to initalize parse context");
259 		return false;
260 	}
261 
262 	return true;
263 }
264 
FreeCompilerGlobals()265 void FreeCompilerGlobals()
266 {
267 	FreeParseContextIndex();
268 	FreePoolIndex();
269 }
270