• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2002-2010 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 
7 #include "compiler/Initialize.h"
8 #include "compiler/ParseHelper.h"
9 #include "compiler/ShHandle.h"
10 #include "compiler/ValidateLimitations.h"
11 
12 namespace {
InitializeSymbolTable(const TBuiltInStrings & builtInStrings,ShShaderType type,ShShaderSpec spec,const ShBuiltInResources & resources,TInfoSink & infoSink,TSymbolTable & symbolTable)13 bool InitializeSymbolTable(
14     const TBuiltInStrings& builtInStrings,
15     ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
16     TInfoSink& infoSink, TSymbolTable& symbolTable)
17 {
18     TIntermediate intermediate(infoSink);
19     TExtensionBehavior extBehavior;
20     TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, infoSink);
21 
22     GlobalParseContext = &parseContext;
23 
24     assert(symbolTable.isEmpty());
25     //
26     // Parse the built-ins.  This should only happen once per
27     // language symbol table.
28     //
29     // Push the symbol table to give it an initial scope.  This
30     // push should not have a corresponding pop, so that built-ins
31     // are preserved, and the test for an empty table fails.
32     //
33     symbolTable.push();
34 
35     for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
36     {
37         const char* builtInShaders = i->c_str();
38         int builtInLengths = static_cast<int>(i->size());
39         if (builtInLengths <= 0)
40           continue;
41 
42         if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0)
43         {
44             infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
45             return false;
46         }
47     }
48 
49     IdentifyBuiltIns(type, spec, resources, symbolTable);
50 
51     return true;
52 }
53 
54 class TScopedPoolAllocator {
55 public:
TScopedPoolAllocator(TPoolAllocator * allocator,bool pushPop)56     TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
57         : mAllocator(allocator), mPushPopAllocator(pushPop) {
58         if (mPushPopAllocator) mAllocator->push();
59         SetGlobalPoolAllocator(mAllocator);
60     }
~TScopedPoolAllocator()61     ~TScopedPoolAllocator() {
62         SetGlobalPoolAllocator(NULL);
63         if (mPushPopAllocator) mAllocator->pop();
64     }
65 
66 private:
67     TPoolAllocator* mAllocator;
68     bool mPushPopAllocator;
69 };
70 }  // namespace
71 
TShHandleBase()72 TShHandleBase::TShHandleBase() {
73     allocator.push();
74     SetGlobalPoolAllocator(&allocator);
75 }
76 
~TShHandleBase()77 TShHandleBase::~TShHandleBase() {
78     SetGlobalPoolAllocator(NULL);
79     allocator.popAll();
80 }
81 
TCompiler(ShShaderType type,ShShaderSpec spec)82 TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
83     : shaderType(type),
84       shaderSpec(spec)
85 {
86 }
87 
~TCompiler()88 TCompiler::~TCompiler()
89 {
90 }
91 
Init(const ShBuiltInResources & resources)92 bool TCompiler::Init(const ShBuiltInResources& resources)
93 {
94     TScopedPoolAllocator scopedAlloc(&allocator, false);
95 
96     // Generate built-in symbol table.
97     if (!InitBuiltInSymbolTable(resources))
98         return false;
99     InitExtensionBehavior(resources, extensionBehavior);
100 
101     return true;
102 }
103 
compile(const char * const shaderStrings[],const int numStrings,int compileOptions)104 bool TCompiler::compile(const char* const shaderStrings[],
105                         const int numStrings,
106                         int compileOptions)
107 {
108     TScopedPoolAllocator scopedAlloc(&allocator, true);
109     clearResults();
110 
111     if (numStrings == 0)
112         return true;
113 
114     // If compiling for WebGL, validate loop and indexing as well.
115     if (shaderSpec == SH_WEBGL_SPEC)
116         compileOptions |= SH_VALIDATE_LOOP_INDEXING;
117 
118     TIntermediate intermediate(infoSink);
119     TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
120                                shaderType, shaderSpec, infoSink);
121     GlobalParseContext = &parseContext;
122 
123     // We preserve symbols at the built-in level from compile-to-compile.
124     // Start pushing the user-defined symbols at global level.
125     symbolTable.push();
126     if (!symbolTable.atGlobalLevel())
127         infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
128 
129     // Parse shader.
130     bool success =
131         (PaParseStrings(numStrings, shaderStrings, NULL, &parseContext) == 0) &&
132         (parseContext.treeRoot != NULL);
133     if (success) {
134         TIntermNode* root = parseContext.treeRoot;
135         success = intermediate.postProcess(root);
136 
137         if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
138             success = validateLimitations(root);
139 
140         if (success && (compileOptions & SH_INTERMEDIATE_TREE))
141             intermediate.outputTree(root);
142 
143         if (success && (compileOptions & SH_OBJECT_CODE))
144             translate(root);
145 
146         if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS))
147             collectAttribsUniforms(root);
148     }
149 
150     // Cleanup memory.
151     intermediate.remove(parseContext.treeRoot);
152     // Ensure symbol table is returned to the built-in level,
153     // throwing away all but the built-ins.
154     while (!symbolTable.atBuiltInLevel())
155         symbolTable.pop();
156 
157     return success;
158 }
159 
InitBuiltInSymbolTable(const ShBuiltInResources & resources)160 bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
161 {
162     TBuiltIns builtIns;
163 
164     builtIns.initialize(shaderType, shaderSpec, resources);
165     return InitializeSymbolTable(builtIns.getBuiltInStrings(),
166         shaderType, shaderSpec, resources, infoSink, symbolTable);
167 }
168 
clearResults()169 void TCompiler::clearResults()
170 {
171     infoSink.info.erase();
172     infoSink.obj.erase();
173     infoSink.debug.erase();
174 
175     attribs.clear();
176     uniforms.clear();
177 }
178 
validateLimitations(TIntermNode * root)179 bool TCompiler::validateLimitations(TIntermNode* root) {
180     ValidateLimitations validate(shaderType, infoSink.info);
181     root->traverse(&validate);
182     return validate.numErrors() == 0;
183 }
184 
collectAttribsUniforms(TIntermNode * root)185 void TCompiler::collectAttribsUniforms(TIntermNode* root)
186 {
187     CollectAttribsUniforms collect(attribs, uniforms);
188     root->traverse(&collect);
189 }
190