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