diff options
-rw-r--r-- | llvm/include/llvm/Support/Endian.h | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/llvm/include/llvm/Support/Endian.h b/llvm/include/llvm/Support/Endian.h index b72200e7ba4..7680240deac 100644 --- a/llvm/include/llvm/Support/Endian.h +++ b/llvm/include/llvm/Support/Endian.h @@ -131,14 +131,22 @@ inline void writeAtBitAlignment(void *memory, value_type value, // Mask off any existing bits in the upper part of the lower value that // we want to replace. val[0] &= (1 << startBit) - 1; - // Now shift in the new bits - val[0] |= value << startBit; + unsigned numBitsFirstVal = (sizeof(value_type) * 8) - startBit; + unsigned lowerVal = value; + if (startBit > 0) { + // Mask off the upper bits in the new value that are not going to go into + // the lower value. This avoids a left shift of a negative value, which + // is undefined behavior. + lowerVal &= ((1 << numBitsFirstVal) - 1); + // Now shift the new bits into place + lowerVal <<= startBit; + } + val[0] |= lowerVal; // Mask off any existing bits in the lower part of the upper value that // we want to replace. val[1] &= ~((1 << startBit) - 1); // Next shift the bits that go into the upper value into position. - unsigned numBitsFirstVal = (sizeof(value_type) * 8) - startBit; unsigned upperVal = value >> numBitsFirstVal; // Mask off upper bits after right shift in case of signed type. upperVal &= (1 << startBit) - 1; |