blob: 6008f964779030fa71528d19de6f72834982c04e [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
11static bool InitializeSymbolTable(
12 const TBuiltInStrings& builtInStrings,
13 EShLanguage language, EShSpec spec, const TBuiltInResource& resources,
14 TInfoSink& infoSink, TSymbolTable& symbolTable)
15{
16 TIntermediate intermediate(infoSink);
17 TExtensionBehavior extBehavior;
18 TParseContext parseContext(symbolTable, extBehavior, intermediate, language, spec, infoSink);
19
20 GlobalParseContext = &parseContext;
21
22 setInitialState();
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 //Initialize the Preprocessor
36 if (InitPreprocessor())
37 {
38 infoSink.info.message(EPrefixInternalError, "Unable to intialize the Preprocessor");
39 return false;
40 }
41
42 for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
43 {
44 const char* builtInShaders[1];
45 int builtInLengths[1];
46
47 builtInShaders[0] = (*i).c_str();
48 builtInLengths[0] = (int) (*i).size();
49
50 if (PaParseStrings(builtInShaders, builtInLengths, 1, parseContext) != 0)
51 {
52 infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
53 return false;
54 }
55 }
56
57 IdentifyBuiltIns(language, spec, resources, symbolTable);
58
59 FinalizePreprocessor();
60
61 return true;
62}
63
64static void DefineExtensionMacros(const TExtensionBehavior& extBehavior)
65{
66 for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
67 iter != extBehavior.end(); ++iter) {
68 PredefineIntMacro(iter->first.c_str(), 1);
69 }
70}
71
72bool TCompiler::Init(const TBuiltInResource& resources)
73{
74 // Generate built-in symbol table.
75 if (!InitBuiltInSymbolTable(resources))
76 return false;
77
78 InitExtensionBehavior(resources, extensionBehavior);
79 return true;
80}
81
82bool TCompiler::compile(const char* const shaderStrings[],
83 const int numStrings,
84 int compileOptions)
85{
86 clearResults();
87
88 if (numStrings == 0)
89 return true;
90
91 TIntermediate intermediate(infoSink);
92 TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
93 language, spec, infoSink);
94 GlobalParseContext = &parseContext;
95 setInitialState();
96
97 // Initialize preprocessor.
98 InitPreprocessor();
99 DefineExtensionMacros(extensionBehavior);
100
101 // We preserve symbols at the built-in level from compile-to-compile.
102 // Start pushing the user-defined symbols at global level.
103 symbolTable.push();
104 if (!symbolTable.atGlobalLevel())
105 infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
106
107 // Parse shader.
108 bool success =
109 (PaParseStrings(shaderStrings, 0, numStrings, parseContext) == 0) &&
110 (parseContext.treeRoot != NULL);
111 if (success) {
112 success = intermediate.postProcess(parseContext.treeRoot);
113
114 if (success && (compileOptions & EShOptIntermediateTree))
115 intermediate.outputTree(parseContext.treeRoot);
116
117 if (success && (compileOptions & EShOptObjectCode))
118 translate(parseContext.treeRoot);
119
120 if (success && (compileOptions & EShOptAttribsUniforms))
121 collectAttribsUniforms(parseContext.treeRoot);
122 }
123
124 // Cleanup memory.
125 intermediate.remove(parseContext.treeRoot);
126 // Ensure symbol table is returned to the built-in level,
127 // throwing away all but the built-ins.
128 while (!symbolTable.atBuiltInLevel())
129 symbolTable.pop();
130 FinalizePreprocessor();
131
132 return success;
133}
134
135bool TCompiler::InitBuiltInSymbolTable(const TBuiltInResource& resources)
136{
137 TBuiltIns builtIns;
138
139 builtIns.initialize(language, spec, resources);
140 return InitializeSymbolTable(builtIns.getBuiltInStrings(), language, spec, resources, infoSink, symbolTable);
141}
142
143void TCompiler::clearResults()
144{
145 infoSink.info.erase();
146 infoSink.obj.erase();
147 infoSink.debug.erase();
148
149 attribs.clear();
150 uniforms.clear();
151}
152
153void TCompiler::collectAttribsUniforms(TIntermNode* root)
154{
155 CollectAttribsUniforms collect(attribs, uniforms);
156 root->traverse(&collect);
157}
158