blob: 649b457d750122222c555808f48121d6b7211307 [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"
alokp@chromium.org07620a52010-09-23 17:53:56 +000011
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000012namespace {
13bool InitializeSymbolTable(
14 const TBuiltInStrings& builtInStrings,
15 ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
16 TInfoSink& infoSink, TSymbolTable& symbolTable)
alokp@chromium.org07620a52010-09-23 17:53:56 +000017{
18 TIntermediate intermediate(infoSink);
19 TExtensionBehavior extBehavior;
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000020 TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, infoSink);
alokp@chromium.org07620a52010-09-23 17:53:56 +000021
22 GlobalParseContext = &parseContext;
23
alokp@chromium.org07620a52010-09-23 17:53:56 +000024 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();
alokp@chromium.org07620a52010-09-23 17:53:56 +000034
35 for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
36 {
alokp@chromium.org570bfc72010-09-24 17:19:25 +000037 const char* builtInShaders = i->c_str();
38 int builtInLengths = static_cast<int>(i->size());
39 if (builtInLengths <= 0)
40 continue;
alokp@chromium.org07620a52010-09-23 17:53:56 +000041
alokp@chromium.org044a5cf2010-11-12 15:42:16 +000042 if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0)
alokp@chromium.org07620a52010-09-23 17:53:56 +000043 {
44 infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
45 return false;
46 }
47 }
48
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000049 IdentifyBuiltIns(type, spec, resources, symbolTable);
alokp@chromium.org07620a52010-09-23 17:53:56 +000050
alokp@chromium.org07620a52010-09-23 17:53:56 +000051 return true;
52}
53
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000054class TScopedPoolAllocator {
55public:
56 TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
57 : mAllocator(allocator), mPushPopAllocator(pushPop) {
58 if (mPushPopAllocator) mAllocator->push();
59 SetGlobalPoolAllocator(mAllocator);
60 }
61 ~TScopedPoolAllocator() {
62 SetGlobalPoolAllocator(NULL);
63 if (mPushPopAllocator) mAllocator->pop();
64 }
65
66private:
67 TPoolAllocator* mAllocator;
68 bool mPushPopAllocator;
69};
70} // namespace
71
72TShHandleBase::TShHandleBase() {
73 allocator.push();
74 SetGlobalPoolAllocator(&allocator);
75}
76
77TShHandleBase::~TShHandleBase() {
78 SetGlobalPoolAllocator(NULL);
79 allocator.popAll();
80}
81
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000082TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
83 : shaderType(type),
84 shaderSpec(spec)
85{
86}
87
88TCompiler::~TCompiler()
89{
90}
91
92bool TCompiler::Init(const ShBuiltInResources& resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +000093{
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000094 TScopedPoolAllocator scopedAlloc(&allocator, false);
95
alokp@chromium.org07620a52010-09-23 17:53:56 +000096 // Generate built-in symbol table.
97 if (!InitBuiltInSymbolTable(resources))
98 return false;
alokp@chromium.org07620a52010-09-23 17:53:56 +000099 InitExtensionBehavior(resources, extensionBehavior);
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000100
alokp@chromium.org07620a52010-09-23 17:53:56 +0000101 return true;
102}
103
104bool TCompiler::compile(const char* const shaderStrings[],
105 const int numStrings,
106 int compileOptions)
107{
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000108 TScopedPoolAllocator scopedAlloc(&allocator, true);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000109 clearResults();
110
111 if (numStrings == 0)
112 return true;
113
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000114 // If compiling for WebGL, validate loop and indexing as well.
115 if (shaderSpec == SH_WEBGL_SPEC)
116 compileOptions |= SH_VALIDATE_LOOP_INDEXING;
alokp@chromium.org1f299542010-11-12 15:50:23 +0000117
alokp@chromium.org07620a52010-09-23 17:53:56 +0000118 TIntermediate intermediate(infoSink);
119 TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000120 shaderType, shaderSpec, infoSink);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000121 GlobalParseContext = &parseContext;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000122
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 =
alokp@chromium.org044a5cf2010-11-12 15:42:16 +0000131 (PaParseStrings(numStrings, shaderStrings, NULL, &parseContext) == 0) &&
alokp@chromium.org07620a52010-09-23 17:53:56 +0000132 (parseContext.treeRoot != NULL);
133 if (success) {
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000134 TIntermNode* root = parseContext.treeRoot;
135 success = intermediate.postProcess(root);
136
137 if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
138 success = validateLimitations(root);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000139
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000140 if (success && (compileOptions & SH_INTERMEDIATE_TREE))
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000141 intermediate.outputTree(root);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000142
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000143 if (success && (compileOptions & SH_OBJECT_CODE))
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000144 translate(root);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000145
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000146 if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS))
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000147 collectAttribsUniforms(root);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000148 }
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();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000156
157 return success;
158}
159
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000160bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000161{
162 TBuiltIns builtIns;
163
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000164 builtIns.initialize(shaderType, shaderSpec, resources);
165 return InitializeSymbolTable(builtIns.getBuiltInStrings(),
166 shaderType, shaderSpec, resources, infoSink, symbolTable);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000167}
168
169void TCompiler::clearResults()
170{
171 infoSink.info.erase();
172 infoSink.obj.erase();
173 infoSink.debug.erase();
174
175 attribs.clear();
176 uniforms.clear();
177}
178
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000179bool TCompiler::validateLimitations(TIntermNode* root) {
180 ValidateLimitations validate(shaderType, infoSink.info);
181 root->traverse(&validate);
182 return validate.numErrors() == 0;
183}
184
alokp@chromium.org07620a52010-09-23 17:53:56 +0000185void TCompiler::collectAttribsUniforms(TIntermNode* root)
186{
187 CollectAttribsUniforms collect(attribs, uniforms);
188 root->traverse(&collect);
189}