- Moved the implementation for ShCompile to the compiler class so that internal details about compiler can be encapsulated. Now we do not need to expose built-in symbol table.
- Fixed a few const violations.
- Added CollectAttribsUniforms class.
BUG=26
Review URL: http://codereview.appspot.com/2263041
git-svn-id: https://angleproject.googlecode.com/svn/trunk@437 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/Compiler.cpp b/src/compiler/Compiler.cpp
new file mode 100644
index 0000000..6008f96
--- /dev/null
+++ b/src/compiler/Compiler.cpp
@@ -0,0 +1,158 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/Initialize.h"
+#include "compiler/ParseHelper.h"
+#include "compiler/ShHandle.h"
+
+static bool InitializeSymbolTable(
+ const TBuiltInStrings& builtInStrings,
+ EShLanguage language, EShSpec spec, const TBuiltInResource& resources,
+ TInfoSink& infoSink, TSymbolTable& symbolTable)
+{
+ TIntermediate intermediate(infoSink);
+ TExtensionBehavior extBehavior;
+ TParseContext parseContext(symbolTable, extBehavior, intermediate, language, spec, infoSink);
+
+ GlobalParseContext = &parseContext;
+
+ setInitialState();
+
+ assert(symbolTable.isEmpty());
+ //
+ // Parse the built-ins. This should only happen once per
+ // language symbol table.
+ //
+ // Push the symbol table to give it an initial scope. This
+ // push should not have a corresponding pop, so that built-ins
+ // are preserved, and the test for an empty table fails.
+ //
+ symbolTable.push();
+
+ //Initialize the Preprocessor
+ if (InitPreprocessor())
+ {
+ infoSink.info.message(EPrefixInternalError, "Unable to intialize the Preprocessor");
+ return false;
+ }
+
+ for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
+ {
+ const char* builtInShaders[1];
+ int builtInLengths[1];
+
+ builtInShaders[0] = (*i).c_str();
+ builtInLengths[0] = (int) (*i).size();
+
+ if (PaParseStrings(builtInShaders, builtInLengths, 1, parseContext) != 0)
+ {
+ infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
+ return false;
+ }
+ }
+
+ IdentifyBuiltIns(language, spec, resources, symbolTable);
+
+ FinalizePreprocessor();
+
+ return true;
+}
+
+static void DefineExtensionMacros(const TExtensionBehavior& extBehavior)
+{
+ for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
+ iter != extBehavior.end(); ++iter) {
+ PredefineIntMacro(iter->first.c_str(), 1);
+ }
+}
+
+bool TCompiler::Init(const TBuiltInResource& resources)
+{
+ // Generate built-in symbol table.
+ if (!InitBuiltInSymbolTable(resources))
+ return false;
+
+ InitExtensionBehavior(resources, extensionBehavior);
+ return true;
+}
+
+bool TCompiler::compile(const char* const shaderStrings[],
+ const int numStrings,
+ int compileOptions)
+{
+ clearResults();
+
+ if (numStrings == 0)
+ return true;
+
+ TIntermediate intermediate(infoSink);
+ TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
+ language, spec, infoSink);
+ GlobalParseContext = &parseContext;
+ setInitialState();
+
+ // Initialize preprocessor.
+ InitPreprocessor();
+ DefineExtensionMacros(extensionBehavior);
+
+ // We preserve symbols at the built-in level from compile-to-compile.
+ // Start pushing the user-defined symbols at global level.
+ symbolTable.push();
+ if (!symbolTable.atGlobalLevel())
+ infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
+
+ // Parse shader.
+ bool success =
+ (PaParseStrings(shaderStrings, 0, numStrings, parseContext) == 0) &&
+ (parseContext.treeRoot != NULL);
+ if (success) {
+ success = intermediate.postProcess(parseContext.treeRoot);
+
+ if (success && (compileOptions & EShOptIntermediateTree))
+ intermediate.outputTree(parseContext.treeRoot);
+
+ if (success && (compileOptions & EShOptObjectCode))
+ translate(parseContext.treeRoot);
+
+ if (success && (compileOptions & EShOptAttribsUniforms))
+ collectAttribsUniforms(parseContext.treeRoot);
+ }
+
+ // Cleanup memory.
+ intermediate.remove(parseContext.treeRoot);
+ // Ensure symbol table is returned to the built-in level,
+ // throwing away all but the built-ins.
+ while (!symbolTable.atBuiltInLevel())
+ symbolTable.pop();
+ FinalizePreprocessor();
+
+ return success;
+}
+
+bool TCompiler::InitBuiltInSymbolTable(const TBuiltInResource& resources)
+{
+ TBuiltIns builtIns;
+
+ builtIns.initialize(language, spec, resources);
+ return InitializeSymbolTable(builtIns.getBuiltInStrings(), language, spec, resources, infoSink, symbolTable);
+}
+
+void TCompiler::clearResults()
+{
+ infoSink.info.erase();
+ infoSink.obj.erase();
+ infoSink.debug.erase();
+
+ attribs.clear();
+ uniforms.clear();
+}
+
+void TCompiler::collectAttribsUniforms(TIntermNode* root)
+{
+ CollectAttribsUniforms collect(attribs, uniforms);
+ root->traverse(&collect);
+}
+