diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.cpp b/lib/SPIRV/libSPIRV/SPIRVModule.cpp index c07d5c1ac9..064076d1fe 100644 --- a/lib/SPIRV/libSPIRV/SPIRVModule.cpp +++ b/lib/SPIRV/libSPIRV/SPIRVModule.cpp @@ -2623,7 +2623,8 @@ std::istream &SPIRVModuleImpl::parseSPIRV(std::istream &I) { MI.setAutoAddExtensions(false); SPIRVWord Header[5] = {0}; - I.read(reinterpret_cast(&Header), sizeof(Header)); + for (auto &H : Header) + H = readSPIRVWord(I); SPIRVErrorLog &ErrorLog = MI.getErrorLog(); if (!ErrorLog.checkError(!I.eof(), SPIRVEC_InvalidModule, @@ -2660,8 +2661,7 @@ std::istream &SPIRVModuleImpl::parseSPIRV(std::istream &I) { SPIRVEntry *Scope = nullptr; while (true) { - SPIRVWord WordCountAndOpCode = 0; - I.read(reinterpret_cast(&WordCountAndOpCode), sizeof(SPIRVWord)); + SPIRVWord WordCountAndOpCode = readSPIRVWord(I); SPIRVDBG(spvdbgs() << "Read word: W = " << WordCountAndOpCode << " V = 0\n"); SPIRVWord WordCount = WordCountAndOpCode >> 16; @@ -2784,8 +2784,8 @@ SPIRVId SPIRVModuleImpl::getExtInstSetId(SPIRVExtInstSetKind Kind) const { bool isSpirvBinary(const std::string &Img) { if (Img.size() < sizeof(unsigned)) return false; - const auto *Magic = reinterpret_cast(Img.data()); - return *Magic == MagicNumber; + std::istringstream IS(Img); + return readSPIRVWord(IS) == MagicNumber; } #ifdef _SPIRV_SUPPORT_TEXT_FMT diff --git a/lib/SPIRV/libSPIRV/SPIRVStream.h b/lib/SPIRV/libSPIRV/SPIRVStream.h index 21cb51a3a0..68df75e3e7 100644 --- a/lib/SPIRV/libSPIRV/SPIRVStream.h +++ b/lib/SPIRV/libSPIRV/SPIRVStream.h @@ -98,10 +98,20 @@ class SPIRVNL { friend spv_ostream &operator<<(spv_ostream &O, const SPIRVNL &E); }; +/// Read a single SPIR-V word from a binary stream, byte-swapping from +/// little-endian on big-endian hosts. +inline uint32_t readSPIRVWord(std::istream &IS) { + uint32_t W; + IS.read(reinterpret_cast(&W), sizeof(W)); +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + W = __builtin_bswap32(W); +#endif + return W; +} + template const SPIRVDecoder &decodeBinary(const SPIRVDecoder &I, T &V) { - uint32_t W; - I.IS.read(reinterpret_cast(&W), sizeof(W)); + uint32_t W = readSPIRVWord(I.IS); V = static_cast(W); SPIRVDBG(spvdbgs() << "Read word: W = " << W << " V = " << V << '\n'); return I; @@ -186,6 +196,10 @@ const SPIRVEncoder &operator<<(const SPIRVEncoder &O, T V) { } #endif uint32_t W = static_cast(V); +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + // SPIR-V binary format is little-endian; byte-swap on big-endian hosts. + W = __builtin_bswap32(W); +#endif O.OS.write(reinterpret_cast(&W), sizeof(W)); return O; }