diff --git a/glslang-big-endian_1.patch b/glslang-big-endian_1.patch new file mode 100644 index 0000000..8c90ab8 --- /dev/null +++ b/glslang-big-endian_1.patch @@ -0,0 +1,189 @@ +From 78ce7e567fce86d611353c5a9194833a54a6fbe0 Mon Sep 17 00:00:00 2001 +From: Marius Hillenbrand +Date: Tue, 19 Oct 2021 18:09:52 +0200 +Subject: [PATCH] Fix encoding/decoding of string literals for big-endian + systems + +Per SPIR-V spec, a string literal's UTF-8 octets are encoded packed into +words with little-endian convention. Explicitly perform that encoding +instead of assuming that the host system is little-endian. + +Note that this change requires corresponding fixes in SPIRV-Tools. + +Fixes #202 +--- + SPIRV/SPVRemapper.cpp | 18 +++++++++++------ + SPIRV/disassemble.cpp | 47 ++++++++++++++++++++++++++++--------------- + SPIRV/spvIR.h | 22 +++++++++----------- + 3 files changed, 52 insertions(+), 35 deletions(-) + +diff --git a/SPIRV/SPVRemapper.cpp b/SPIRV/SPVRemapper.cpp +index 56d6d5d4a5..fdfbeb90cd 100644 +--- a/SPIRV/SPVRemapper.cpp ++++ b/SPIRV/SPVRemapper.cpp +@@ -297,15 +297,21 @@ namespace spv { + std::string spirvbin_t::literalString(unsigned word) const + { + std::string literal; ++ const spirword_t * pos = spv.data() + word; + + literal.reserve(16); + +- const char* bytes = reinterpret_cast(spv.data() + word); +- +- while (bytes && *bytes) +- literal += *bytes++; +- +- return literal; ++ do { ++ spirword_t word = *pos; ++ for (int i = 0; i < 4; i++) { ++ char c = word & 0xff; ++ if (c == '\0') ++ return literal; ++ literal += c; ++ word >>= 8; ++ } ++ pos++; ++ } while (true); + } + + void spirvbin_t::applyMap() +diff --git a/SPIRV/disassemble.cpp b/SPIRV/disassemble.cpp +index 73c988c5b3..74dd605409 100644 +--- a/SPIRV/disassemble.cpp ++++ b/SPIRV/disassemble.cpp +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + + #include "disassemble.h" + #include "doc.h" +@@ -100,6 +101,7 @@ class SpirvStream { + void outputMask(OperandClass operandClass, unsigned mask); + void disassembleImmediates(int numOperands); + void disassembleIds(int numOperands); ++ std::pair decodeString(); + int disassembleString(); + void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands); + +@@ -290,31 +292,44 @@ void SpirvStream::disassembleIds(int numOperands) + } + } + +-// return the number of operands consumed by the string +-int SpirvStream::disassembleString() ++// decode string from words at current position (non-consuming) ++std::pair SpirvStream::decodeString() + { +- int startWord = word; +- +- out << " \""; +- +- const char* wordString; ++ std::string res; ++ int wordPos = word; ++ char c; + bool done = false; ++ + do { +- unsigned int content = stream[word]; +- wordString = (const char*)&content; ++ unsigned int content = stream[wordPos]; + for (int charCount = 0; charCount < 4; ++charCount) { +- if (*wordString == 0) { ++ c = content & 0xff; ++ content >>= 8; ++ if (c == '\0') { + done = true; + break; + } +- out << *(wordString++); ++ res += c; + } +- ++word; +- } while (! done); ++ ++wordPos; ++ } while(! done); ++ ++ return std::make_pair(wordPos - word, res); ++} ++ ++// return the number of operands consumed by the string ++int SpirvStream::disassembleString() ++{ ++ out << " \""; + ++ std::pair decoderes = decodeString(); ++ ++ out << decoderes.second; + out << "\""; + +- return word - startWord; ++ word += decoderes.first; ++ ++ return decoderes.first; + } + + void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands) +@@ -331,7 +346,7 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, + nextNestedControl = 0; + } + } else if (opCode == OpExtInstImport) { +- idDescriptor[resultId] = (const char*)(&stream[word]); ++ idDescriptor[resultId] = decodeString().second; + } + else { + if (resultId != 0 && idDescriptor[resultId].size() == 0) { +@@ -428,7 +443,7 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, + --numOperands; + // Get names for printing "(XXX)" for readability, *after* this id + if (opCode == OpName) +- idDescriptor[stream[word - 1]] = (const char*)(&stream[word]); ++ idDescriptor[stream[word - 1]] = decodeString().second; + break; + case OperandVariableIds: + disassembleIds(numOperands); +diff --git a/SPIRV/spvIR.h b/SPIRV/spvIR.h +index 486e80d000..5249a5ba73 100644 +--- a/SPIRV/spvIR.h ++++ b/SPIRV/spvIR.h +@@ -111,27 +111,23 @@ class Instruction { + + void addStringOperand(const char* str) + { +- unsigned int word; +- char* wordString = (char*)&word; +- char* wordPtr = wordString; +- int charCount = 0; ++ unsigned int word = 0; ++ unsigned int shiftAmount = 0; + char c; ++ + do { + c = *(str++); +- *(wordPtr++) = c; +- ++charCount; +- if (charCount == 4) { ++ word |= ((unsigned int)c) << shiftAmount; ++ shiftAmount += 8; ++ if (shiftAmount == 32) { + addImmediateOperand(word); +- wordPtr = wordString; +- charCount = 0; ++ word = 0; ++ shiftAmount = 0; + } + } while (c != 0); + + // deal with partial last word +- if (charCount > 0) { +- // pad with 0s +- for (; charCount < 4; ++charCount) +- *(wordPtr++) = 0; ++ if (shiftAmount > 0) { + addImmediateOperand(word); + } + } diff --git a/glslang-big-endian_2.patch b/glslang-big-endian_2.patch new file mode 100644 index 0000000..218fbe4 --- /dev/null +++ b/glslang-big-endian_2.patch @@ -0,0 +1,173 @@ +From 0eda343970e04e7c9447d264271b1c4cfdc923f4 Mon Sep 17 00:00:00 2001 +From: Marius Hillenbrand +Date: Tue, 9 Nov 2021 16:31:22 +0100 +Subject: [PATCH] Use intermOut.cpp's IsNan and IsInfinity for parse-time + constant folding (updated) + +There were two implementations of isInf() and isNan(), in Constant.cpp +and in intermOut.cpp. The former only works on little-endian systems, +the latter is a wrapper for library functions and works regardless of +endianness. Move the second version into Common.h and adopt it in both +places. Thereby avoid the duplication and fix for big-endian systems. + +A previous commit with the same intent and purpose had missed a required +header for builds on Windows. + +On s390x, this fixes the test case +Glsl/CompileToAstTest.FromFile/constFold_frag. + +Fixes #2802 +--- + glslang/Include/Common.h | 33 ++++++++++++++++++++++++ + glslang/MachineIndependent/Constant.cpp | 33 ++---------------------- + glslang/MachineIndependent/intermOut.cpp | 31 ---------------------- + 3 files changed, 35 insertions(+), 62 deletions(-) + +diff --git a/glslang/Include/Common.h b/glslang/Include/Common.h +index e7b5e072b..9042a1aa2 100644 +--- a/glslang/Include/Common.h ++++ b/glslang/Include/Common.h +@@ -39,6 +39,11 @@ + + #include + #include ++#ifdef _MSC_VER ++#include ++#else ++#include ++#endif + #include + #include + #include +@@ -302,6 +307,34 @@ template int IntLog2(T n) + return result; + } + ++inline bool IsInfinity(double x) { ++#ifdef _MSC_VER ++ switch (_fpclass(x)) { ++ case _FPCLASS_NINF: ++ case _FPCLASS_PINF: ++ return true; ++ default: ++ return false; ++ } ++#else ++ return std::isinf(x); ++#endif ++} ++ ++inline bool IsNan(double x) { ++#ifdef _MSC_VER ++ switch (_fpclass(x)) { ++ case _FPCLASS_SNAN: ++ case _FPCLASS_QNAN: ++ return true; ++ default: ++ return false; ++ } ++#else ++ return std::isnan(x); ++#endif ++} ++ + } // end namespace glslang + + #endif // _COMMON_INCLUDED_ +diff --git a/glslang/MachineIndependent/Constant.cpp b/glslang/MachineIndependent/Constant.cpp +index 7f5d4c4f2..5fc61dbb7 100644 +--- a/glslang/MachineIndependent/Constant.cpp ++++ b/glslang/MachineIndependent/Constant.cpp +@@ -46,35 +46,6 @@ namespace { + + using namespace glslang; + +-typedef union { +- double d; +- int i[2]; +-} DoubleIntUnion; +- +-// Some helper functions +- +-bool isNan(double x) +-{ +- DoubleIntUnion u; +- // tough to find a platform independent library function, do it directly +- u.d = x; +- int bitPatternL = u.i[0]; +- int bitPatternH = u.i[1]; +- return (bitPatternH & 0x7ff80000) == 0x7ff80000 && +- ((bitPatternH & 0xFFFFF) != 0 || bitPatternL != 0); +-} +- +-bool isInf(double x) +-{ +- DoubleIntUnion u; +- // tough to find a platform independent library function, do it directly +- u.d = x; +- int bitPatternL = u.i[0]; +- int bitPatternH = u.i[1]; +- return (bitPatternH & 0x7ff00000) == 0x7ff00000 && +- (bitPatternH & 0xFFFFF) == 0 && bitPatternL == 0; +-} +- + const double pi = 3.1415926535897932384626433832795; + + } // end anonymous namespace +@@ -663,12 +634,12 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) + + case EOpIsNan: + { +- newConstArray[i].setBConst(isNan(unionArray[i].getDConst())); ++ newConstArray[i].setBConst(IsNan(unionArray[i].getDConst())); + break; + } + case EOpIsInf: + { +- newConstArray[i].setBConst(isInf(unionArray[i].getDConst())); ++ newConstArray[i].setBConst(IsInfinity(unionArray[i].getDConst())); + break; + } + +diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp +index a0fade16c..d8a3aab5d 100644 +--- a/glslang/MachineIndependent/intermOut.cpp ++++ b/glslang/MachineIndependent/intermOut.cpp +@@ -48,37 +48,6 @@ + #endif + #include + +-namespace { +- +-bool IsInfinity(double x) { +-#ifdef _MSC_VER +- switch (_fpclass(x)) { +- case _FPCLASS_NINF: +- case _FPCLASS_PINF: +- return true; +- default: +- return false; +- } +-#else +- return std::isinf(x); +-#endif +-} +- +-bool IsNan(double x) { +-#ifdef _MSC_VER +- switch (_fpclass(x)) { +- case _FPCLASS_SNAN: +- case _FPCLASS_QNAN: +- return true; +- default: +- return false; +- } +-#else +- return std::isnan(x); +-#endif +-} +- +-} + + namespace glslang { + diff --git a/glslang-big-endian_3.patch b/glslang-big-endian_3.patch new file mode 100644 index 0000000..8d165e3 --- /dev/null +++ b/glslang-big-endian_3.patch @@ -0,0 +1,29 @@ +From f1fa8afa25c99a550b3d80c516b7cfa3ac725de5 Mon Sep 17 00:00:00 2001 +From: Marius Hillenbrand +Date: Wed, 10 Nov 2021 18:10:58 +0100 +Subject: [PATCH] TIntermediate::promoteConstantUnion(): fix conversion to int8 + +The signedness of type char is implementation-defined in C++. The +conversion to (signed) int8 currently uses a cast to char, which is +undefined for negative values when the type char is implemented as +unsigned. Thus, fix to cast to "signed char", which has the intended +semantic on all implementations. + +Fixes #2807 +--- + glslang/MachineIndependent/Intermediate.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp +index 1283f4493..6aea5b3d7 100644 +--- a/glslang/MachineIndependent/Intermediate.cpp ++++ b/glslang/MachineIndependent/Intermediate.cpp +@@ -3902,7 +3902,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC + case EbtFloat16: PROMOTE(setDConst, double, Get); break; \ + case EbtFloat: PROMOTE(setDConst, double, Get); break; \ + case EbtDouble: PROMOTE(setDConst, double, Get); break; \ +- case EbtInt8: PROMOTE(setI8Const, char, Get); break; \ ++ case EbtInt8: PROMOTE(setI8Const, signed char, Get); break; \ + case EbtInt16: PROMOTE(setI16Const, short, Get); break; \ + case EbtInt: PROMOTE(setIConst, int, Get); break; \ + case EbtInt64: PROMOTE(setI64Const, long long, Get); break; \ diff --git a/glslang.changes b/glslang.changes index 8acba3d..db6ba67 100644 --- a/glslang.changes +++ b/glslang.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Thu Dec 9 19:18:39 UTC 2021 - Christophe Giboudeaux + +- Add patches to fix issues on big endian platforms + (Needed to fix https://bugreports.qt.io/browse/QTBUG-93101) + * glslang-big-endian_1.patch + * glslang-big-endian_2.patch + * glslang-big-endian_3.patch + ------------------------------------------------------------------- Sat Nov 27 14:11:19 UTC 2021 - Jan Engelhardt diff --git a/glslang.spec b/glslang.spec index 715ebd3..ade32d2 100644 --- a/glslang.spec +++ b/glslang.spec @@ -28,7 +28,10 @@ URL: https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/ #Git-URL: https://github.com/KhronosGroup/glslang Source: https://github.com/KhronosGroup/glslang/archive/%version.tar.gz -Patch1: 0001-build-set-SOVERSION-on-all-libraries.patch +Patch0: 0001-build-set-SOVERSION-on-all-libraries.patch +Patch1: glslang-big-endian_1.patch +Patch2: glslang-big-endian_2.patch +Patch3: glslang-big-endian_3.patch BuildRequires: bison BuildRequires: cmake >= 2.8 BuildRequires: fdupes