Added -C option to request cascading errors. By default, will exit early, to avoid all error-recovery-based crashes. This works by simulating end-of-file in input on first error, so no need for exception handling, or stack unwinding, or any complex error checking/handling to get out of the stack.
This commit is contained in:
parent
75b0316f6a
commit
a86836ede2
@ -58,25 +58,26 @@ extern "C" {
|
|||||||
|
|
||||||
// Command-line options
|
// Command-line options
|
||||||
enum TOptions {
|
enum TOptions {
|
||||||
EOptionNone = 0x0000,
|
EOptionNone = 0,
|
||||||
EOptionIntermediate = 0x0001,
|
EOptionIntermediate = (1 << 0),
|
||||||
EOptionSuppressInfolog = 0x0002,
|
EOptionSuppressInfolog = (1 << 1),
|
||||||
EOptionMemoryLeakMode = 0x0004,
|
EOptionMemoryLeakMode = (1 << 2),
|
||||||
EOptionRelaxedErrors = 0x0008,
|
EOptionRelaxedErrors = (1 << 3),
|
||||||
EOptionGiveWarnings = 0x0010,
|
EOptionGiveWarnings = (1 << 4),
|
||||||
EOptionLinkProgram = 0x0020,
|
EOptionLinkProgram = (1 << 5),
|
||||||
EOptionMultiThreaded = 0x0040,
|
EOptionMultiThreaded = (1 << 6),
|
||||||
EOptionDumpConfig = 0x0080,
|
EOptionDumpConfig = (1 << 7),
|
||||||
EOptionDumpReflection = 0x0100,
|
EOptionDumpReflection = (1 << 8),
|
||||||
EOptionSuppressWarnings = 0x0200,
|
EOptionSuppressWarnings = (1 << 9),
|
||||||
EOptionDumpVersions = 0x0400,
|
EOptionDumpVersions = (1 << 10),
|
||||||
EOptionSpv = 0x0800,
|
EOptionSpv = (1 << 11),
|
||||||
EOptionHumanReadableSpv = 0x1000,
|
EOptionHumanReadableSpv = (1 << 12),
|
||||||
EOptionVulkanRules = 0x2000,
|
EOptionVulkanRules = (1 << 13),
|
||||||
EOptionDefaultDesktop = 0x4000,
|
EOptionDefaultDesktop = (1 << 14),
|
||||||
EOptionOutputPreprocessed = 0x8000,
|
EOptionOutputPreprocessed = (1 << 15),
|
||||||
EOptionOutputHexadecimal = 0x10000,
|
EOptionOutputHexadecimal = (1 << 16),
|
||||||
EOptionReadHlsl = 0x20000,
|
EOptionReadHlsl = (1 << 17),
|
||||||
|
EOptionCascadingErrors = (1 << 18),
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -247,6 +248,9 @@ void ProcessArguments(int argc, char* argv[])
|
|||||||
case 'c':
|
case 'c':
|
||||||
Options |= EOptionDumpConfig;
|
Options |= EOptionDumpConfig;
|
||||||
break;
|
break;
|
||||||
|
case 'C':
|
||||||
|
Options |= EOptionCascadingErrors;
|
||||||
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
Options |= EOptionDefaultDesktop;
|
Options |= EOptionDefaultDesktop;
|
||||||
break;
|
break;
|
||||||
@ -347,6 +351,8 @@ void SetMessageOptions(EShMessages& messages)
|
|||||||
messages = (EShMessages)(messages | EShMsgOnlyPreprocessor);
|
messages = (EShMessages)(messages | EShMsgOnlyPreprocessor);
|
||||||
if (Options & EOptionReadHlsl)
|
if (Options & EOptionReadHlsl)
|
||||||
messages = (EShMessages)(messages | EShMsgReadHlsl);
|
messages = (EShMessages)(messages | EShMsgReadHlsl);
|
||||||
|
if (Options & EOptionCascadingErrors)
|
||||||
|
messages = (EShMessages)(messages | EShMsgCascadingErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -772,6 +778,7 @@ void usage()
|
|||||||
" errors will appear on stderr.\n"
|
" errors will appear on stderr.\n"
|
||||||
" -c configuration dump;\n"
|
" -c configuration dump;\n"
|
||||||
" creates the default configuration file (redirect to a .conf file)\n"
|
" creates the default configuration file (redirect to a .conf file)\n"
|
||||||
|
" -C cascading errors; risks crashes from accumulation of error recoveries\n"
|
||||||
" -d default to desktop (#version 110) when there is no shader #version\n"
|
" -d default to desktop (#version 110) when there is no shader #version\n"
|
||||||
" (default is ES version 100)\n"
|
" (default is ES version 100)\n"
|
||||||
" -D input is HLSL\n"
|
" -D input is HLSL\n"
|
||||||
|
@ -22,15 +22,15 @@ rm -f comp.spv frag.spv geom.spv tesc.spv tese.spv vert.spv
|
|||||||
# reflection tests
|
# reflection tests
|
||||||
#
|
#
|
||||||
echo Running reflection...
|
echo Running reflection...
|
||||||
$EXE -l -q reflection.vert > $TARGETDIR/reflection.vert.out
|
$EXE -l -q -C reflection.vert > $TARGETDIR/reflection.vert.out
|
||||||
diff -b $BASEDIR/reflection.vert.out $TARGETDIR/reflection.vert.out || HASERROR=1
|
diff -b $BASEDIR/reflection.vert.out $TARGETDIR/reflection.vert.out || HASERROR=1
|
||||||
|
|
||||||
#
|
#
|
||||||
# multi-threaded test
|
# multi-threaded test
|
||||||
#
|
#
|
||||||
echo Comparing single thread to multithread for all tests in current directory...
|
echo Comparing single thread to multithread for all tests in current directory...
|
||||||
$EXE -i *.vert *.geom *.frag *.tes* *.comp > singleThread.out
|
$EXE -i -C *.vert *.geom *.frag *.tes* *.comp > singleThread.out
|
||||||
$EXE -i *.vert *.geom *.frag *.tes* *.comp -t > multiThread.out
|
$EXE -i -C *.vert *.geom *.frag *.tes* *.comp -t > multiThread.out
|
||||||
diff singleThread.out multiThread.out || HASERROR=1
|
diff singleThread.out multiThread.out || HASERROR=1
|
||||||
|
|
||||||
if [ $HASERROR -eq 0 ]
|
if [ $HASERROR -eq 0 ]
|
||||||
|
@ -377,6 +377,9 @@ void C_DECL TParseContext::error(const TSourceLoc& loc, const char* szReason, co
|
|||||||
va_start(args, szExtraInfoFormat);
|
va_start(args, szExtraInfoFormat);
|
||||||
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
|
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
|
if ((messages & EShMsgCascadingErrors) == 0)
|
||||||
|
currentScanner->setEndOfInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
void C_DECL TParseContext::warn(const TSourceLoc& loc, const char* szReason, const char* szToken,
|
void C_DECL TParseContext::warn(const TSourceLoc& loc, const char* szReason, const char* szToken,
|
||||||
@ -397,6 +400,9 @@ void C_DECL TParseContext::ppError(const TSourceLoc& loc, const char* szReason,
|
|||||||
va_start(args, szExtraInfoFormat);
|
va_start(args, szExtraInfoFormat);
|
||||||
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
|
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
|
if ((messages & EShMsgCascadingErrors) == 0)
|
||||||
|
currentScanner->setEndOfInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
void C_DECL TParseContext::ppWarn(const TSourceLoc& loc, const char* szReason, const char* szToken,
|
void C_DECL TParseContext::ppWarn(const TSourceLoc& loc, const char* szReason, const char* szToken,
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
namespace glslang {
|
namespace glslang {
|
||||||
|
|
||||||
// Use a global end-of-input character, so no tranlation is needed across
|
// Use a global end-of-input character, so no translation is needed across
|
||||||
// layers of encapsulation. Characters are all 8 bit, and positive, so there is
|
// layers of encapsulation. Characters are all 8 bit, and positive, so there is
|
||||||
// no aliasing of character 255 onto -1, for example.
|
// no aliasing of character 255 onto -1, for example.
|
||||||
const int EndOfInput = -1;
|
const int EndOfInput = -1;
|
||||||
@ -82,7 +82,8 @@ public:
|
|||||||
int get()
|
int get()
|
||||||
{
|
{
|
||||||
int ret = peek();
|
int ret = peek();
|
||||||
if (ret == EndOfInput) return ret;
|
if (ret == EndOfInput)
|
||||||
|
return ret;
|
||||||
++loc[currentSource].column;
|
++loc[currentSource].column;
|
||||||
++logicalSourceLoc.column;
|
++logicalSourceLoc.column;
|
||||||
if (ret == '\n') {
|
if (ret == '\n') {
|
||||||
@ -123,7 +124,8 @@ public:
|
|||||||
void unget()
|
void unget()
|
||||||
{
|
{
|
||||||
// Do not roll back once we've reached the end of the file.
|
// Do not roll back once we've reached the end of the file.
|
||||||
if (endOfFileReached) return;
|
if (endOfFileReached)
|
||||||
|
return;
|
||||||
|
|
||||||
if (currentChar > 0) {
|
if (currentChar > 0) {
|
||||||
--currentChar;
|
--currentChar;
|
||||||
@ -196,6 +198,12 @@ public:
|
|||||||
loc[getLastValidSourceIndex()].column = col;
|
loc[getLastValidSourceIndex()].column = col;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setEndOfInput()
|
||||||
|
{
|
||||||
|
endOfFileReached = true;
|
||||||
|
currentSource = numSources;
|
||||||
|
}
|
||||||
|
|
||||||
const TSourceLoc& getSourceLoc() const
|
const TSourceLoc& getSourceLoc() const
|
||||||
{
|
{
|
||||||
if (singleLogical) {
|
if (singleLogical) {
|
||||||
@ -255,7 +263,7 @@ protected:
|
|||||||
bool singleLogical; // treats the strings as a single logical string.
|
bool singleLogical; // treats the strings as a single logical string.
|
||||||
// locations will be reported from the first string.
|
// locations will be reported from the first string.
|
||||||
|
|
||||||
// set to true once peak() returns EndOfFile, so that we won't roll back
|
// Set to true once peek() returns EndOfFile, so that we won't roll back
|
||||||
// once we've reached EndOfFile.
|
// once we've reached EndOfFile.
|
||||||
bool endOfFileReached;
|
bool endOfFileReached;
|
||||||
};
|
};
|
||||||
|
@ -141,6 +141,7 @@ enum EShMessages {
|
|||||||
EShMsgVulkanRules = (1 << 4), // issue messages for Vulkan-requirements of GLSL for SPIR-V
|
EShMsgVulkanRules = (1 << 4), // issue messages for Vulkan-requirements of GLSL for SPIR-V
|
||||||
EShMsgOnlyPreprocessor = (1 << 5), // only print out errors produced by the preprocessor
|
EShMsgOnlyPreprocessor = (1 << 5), // only print out errors produced by the preprocessor
|
||||||
EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics
|
EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics
|
||||||
|
EShMsgCascadingErrors = (1 << 7), // get cascading errors; risks error-recovery issues, instead of an early exit
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -97,8 +97,8 @@ TEST_P(ConfigTest, FromFile)
|
|||||||
INSTANTIATE_TEST_CASE_P(
|
INSTANTIATE_TEST_CASE_P(
|
||||||
Glsl, ConfigTest,
|
Glsl, ConfigTest,
|
||||||
::testing::ValuesIn(std::vector<TestCaseSpec>({
|
::testing::ValuesIn(std::vector<TestCaseSpec>({
|
||||||
{"specExamples.vert", "baseResults/test.conf", "specExamples.vert.out", EShMsgAST},
|
{"specExamples.vert", "baseResults/test.conf", "specExamples.vert.out", (EShMessages)(EShMsgAST | EShMsgCascadingErrors)},
|
||||||
{"100Limits.vert", "100.conf", "100LimitsConf.vert.out", EShMsgDefault},
|
{"100Limits.vert", "100.conf", "100LimitsConf.vert.out", EShMsgCascadingErrors},
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
@ -51,7 +51,7 @@ namespace glslangtest {
|
|||||||
// gets fixed.
|
// gets fixed.
|
||||||
class GlslangInitializer {
|
class GlslangInitializer {
|
||||||
public:
|
public:
|
||||||
GlslangInitializer() : lastMessages(EShMsgDefault)
|
GlslangInitializer() : lastMessages(EShMsgCascadingErrors)
|
||||||
{
|
{
|
||||||
glslang::InitializeProcess();
|
glslang::InitializeProcess();
|
||||||
}
|
}
|
||||||
|
@ -48,8 +48,7 @@ TEST_P(LinkTest, FromFile)
|
|||||||
{
|
{
|
||||||
const auto& fileNames = GetParam();
|
const auto& fileNames = GetParam();
|
||||||
const size_t fileCount = fileNames.size();
|
const size_t fileCount = fileNames.size();
|
||||||
const EShMessages controls = DeriveOptions(
|
const EShMessages controls = DeriveOptions(Source::GLSL, Semantics::OpenGL, Target::AST);
|
||||||
Source::GLSL, Semantics::OpenGL, Target::AST);
|
|
||||||
GlslangResult result;
|
GlslangResult result;
|
||||||
|
|
||||||
// Compile each input shader file.
|
// Compile each input shader file.
|
||||||
|
@ -68,7 +68,7 @@ EShLanguage GetShaderStage(const std::string& stage)
|
|||||||
|
|
||||||
EShMessages DeriveOptions(Source source, Semantics semantics, Target target)
|
EShMessages DeriveOptions(Source source, Semantics semantics, Target target)
|
||||||
{
|
{
|
||||||
EShMessages result = EShMsgDefault;
|
EShMessages result = EShMsgCascadingErrors;
|
||||||
|
|
||||||
switch (source) {
|
switch (source) {
|
||||||
case Source::GLSL:
|
case Source::GLSL:
|
||||||
|
@ -264,8 +264,7 @@ public:
|
|||||||
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
|
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
|
||||||
|
|
||||||
const EShMessages controls = DeriveOptions(source, semantics, target);
|
const EShMessages controls = DeriveOptions(source, semantics, target);
|
||||||
GlslangResult result =
|
GlslangResult result = compileAndLink(testName, input, entryPointName, controls);
|
||||||
compileAndLink(testName, input, entryPointName, controls);
|
|
||||||
|
|
||||||
// Generate the hybrid output in the way of glslangValidator.
|
// Generate the hybrid output in the way of glslangValidator.
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
@ -290,7 +289,7 @@ public:
|
|||||||
glslang::TShader::ForbidInclude includer;
|
glslang::TShader::ForbidInclude includer;
|
||||||
const bool success = shader.preprocess(
|
const bool success = shader.preprocess(
|
||||||
&glslang::DefaultTBuiltInResource, defaultVersion, defaultProfile,
|
&glslang::DefaultTBuiltInResource, defaultVersion, defaultProfile,
|
||||||
forceVersionProfile, isForwardCompatible, EShMsgOnlyPreprocessor,
|
forceVersionProfile, isForwardCompatible, (EShMessages)(EShMsgOnlyPreprocessor | EShMsgCascadingErrors),
|
||||||
&ppShader, includer);
|
&ppShader, includer);
|
||||||
|
|
||||||
std::string log = shader.getInfoLog();
|
std::string log = shader.getInfoLog();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user