blob: 11acfaedbd730c9c3cc175565fcf73913e34cc4c [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"
10
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000011namespace {
12bool InitializeSymbolTable(
13 const TBuiltInStrings& builtInStrings,
14 ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
15 TInfoSink& infoSink, TSymbolTable& symbolTable)
alokp@chromium.org07620a52010-09-23 17:53:56 +000016{
17 TIntermediate intermediate(infoSink);
18 TExtensionBehavior extBehavior;
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000019 TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, infoSink);
alokp@chromium.org07620a52010-09-23 17:53:56 +000020
21 GlobalParseContext = &parseContext;
22
alokp@chromium.org07620a52010-09-23 17:53:56 +000023 assert(symbolTable.isEmpty());
24 //
25 // Parse the built-ins. This should only happen once per
26 // language symbol table.
27 //
28 // Push the symbol table to give it an initial scope. This
29 // push should not have a corresponding pop, so that built-ins
30 // are preserved, and the test for an empty table fails.
31 //
32 symbolTable.push();
alokp@chromium.org07620a52010-09-23 17:53:56 +000033
34 for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
35 {
alokp@chromium.org570bfc72010-09-24 17:19:25 +000036 const char* builtInShaders = i->c_str();
37 int builtInLengths = static_cast<int>(i->size());
38 if (builtInLengths <= 0)
39 continue;
alokp@chromium.org07620a52010-09-23 17:53:56 +000040
alokp@chromium.org044a5cf2010-11-12 15:42:16 +000041 if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0)
alokp@chromium.org07620a52010-09-23 17:53:56 +000042 {
43 infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
44 return false;
45 }
46 }
47
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000048 IdentifyBuiltIns(type, spec, resources, symbolTable);
alokp@chromium.org07620a52010-09-23 17:53:56 +000049
alokp@chromium.org07620a52010-09-23 17:53:56 +000050 return true;
51}
52
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000053class TScopedPoolAllocator {
54public:
55 TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
56 : mAllocator(allocator), mPushPopAllocator(pushPop) {
57 if (mPushPopAllocator) mAllocator->push();
58 SetGlobalPoolAllocator(mAllocator);
59 }
60 ~TScopedPoolAllocator() {
61 SetGlobalPoolAllocator(NULL);
62 if (mPushPopAllocator) mAllocator->pop();
63 }
64
65private:
66 TPoolAllocator* mAllocator;
67 bool mPushPopAllocator;
68};
69} // namespace
70
71TShHandleBase::TShHandleBase() {
72 allocator.push();
73 SetGlobalPoolAllocator(&allocator);
74}
75
76TShHandleBase::~TShHandleBase() {
77 SetGlobalPoolAllocator(NULL);
78 allocator.popAll();
79}
80
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000081TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
82 : shaderType(type),
83 shaderSpec(spec)
84{
85}
86
87TCompiler::~TCompiler()
88{
89}
90
91bool TCompiler::Init(const ShBuiltInResources& resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +000092{
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000093 TScopedPoolAllocator scopedAlloc(&allocator, false);
94
alokp@chromium.org07620a52010-09-23 17:53:56 +000095 // Generate built-in symbol table.
96 if (!InitBuiltInSymbolTable(resources))
97 return false;
alokp@chromium.org07620a52010-09-23 17:53:56 +000098 InitExtensionBehavior(resources, extensionBehavior);
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000099
alokp@chromium.org07620a52010-09-23 17:53:56 +0000100 return true;
101}
102
103bool TCompiler::compile(const char* const shaderStrings[],
104 const int numStrings,
105 int compileOptions)
106{
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000107 TScopedPoolAllocator scopedAlloc(&allocator, true);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000108 clearResults();
109
110 if (numStrings == 0)
111 return true;
112
alokp@chromium.org1f299542010-11-12 15:50:23 +0000113 // If compiling for WebGL, validate control-flow and indexing as well.
114 if (shaderSpec == SH_WEBGL_SPEC) {
115 compileOptions |= SH_VALIDATE_CONTROL_FLOW | SH_VALIDATE_INDEXING;
116 }
117
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) {
134 success = intermediate.postProcess(parseContext.treeRoot);
135
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000136 if (success && (compileOptions & SH_INTERMEDIATE_TREE))
alokp@chromium.org07620a52010-09-23 17:53:56 +0000137 intermediate.outputTree(parseContext.treeRoot);
138
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000139 if (success && (compileOptions & SH_OBJECT_CODE))
alokp@chromium.org07620a52010-09-23 17:53:56 +0000140 translate(parseContext.treeRoot);
141
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000142 if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS))
alokp@chromium.org07620a52010-09-23 17:53:56 +0000143 collectAttribsUniforms(parseContext.treeRoot);
144 }
145
146 // Cleanup memory.
147 intermediate.remove(parseContext.treeRoot);
148 // Ensure symbol table is returned to the built-in level,
149 // throwing away all but the built-ins.
150 while (!symbolTable.atBuiltInLevel())
151 symbolTable.pop();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000152
153 return success;
154}
155
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000156bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000157{
158 TBuiltIns builtIns;
159
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000160 builtIns.initialize(shaderType, shaderSpec, resources);
161 return InitializeSymbolTable(builtIns.getBuiltInStrings(),
162 shaderType, shaderSpec, resources, infoSink, symbolTable);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000163}
164
165void TCompiler::clearResults()
166{
167 infoSink.info.erase();
168 infoSink.obj.erase();
169 infoSink.debug.erase();
170
171 attribs.clear();
172 uniforms.clear();
173}
174
175void TCompiler::collectAttribsUniforms(TIntermNode* root)
176{
177 CollectAttribsUniforms collect(attribs, uniforms);
178 root->traverse(&collect);
179}
180