Files
swift-mirror/lib/IRGen/BitPatternReader.h
Michael Munday bb2740e540 IRGen: fix enum bit packing on big-endian platforms.
This change modifies spare bit masks so that they are arranged in
the byte order of the target platform. It also modifies and
consolidates the code that gathers and scatters bits into enum
values.

All enum-related validation tests are now passing on IBM Z (s390x)
which is a big-endian platform.
2019-08-07 03:54:16 -04:00

83 lines
2.4 KiB
C++

//===--- BitPatternReader.h - Split bit patterns into chunks. -------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#pragma once
#include "swift/Basic/ClusteredBitVector.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/Optional.h"
namespace swift {
namespace irgen {
/// BitPatternReader allows an APInt to be read from in chunks.
/// Chunks may be read starting from either the least significant bit
/// (little-endian) or the most significant bit (big-endian).
///
/// This is useful when interpreting an APInt as a multi-byte mask
/// that needs to be applied to a value with a composite type.
///
/// Example:
///
/// // big-endian
/// auto x = BitPatternReader(APInt(32, 0x1234), false);
/// x.read(16) // 0x12
/// x.read(8) // 0x3
/// x.read(8) // 0x4
///
/// // little-endian
/// auto y = BitPatternReader(APInt(32, 0x1234), true);
/// y.read(16) // 0x34
/// y.read(8) // 0x2
/// y.read(8) // 0x1
///
class BitPatternReader {
using APInt = llvm::APInt;
const APInt Value;
const bool LittleEndian;
unsigned Offset = 0;
public:
/// If the reader is in little-endian mode then bits will be read
/// from the least significant to the most significant. Otherwise
/// they will be read from the most significant to the least
/// significant.
BitPatternReader(const APInt &value, bool littleEndian) :
Value(value),
LittleEndian(littleEndian) {}
/// Read the given number of bits from the unread part of the
/// underlying value and adjust the remaining value as appropriate.
APInt read(unsigned numBits) {
assert(numBits % 8 == 0);
assert(Value.getBitWidth() >= Offset + numBits);
unsigned offset = Offset;
if (!LittleEndian) {
offset = Value.getBitWidth() - offset - numBits;
}
Offset += numBits;
return Value.extractBits(numBits, offset);
}
// Skip the number of bits provided.
void skip(unsigned numBits) {
assert(numBits % 8 == 0);
assert(Value.getBitWidth() >= Offset + numBits);
Offset += numBits;
}
};
} // end namespace irgen
} // end namespace swift