Commit 07620a58 by alokp@chromium.org

- Moved the implementation for ShCompile to the compiler class so that internal…

- 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
parent 36af61c5
......@@ -19,6 +19,7 @@
'sources': [
'compiler/BaseTypes.h',
'compiler/Common.h',
'compiler/Compiler.cpp',
'compiler/ConstantUnion.h',
'compiler/debug.cpp',
'compiler/debug.h',
......@@ -52,6 +53,8 @@
'compiler/SymbolTable.h',
'compiler/Types.h',
'compiler/unistd.h',
'compiler/VariableInfo.cpp',
'compiler/VariableInfo.h',
'compiler/preprocessor/atom.c',
'compiler/preprocessor/atom.h',
'compiler/preprocessor/compile.h',
......
//
// 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);
}
......@@ -631,7 +631,7 @@ TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expres
// This is to be executed once the final root is put on top by the parsing
// process.
//
bool TIntermediate::postProcess(TIntermNode* root, EShLanguage language)
bool TIntermediate::postProcess(TIntermNode* root)
{
if (root == 0)
return true;
......
......@@ -98,7 +98,7 @@ struct TParseContext {
bool AfterEOF;
};
int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext&);
int PaParseStrings(const char* const argv[], const int strLen[], int argc, TParseContext&);
void PaReservedWord();
int PaIdentOrType(TString& id, TParseContext&, TSymbol*&);
int PaParseComment(int &lineno, TParseContext&);
......
......@@ -19,9 +19,9 @@
#include "compiler/ExtensionBehavior.h"
#include "compiler/InfoSink.h"
#include "compiler/SymbolTable.h"
#include "compiler/VariableInfo.h"
class TCompiler;
class TIntermNode;
//
// The base class used to back handles returned to the driver.
......@@ -39,20 +39,31 @@ public:
//
class TCompiler : public TShHandleBase {
public:
TCompiler(EShLanguage l, EShSpec s) : language(l), spec(s) { }
virtual ~TCompiler() { }
EShLanguage getLanguage() const { return language; }
EShSpec getSpec() const { return spec; }
TSymbolTable& getSymbolTable() { return symbolTable; }
TExtensionBehavior& getExtensionBehavior() { return extensionBehavior; }
TInfoSink& getInfoSink() { return infoSink; }
TCompiler(EShLanguage l, EShSpec s) : language(l), spec(s) {}
virtual ~TCompiler() {}
virtual TCompiler* getAsCompiler() { return this; }
virtual bool compile(TIntermNode* root) = 0;
bool Init(const TBuiltInResource& resources);
bool compile(const char* const shaderStrings[],
const int numStrings,
int compileOptions);
virtual TCompiler* getAsCompiler() { return this; }
// Get results of the last compilation.
TInfoSink& getInfoSink() { return infoSink; }
const TVariableInfoList& getAttribs() const { return attribs; }
const TVariableInfoList& getUniforms() const { return uniforms; }
protected:
// Initialize symbol-table with built-in symbols.
bool InitBuiltInSymbolTable(const TBuiltInResource& resources);
// Clears the results from the previous compilation.
void clearResults();
// Collect info for all attribs and uniforms.
void collectAttribsUniforms(TIntermNode* root);
// Translate to object code.
virtual void translate(TIntermNode* root) = 0;
private:
EShLanguage language;
EShSpec spec;
......@@ -61,8 +72,11 @@ protected:
TSymbolTable symbolTable;
// Built-in extensions with default behavior.
TExtensionBehavior extensionBehavior;
// Output sink.
TInfoSink infoSink;
// Results of compilation.
TInfoSink infoSink; // Output sink.
TVariableInfoList attribs; // Active attributes in the compiled shader.
TVariableInfoList uniforms; // Active uniforms in the compiled shader.
};
//
......
......@@ -17,77 +17,6 @@
#include "compiler/ShHandle.h"
#include "compiler/SymbolTable.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 (builtInLengths[0] && PaParseStrings(const_cast<char**>(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 bool GenerateBuiltInSymbolTable(
EShLanguage language, EShSpec spec, const TBuiltInResource& resources,
TInfoSink& infoSink, TSymbolTable& symbolTable)
{
TBuiltIns builtIns;
builtIns.initialize(language, spec, resources);
return InitializeSymbolTable(builtIns.getBuiltInStrings(), language, spec, resources, infoSink, symbolTable);
}
static void DefineExtensionMacros(const TExtensionBehavior& extBehavior)
{
for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
iter != extBehavior.end(); ++iter) {
PredefineIntMacro(iter->first.c_str(), 1);
}
}
//
// This is the platform independent interface between an OGL driver
// and the shading language compiler.
......@@ -149,11 +78,10 @@ ShHandle ShConstructCompiler(EShLanguage language, EShSpec spec, const TBuiltInR
return 0;
// Generate built-in symbol table.
if (!GenerateBuiltInSymbolTable(language, spec, *resources, compiler->getInfoSink(), compiler->getSymbolTable())) {
if (!compiler->Init(*resources)) {
ShDestruct(base);
return 0;
}
InitExtensionBehavior(*resources, compiler->getExtensionBehavior());
return reinterpret_cast<void*>(base);
}
......@@ -192,79 +120,11 @@ int ShCompile(
TCompiler* compiler = base->getAsCompiler();
if (compiler == 0)
return 0;
GlobalPoolAllocator.push();
TInfoSink& infoSink = compiler->getInfoSink();
infoSink.info.erase();
infoSink.debug.erase();
infoSink.obj.erase();
if (numStrings == 0)
return 1;
TIntermediate intermediate(infoSink);
TSymbolTable& symbolTable = compiler->getSymbolTable();
const TExtensionBehavior& extBehavior = compiler->getExtensionBehavior();
TParseContext parseContext(symbolTable, extBehavior, intermediate,
compiler->getLanguage(), compiler->getSpec(), infoSink);
GlobalParseContext = &parseContext;
setInitialState();
InitPreprocessor();
DefineExtensionMacros(extBehavior);
//
// Parse the application's shaders. All the following symbol table
// work will be throw-away, so push a new allocation scope that can
// be thrown away, then push a scope for the current shader's globals.
//
bool success = true;
symbolTable.push();
if (!symbolTable.atGlobalLevel())
parseContext.infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
if (PaParseStrings(const_cast<char**>(shaderStrings), 0, numStrings, parseContext))
success = false;
if (success && parseContext.treeRoot) {
success = intermediate.postProcess(parseContext.treeRoot, parseContext.language);
if (success) {
if (compileOptions & EShOptIntermediateTree)
intermediate.outputTree(parseContext.treeRoot);
//
// Call the machine dependent compiler
//
if (compileOptions & EShOptObjectCode)
success = compiler->compile(parseContext.treeRoot);
// TODO(alokp): Extract attributes and uniforms.
//if (compileOptions & EShOptAttribsUniforms)
}
} else if (!success) {
parseContext.infoSink.info.prefix(EPrefixError);
parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n";
success = false;
if (compileOptions & EShOptIntermediateTree)
intermediate.outputTree(parseContext.treeRoot);
} else if (!parseContext.treeRoot) {
parseContext.error(1, "Unexpected end of file.", "", "");
parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n";
success = false;
}
intermediate.remove(parseContext.treeRoot);
GlobalPoolAllocator.push();
//
// Ensure symbol table is returned to the built-in level,
// throwing away all but the built-ins.
//
while (!symbolTable.atBuiltInLevel())
symbolTable.pop();
bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
FinalizePreprocessor();
//
// Throw away all the temporary memory used by the compilation process.
//
......
......@@ -12,9 +12,7 @@ TranslatorGLSL::TranslatorGLSL(EShLanguage lang, EShSpec spec)
: TCompiler(lang, spec) {
}
bool TranslatorGLSL::compile(TIntermNode* root) {
TOutputGLSL outputGLSL(infoSink.obj);
void TranslatorGLSL::translate(TIntermNode* root) {
TOutputGLSL outputGLSL(getInfoSink().obj);
root->traverse(&outputGLSL);
return true;
}
......@@ -12,7 +12,9 @@
class TranslatorGLSL : public TCompiler {
public:
TranslatorGLSL(EShLanguage lang, EShSpec spec);
virtual bool compile(TIntermNode* root);
protected:
virtual void translate(TIntermNode* root);
};
#endif // COMPILER_TRANSLATORGLSL_H_
......@@ -13,12 +13,10 @@ TranslatorHLSL::TranslatorHLSL(EShLanguage lang, EShSpec spec)
{
}
bool TranslatorHLSL::compile(TIntermNode *root)
void TranslatorHLSL::translate(TIntermNode *root)
{
TParseContext& parseContext = *GetGlobalParseContext();
sh::OutputHLSL outputHLSL(parseContext);
outputHLSL.output();
return true;
}
......@@ -12,7 +12,9 @@
class TranslatorHLSL : public TCompiler {
public:
TranslatorHLSL(EShLanguage lang, EShSpec spec);
virtual bool compile(TIntermNode* root);
protected:
virtual void translate(TIntermNode* root);
};
#endif // COMPILER_TRANSLATORHLSL_H_
//
// 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/VariableInfo.h"
CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs,
TVariableInfoList& uniforms)
: mAttribs(attribs),
mUniforms(uniforms)
{
}
// TODO(alokp): Implement these functions.
void CollectAttribsUniforms::visitSymbol(TIntermSymbol*)
{
}
void CollectAttribsUniforms::visitConstantUnion(TIntermConstantUnion*)
{
}
bool CollectAttribsUniforms::visitBinary(Visit visit, TIntermBinary*)
{
return false;
}
bool CollectAttribsUniforms::visitUnary(Visit visit, TIntermUnary*)
{
return false;
}
bool CollectAttribsUniforms::visitSelection(Visit visit, TIntermSelection*)
{
return false;
}
bool CollectAttribsUniforms::visitAggregate(Visit visit, TIntermAggregate*)
{
return false;
}
bool CollectAttribsUniforms::visitLoop(Visit visit, TIntermLoop*)
{
return false;
}
bool CollectAttribsUniforms::visitBranch(Visit visit, TIntermBranch*)
{
return false;
}
//
// 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 "GLSLANG/ShaderLang.h"
#include "compiler/intermediate.h"
// Provides information about a variable.
// It is currently being used to store info about active attribs and uniforms.
struct TVariableInfo {
TPersistString name;
EShDataType type;
int size;
};
typedef std::vector<TVariableInfo> TVariableInfoList;
// Traverses intermediate tree to collect all attributes and uniforms.
class CollectAttribsUniforms : public TIntermTraverser {
public:
CollectAttribsUniforms(TVariableInfoList& attribs,
TVariableInfoList& uniforms);
virtual void visitSymbol(TIntermSymbol*);
virtual void visitConstantUnion(TIntermConstantUnion*);
virtual bool visitBinary(Visit visit, TIntermBinary*);
virtual bool visitUnary(Visit visit, TIntermUnary*);
virtual bool visitSelection(Visit visit, TIntermSelection*);
virtual bool visitAggregate(Visit visit, TIntermAggregate*);
virtual bool visitLoop(Visit visit, TIntermLoop*);
virtual bool visitBranch(Visit visit, TIntermBranch*);
private:
TVariableInfoList& mAttribs;
TVariableInfoList& mUniforms;
};
......@@ -274,7 +274,7 @@ int yy_input(char* buf, int max_size)
//
// Returns 0 for success, as per yyparse().
//
int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseContextLocal)
int PaParseStrings(const char* const argv[], const int strLen[], int argc, TParseContext& parseContextLocal)
{
int argv0len;
......
......@@ -44,7 +44,7 @@ public:
TIntermBranch* addBranch(TOperator, TSourceLoc);
TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);
bool postProcess(TIntermNode*, EShLanguage);
bool postProcess(TIntermNode*);
void remove(TIntermNode*);
void outputTree(TIntermNode*);
......
......@@ -89,10 +89,10 @@ struct CPPStruct_Rec {
// Globals used to communicate between PaParseStrings() and yy_input()and
// also across the files.(gen_glslang.cpp and scanner.c)
//
int PaWhichStr; // which string we're parsing
int* PaStrLen; // array of lengths of the PaArgv strings
int PaArgc; // count of strings in the array
char** PaArgv; // our array of strings to parse
int PaWhichStr; // which string we're parsing
const int* PaStrLen; // array of lengths of the PaArgv strings
int PaArgc; // count of strings in the array
const char* const* PaArgv; // our array of strings to parse
unsigned int tokensBeforeEOF : 1;
};
......
......@@ -47,5 +47,5 @@ extern CPPStruct *cpp;
int InitCPPStruct(void);
int InitScanner(CPPStruct *cpp);
int InitAtomTable(AtomTable *atable, int htsize);
int ScanFromString(char *s);
int ScanFromString(const char *s);
char* GetStringOfAtom(AtomTable *atable, int atom);
......@@ -170,7 +170,7 @@ static void str_ungetch(StringInputSrc *in, int ch, yystypepp *type) {
}
} // str_ungetch
int ScanFromString(char *s)
int ScanFromString(const char *s)
{
StringInputSrc *in = malloc(sizeof(StringInputSrc));
......
......@@ -73,7 +73,7 @@ typedef struct InputSrc {
} InputSrc;
int InitScanner(CPPStruct *cpp); // Intialise the cpp scanner.
int ScanFromString(char *); // Start scanning the input from the string mentioned.
int ScanFromString(const char *); // Start scanning the input from the string mentioned.
int check_EOF(int); // check if we hit a EOF abruptly
void CPPErrorToInfoLog(char *); // sticking the msg,line into the Shader's.Info.log
void SetLineNumber(int);
......
......@@ -152,6 +152,10 @@
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\Compiler.cpp"
>
</File>
<File
RelativePath=".\debug.cpp"
>
</File>
......@@ -261,6 +265,10 @@
RelativePath=".\SymbolTable.cpp"
>
</File>
<File
RelativePath=".\VariableInfo.cpp"
>
</File>
<Filter
Name="preprocessor"
>
......@@ -403,6 +411,10 @@
RelativePath=".\unistd.h"
>
</File>
<File
RelativePath=".\VariableInfo.h"
>
</File>
<Filter
Name="preprocessor"
>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment