blob: 7e8a835ff2a83268c6fa5da24748dbf26fd347fb [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,
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000013 ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
alokp@chromium.org07620a52010-09-23 17:53:56 +000014 TInfoSink& infoSink, TSymbolTable& symbolTable)
15{
16 TIntermediate intermediate(infoSink);
17 TExtensionBehavior extBehavior;
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000018 TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, infoSink);
alokp@chromium.org07620a52010-09-23 17:53:56 +000019
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
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000056 IdentifyBuiltIns(type, spec, resources, symbolTable);
alokp@chromium.org07620a52010-09-23 17:53:56 +000057
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
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000071TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
72 : shaderType(type),
73 shaderSpec(spec)
74{
75}
76
77TCompiler::~TCompiler()
78{
79}
80
81bool TCompiler::Init(const ShBuiltInResources& resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +000082{
83 // Generate built-in symbol table.
84 if (!InitBuiltInSymbolTable(resources))
85 return false;
86
87 InitExtensionBehavior(resources, extensionBehavior);
88 return true;
89}
90
91bool TCompiler::compile(const char* const shaderStrings[],
92 const int numStrings,
93 int compileOptions)
94{
95 clearResults();
96
97 if (numStrings == 0)
98 return true;
99
100 TIntermediate intermediate(infoSink);
101 TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000102 shaderType, shaderSpec, infoSink);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000103 GlobalParseContext = &parseContext;
104 setInitialState();
105
106 // Initialize preprocessor.
107 InitPreprocessor();
108 DefineExtensionMacros(extensionBehavior);
109
110 // We preserve symbols at the built-in level from compile-to-compile.
111 // Start pushing the user-defined symbols at global level.
112 symbolTable.push();
113 if (!symbolTable.atGlobalLevel())
114 infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
115
116 // Parse shader.
117 bool success =
118 (PaParseStrings(shaderStrings, 0, numStrings, parseContext) == 0) &&
119 (parseContext.treeRoot != NULL);
120 if (success) {
121 success = intermediate.postProcess(parseContext.treeRoot);
122
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000123 if (success && (compileOptions & SH_INTERMEDIATE_TREE))
alokp@chromium.org07620a52010-09-23 17:53:56 +0000124 intermediate.outputTree(parseContext.treeRoot);
125
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000126 if (success && (compileOptions & SH_OBJECT_CODE))
alokp@chromium.org07620a52010-09-23 17:53:56 +0000127 translate(parseContext.treeRoot);
128
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000129 if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS))
alokp@chromium.org07620a52010-09-23 17:53:56 +0000130 collectAttribsUniforms(parseContext.treeRoot);
131 }
132
133 // Cleanup memory.
134 intermediate.remove(parseContext.treeRoot);
135 // Ensure symbol table is returned to the built-in level,
136 // throwing away all but the built-ins.
137 while (!symbolTable.atBuiltInLevel())
138 symbolTable.pop();
139 FinalizePreprocessor();
140
141 return success;
142}
143
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000144bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000145{
146 TBuiltIns builtIns;
147
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000148 builtIns.initialize(shaderType, shaderSpec, resources);
149 return InitializeSymbolTable(builtIns.getBuiltInStrings(),
150 shaderType, shaderSpec, resources, infoSink, symbolTable);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000151}
152
153void TCompiler::clearResults()
154{
155 infoSink.info.erase();
156 infoSink.obj.erase();
157 infoSink.debug.erase();
158
159 attribs.clear();
160 uniforms.clear();
161}
162
163void TCompiler::collectAttribsUniforms(TIntermNode* root)
164{
165 CollectAttribsUniforms collect(attribs, uniforms);
166 root->traverse(&collect);
167}
168