diff --git a/mlir/lib/IR/Attributes.cpp b/mlir/lib/IR/Attributes.cpp --- a/mlir/lib/IR/Attributes.cpp +++ b/mlir/lib/IR/Attributes.cpp @@ -546,25 +546,57 @@ /// Get start position of actual data in `value`. Actual data is /// stored in last `bitWidth`/CHAR_BIT bytes in big endian. -static char *getAPIntDataPos(APInt &value, size_t bitWidth) { +static char *getAPIntDataPosBE(APInt &value, size_t bitWidth, size_t wordNum) { char *dataPos = const_cast(reinterpret_cast(value.getRawData())); - if (llvm::support::endian::system_endianness() == - llvm::support::endianness::big) - dataPos = dataPos + 8 - llvm::divideCeil(bitWidth, CHAR_BIT); + unsigned apintBytesPerWord = APInt::APINT_BITS_PER_WORD / CHAR_BIT; + + dataPos = dataPos + apintBytesPerWord * wordNum - + llvm::divideCeil(bitWidth, CHAR_BIT); + return dataPos; } /// Read APInt `value` from appropriate position. static void readAPInt(APInt &value, size_t bitWidth, char *outData) { - char *dataPos = getAPIntDataPos(value, bitWidth); - std::copy_n(dataPos, llvm::divideCeil(bitWidth, CHAR_BIT), outData); + char *dataPos = + const_cast(reinterpret_cast(value.getRawData())); + if (llvm::support::endian::system_endianness() == + llvm::support::endianness::big) { + unsigned numFilledWords = bitWidth / APInt::APINT_BITS_PER_WORD; + unsigned resBits = bitWidth - numFilledWords * APInt::APINT_BITS_PER_WORD; + unsigned apintBytesPerWord = APInt::APINT_BITS_PER_WORD / CHAR_BIT; + // Read words filled with 8 bytes data (multiple of `APINT_BITS_PER_WORD` + // bits) + std::copy_n(dataPos, apintBytesPerWord * numFilledWords, outData); + // Then, read the rest bits from apropriate position in big endian + dataPos = getAPIntDataPosBE(value, resBits, numFilledWords + 1); + std::copy_n(dataPos, llvm::divideCeil(resBits, CHAR_BIT), + outData + apintBytesPerWord * numFilledWords); + } else { + std::copy_n(dataPos, llvm::divideCeil(bitWidth, CHAR_BIT), outData); + } } /// Write `inData` to appropriate position of APInt `value`. static void writeAPInt(const char *inData, size_t bitWidth, APInt &value) { - char *dataPos = getAPIntDataPos(value, bitWidth); - std::copy_n(inData, llvm::divideCeil(bitWidth, CHAR_BIT), dataPos); + char *dataPos = + const_cast(reinterpret_cast(value.getRawData())); + if (llvm::support::endian::system_endianness() == + llvm::support::endianness::big) { + unsigned numFilledWords = bitWidth / APInt::APINT_BITS_PER_WORD; + unsigned resBits = bitWidth - numFilledWords * APInt::APINT_BITS_PER_WORD; + unsigned apintBytesPerWord = APInt::APINT_BITS_PER_WORD / CHAR_BIT; + // Write words filled with 8 bytes data (multiple of `APINT_BITS_PER_WORD` + // bits) + std::copy_n(inData, apintBytesPerWord * numFilledWords, dataPos); + // Then, write the rest bits from apropriate position in big endian + dataPos = getAPIntDataPosBE(value, resBits, numFilledWords + 1); + std::copy_n(inData + apintBytesPerWord * numFilledWords, + llvm::divideCeil(resBits, CHAR_BIT), dataPos); + } else { + std::copy_n(inData, llvm::divideCeil(bitWidth, CHAR_BIT), dataPos); + } } /// Writes value to the bit position `bitPos` in array `rawData`.