Commit 77ba408a by Olli Etuaho Committed by Commit Bot

Unify Diagnostics interface

Use the same kind of interface for reporting preprocessor errors as for reporting regular compiler errors, and make global errors like having too many uniforms also go through Diagnostics. Also don't create std::string objects unnecessarily. Includes cleanups of some dead code related to reporting errors. BUG=angleproject:1670 TEST=angle_unittests Change-Id: I3ee794d32ddeec1826bdf1b76b558f35259f82c0 Reviewed-on: https://chromium-review.googlesource.com/421527Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent a26c6b7c
...@@ -103,6 +103,7 @@ ...@@ -103,6 +103,7 @@
'compiler/translator/ScalarizeVecAndMatConstructorArgs.h', 'compiler/translator/ScalarizeVecAndMatConstructorArgs.h',
'compiler/translator/SearchSymbol.cpp', 'compiler/translator/SearchSymbol.cpp',
'compiler/translator/SearchSymbol.h', 'compiler/translator/SearchSymbol.h',
'compiler/translator/Severity.h',
'compiler/translator/ShaderLang.cpp', 'compiler/translator/ShaderLang.cpp',
'compiler/translator/ShaderVars.cpp', 'compiler/translator/ShaderVars.cpp',
'compiler/translator/SymbolTable.cpp', 'compiler/translator/SymbolTable.cpp',
......
...@@ -17,23 +17,22 @@ Diagnostics::~Diagnostics() ...@@ -17,23 +17,22 @@ Diagnostics::~Diagnostics()
void Diagnostics::report(ID id, const SourceLocation &loc, const std::string &text) void Diagnostics::report(ID id, const SourceLocation &loc, const std::string &text)
{ {
// TODO(alokp): Keep a count of errors and warnings.
print(id, loc, text); print(id, loc, text);
} }
Diagnostics::Severity Diagnostics::severity(ID id) bool Diagnostics::isError(ID id)
{ {
if ((id > PP_ERROR_BEGIN) && (id < PP_ERROR_END)) if ((id > PP_ERROR_BEGIN) && (id < PP_ERROR_END))
return PP_ERROR; return true;
if ((id > PP_WARNING_BEGIN) && (id < PP_WARNING_END)) if ((id > PP_WARNING_BEGIN) && (id < PP_WARNING_END))
return PP_WARNING; return false;
UNREACHABLE(); UNREACHABLE();
return PP_ERROR; return true;
} }
std::string Diagnostics::message(ID id) const char *Diagnostics::message(ID id)
{ {
switch (id) switch (id)
{ {
......
...@@ -19,11 +19,6 @@ struct SourceLocation; ...@@ -19,11 +19,6 @@ struct SourceLocation;
class Diagnostics class Diagnostics
{ {
public: public:
enum Severity
{
PP_ERROR,
PP_WARNING
};
enum ID enum ID
{ {
PP_ERROR_BEGIN, PP_ERROR_BEGIN,
...@@ -83,8 +78,8 @@ class Diagnostics ...@@ -83,8 +78,8 @@ class Diagnostics
void report(ID id, const SourceLocation &loc, const std::string &text); void report(ID id, const SourceLocation &loc, const std::string &text);
protected: protected:
Severity severity(ID id); bool isError(ID id);
std::string message(ID id); const char *message(ID id);
virtual void print(ID id, const SourceLocation &loc, const std::string &text) = 0; virtual void print(ID id, const SourceLocation &loc, const std::string &text) = 0;
}; };
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
// order. // order.
#include "compiler/translator/CallDAG.h" #include "compiler/translator/CallDAG.h"
#include "compiler/translator/InfoSink.h" #include "compiler/translator/Diagnostics.h"
namespace sh namespace sh
{ {
...@@ -19,9 +19,9 @@ namespace sh ...@@ -19,9 +19,9 @@ namespace sh
class CallDAG::CallDAGCreator : public TIntermTraverser class CallDAG::CallDAGCreator : public TIntermTraverser
{ {
public: public:
CallDAGCreator(TInfoSinkBase *info) CallDAGCreator(TDiagnostics *diagnostics)
: TIntermTraverser(true, false, true), : TIntermTraverser(true, false, true),
mCreationInfo(info), mDiagnostics(diagnostics),
mCurrentFunction(nullptr), mCurrentFunction(nullptr),
mCurrentIndex(0) mCurrentIndex(0)
{ {
...@@ -38,7 +38,6 @@ class CallDAG::CallDAGCreator : public TIntermTraverser ...@@ -38,7 +38,6 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
InitResult result = assignIndicesInternal(&it.second); InitResult result = assignIndicesInternal(&it.second);
if (result != INITDAG_SUCCESS) if (result != INITDAG_SUCCESS)
{ {
*mCreationInfo << "\n";
return result; return result;
} }
} }
...@@ -190,6 +189,8 @@ class CallDAG::CallDAGCreator : public TIntermTraverser ...@@ -190,6 +189,8 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
InitResult result = INITDAG_SUCCESS; InitResult result = INITDAG_SUCCESS;
std::stringstream errorStream;
while (!functionsToProcess.empty()) while (!functionsToProcess.empty())
{ {
CreatorFunctionData *function = functionsToProcess.back(); CreatorFunctionData *function = functionsToProcess.back();
...@@ -206,8 +207,8 @@ class CallDAG::CallDAGCreator : public TIntermTraverser ...@@ -206,8 +207,8 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
if (!function->node) if (!function->node)
{ {
*mCreationInfo << "Undefined function '" << function->name errorStream << "Undefined function '" << function->name
<< ")' used in the following call chain:"; << ")' used in the following call chain:";
result = INITDAG_UNDEFINED; result = INITDAG_UNDEFINED;
break; break;
} }
...@@ -228,7 +229,7 @@ class CallDAG::CallDAGCreator : public TIntermTraverser ...@@ -228,7 +229,7 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
// in the chain printed in the info log. // in the chain printed in the info log.
if (callee->visiting) if (callee->visiting)
{ {
*mCreationInfo << "Recursive function call in the following call chain:"; errorStream << "Recursive function call in the following call chain:";
result = INITDAG_RECURSION; result = INITDAG_RECURSION;
break; break;
} }
...@@ -250,18 +251,23 @@ class CallDAG::CallDAGCreator : public TIntermTraverser ...@@ -250,18 +251,23 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
{ {
if (!first) if (!first)
{ {
*mCreationInfo << " -> "; errorStream << " -> ";
} }
*mCreationInfo << function->name << ")"; errorStream << function->name << ")";
first = false; first = false;
} }
} }
if (mDiagnostics)
{
std::string errorStr = errorStream.str();
mDiagnostics->globalError(errorStr.c_str());
}
} }
return result; return result;
} }
TInfoSinkBase *mCreationInfo; TDiagnostics *mDiagnostics;
std::map<TString, CreatorFunctionData> mFunctions; std::map<TString, CreatorFunctionData> mFunctions;
CreatorFunctionData *mCurrentFunction; CreatorFunctionData *mCurrentFunction;
...@@ -318,11 +324,9 @@ void CallDAG::clear() ...@@ -318,11 +324,9 @@ void CallDAG::clear()
mFunctionIdToIndex.clear(); mFunctionIdToIndex.clear();
} }
CallDAG::InitResult CallDAG::init(TIntermNode *root, TInfoSinkBase *info) CallDAG::InitResult CallDAG::init(TIntermNode *root, TDiagnostics *diagnostics)
{ {
ASSERT(info); CallDAGCreator creator(diagnostics);
CallDAGCreator creator(info);
// Creates the mapping of functions to callees // Creates the mapping of functions to callees
root->traverse(&creator); root->traverse(&creator);
......
...@@ -55,8 +55,8 @@ class CallDAG : angle::NonCopyable ...@@ -55,8 +55,8 @@ class CallDAG : angle::NonCopyable
}; };
// Returns INITDAG_SUCCESS if it was able to create the DAG, otherwise prints // Returns INITDAG_SUCCESS if it was able to create the DAG, otherwise prints
// the initialization error in info, if present. // the initialization error in diagnostics, if present.
InitResult init(TIntermNode *root, TInfoSinkBase *info); InitResult init(TIntermNode *root, TDiagnostics *diagnostics);
// Returns InvalidIndex if the function wasn't found // Returns InvalidIndex if the function wasn't found
size_t findIndex(const TFunctionSymbolInfo *functionInfo) const; size_t findIndex(const TFunctionSymbolInfo *functionInfo) const;
......
...@@ -215,6 +215,7 @@ TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) ...@@ -215,6 +215,7 @@ TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
fragmentPrecisionHigh(false), fragmentPrecisionHigh(false),
clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC), clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
builtInFunctionEmulator(), builtInFunctionEmulator(),
mDiagnostics(infoSink.info),
mSourcePath(NULL), mSourcePath(NULL),
mComputeShaderLocalSizeDeclared(false), mComputeShaderLocalSizeDeclared(false),
mTemporaryIndex(0) mTemporaryIndex(0)
...@@ -288,7 +289,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], ...@@ -288,7 +289,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
} }
TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec, TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec,
compileOptions, true, infoSink, getResources()); compileOptions, true, &mDiagnostics, getResources());
parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh); parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh);
SetGlobalParseContext(&parseContext); SetGlobalParseContext(&parseContext);
...@@ -305,8 +306,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], ...@@ -305,8 +306,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
shaderVersion = parseContext.getShaderVersion(); shaderVersion = parseContext.getShaderVersion();
if (success && MapSpecToShaderVersion(shaderSpec) < shaderVersion) if (success && MapSpecToShaderVersion(shaderSpec) < shaderVersion)
{ {
infoSink.info.prefix(EPrefixError); mDiagnostics.globalError("unsupported shader version");
infoSink.info << "unsupported shader version";
success = false; success = false;
} }
...@@ -364,8 +364,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], ...@@ -364,8 +364,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
{ {
if (!EmulatePrecision::SupportedInLanguage(outputType)) if (!EmulatePrecision::SupportedInLanguage(outputType))
{ {
infoSink.info.prefix(EPrefixError); mDiagnostics.globalError("Precision emulation not supported for this output type.");
infoSink.info << "Precision emulation not supported for this output type.";
success = false; success = false;
} }
} }
...@@ -424,8 +423,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], ...@@ -424,8 +423,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
success = enforcePackingRestrictions(); success = enforcePackingRestrictions();
if (!success) if (!success)
{ {
infoSink.info.prefix(EPrefixError); mDiagnostics.globalError("too many uniforms");
infoSink.info << "too many uniforms";
} }
} }
if (success && (compileOptions & SH_INIT_OUTPUT_VARIABLES)) if (success && (compileOptions & SH_INIT_OUTPUT_VARIABLES))
...@@ -642,6 +640,7 @@ void TCompiler::clearResults() ...@@ -642,6 +640,7 @@ void TCompiler::clearResults()
infoSink.info.erase(); infoSink.info.erase();
infoSink.obj.erase(); infoSink.obj.erase();
infoSink.debug.erase(); infoSink.debug.erase();
mDiagnostics.resetErrorCount();
attributes.clear(); attributes.clear();
outputVariables.clear(); outputVariables.clear();
...@@ -663,17 +662,14 @@ bool TCompiler::initCallDag(TIntermNode *root) ...@@ -663,17 +662,14 @@ bool TCompiler::initCallDag(TIntermNode *root)
{ {
mCallDag.clear(); mCallDag.clear();
switch (mCallDag.init(root, &infoSink.info)) switch (mCallDag.init(root, &mDiagnostics))
{ {
case CallDAG::INITDAG_SUCCESS: case CallDAG::INITDAG_SUCCESS:
return true; return true;
case CallDAG::INITDAG_RECURSION: case CallDAG::INITDAG_RECURSION:
infoSink.info.prefix(EPrefixError);
infoSink.info << "Function recursion detected";
return false;
case CallDAG::INITDAG_UNDEFINED: case CallDAG::INITDAG_UNDEFINED:
infoSink.info.prefix(EPrefixError); // Error message has already been written out.
infoSink.info << "Unimplemented function detected"; ASSERT(mDiagnostics.numErrors() > 0);
return false; return false;
} }
...@@ -700,16 +696,16 @@ bool TCompiler::checkCallDepth() ...@@ -700,16 +696,16 @@ bool TCompiler::checkCallDepth()
if (depth >= maxCallStackDepth) if (depth >= maxCallStackDepth)
{ {
// Trace back the function chain to have a meaningful info log. // Trace back the function chain to have a meaningful info log.
infoSink.info.prefix(EPrefixError); std::stringstream errorStream;
infoSink.info << "Call stack too deep (larger than " << maxCallStackDepth errorStream << "Call stack too deep (larger than " << maxCallStackDepth
<< ") with the following call chain: " << record.name; << ") with the following call chain: " << record.name;
int currentFunction = static_cast<int>(i); int currentFunction = static_cast<int>(i);
int currentDepth = depth; int currentDepth = depth;
while (currentFunction != -1) while (currentFunction != -1)
{ {
infoSink.info << " -> " << mCallDag.getRecordFromIndex(currentFunction).name; errorStream << " -> " << mCallDag.getRecordFromIndex(currentFunction).name;
int nextFunction = -1; int nextFunction = -1;
for (auto &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees) for (auto &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
...@@ -724,6 +720,9 @@ bool TCompiler::checkCallDepth() ...@@ -724,6 +720,9 @@ bool TCompiler::checkCallDepth()
currentFunction = nextFunction; currentFunction = nextFunction;
} }
std::string errorStr = errorStream.str();
mDiagnostics.globalError(errorStr.c_str());
return false; return false;
} }
} }
...@@ -743,8 +742,7 @@ bool TCompiler::tagUsedFunctions() ...@@ -743,8 +742,7 @@ bool TCompiler::tagUsedFunctions()
} }
} }
infoSink.info.prefix(EPrefixError); mDiagnostics.globalError("Missing main()");
infoSink.info << "Missing main()\n";
return false; return false;
} }
...@@ -830,14 +828,15 @@ bool TCompiler::validateOutputs(TIntermNode *root) ...@@ -830,14 +828,15 @@ bool TCompiler::validateOutputs(TIntermNode *root)
{ {
ValidateOutputs validateOutputs(getExtensionBehavior(), compileResources.MaxDrawBuffers); ValidateOutputs validateOutputs(getExtensionBehavior(), compileResources.MaxDrawBuffers);
root->traverse(&validateOutputs); root->traverse(&validateOutputs);
return (validateOutputs.validateAndCountErrors(infoSink.info) == 0); validateOutputs.validate(&mDiagnostics);
return (mDiagnostics.numErrors() == 0);
} }
bool TCompiler::validateLimitations(TIntermNode *root) bool TCompiler::validateLimitations(TIntermNode *root)
{ {
ValidateLimitations validate(shaderType, &infoSink.info); ValidateLimitations validate(shaderType, &mDiagnostics);
root->traverse(&validate); root->traverse(&validate);
return validate.numErrors() == 0; return mDiagnostics.numErrors() == 0;
} }
bool TCompiler::limitExpressionComplexity(TIntermNode *root) bool TCompiler::limitExpressionComplexity(TIntermNode *root)
...@@ -847,13 +846,13 @@ bool TCompiler::limitExpressionComplexity(TIntermNode *root) ...@@ -847,13 +846,13 @@ bool TCompiler::limitExpressionComplexity(TIntermNode *root)
if (traverser.getMaxDepth() > maxExpressionComplexity) if (traverser.getMaxDepth() > maxExpressionComplexity)
{ {
infoSink.info << "Expression too complex."; mDiagnostics.globalError("Expression too complex.");
return false; return false;
} }
if (!ValidateMaxParameters::validate(root, maxFunctionParameters)) if (!ValidateMaxParameters::validate(root, maxFunctionParameters))
{ {
infoSink.info << "Function has too many parameters."; mDiagnostics.globalError("Function has too many parameters.");
return false; return false;
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/CallDAG.h" #include "compiler/translator/CallDAG.h"
#include "compiler/translator/Diagnostics.h"
#include "compiler/translator/ExtensionBehavior.h" #include "compiler/translator/ExtensionBehavior.h"
#include "compiler/translator/HashNames.h" #include "compiler/translator/HashNames.h"
#include "compiler/translator/InfoSink.h" #include "compiler/translator/InfoSink.h"
...@@ -239,6 +240,7 @@ class TCompiler : public TShHandleBase ...@@ -239,6 +240,7 @@ class TCompiler : public TShHandleBase
// Results of compilation. // Results of compilation.
int shaderVersion; int shaderVersion;
TInfoSink infoSink; // Output sink. TInfoSink infoSink; // Output sink.
TDiagnostics mDiagnostics;
const char *mSourcePath; // Path of source file or NULL const char *mSourcePath; // Path of source file or NULL
// compute shader local group size // compute shader local group size
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
namespace sh namespace sh
{ {
TDiagnostics::TDiagnostics(TInfoSink &infoSink) TDiagnostics::TDiagnostics(TInfoSinkBase &infoSink)
: mInfoSink(infoSink), mNumErrors(0), mNumWarnings(0) : mInfoSink(infoSink), mNumErrors(0), mNumWarnings(0)
{ {
} }
...@@ -25,30 +25,43 @@ TDiagnostics::~TDiagnostics() ...@@ -25,30 +25,43 @@ TDiagnostics::~TDiagnostics()
void TDiagnostics::writeInfo(Severity severity, void TDiagnostics::writeInfo(Severity severity,
const pp::SourceLocation &loc, const pp::SourceLocation &loc,
const std::string &reason, const char *reason,
const std::string &token) const char *token)
{ {
TPrefixType prefix = EPrefixNone;
switch (severity) switch (severity)
{ {
case PP_ERROR: case SH_ERROR:
++mNumErrors; ++mNumErrors;
prefix = EPrefixError;
break; break;
case PP_WARNING: case SH_WARNING:
++mNumWarnings; ++mNumWarnings;
prefix = EPrefixWarning;
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
} }
TInfoSinkBase &sink = mInfoSink.info;
/* VC++ format: file(linenum) : error #: 'token' : extrainfo */ /* VC++ format: file(linenum) : error #: 'token' : extrainfo */
sink.prefix(prefix); mInfoSink.prefix(severity);
sink.location(loc.file, loc.line); mInfoSink.location(loc.file, loc.line);
sink << "'" << token << "' : " << reason << "\n"; mInfoSink << "'" << token << "' : " << reason << "\n";
}
void TDiagnostics::globalError(const char *message)
{
++mNumErrors;
mInfoSink.prefix(SH_ERROR);
mInfoSink << message << "\n";
}
void TDiagnostics::error(const pp::SourceLocation &loc, const char *reason, const char *token)
{
writeInfo(SH_ERROR, loc, reason, token);
}
void TDiagnostics::warning(const pp::SourceLocation &loc, const char *reason, const char *token)
{
writeInfo(SH_WARNING, loc, reason, token);
} }
void TDiagnostics::error(const TSourceLoc &loc, const char *reason, const char *token) void TDiagnostics::error(const TSourceLoc &loc, const char *reason, const char *token)
...@@ -56,7 +69,7 @@ void TDiagnostics::error(const TSourceLoc &loc, const char *reason, const char * ...@@ -56,7 +69,7 @@ void TDiagnostics::error(const TSourceLoc &loc, const char *reason, const char *
pp::SourceLocation srcLoc; pp::SourceLocation srcLoc;
srcLoc.file = loc.first_file; srcLoc.file = loc.first_file;
srcLoc.line = loc.first_line; srcLoc.line = loc.first_line;
writeInfo(pp::Diagnostics::PP_ERROR, srcLoc, reason, token); error(srcLoc, reason, token);
} }
void TDiagnostics::warning(const TSourceLoc &loc, const char *reason, const char *token) void TDiagnostics::warning(const TSourceLoc &loc, const char *reason, const char *token)
...@@ -64,12 +77,18 @@ void TDiagnostics::warning(const TSourceLoc &loc, const char *reason, const char ...@@ -64,12 +77,18 @@ void TDiagnostics::warning(const TSourceLoc &loc, const char *reason, const char
pp::SourceLocation srcLoc; pp::SourceLocation srcLoc;
srcLoc.file = loc.first_file; srcLoc.file = loc.first_file;
srcLoc.line = loc.first_line; srcLoc.line = loc.first_line;
writeInfo(pp::Diagnostics::PP_WARNING, srcLoc, reason, token); warning(srcLoc, reason, token);
} }
void TDiagnostics::print(ID id, const pp::SourceLocation &loc, const std::string &text) void TDiagnostics::print(ID id, const pp::SourceLocation &loc, const std::string &text)
{ {
writeInfo(severity(id), loc, message(id), text); writeInfo(isError(id) ? SH_ERROR : SH_WARNING, loc, message(id), text.c_str());
}
void TDiagnostics::resetErrorCount()
{
mNumErrors = 0;
mNumWarnings = 0;
} }
} // namespace sh } // namespace sh
...@@ -9,37 +9,43 @@ ...@@ -9,37 +9,43 @@
#include "common/angleutils.h" #include "common/angleutils.h"
#include "compiler/preprocessor/DiagnosticsBase.h" #include "compiler/preprocessor/DiagnosticsBase.h"
#include "compiler/translator/Severity.h"
namespace sh namespace sh
{ {
class TInfoSink; class TInfoSinkBase;
struct TSourceLoc; struct TSourceLoc;
class TDiagnostics : public pp::Diagnostics, angle::NonCopyable class TDiagnostics : public pp::Diagnostics, angle::NonCopyable
{ {
public: public:
TDiagnostics(TInfoSink &infoSink); TDiagnostics(TInfoSinkBase &infoSink);
~TDiagnostics() override; ~TDiagnostics() override;
TInfoSink &infoSink() { return mInfoSink; }
int numErrors() const { return mNumErrors; } int numErrors() const { return mNumErrors; }
int numWarnings() const { return mNumWarnings; } int numWarnings() const { return mNumWarnings; }
void writeInfo(Severity severity, void error(const pp::SourceLocation &loc, const char *reason, const char *token);
const pp::SourceLocation &loc, void warning(const pp::SourceLocation &loc, const char *reason, const char *token);
const std::string &reason,
const std::string &token);
void error(const TSourceLoc &loc, const char *reason, const char *token); void error(const TSourceLoc &loc, const char *reason, const char *token);
void warning(const TSourceLoc &loc, const char *reason, const char *token); void warning(const TSourceLoc &loc, const char *reason, const char *token);
void globalError(const char *message);
void resetErrorCount();
protected: protected:
void writeInfo(Severity severity,
const pp::SourceLocation &loc,
const char *reason,
const char *token);
void print(ID id, const pp::SourceLocation &loc, const std::string &text) override; void print(ID id, const pp::SourceLocation &loc, const std::string &text) override;
private: private:
TInfoSink &mInfoSink; TInfoSinkBase &mInfoSink;
int mNumErrors; int mNumErrors;
int mNumWarnings; int mNumWarnings;
}; };
......
...@@ -52,7 +52,7 @@ TDirectiveHandler::~TDirectiveHandler() ...@@ -52,7 +52,7 @@ TDirectiveHandler::~TDirectiveHandler()
void TDirectiveHandler::handleError(const pp::SourceLocation &loc, const std::string &msg) void TDirectiveHandler::handleError(const pp::SourceLocation &loc, const std::string &msg)
{ {
mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, msg, ""); mDiagnostics.error(loc, msg.c_str(), "");
} }
void TDirectiveHandler::handlePragma(const pp::SourceLocation &loc, void TDirectiveHandler::handlePragma(const pp::SourceLocation &loc,
...@@ -70,9 +70,9 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation &loc, ...@@ -70,9 +70,9 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation &loc,
if (mShaderVersion == 300 && mShaderType == GL_FRAGMENT_SHADER) if (mShaderVersion == 300 && mShaderType == GL_FRAGMENT_SHADER)
{ {
// ESSL 3.00.4 section 4.6.1 // ESSL 3.00.4 section 4.6.1
mDiagnostics.writeInfo( mDiagnostics.error(
pp::Diagnostics::PP_ERROR, loc, loc, "#pragma STDGL invariant(all) can not be used in fragment shader",
"#pragma STDGL invariant(all) can not be used in fragment shader", name); name.c_str());
} }
mPragma.stdgl.invariantAll = true; mPragma.stdgl.invariantAll = true;
} }
...@@ -125,8 +125,7 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation &loc, ...@@ -125,8 +125,7 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation &loc,
if (invalidValue) if (invalidValue)
{ {
mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, mDiagnostics.error(loc, "invalid pragma value - 'on' or 'off' expected", value.c_str());
"invalid pragma value - 'on' or 'off' expected", value);
} }
} }
} }
...@@ -140,7 +139,7 @@ void TDirectiveHandler::handleExtension(const pp::SourceLocation &loc, ...@@ -140,7 +139,7 @@ void TDirectiveHandler::handleExtension(const pp::SourceLocation &loc,
TBehavior behaviorVal = getBehavior(behavior); TBehavior behaviorVal = getBehavior(behavior);
if (behaviorVal == EBhUndefined) if (behaviorVal == EBhUndefined)
{ {
mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, "behavior invalid", name); mDiagnostics.error(loc, "behavior invalid", name.c_str());
return; return;
} }
...@@ -148,13 +147,11 @@ void TDirectiveHandler::handleExtension(const pp::SourceLocation &loc, ...@@ -148,13 +147,11 @@ void TDirectiveHandler::handleExtension(const pp::SourceLocation &loc,
{ {
if (behaviorVal == EBhRequire) if (behaviorVal == EBhRequire)
{ {
mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, mDiagnostics.error(loc, "extension cannot have 'require' behavior", name.c_str());
"extension cannot have 'require' behavior", name);
} }
else if (behaviorVal == EBhEnable) else if (behaviorVal == EBhEnable)
{ {
mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, mDiagnostics.error(loc, "extension cannot have 'enable' behavior", name.c_str());
"extension cannot have 'enable' behavior", name);
} }
else else
{ {
...@@ -172,22 +169,20 @@ void TDirectiveHandler::handleExtension(const pp::SourceLocation &loc, ...@@ -172,22 +169,20 @@ void TDirectiveHandler::handleExtension(const pp::SourceLocation &loc,
return; return;
} }
pp::Diagnostics::Severity severity = pp::Diagnostics::PP_ERROR;
switch (behaviorVal) switch (behaviorVal)
{ {
case EBhRequire: case EBhRequire:
severity = pp::Diagnostics::PP_ERROR; mDiagnostics.error(loc, "extension is not supported", name.c_str());
break; break;
case EBhEnable: case EBhEnable:
case EBhWarn: case EBhWarn:
case EBhDisable: case EBhDisable:
severity = pp::Diagnostics::PP_WARNING; mDiagnostics.warning(loc, "extension is not supported", name.c_str());
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
} }
mDiagnostics.writeInfo(severity, loc, "extension is not supported", name);
} }
void TDirectiveHandler::handleVersion(const pp::SourceLocation &loc, int version) void TDirectiveHandler::handleVersion(const pp::SourceLocation &loc, int version)
...@@ -201,7 +196,7 @@ void TDirectiveHandler::handleVersion(const pp::SourceLocation &loc, int version ...@@ -201,7 +196,7 @@ void TDirectiveHandler::handleVersion(const pp::SourceLocation &loc, int version
std::stringstream stream; std::stringstream stream;
stream << version; stream << version;
std::string str = stream.str(); std::string str = stream.str();
mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, "version number not supported", str); mDiagnostics.error(loc, "version number not supported", str.c_str());
} }
} }
......
...@@ -9,27 +9,16 @@ ...@@ -9,27 +9,16 @@
namespace sh namespace sh
{ {
void TInfoSinkBase::prefix(TPrefixType p) void TInfoSinkBase::prefix(Severity severity)
{ {
switch (p) switch (severity)
{ {
case EPrefixNone: case SH_WARNING:
break;
case EPrefixWarning:
sink.append("WARNING: "); sink.append("WARNING: ");
break; break;
case EPrefixError: case SH_ERROR:
sink.append("ERROR: "); sink.append("ERROR: ");
break; break;
case EPrefixInternalError:
sink.append("INTERNAL ERROR: ");
break;
case EPrefixUnimplemented:
sink.append("UNIMPLEMENTED: ");
break;
case EPrefixNote:
sink.append("NOTE: ");
break;
default: default:
sink.append("UNKOWN ERROR: "); sink.append("UNKOWN ERROR: ");
break; break;
...@@ -48,17 +37,4 @@ void TInfoSinkBase::location(int file, int line) ...@@ -48,17 +37,4 @@ void TInfoSinkBase::location(int file, int line)
sink.append(stream.str()); sink.append(stream.str());
} }
void TInfoSinkBase::location(const TSourceLoc &loc)
{
location(loc.first_file, loc.first_line);
}
void TInfoSinkBase::message(TPrefixType p, const TSourceLoc &loc, const char *m)
{
prefix(p);
location(loc);
sink.append(m);
sink.append("\n");
}
} // namespace sh } // namespace sh
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include "compiler/translator/Common.h" #include "compiler/translator/Common.h"
#include "compiler/translator/Severity.h"
namespace sh namespace sh
{ {
...@@ -22,20 +23,6 @@ inline float fractionalPart(float f) ...@@ -22,20 +23,6 @@ inline float fractionalPart(float f)
} }
// //
// TPrefixType is used to centralize how info log messages start.
// See below.
//
enum TPrefixType
{
EPrefixNone,
EPrefixWarning,
EPrefixError,
EPrefixInternalError,
EPrefixUnimplemented,
EPrefixNote
};
//
// Encapsulate info logs for all objects that have them. // Encapsulate info logs for all objects that have them.
// //
// The methods are a general set of tools for getting a variety of // The methods are a general set of tools for getting a variety of
...@@ -113,10 +100,8 @@ class TInfoSinkBase ...@@ -113,10 +100,8 @@ class TInfoSinkBase
const TPersistString &str() const { return sink; } const TPersistString &str() const { return sink; }
const char *c_str() const { return sink.c_str(); } const char *c_str() const { return sink.c_str(); }
void prefix(TPrefixType p); void prefix(Severity severity);
void location(int file, int line); void location(int file, int line);
void location(const TSourceLoc &loc);
void message(TPrefixType p, const TSourceLoc &loc, const char *m);
private: private:
TPersistString sink; TPersistString sink;
......
...@@ -176,7 +176,7 @@ void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink) ...@@ -176,7 +176,7 @@ void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink)
builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(treeRoot); builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(treeRoot);
// Now that we are done changing the AST, do the analyses need for HLSL generation // Now that we are done changing the AST, do the analyses need for HLSL generation
CallDAG::InitResult success = mCallDag.init(treeRoot, &objSink); CallDAG::InitResult success = mCallDag.init(treeRoot, nullptr);
ASSERT(success == CallDAG::INITDAG_SUCCESS); ASSERT(success == CallDAG::INITDAG_SUCCESS);
mASTMetadataList = CreateASTMetadataHLSL(treeRoot, mCallDag); mASTMetadataList = CreateASTMetadataHLSL(treeRoot, mCallDag);
......
...@@ -74,7 +74,7 @@ TParseContext::TParseContext(TSymbolTable &symt, ...@@ -74,7 +74,7 @@ TParseContext::TParseContext(TSymbolTable &symt,
ShShaderSpec spec, ShShaderSpec spec,
ShCompileOptions options, ShCompileOptions options,
bool checksPrecErrors, bool checksPrecErrors,
TInfoSink &is, TDiagnostics *diagnostics,
const ShBuiltInResources &resources) const ShBuiltInResources &resources)
: intermediate(), : intermediate(),
symbolTable(symt), symbolTable(symt),
...@@ -93,13 +93,13 @@ TParseContext::TParseContext(TSymbolTable &symt, ...@@ -93,13 +93,13 @@ TParseContext::TParseContext(TSymbolTable &symt,
mFragmentPrecisionHighOnESSL1(false), mFragmentPrecisionHighOnESSL1(false),
mDefaultMatrixPacking(EmpColumnMajor), mDefaultMatrixPacking(EmpColumnMajor),
mDefaultBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared), mDefaultBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
mDiagnostics(is), mDiagnostics(diagnostics),
mDirectiveHandler(ext, mDirectiveHandler(ext,
mDiagnostics, *mDiagnostics,
mShaderVersion, mShaderVersion,
mShaderType, mShaderType,
resources.WEBGL_debug_shader_precision == 1), resources.WEBGL_debug_shader_precision == 1),
mPreprocessor(&mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()), mPreprocessor(mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()),
mScanner(nullptr), mScanner(nullptr),
mUsesFragData(false), mUsesFragData(false),
mUsesFragColor(false), mUsesFragColor(false),
...@@ -227,12 +227,12 @@ bool TParseContext::parseVectorFields(const TString &compString, ...@@ -227,12 +227,12 @@ bool TParseContext::parseVectorFields(const TString &compString,
// //
void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token) void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token)
{ {
mDiagnostics.error(loc, reason, token); mDiagnostics->error(loc, reason, token);
} }
void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token) void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token)
{ {
mDiagnostics.warning(loc, reason, token); mDiagnostics->warning(loc, reason, token);
} }
void TParseContext::outOfRangeError(bool isError, void TParseContext::outOfRangeError(bool isError,
...@@ -1049,7 +1049,7 @@ void TParseContext::checkIsParameterQualifierValid( ...@@ -1049,7 +1049,7 @@ void TParseContext::checkIsParameterQualifierValid(
const TTypeQualifierBuilder &typeQualifierBuilder, const TTypeQualifierBuilder &typeQualifierBuilder,
TType *type) TType *type)
{ {
TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(&mDiagnostics); TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics);
if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut) if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
{ {
...@@ -1688,7 +1688,7 @@ void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier) ...@@ -1688,7 +1688,7 @@ void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder, TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
const TPublicType &typeSpecifier) const TPublicType &typeSpecifier)
{ {
TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics); TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
TPublicType returnType = typeSpecifier; TPublicType returnType = typeSpecifier;
returnType.qualifier = typeQualifier.qualifier; returnType.qualifier = typeQualifier.qualifier;
...@@ -2052,7 +2052,7 @@ TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration( ...@@ -2052,7 +2052,7 @@ TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
const TString *identifier, const TString *identifier,
const TSymbol *symbol) const TSymbol *symbol)
{ {
TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics); TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
if (!typeQualifier.invariant) if (!typeQualifier.invariant)
{ {
...@@ -2242,7 +2242,7 @@ void TParseContext::parseArrayInitDeclarator(const TPublicType &publicType, ...@@ -2242,7 +2242,7 @@ void TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder) void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
{ {
TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics); TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier; const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier, checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
...@@ -2627,7 +2627,7 @@ TFunction *TParseContext::parseFunctionHeader(const TPublicType &type, ...@@ -2627,7 +2627,7 @@ TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
{ {
// Array return values are forbidden, but there's also no valid syntax for declaring array // Array return values are forbidden, but there's also no valid syntax for declaring array
// return values in ESSL 1.00. // return values in ESSL 1.00.
ASSERT(type.arraySize == 0 || mDiagnostics.numErrors() > 0); ASSERT(type.arraySize == 0 || mDiagnostics->numErrors() > 0);
if (type.isStructureContainingArrays()) if (type.isStructureContainingArrays())
{ {
...@@ -2730,7 +2730,7 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, ...@@ -2730,7 +2730,7 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments,
constructor->setType(type); constructor->setType(type);
TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor, &mDiagnostics); TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor, mDiagnostics);
if (constConstructor) if (constConstructor)
{ {
return constConstructor; return constConstructor;
...@@ -2754,7 +2754,7 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( ...@@ -2754,7 +2754,7 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
{ {
checkIsNotReserved(nameLine, blockName); checkIsNotReserved(nameLine, blockName);
TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics); TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
if (typeQualifier.qualifier != EvqUniform) if (typeQualifier.qualifier != EvqUniform)
{ {
...@@ -3075,12 +3075,12 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, ...@@ -3075,12 +3075,12 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
} }
return intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location, return intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location,
&mDiagnostics); mDiagnostics);
} }
else else
{ {
return intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location, return intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location,
&mDiagnostics); mDiagnostics);
} }
} }
...@@ -3156,7 +3156,7 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre ...@@ -3156,7 +3156,7 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
TIntermTyped *index = TIntermTyped::CreateIndexNode(i); TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
index->setLine(fieldLocation); index->setLine(fieldLocation);
return intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index, return intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index,
dotLocation, &mDiagnostics); dotLocation, mDiagnostics);
} }
else else
{ {
...@@ -3190,7 +3190,7 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre ...@@ -3190,7 +3190,7 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
TIntermTyped *index = TIntermTyped::CreateIndexNode(i); TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
index->setLine(fieldLocation); index->setLine(fieldLocation);
return intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index, return intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
dotLocation, &mDiagnostics); dotLocation, mDiagnostics);
} }
else else
{ {
...@@ -3406,7 +3406,7 @@ TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualif ...@@ -3406,7 +3406,7 @@ TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualif
const TSourceLoc &rightQualifierLocation) const TSourceLoc &rightQualifierLocation)
{ {
return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation, return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
&mDiagnostics); mDiagnostics);
} }
TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields, TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
...@@ -3432,7 +3432,7 @@ TFieldList *TParseContext::addStructDeclaratorListWithQualifiers( ...@@ -3432,7 +3432,7 @@ TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
TPublicType *typeSpecifier, TPublicType *typeSpecifier,
TFieldList *fieldList) TFieldList *fieldList)
{ {
TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics); TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
typeSpecifier->qualifier = typeQualifier.qualifier; typeSpecifier->qualifier = typeQualifier.qualifier;
typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier; typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
...@@ -3563,7 +3563,7 @@ TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init, ...@@ -3563,7 +3563,7 @@ TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
if (statementList) if (statementList)
{ {
if (!ValidateSwitchStatementList(switchType, &mDiagnostics, statementList, loc)) if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
{ {
return nullptr; return nullptr;
} }
...@@ -3673,7 +3673,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op, ...@@ -3673,7 +3673,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
TIntermUnary *node = new TIntermUnary(op, child); TIntermUnary *node = new TIntermUnary(op, child);
node->setLine(loc); node->setLine(loc);
TIntermTyped *foldedNode = node->fold(&mDiagnostics); TIntermTyped *foldedNode = node->fold(mDiagnostics);
if (foldedNode) if (foldedNode)
return foldedNode; return foldedNode;
...@@ -4008,7 +4008,7 @@ TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op, ...@@ -4008,7 +4008,7 @@ TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
node->setLine(loc); node->setLine(loc);
// See if we can fold constants. // See if we can fold constants.
TIntermTyped *foldedNode = node->fold(&mDiagnostics); TIntermTyped *foldedNode = node->fold(mDiagnostics);
if (foldedNode) if (foldedNode)
return foldedNode; return foldedNode;
...@@ -4408,7 +4408,7 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, ...@@ -4408,7 +4408,7 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
// See if we can constant fold a built-in. Note that this may be possible even // See if we can constant fold a built-in. Note that this may be possible even
// if it is not const-qualified. // if it is not const-qualified.
TIntermTyped *foldedNode = TIntermTyped *foldedNode =
intermediate.foldAggregateBuiltIn(aggregate, &mDiagnostics); intermediate.foldAggregateBuiltIn(aggregate, mDiagnostics);
if (foldedNode) if (foldedNode)
{ {
callNode = foldedNode; callNode = foldedNode;
......
...@@ -38,7 +38,7 @@ class TParseContext : angle::NonCopyable ...@@ -38,7 +38,7 @@ class TParseContext : angle::NonCopyable
ShShaderSpec spec, ShShaderSpec spec,
ShCompileOptions options, ShCompileOptions options,
bool checksPrecErrors, bool checksPrecErrors,
TInfoSink &is, TDiagnostics *diagnostics,
const ShBuiltInResources &resources); const ShBuiltInResources &resources);
const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; } const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; }
...@@ -48,8 +48,7 @@ class TParseContext : angle::NonCopyable ...@@ -48,8 +48,7 @@ class TParseContext : angle::NonCopyable
int getShaderVersion() const { return mShaderVersion; } int getShaderVersion() const { return mShaderVersion; }
sh::GLenum getShaderType() const { return mShaderType; } sh::GLenum getShaderType() const { return mShaderType; }
ShShaderSpec getShaderSpec() const { return mShaderSpec; } ShShaderSpec getShaderSpec() const { return mShaderSpec; }
int numErrors() const { return mDiagnostics.numErrors(); } int numErrors() const { return mDiagnostics->numErrors(); }
TInfoSink &infoSink() { return mDiagnostics.infoSink(); }
void error(const TSourceLoc &loc, const char *reason, const char *token); void error(const TSourceLoc &loc, const char *reason, const char *token);
void warning(const TSourceLoc &loc, const char *reason, const char *token); void warning(const TSourceLoc &loc, const char *reason, const char *token);
...@@ -435,7 +434,7 @@ class TParseContext : angle::NonCopyable ...@@ -435,7 +434,7 @@ class TParseContext : angle::NonCopyable
TLayoutMatrixPacking mDefaultMatrixPacking; TLayoutMatrixPacking mDefaultMatrixPacking;
TLayoutBlockStorage mDefaultBlockStorage; TLayoutBlockStorage mDefaultBlockStorage;
TString mHashErrMsg; TString mHashErrMsg;
TDiagnostics mDiagnostics; TDiagnostics *mDiagnostics;
TDirectiveHandler mDirectiveHandler; TDirectiveHandler mDirectiveHandler;
pp::Preprocessor mPreprocessor; pp::Preprocessor mPreprocessor;
void *mScanner; void *mScanner;
......
//
// Copyright (c) 2016 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.
//
#ifndef COMPILER_TRANSLATOR_SEVERITY_H_
#define COMPILER_TRANSLATOR_SEVERITY_H_
namespace sh
{
// Severity is used to classify info log messages.
enum Severity
{
SH_WARNING,
SH_ERROR
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_SEVERITY_H_
...@@ -5,7 +5,8 @@ ...@@ -5,7 +5,8 @@
// //
#include "compiler/translator/ValidateLimitations.h" #include "compiler/translator/ValidateLimitations.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/Diagnostics.h"
#include "compiler/translator/InitializeParseContext.h" #include "compiler/translator/InitializeParseContext.h"
#include "compiler/translator/ParseContext.h" #include "compiler/translator/ParseContext.h"
#include "angle_gl.h" #include "angle_gl.h"
...@@ -66,35 +67,14 @@ class ValidateConstIndexExpr : public TIntermTraverser ...@@ -66,35 +67,14 @@ class ValidateConstIndexExpr : public TIntermTraverser
} // namespace anonymous } // namespace anonymous
ValidateLimitations::ValidateLimitations(sh::GLenum shaderType, TInfoSinkBase *sink) ValidateLimitations::ValidateLimitations(sh::GLenum shaderType, TDiagnostics *diagnostics)
: TIntermTraverser(true, false, false), : TIntermTraverser(true, false, false),
mShaderType(shaderType), mShaderType(shaderType),
mSink(sink), mDiagnostics(diagnostics),
mNumErrors(0),
mValidateIndexing(true), mValidateIndexing(true),
mValidateInnerLoops(true) mValidateInnerLoops(true)
{ {
} ASSERT(diagnostics);
// static
bool ValidateLimitations::IsLimitedForLoop(TIntermLoop *loop)
{
// The shader type doesn't matter in this case.
ValidateLimitations validate(GL_FRAGMENT_SHADER, nullptr);
validate.mValidateIndexing = false;
validate.mValidateInnerLoops = false;
if (!validate.validateLoopType(loop))
return false;
if (!validate.validateForLoopHeader(loop))
return false;
TIntermNode *body = loop->getBody();
if (body != nullptr)
{
validate.mLoopSymbolIds.push_back(GetLoopSymbolId(loop));
body->traverse(&validate);
validate.mLoopSymbolIds.pop_back();
}
return (validate.mNumErrors == 0);
} }
bool ValidateLimitations::visitBinary(Visit, TIntermBinary *node) bool ValidateLimitations::visitBinary(Visit, TIntermBinary *node)
...@@ -162,13 +142,7 @@ bool ValidateLimitations::visitLoop(Visit, TIntermLoop *node) ...@@ -162,13 +142,7 @@ bool ValidateLimitations::visitLoop(Visit, TIntermLoop *node)
void ValidateLimitations::error(TSourceLoc loc, const char *reason, const char *token) void ValidateLimitations::error(TSourceLoc loc, const char *reason, const char *token)
{ {
if (mSink) mDiagnostics->error(loc, reason, token);
{
mSink->prefix(EPrefixError);
mSink->location(loc);
(*mSink) << "'" << token << "' : " << reason << "\n";
}
++mNumErrors;
} }
bool ValidateLimitations::withinLoopBody() const bool ValidateLimitations::withinLoopBody() const
......
...@@ -12,24 +12,20 @@ ...@@ -12,24 +12,20 @@
namespace sh namespace sh
{ {
class TInfoSinkBase; class TDiagnostics;
// Traverses intermediate tree to ensure that the shader does not exceed the // Traverses intermediate tree to ensure that the shader does not exceed the
// minimum functionality mandated in GLSL 1.0 spec, Appendix A. // minimum functionality mandated in GLSL 1.0 spec, Appendix A.
class ValidateLimitations : public TIntermTraverser class ValidateLimitations : public TIntermTraverser
{ {
public: public:
ValidateLimitations(sh::GLenum shaderType, TInfoSinkBase *sink); ValidateLimitations(sh::GLenum shaderType, TDiagnostics *diagnostics);
int numErrors() const { return mNumErrors; }
bool visitBinary(Visit, TIntermBinary *) override; bool visitBinary(Visit, TIntermBinary *) override;
bool visitUnary(Visit, TIntermUnary *) override; bool visitUnary(Visit, TIntermUnary *) override;
bool visitAggregate(Visit, TIntermAggregate *) override; bool visitAggregate(Visit, TIntermAggregate *) override;
bool visitLoop(Visit, TIntermLoop *) override; bool visitLoop(Visit, TIntermLoop *) override;
static bool IsLimitedForLoop(TIntermLoop *node);
private: private:
void error(TSourceLoc loc, const char *reason, const char *token); void error(TSourceLoc loc, const char *reason, const char *token);
...@@ -55,8 +51,7 @@ class ValidateLimitations : public TIntermTraverser ...@@ -55,8 +51,7 @@ class ValidateLimitations : public TIntermTraverser
bool validateIndexing(TIntermBinary *node); bool validateIndexing(TIntermBinary *node);
sh::GLenum mShaderType; sh::GLenum mShaderType;
TInfoSinkBase *mSink; TDiagnostics *mDiagnostics;
int mNumErrors;
std::vector<int> mLoopSymbolIds; std::vector<int> mLoopSymbolIds;
bool mValidateIndexing; bool mValidateIndexing;
bool mValidateInnerLoops; bool mValidateInnerLoops;
......
...@@ -14,12 +14,9 @@ namespace sh ...@@ -14,12 +14,9 @@ namespace sh
namespace namespace
{ {
void error(int *errorCount, TInfoSinkBase &sink, const TIntermSymbol &symbol, const char *reason) void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics)
{ {
sink.prefix(EPrefixError); diagnostics->error(symbol.getLine(), reason, symbol.getSymbol().c_str());
sink.location(symbol.getLine());
sink << "'" << symbol.getSymbol() << "' : " << reason << "\n";
(*errorCount)++;
} }
} // namespace } // namespace
...@@ -55,10 +52,10 @@ void ValidateOutputs::visitSymbol(TIntermSymbol *symbol) ...@@ -55,10 +52,10 @@ void ValidateOutputs::visitSymbol(TIntermSymbol *symbol)
} }
} }
int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const void ValidateOutputs::validate(TDiagnostics *diagnostics) const
{ {
ASSERT(diagnostics);
OutputVector validOutputs(mMaxDrawBuffers); OutputVector validOutputs(mMaxDrawBuffers);
int errorCount = 0;
for (const auto &symbol : mOutputs) for (const auto &symbol : mOutputs)
{ {
...@@ -78,7 +75,7 @@ int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const ...@@ -78,7 +75,7 @@ int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const
std::stringstream strstr; std::stringstream strstr;
strstr << "conflicting output locations with previously defined output '" strstr << "conflicting output locations with previously defined output '"
<< validOutputs[offsetLocation]->getSymbol() << "'"; << validOutputs[offsetLocation]->getSymbol() << "'";
error(&errorCount, sink, *symbol, strstr.str().c_str()); error(*symbol, strstr.str().c_str(), diagnostics);
} }
else else
{ {
...@@ -90,9 +87,10 @@ int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const ...@@ -90,9 +87,10 @@ int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const
{ {
if (elementCount > 0) if (elementCount > 0)
{ {
error(&errorCount, sink, *symbol, error(*symbol,
elementCount > 1 ? "output array locations would exceed MAX_DRAW_BUFFERS" elementCount > 1 ? "output array locations would exceed MAX_DRAW_BUFFERS"
: "output location must be < MAX_DRAW_BUFFERS"); : "output location must be < MAX_DRAW_BUFFERS",
diagnostics);
} }
} }
} }
...@@ -103,11 +101,11 @@ int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const ...@@ -103,11 +101,11 @@ int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const
{ {
for (const auto &symbol : mUnspecifiedLocationOutputs) for (const auto &symbol : mUnspecifiedLocationOutputs)
{ {
error(&errorCount, sink, *symbol, error(*symbol,
"must explicitly specify all locations when using multiple fragment outputs"); "must explicitly specify all locations when using multiple fragment outputs",
diagnostics);
} }
} }
return errorCount;
} }
} // namespace sh } // namespace sh
...@@ -22,7 +22,7 @@ class ValidateOutputs : public TIntermTraverser ...@@ -22,7 +22,7 @@ class ValidateOutputs : public TIntermTraverser
public: public:
ValidateOutputs(const TExtensionBehavior &extBehavior, int maxDrawBuffers); ValidateOutputs(const TExtensionBehavior &extBehavior, int maxDrawBuffers);
int validateAndCountErrors(TInfoSinkBase &sink) const; void validate(TDiagnostics *diagnostics) const;
void visitSymbol(TIntermSymbol *) override; void visitSymbol(TIntermSymbol *) override;
......
...@@ -65,7 +65,7 @@ void OutputTreeText(TInfoSinkBase &sink, TIntermNode *node, const int depth) ...@@ -65,7 +65,7 @@ void OutputTreeText(TInfoSinkBase &sink, TIntermNode *node, const int depth)
{ {
int i; int i;
sink.location(node->getLine()); sink.location(node->getLine().first_file, node->getLine().first_line);
for (i = 0; i < depth; ++i) for (i = 0; i < depth; ++i)
sink << " "; sink << " ";
...@@ -476,7 +476,7 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) ...@@ -476,7 +476,7 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
break; break;
default: default:
out.prefix(EPrefixError); out.prefix(SH_ERROR);
out << "Bad unary op"; out << "Bad unary op";
} }
...@@ -512,7 +512,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -512,7 +512,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
if (node->getOp() == EOpNull) if (node->getOp() == EOpNull)
{ {
out.prefix(EPrefixError); out.prefix(SH_ERROR);
out << "node is still EOpNull!\n"; out << "node is still EOpNull!\n";
return true; return true;
} }
...@@ -687,7 +687,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -687,7 +687,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
break; break;
default: default:
out.prefix(EPrefixError); out.prefix(SH_ERROR);
out << "Bad aggregation op"; out << "Bad aggregation op";
} }
...@@ -853,7 +853,8 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node) ...@@ -853,7 +853,8 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node)
out << " (const uint)\n"; out << " (const uint)\n";
break; break;
default: default:
out.message(EPrefixInternalError, node->getLine(), "Unknown constant"); out.prefix(SH_ERROR);
out << "Unknown constant";
break; break;
} }
} }
......
...@@ -203,7 +203,7 @@ const char* ExpressionLimitTest::kExpressionTooComplex = ...@@ -203,7 +203,7 @@ const char* ExpressionLimitTest::kExpressionTooComplex =
const char* ExpressionLimitTest::kCallStackTooDeep = const char* ExpressionLimitTest::kCallStackTooDeep =
"Call stack too deep"; "Call stack too deep";
const char* ExpressionLimitTest::kHasRecursion = const char* ExpressionLimitTest::kHasRecursion =
"Function recursion detected"; "Recursive function call in the following call chain";
const char* ExpressionLimitTest::kTooManyParameters = const char* ExpressionLimitTest::kTooManyParameters =
"Function has too many parameters"; "Function has too many parameters";
......
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