zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Compiler.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2002-2013 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 
10 #include "compiler/Initialize.h"
13 #include "compiler/ParseHelper.h"
15 #include "compiler/ShHandle.h"
23 
25 {
26  return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC;
27 }
28 
29 namespace {
30 class TScopedPoolAllocator {
31 public:
32  TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
33  : mAllocator(allocator), mPushPopAllocator(pushPop) {
34  if (mPushPopAllocator) mAllocator->push();
35  SetGlobalPoolAllocator(mAllocator);
36  }
37  ~TScopedPoolAllocator() {
39  if (mPushPopAllocator) mAllocator->pop();
40  }
41 
42 private:
43  TPoolAllocator* mAllocator;
44  bool mPushPopAllocator;
45 };
46 } // namespace
47 
49  allocator.push();
50  SetGlobalPoolAllocator(&allocator);
51 }
52 
55  allocator.popAll();
56 }
57 
59  : shaderType(type),
60  shaderSpec(spec),
61  maxUniformVectors(0),
62  maxExpressionComplexity(0),
63  maxCallStackDepth(0),
64  fragmentPrecisionHigh(false),
65  clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
66  builtInFunctionEmulator(type)
67 {
68  longNameMap = LongNameMap::GetInstance();
69 }
70 
72 {
73  ASSERT(longNameMap);
74  longNameMap->Release();
75 }
76 
77 bool TCompiler::Init(const ShBuiltInResources& resources)
78 {
79  maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ?
80  resources.MaxVertexUniformVectors :
81  resources.MaxFragmentUniformVectors;
82  maxExpressionComplexity = resources.MaxExpressionComplexity;
83  maxCallStackDepth = resources.MaxCallStackDepth;
84  TScopedPoolAllocator scopedAlloc(&allocator, false);
85 
86  // Generate built-in symbol table.
87  if (!InitBuiltInSymbolTable(resources))
88  return false;
89  InitExtensionBehavior(resources, extensionBehavior);
90  fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
91 
92  arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
93  clampingStrategy = resources.ArrayIndexClampingStrategy;
94 
95  hashFunction = resources.HashFunction;
96 
97  return true;
98 }
99 
100 bool TCompiler::compile(const char* const shaderStrings[],
101  size_t numStrings,
102  int compileOptions)
103 {
104  TScopedPoolAllocator scopedAlloc(&allocator, true);
105  clearResults();
106 
107  if (numStrings == 0)
108  return true;
109 
110  // If compiling for WebGL, validate loop and indexing as well.
111  if (isWebGLBasedSpec(shaderSpec))
112  compileOptions |= SH_VALIDATE_LOOP_INDEXING;
113 
114  // First string is path of source file if flag is set. The actual source follows.
115  const char* sourcePath = NULL;
116  size_t firstSource = 0;
117  if (compileOptions & SH_SOURCE_PATH)
118  {
119  sourcePath = shaderStrings[0];
120  ++firstSource;
121  }
122 
123  TIntermediate intermediate(infoSink);
124  TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
125  shaderType, shaderSpec, compileOptions, true,
126  sourcePath, infoSink);
127  parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
128  SetGlobalParseContext(&parseContext);
129 
130  // We preserve symbols at the built-in level from compile-to-compile.
131  // Start pushing the user-defined symbols at global level.
132  symbolTable.push();
133  if (!symbolTable.atGlobalLevel()) {
134  infoSink.info.prefix(EPrefixInternalError);
135  infoSink.info << "Wrong symbol table level";
136  }
137 
138  // Parse shader.
139  bool success =
140  (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) &&
141  (parseContext.treeRoot != NULL);
142  if (success) {
143  TIntermNode* root = parseContext.treeRoot;
144  success = intermediate.postProcess(root);
145 
146  if (success)
147  success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0);
148 
149  if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
150  success = validateLimitations(root);
151 
152  if (success && (compileOptions & SH_TIMING_RESTRICTIONS))
153  success = enforceTimingRestrictions(root, (compileOptions & SH_DEPENDENCY_GRAPH) != 0);
154 
155  if (success && shaderSpec == SH_CSS_SHADERS_SPEC)
156  rewriteCSSShader(root);
157 
158  // Unroll for-loop markup needs to happen after validateLimitations pass.
159  if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
161 
162  // Built-in function emulation needs to happen after validateLimitations pass.
163  if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS))
164  builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
165 
166  // Clamping uniform array bounds needs to happen after validateLimitations pass.
167  if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
168  arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
169 
170  // Disallow expressions deemed too complex.
171  if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
172  success = limitExpressionComplexity(root);
173 
174  // Call mapLongVariableNames() before collectAttribsUniforms() so in
175  // collectAttribsUniforms() we already have the mapped symbol names and
176  // we could composite mapped and original variable names.
177  // Also, if we hash all the names, then no need to do this for long names.
178  if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL)
179  mapLongVariableNames(root);
180 
181  if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) {
183  if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) {
184  success = enforcePackingRestrictions();
185  if (!success) {
186  infoSink.info.prefix(EPrefixError);
187  infoSink.info << "too many uniforms";
188  }
189  }
190  }
191 
192  if (success && (compileOptions & SH_INTERMEDIATE_TREE))
193  intermediate.outputTree(root);
194 
195  if (success && (compileOptions & SH_OBJECT_CODE))
196  translate(root);
197  }
198 
199  // Cleanup memory.
200  intermediate.remove(parseContext.treeRoot);
201  // Ensure symbol table is returned to the built-in level,
202  // throwing away all but the built-ins.
203  while (!symbolTable.atBuiltInLevel())
204  symbolTable.pop();
205 
206  return success;
207 }
208 
210 {
211  compileResources = resources;
212 
213  assert(symbolTable.isEmpty());
214  symbolTable.push();
215 
216  TPublicType integer;
217  integer.type = EbtInt;
218  integer.size = 1;
219  integer.matrix = false;
220  integer.array = false;
221 
222  TPublicType floatingPoint;
223  floatingPoint.type = EbtFloat;
224  floatingPoint.size = 1;
225  floatingPoint.matrix = false;
226  floatingPoint.array = false;
227 
228  switch(shaderType)
229  {
230  case SH_FRAGMENT_SHADER:
231  symbolTable.setDefaultPrecision(integer, EbpMedium);
232  break;
233  case SH_VERTEX_SHADER:
234  symbolTable.setDefaultPrecision(integer, EbpHigh);
235  symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
236  break;
237  default: assert(false && "Language not supported");
238  }
239 
240  InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
241 
242  IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
243 
244  return true;
245 }
246 
248 {
249  arrayBoundsClamper.Cleanup();
250  infoSink.info.erase();
251  infoSink.obj.erase();
252  infoSink.debug.erase();
253 
254  attribs.clear();
255  uniforms.clear();
256 
257  builtInFunctionEmulator.Cleanup();
258 
259  nameMap.clear();
260 }
261 
262 bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth)
263 {
264  DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth);
265  root->traverse(&detect);
266  switch (detect.detectCallDepth()) {
268  return true;
270  infoSink.info.prefix(EPrefixError);
271  infoSink.info << "Missing main()";
272  return false;
274  infoSink.info.prefix(EPrefixError);
275  infoSink.info << "Function recursion detected";
276  return false;
278  infoSink.info.prefix(EPrefixError);
279  infoSink.info << "Function call stack too deep";
280  return false;
281  default:
282  UNREACHABLE();
283  return false;
284  }
285 }
286 
288 {
289  RenameFunction renamer("main(", "css_main(");
290  root->traverse(&renamer);
291 }
292 
294  ValidateLimitations validate(shaderType, infoSink.info);
295  root->traverse(&validate);
296  return validate.numErrors() == 0;
297 }
298 
300 {
301  if (shaderSpec != SH_WEBGL_SPEC) {
302  infoSink.info << "Timing restrictions must be enforced under the WebGL spec.";
303  return false;
304  }
305 
306  if (shaderType == SH_FRAGMENT_SHADER) {
307  TDependencyGraph graph(root);
308 
309  // Output any errors first.
310  bool success = enforceFragmentShaderTimingRestrictions(graph);
311 
312  // Then, output the dependency graph.
313  if (outputGraph) {
315  output.outputAllSpanningTrees(graph);
316  }
317 
318  return success;
319  }
320  else {
322  }
323 }
324 
326 {
327  TIntermTraverser traverser;
328  root->traverse(&traverser);
329  TDependencyGraph graph(root);
330 
331  for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
332  iter != graph.endUserDefinedFunctionCalls();
333  ++iter)
334  {
335  TGraphFunctionCall* samplerSymbol = *iter;
336  TDependencyGraphTraverser graphTraverser;
337  samplerSymbol->traverse(&graphTraverser);
338  }
339 
340  if (traverser.getMaxDepth() > maxExpressionComplexity) {
341  infoSink.info << "Expression too complex.";
342  return false;
343  }
344  return true;
345 }
346 
348 {
349  RestrictFragmentShaderTiming restrictor(infoSink.info);
350  restrictor.enforceRestrictions(graph);
351  return restrictor.numErrors() == 0;
352 }
353 
355 {
356  RestrictVertexShaderTiming restrictor(infoSink.info);
357  restrictor.enforceRestrictions(root);
358  return restrictor.numErrors() == 0;
359 }
360 
362 {
363  CollectAttribsUniforms collect(attribs, uniforms, hashFunction);
364  root->traverse(&collect);
365 }
366 
368 {
369  VariablePacker packer;
370  return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, uniforms);
371 }
372 
374 {
375  ASSERT(longNameMap);
376  MapLongVariableNames map(longNameMap);
377  root->traverse(&map);
378 }
379 
381 {
383 }
384 
386 {
387  return extensionBehavior;
388 }
389 
391 {
392  return compileResources;
393 }
394 
396 {
397  return arrayBoundsClamper;
398 }
399 
401 {
402  return clampingStrategy;
403 }
404 
406 {
407  return builtInFunctionEmulator;
408 }
void MarkIndirectArrayBoundsForClamping(TIntermNode *root)
TCompiler(ShShaderType type, ShShaderSpec spec)
Definition: Compiler.cpp:58
bool Init(const ShBuiltInResources &resources)
Definition: Compiler.cpp:77
virtual void translate(TIntermNode *root)=0
bool validateLimitations(TIntermNode *root)
Definition: Compiler.cpp:293
void remove(TIntermNode *)
bool enforceVertexShaderTimingRestrictions(TIntermNode *root)
Definition: Compiler.cpp:354
std::map< std::string, TBehavior > TExtensionBehavior
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
bool isEmpty()
Definition: SymbolTable.h:260
bool enforceTimingRestrictions(TIntermNode *root, bool outputGraph)
Definition: Compiler.cpp:299
#define NULL
Definition: ftobjs.h:61
int getMappedNameMaxLength() const
Definition: Compiler.cpp:380
#define MAX_SHORTENED_IDENTIFIER_SIZE
int getMaxDepth() const
Definition: intermediate.h:561
int MaxFragmentUniformVectors
Definition: ShaderLang.h:212
bool fragmentPrecisionHigh
Definition: ParseHelper.h:57
TFunctionCallVector::const_iterator endUserDefinedFunctionCalls() const
const BuiltInFunctionEmulator & getBuiltInFunctionEmulator() const
Definition: Compiler.cpp:405
bool enforcePackingRestrictions()
Definition: Compiler.cpp:367
virtual ~TCompiler()
Definition: Compiler.cpp:71
#define assert(x)
Definition: SDL_malloc.c:1234
void SetClampingStrategy(ShArrayIndexClampingStrategy clampingStrategy)
const ArrayBoundsClamper & getArrayBoundsClamper() const
Definition: Compiler.cpp:395
const GLint * attribs
Definition: glew.h:13064
void clearResults()
Definition: Compiler.cpp:247
void collectAttribsUniforms(TIntermNode *root)
Definition: Compiler.cpp:361
bool CheckVariablesWithinPackingLimits(int maxVectors, const TVariableInfoList &in_variables)
ShArrayIndexClampingStrategy
Definition: ShaderLang.h:175
int PaParseStrings(size_t count, const char *const string[], const int length[], TParseContext *context)
void outputAllSpanningTrees(TDependencyGraph &graph)
bool isWebGLBasedSpec(ShShaderSpec spec)
Definition: Compiler.cpp:24
ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const
Definition: Compiler.cpp:400
TInfoSinkBase debug
Definition: InfoSink.h:111
bool array
Definition: Types.h:266
#define ASSERT(expression)
Definition: debug.h:36
bool InitBuiltInSymbolTable(const ShBuiltInResources &resources)
Definition: Compiler.cpp:209
void rewriteCSSShader(TIntermNode *root)
Definition: Compiler.cpp:287
ShArrayIndexClampingStrategy ArrayIndexClampingStrategy
Definition: ShaderLang.h:234
int size
Definition: Types.h:264
bool setDefaultPrecision(const TPublicType &type, TPrecision prec)
Definition: SymbolTable.h:351
bool limitExpressionComplexity(TIntermNode *root)
Definition: Compiler.cpp:325
void mapLongVariableNames(TIntermNode *root)
Definition: Compiler.cpp:373
virtual void traverse(TIntermTraverser *)=0
void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable)
Definition: Initialize.cpp:17
bool matrix
Definition: Types.h:265
#define UNREACHABLE()
Definition: debug.h:47
static void MarkForLoopsWithIntegerIndicesForUnrolling(TIntermNode *root)
const TExtensionBehavior & getExtensionBehavior() const
Definition: Compiler.cpp:385
void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable)
Definition: Initialize.cpp:421
bool atBuiltInLevel()
Definition: SymbolTable.h:261
virtual void traverse(TDependencyGraphTraverser *graphTraverser)
void SetGlobalPoolAllocator(TPoolAllocator *poolAllocator)
Definition: PoolAlloc.cpp:42
bool atGlobalLevel()
Definition: SymbolTable.h:262
void SetGlobalParseContext(TParseContext *context)
void outputTree(TIntermNode *)
Definition: intermOut.cpp:416
TIntermNode * treeRoot
Definition: ParseHelper.h:51
void erase()
Definition: InfoSink.h:93
ErrorCode detectCallDepth()
void enforceRestrictions(TIntermNode *root)
static LongNameMap * GetInstance()
ShShaderType
Definition: ShaderLang.h:48
const ShBuiltInResources & getResources() const
Definition: Compiler.cpp:390
void MarkBuiltInFunctionsForEmulation(TIntermNode *root)
ShShaderSpec
Definition: ShaderLang.h:53
TInfoSinkBase info
Definition: InfoSink.h:110
virtual ~TShHandleBase()
Definition: Compiler.cpp:53
TInfoSinkBase obj
Definition: InfoSink.h:112
const GLubyte GLuint GLuint GLuint GLuint alpha GLboolean GLboolean GLboolean GLboolean alpha GLint GLint GLsizei GLsizei GLenum type GLenum GLint GLenum GLint GLint GLsizei GLsizei GLint border GLenum GLint GLint GLint GLint GLint GLsizei GLsizei height GLsizei GLsizei GLenum GLenum const GLvoid *pixels GLenum GLint GLint GLint GLint j2 GLdouble GLdouble GLdouble GLdouble GLdouble GLdouble zFar GLenum GLenum GLint *params GLenum GLenum GLint *params GLenum GLenum GLint *params GLenum GLenum GLfloat *params GLenum GLint GLenum GLenum GLvoid *pixels GLenum GLint GLenum GLint *params GLenum GLenum GLint *params GLenum GLsizei const GLvoid *pointer GLenum GLenum const GLint *params GLenum GLfloat GLfloat GLint GLint const GLfloat *points GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat *points GLint GLfloat GLfloat GLint GLfloat GLfloat v2 GLenum GLenum const GLint *params GLdouble GLdouble GLdouble GLdouble GLdouble GLdouble zFar GLenum map
Definition: SDL_glfuncs.h:268
void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavior &extBehavior)
Definition: Initialize.cpp:551
bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph &graph)
Definition: Compiler.cpp:347
bool compile(const char *const shaderStrings[], size_t numStrings, int compileOptions)
Definition: Compiler.cpp:100
TFunctionCallVector::const_iterator beginUserDefinedFunctionCalls() const
bool detectCallDepth(TIntermNode *root, TInfoSink &infoSink, bool limitCallStackDepth)
Definition: Compiler.cpp:262
#define false
Definition: ftrandom.c:50
TBasicType type
Definition: Types.h:261
bool postProcess(TIntermNode *)
void prefix(TPrefixType p)
Definition: InfoSink.cpp:9
void enforceRestrictions(const TDependencyGraph &graph)
ShHashFunction64 HashFunction
Definition: ShaderLang.h:230