Merge branch 'patch-1' of https://github.com/HaydnTrigg/glslang into HaydnTrigg-patch-1
diff --git a/SPIRV/CMakeLists.txt b/SPIRV/CMakeLists.txt
index 1e5513c..bf2be16 100755
--- a/SPIRV/CMakeLists.txt
+++ b/SPIRV/CMakeLists.txt
@@ -60,6 +60,7 @@
PRIVATE ${spirv-tools_SOURCE_DIR}/source
)
target_link_libraries(SPIRV glslang SPIRV-Tools-opt)
+ target_include_directories(SPIRV PUBLIC ../External)
else()
target_link_libraries(SPIRV glslang)
endif(ENABLE_OPT)
diff --git a/SPIRV/disassemble.cpp b/SPIRV/disassemble.cpp
index b432e65..16770c4 100755
--- a/SPIRV/disassemble.cpp
+++ b/SPIRV/disassemble.cpp
@@ -716,4 +716,25 @@
SpirvStream.processInstructions();
}
+#if ENABLE_OPT
+
+#include "spirv-tools/source/disassemble.h"
+
+// Use the SPIRV-Tools disassembler to print SPIR-V.
+void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
+{
+ spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_3);
+ spv_text text;
+ spv_diagnostic diagnostic = nullptr;
+ spvBinaryToText(context, &spirv.front(), spirv.size(),
+ SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT,
+ &text, &diagnostic);
+ if (diagnostic == nullptr)
+ out << text->str;
+ else
+ spvDiagnosticPrint(diagnostic);
+}
+
+#endif
+
}; // end namespace spv
diff --git a/SPIRV/disassemble.h b/SPIRV/disassemble.h
index 47cef65..bdde5cb 100755
--- a/SPIRV/disassemble.h
+++ b/SPIRV/disassemble.h
@@ -45,8 +45,12 @@
namespace spv {
+ // disassemble with glslang custom disassembler
void Disassemble(std::ostream& out, const std::vector<unsigned int>&);
+ // disassemble with SPIRV-Tools disassembler
+ void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& stream);
+
}; // end namespace spv
#endif // disassembler_H
diff --git a/StandAlone/CMakeLists.txt b/StandAlone/CMakeLists.txt
index d500121..5cea53d 100755
--- a/StandAlone/CMakeLists.txt
+++ b/StandAlone/CMakeLists.txt
@@ -33,6 +33,7 @@
target_link_libraries(glslangValidator ${LIBRARIES})
target_link_libraries(spirv-remap ${LIBRARIES})
+target_include_directories(glslangValidator PUBLIC ../External)
if(WIN32)
source_group("Source" FILES ${SOURCES})
diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp
old mode 100644
new mode 100755
index 6736dbc..549cb0d
--- a/StandAlone/StandAlone.cpp
+++ b/StandAlone/StandAlone.cpp
@@ -102,6 +102,7 @@
EOptionDumpBareVersion = (1 << 31),
};
bool targetHlslFunctionality1 = false;
+bool SpvToolsDisassembler = false;
//
// Return codes from main/exit().
@@ -506,6 +507,8 @@
sourceEntryPointName = argv[1];
bumpArg();
break;
+ } else if (lowerword == "spirv-dis") {
+ SpvToolsDisassembler = true;
} else if (lowerword == "stdin") {
Options |= EOptionStdin;
shaderStageName = argv[1];
@@ -982,9 +985,15 @@
} else {
glslang::OutputSpvBin(spirv, GetBinaryName((EShLanguage)stage));
}
- if (Options & EOptionHumanReadableSpv) {
+#if ENABLE_OPT
+ if (SpvToolsDisassembler)
+ spv::SpirvToolsDisassemble(std::cout, spirv);
+#else
+ if (SpvToolsDisassembler)
+ printf("SPIRV-Tools is not enabled; use -H for human readable SPIR-V\n");
+#endif
+ if (!SpvToolsDisassembler && (Options & EOptionHumanReadableSpv))
spv::Disassemble(std::cout, spirv);
- }
}
}
}
@@ -1405,6 +1414,8 @@
" --shift-UBO-binding [stage] [num set]... per-descriptor-set shift values\n"
" --shift-cbuffer-binding [stage] num synonym for --shift-UBO-binding\n"
" --shift-cbuffer-binding [stage] [num set]... per-descriptor-set shift values\n"
+ " --spirv-dis output standard form disassembly; works only\n"
+ " when a SPIR-V generation option is also used\n"
" --sub [stage] num synonym for --shift-UBO-binding\n"
" --source-entrypoint <name> the given shader source function is\n"
" renamed to be the <name> given in -e\n"
diff --git a/Test/baseResults/cppBad2.vert.out b/Test/baseResults/cppBad2.vert.out
index 0398e5e..af9ff38 100755
--- a/Test/baseResults/cppBad2.vert.out
+++ b/Test/baseResults/cppBad2.vert.out
@@ -1,7 +1,6 @@
cppBad2.vert
ERROR: 0:3: 'macro expansion' : End of input in macro b
-ERROR: 0:3: '' : compilation terminated
-ERROR: 2 compilation errors. No code generated.
+ERROR: 1 compilation errors. No code generated.
Shader version: 100
diff --git a/Test/baseResults/hlsl.pp.expand.frag.err b/Test/baseResults/hlsl.pp.expand.frag.err
new file mode 100644
index 0000000..1b5681f
--- /dev/null
+++ b/Test/baseResults/hlsl.pp.expand.frag.err
@@ -0,0 +1,3 @@
+ERROR: HLSL currently only supported when requesting SPIR-V for Vulkan.
+ERROR: HLSL currently only supported when requesting SPIR-V for Vulkan.
+
diff --git a/Test/baseResults/hlsl.pp.expand.frag.out b/Test/baseResults/hlsl.pp.expand.frag.out
new file mode 100644
index 0000000..7197891
--- /dev/null
+++ b/Test/baseResults/hlsl.pp.expand.frag.out
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+struct A
+{
+ float4 a;
+ float4 b;
+ float4 c = { 1, 2, 3, 4 };
+ float4 d = {({ {(({ 1, 2, 3, 4 }))} })}, { { 1, 2, 3, 4 } };
+};
+
+void main()
+{
+}
+
diff --git a/Test/baseResults/preprocessor.bad_arg.vert.err b/Test/baseResults/preprocessor.bad_arg.vert.err
new file mode 100644
index 0000000..ae970a0
--- /dev/null
+++ b/Test/baseResults/preprocessor.bad_arg.vert.err
@@ -0,0 +1,4 @@
+ERROR: 0:8: 'macro expansion' : End of input in macro EXP2
+ERROR: 1 compilation errors. No code generated.
+
+
diff --git a/Test/baseResults/preprocessor.bad_arg.vert.out b/Test/baseResults/preprocessor.bad_arg.vert.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Test/baseResults/preprocessor.bad_arg.vert.out
diff --git a/Test/hlsl.pp.expand.frag b/Test/hlsl.pp.expand.frag
new file mode 100755
index 0000000..765d17e
--- /dev/null
+++ b/Test/hlsl.pp.expand.frag
@@ -0,0 +1,17 @@
+#define EMP1(a)
+#define EMP2(a, b)
+
+#define EXP1(a) = a
+#define EXP2(a, b) = a, b
+
+struct A
+{
+ float4 a EMP1({1,2,3,4}); // No PP arg errors
+ float4 b EMP2({({{(({1,2,3,4}))}})}, {{1,2,3,4}}); // No PP arg errors
+ float4 c EXP1({1,2,3,4}); // ERROR: No PP arg errors, but init error
+ float4 d EXP2({({{(({1,2,3,4}))}})}, {{1,2,3,4}}); // ERROR: No PP arg errors, but init error
+};
+
+void main()
+{
+}
diff --git a/Test/preprocessor.bad_arg.vert b/Test/preprocessor.bad_arg.vert
new file mode 100755
index 0000000..344fc4b
--- /dev/null
+++ b/Test/preprocessor.bad_arg.vert
@@ -0,0 +1,8 @@
+#define M(a) a
+int M(aou
+ = 2) // Okay, one argument, split across newline
+ ;
+
+// end of file during an argument
+#define EXP2(a, b)
+EXP2(((((1,2,3,4))), );
diff --git a/Test/runtests b/Test/runtests
index a084cb5..390acfc 100755
--- a/Test/runtests
+++ b/Test/runtests
@@ -216,6 +216,13 @@
diff -b $BASEDIR/hlsl.noSemantic.functionality1.comp.out $TARGETDIR/hlsl.noSemantic.functionality1.comp.out || HASERROR=1
#
+# Testing HLSL-specific PP feature expansion
+#
+$EXE -D -E hlsl.pp.expand.frag > $TARGETDIR/hlsl.pp.expand.frag.out 2> $TARGETDIR/hlsl.pp.expand.frag.err
+diff -b $BASEDIR/hlsl.pp.expand.frag.out $TARGETDIR/hlsl.pp.expand.frag.out || HASERROR=1
+diff -b $BASEDIR/hlsl.pp.expand.frag.err $TARGETDIR/hlsl.pp.expand.frag.err || HASERROR=1
+
+#
# Final checking
#
if [ $HASERROR -eq 0 ]
diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h
index f163142..91ea3e6 100644
--- a/glslang/Include/revision.h
+++ b/glslang/Include/revision.h
@@ -1,3 +1,3 @@
// This header is generated by the make-revision script.
-#define GLSLANG_PATCH_LEVEL 2776
+#define GLSLANG_PATCH_LEVEL 2787
diff --git a/glslang/MachineIndependent/preprocessor/Pp.cpp b/glslang/MachineIndependent/preprocessor/Pp.cpp
old mode 100644
new mode 100755
index 8048fa5..1235355
--- a/glslang/MachineIndependent/preprocessor/Pp.cpp
+++ b/glslang/MachineIndependent/preprocessor/Pp.cpp
@@ -515,15 +515,16 @@
int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken* ppToken)
{
while (token == PpAtomIdentifier && strcmp("defined", ppToken->name) != 0) {
- int macroReturn = MacroExpand(ppToken, true, false);
- if (macroReturn == 0) {
+ switch (MacroExpand(ppToken, true, false)) {
+ case MacroExpandNotStarted:
+ case MacroExpandError:
parseContext.ppError(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", "");
err = true;
res = 0;
- token = scanToken(ppToken);
break;
- }
- if (macroReturn == -1) {
+ case MacroExpandStarted:
+ break;
+ case MacroExpandUndef:
if (! shortCircuit && parseContext.profile == EEsProfile) {
const char* message = "undefined macro in expression not allowed in es profile";
if (parseContext.relaxedErrors())
@@ -531,8 +532,11 @@
else
parseContext.ppError(ppToken->loc, message, "preprocessor evaluation", ppToken->name);
}
+ break;
}
token = scanToken(ppToken);
+ if (err)
+ break;
}
return token;
@@ -1011,15 +1015,25 @@
int token;
while ((token = scanToken(ppToken)) != tMarkerInput::marker && token != EndOfInput) {
token = tokenPaste(token, *ppToken);
+ if (token == PpAtomIdentifier) {
+ switch (MacroExpand(ppToken, false, newLineOkay)) {
+ case MacroExpandNotStarted:
+ break;
+ case MacroExpandError:
+ token = EndOfInput;
+ break;
+ case MacroExpandStarted:
+ case MacroExpandUndef:
+ continue;
+ }
+ }
if (token == tMarkerInput::marker || token == EndOfInput)
break;
- if (token == PpAtomIdentifier && MacroExpand(ppToken, false, newLineOkay) != 0)
- continue;
expandedArg->putToken(token, ppToken);
}
if (token == EndOfInput) {
- // MacroExpand ate the marker, so had bad input, recover
+ // Error, or MacroExpand ate the marker, so had bad input, recover
delete expandedArg;
expandedArg = nullptr;
} else {
@@ -1115,14 +1129,18 @@
}
//
-// Check a token to see if it is a macro that should be expanded.
-// If it is, and defined, push a tInput that will produce the appropriate expansion
-// and return 1.
-// If it is, but undefined, and expandUndef is requested, push a tInput that will
-// expand to 0 and return -1.
-// Otherwise, return 0 to indicate no expansion, which is not necessarily an error.
+// Check a token to see if it is a macro that should be expanded:
+// - If it is, and defined, push a tInput that will produce the appropriate
+// expansion and return MacroExpandStarted.
+// - If it is, but undefined, and expandUndef is requested, push a tInput
+// that will expand to 0 and return MacroExpandUndef.
+// - Otherwise, there is no expansion, and there are two cases:
+// * It might be okay there is no expansion, and no specific error was
+// detected. Returns MacroExpandNotStarted.
+// * The expansion was started, but could not be completed, due to an error
+// that cannot be recovered from. Returns MacroExpandError.
//
-int TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay)
+MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay)
{
ppToken->space = false;
int macroAtom = atomStrings.getAtom(ppToken->name);
@@ -1131,7 +1149,7 @@
ppToken->ival = parseContext.getCurrentLoc().line;
snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival);
UngetToken(PpAtomConstInt, ppToken);
- return 1;
+ return MacroExpandStarted;
case PpAtomFileMacro: {
if (parseContext.getCurrentLoc().name)
@@ -1139,34 +1157,33 @@
ppToken->ival = parseContext.getCurrentLoc().string;
snprintf(ppToken->name, sizeof(ppToken->name), "%s", ppToken->loc.getStringNameOrNum().c_str());
UngetToken(PpAtomConstInt, ppToken);
- return 1;
+ return MacroExpandStarted;
}
case PpAtomVersionMacro:
ppToken->ival = parseContext.version;
snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival);
UngetToken(PpAtomConstInt, ppToken);
- return 1;
+ return MacroExpandStarted;
default:
break;
}
MacroSymbol* macro = macroAtom == 0 ? nullptr : lookupMacroDef(macroAtom);
- int depth = 0;
// no recursive expansions
if (macro != nullptr && macro->busy)
- return 0;
+ return MacroExpandNotStarted;
// not expanding undefined macros
if ((macro == nullptr || macro->undef) && ! expandUndef)
- return 0;
+ return MacroExpandNotStarted;
// 0 is the value of an undefined macro
if ((macro == nullptr || macro->undef) && expandUndef) {
pushInput(new tZeroInput(this));
- return -1;
+ return MacroExpandUndef;
}
tMacroInput *in = new tMacroInput(this);
@@ -1182,7 +1199,7 @@
if (token != '(') {
UngetToken(token, ppToken);
delete in;
- return 0;
+ return MacroExpandNotStarted;
}
in->args.resize(in->mac->args.size());
for (size_t i = 0; i < in->mac->args.size(); i++)
@@ -1193,39 +1210,44 @@
size_t arg = 0;
bool tokenRecorded = false;
do {
- depth = 0;
- while (1) {
+ TVector<char> nestStack;
+ while (true) {
token = scanToken(ppToken);
if (token == EndOfInput || token == tMarkerInput::marker) {
parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom));
delete in;
- return 0;
+ return MacroExpandError;
}
if (token == '\n') {
if (! newLineOkay) {
parseContext.ppError(loc, "End of line in macro substitution:", "macro expansion", atomStrings.getString(macroAtom));
delete in;
- return 0;
+ return MacroExpandError;
}
continue;
}
if (token == '#') {
parseContext.ppError(ppToken->loc, "unexpected '#'", "macro expansion", atomStrings.getString(macroAtom));
delete in;
- return 0;
+ return MacroExpandError;
}
if (in->mac->args.size() == 0 && token != ')')
break;
- if (depth == 0 && (token == ',' || token == ')'))
+ if (nestStack.size() == 0 && (token == ',' || token == ')'))
break;
if (token == '(')
- depth++;
- if (token == ')')
- depth--;
+ nestStack.push_back(')');
+ else if (token == '{' && parseContext.isReadingHLSL())
+ nestStack.push_back('}');
+ else if (nestStack.size() > 0 && token == nestStack.back())
+ nestStack.pop_back();
in->args[arg]->putToken(token, ppToken);
tokenRecorded = true;
}
+ // end of single argument scan
+
if (token == ')') {
+ // closing paren of call
if (in->mac->args.size() == 1 && tokenRecorded == 0)
break;
arg++;
@@ -1233,23 +1255,25 @@
}
arg++;
} while (arg < in->mac->args.size());
+ // end of all arguments scan
if (arg < in->mac->args.size())
parseContext.ppError(loc, "Too few args in Macro", "macro expansion", atomStrings.getString(macroAtom));
else if (token != ')') {
- depth=0;
+ // Error recover code; find end of call, if possible
+ int depth = 0;
while (token != EndOfInput && (depth > 0 || token != ')')) {
- if (token == ')')
+ if (token == ')' || token == '}')
depth--;
token = scanToken(ppToken);
- if (token == '(')
+ if (token == '(' || token == '{')
depth++;
}
if (token == EndOfInput) {
parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom));
delete in;
- return 0;
+ return MacroExpandError;
}
parseContext.ppError(loc, "Too many args in macro", "macro expansion", atomStrings.getString(macroAtom));
}
@@ -1264,7 +1288,7 @@
macro->busy = 1;
macro->body.reset();
- return 1;
+ return MacroExpandStarted;
}
} // end namespace glslang
diff --git a/glslang/MachineIndependent/preprocessor/PpContext.h b/glslang/MachineIndependent/preprocessor/PpContext.h
index b3a39c5..5c26081 100755
--- a/glslang/MachineIndependent/preprocessor/PpContext.h
+++ b/glslang/MachineIndependent/preprocessor/PpContext.h
@@ -183,6 +183,13 @@
class TInputScanner;
+enum MacroExpandResult {
+ MacroExpandNotStarted, // macro not expanded, which might not be an error
+ MacroExpandError, // a clear error occurred while expanding, no expansion
+ MacroExpandStarted, // macro expansion process has started
+ MacroExpandUndef // macro is undefined and will be expanded
+};
+
// This class is the result of turning a huge pile of C code communicating through globals
// into a class. This was done to allowing instancing to attain thread safety.
// Don't expect too much in terms of OO design.
@@ -400,7 +407,7 @@
int readCPPline(TPpToken * ppToken);
int scanHeaderName(TPpToken* ppToken, char delimit);
TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay);
- int MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay);
+ MacroExpandResult MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay);
//
// From PpTokens.cpp
diff --git a/glslang/MachineIndependent/preprocessor/PpScanner.cpp b/glslang/MachineIndependent/preprocessor/PpScanner.cpp
index 0c620a5..02b93f9 100755
--- a/glslang/MachineIndependent/preprocessor/PpScanner.cpp
+++ b/glslang/MachineIndependent/preprocessor/PpScanner.cpp
@@ -1061,8 +1061,17 @@
continue;
// expand macros
- if (token == PpAtomIdentifier && MacroExpand(&ppToken, false, true) != 0)
- continue;
+ if (token == PpAtomIdentifier) {
+ switch (MacroExpand(&ppToken, false, true)) {
+ case MacroExpandNotStarted:
+ break;
+ case MacroExpandError:
+ return EndOfInput;
+ case MacroExpandStarted:
+ case MacroExpandUndef:
+ continue;
+ }
+ }
switch (token) {
case PpAtomIdentifier:
diff --git a/gtests/Pp.FromFile.cpp b/gtests/Pp.FromFile.cpp
old mode 100644
new mode 100755
index 13daac0..1bea877
--- a/gtests/Pp.FromFile.cpp
+++ b/gtests/Pp.FromFile.cpp
@@ -50,6 +50,7 @@
INSTANTIATE_TEST_CASE_P(
Glsl, PreprocessingTest,
::testing::ValuesIn(std::vector<std::string>({
+ "preprocessor.bad_arg.vert",
"preprocessor.cpp_style_line_directive.vert",
"preprocessor.cpp_style___FILE__.vert",
"preprocessor.edge_cases.vert",