blob: 5d86a3ec095ef5ee8f055bdf6b4abfa1d7d2b2c8 [file] [log] [blame]
alokp@chromium.org07620a52010-09-23 17:53:56 +00001//
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"
alokp@chromium.orgb59a7782010-11-24 18:38:33 +000010#include "compiler/ValidateLimitations.h"
zmo@google.comfd747b82011-04-23 01:30:07 +000011#include "compiler/MapLongVariableNames.h"
alokp@chromium.org07620a52010-09-23 17:53:56 +000012
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000013namespace {
14bool InitializeSymbolTable(
15 const TBuiltInStrings& builtInStrings,
16 ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
17 TInfoSink& infoSink, TSymbolTable& symbolTable)
alokp@chromium.org07620a52010-09-23 17:53:56 +000018{
19 TIntermediate intermediate(infoSink);
20 TExtensionBehavior extBehavior;
zmo@google.comdc4b4f82011-06-17 00:42:53 +000021 // The builtins deliberately don't specify precisions for the function
22 // arguments and return types. For that reason we don't try to check them.
23 TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, 0, false, NULL, infoSink);
alokp@chromium.org07620a52010-09-23 17:53:56 +000024
25 GlobalParseContext = &parseContext;
26
alokp@chromium.org07620a52010-09-23 17:53:56 +000027 assert(symbolTable.isEmpty());
28 //
29 // Parse the built-ins. This should only happen once per
30 // language symbol table.
31 //
32 // Push the symbol table to give it an initial scope. This
33 // push should not have a corresponding pop, so that built-ins
34 // are preserved, and the test for an empty table fails.
35 //
36 symbolTable.push();
alokp@chromium.org07620a52010-09-23 17:53:56 +000037
38 for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
39 {
alokp@chromium.org570bfc72010-09-24 17:19:25 +000040 const char* builtInShaders = i->c_str();
41 int builtInLengths = static_cast<int>(i->size());
42 if (builtInLengths <= 0)
43 continue;
alokp@chromium.org07620a52010-09-23 17:53:56 +000044
alokp@chromium.org044a5cf2010-11-12 15:42:16 +000045 if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0)
alokp@chromium.org07620a52010-09-23 17:53:56 +000046 {
47 infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
48 return false;
49 }
50 }
51
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000052 IdentifyBuiltIns(type, spec, resources, symbolTable);
alokp@chromium.org07620a52010-09-23 17:53:56 +000053
alokp@chromium.org07620a52010-09-23 17:53:56 +000054 return true;
55}
56
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000057class TScopedPoolAllocator {
58public:
59 TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
60 : mAllocator(allocator), mPushPopAllocator(pushPop) {
61 if (mPushPopAllocator) mAllocator->push();
62 SetGlobalPoolAllocator(mAllocator);
63 }
64 ~TScopedPoolAllocator() {
65 SetGlobalPoolAllocator(NULL);
66 if (mPushPopAllocator) mAllocator->pop();
67 }
68
69private:
70 TPoolAllocator* mAllocator;
71 bool mPushPopAllocator;
72};
73} // namespace
74
75TShHandleBase::TShHandleBase() {
76 allocator.push();
77 SetGlobalPoolAllocator(&allocator);
78}
79
80TShHandleBase::~TShHandleBase() {
81 SetGlobalPoolAllocator(NULL);
82 allocator.popAll();
83}
84
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000085TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
86 : shaderType(type),
87 shaderSpec(spec)
88{
89}
90
91TCompiler::~TCompiler()
92{
93}
94
95bool TCompiler::Init(const ShBuiltInResources& resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +000096{
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000097 TScopedPoolAllocator scopedAlloc(&allocator, false);
98
alokp@chromium.org07620a52010-09-23 17:53:56 +000099 // Generate built-in symbol table.
100 if (!InitBuiltInSymbolTable(resources))
101 return false;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000102 InitExtensionBehavior(resources, extensionBehavior);
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000103
alokp@chromium.org07620a52010-09-23 17:53:56 +0000104 return true;
105}
106
107bool TCompiler::compile(const char* const shaderStrings[],
108 const int numStrings,
109 int compileOptions)
110{
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000111 TScopedPoolAllocator scopedAlloc(&allocator, true);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000112 clearResults();
113
114 if (numStrings == 0)
115 return true;
116
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000117 // If compiling for WebGL, validate loop and indexing as well.
118 if (shaderSpec == SH_WEBGL_SPEC)
119 compileOptions |= SH_VALIDATE_LOOP_INDEXING;
alokp@chromium.org1f299542010-11-12 15:50:23 +0000120
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000121 // First string is path of source file if flag is set. The actual source follows.
122 const char* sourcePath = NULL;
123 int firstSource = 0;
124 if (compileOptions & SH_SOURCE_PATH)
125 {
126 sourcePath = shaderStrings[0];
127 ++firstSource;
128 }
129
alokp@chromium.org07620a52010-09-23 17:53:56 +0000130 TIntermediate intermediate(infoSink);
131 TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
zmo@google.comdc4b4f82011-06-17 00:42:53 +0000132 shaderType, shaderSpec, compileOptions, true,
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000133 sourcePath, infoSink);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000134 GlobalParseContext = &parseContext;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000135
136 // We preserve symbols at the built-in level from compile-to-compile.
137 // Start pushing the user-defined symbols at global level.
138 symbolTable.push();
139 if (!symbolTable.atGlobalLevel())
140 infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
141
142 // Parse shader.
143 bool success =
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000144 (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) &&
alokp@chromium.org07620a52010-09-23 17:53:56 +0000145 (parseContext.treeRoot != NULL);
146 if (success) {
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000147 TIntermNode* root = parseContext.treeRoot;
148 success = intermediate.postProcess(root);
149
150 if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
151 success = validateLimitations(root);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000152
zmo@google.comfd747b82011-04-23 01:30:07 +0000153 // Call mapLongVariableNames() before collectAttribsUniforms() so in
154 // collectAttribsUniforms() we already have the mapped symbol names and
155 // we could composite mapped and original variable names.
156 if (compileOptions & SH_MAP_LONG_VARIABLE_NAMES)
157 mapLongVariableNames(root);
158
159 if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS))
160 collectAttribsUniforms(root);
161
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000162 if (success && (compileOptions & SH_INTERMEDIATE_TREE))
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000163 intermediate.outputTree(root);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000164
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000165 if (success && (compileOptions & SH_OBJECT_CODE))
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000166 translate(root);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000167 }
168
169 // Cleanup memory.
170 intermediate.remove(parseContext.treeRoot);
171 // Ensure symbol table is returned to the built-in level,
172 // throwing away all but the built-ins.
173 while (!symbolTable.atBuiltInLevel())
174 symbolTable.pop();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000175
176 return success;
177}
178
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000179bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000180{
181 TBuiltIns builtIns;
182
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000183 builtIns.initialize(shaderType, shaderSpec, resources);
184 return InitializeSymbolTable(builtIns.getBuiltInStrings(),
185 shaderType, shaderSpec, resources, infoSink, symbolTable);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000186}
187
188void TCompiler::clearResults()
189{
190 infoSink.info.erase();
191 infoSink.obj.erase();
192 infoSink.debug.erase();
193
194 attribs.clear();
195 uniforms.clear();
196}
197
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000198bool TCompiler::validateLimitations(TIntermNode* root) {
199 ValidateLimitations validate(shaderType, infoSink.info);
200 root->traverse(&validate);
201 return validate.numErrors() == 0;
202}
203
alokp@chromium.org07620a52010-09-23 17:53:56 +0000204void TCompiler::collectAttribsUniforms(TIntermNode* root)
205{
206 CollectAttribsUniforms collect(attribs, uniforms);
207 root->traverse(&collect);
208}
zmo@google.comfd747b82011-04-23 01:30:07 +0000209
210void TCompiler::mapLongVariableNames(TIntermNode* root)
211{
zmo@google.com24c08c42011-05-27 17:40:48 +0000212 MapLongVariableNames map(varyingLongNameMap);
zmo@google.comfd747b82011-04-23 01:30:07 +0000213 root->traverse(&map);
214}
215
216int TCompiler::getMappedNameMaxLength() const
217{
218 return MAX_IDENTIFIER_NAME_SIZE + 1;
219}
zmo@google.com5601ea02011-06-10 18:23:25 +0000220
221const TExtensionBehavior& TCompiler::getExtensionBehavior() const
222{
223 return extensionBehavior;
224}