summaryrefslogtreecommitdiff
path: root/lib/Support
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-05-22 19:43:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-05-22 19:43:28 +0000
commitb5630dbadf9a2a06754194387d6b0fd9962a67f1 (patch)
tree3fe1e2bc0dc2823ab21f06959fbb3eaca317ea29 /lib/Support
parent7af96fb3afd6725a2824a0a5ca5dad34e5e0b056 (diff)
Notes
Diffstat (limited to 'lib/Support')
-rw-r--r--lib/Support/APInt.cpp253
-rw-r--r--lib/Support/BinaryStreamReader.cpp18
-rw-r--r--lib/Support/BinaryStreamRef.cpp137
-rw-r--r--lib/Support/BinaryStreamWriter.cpp11
-rw-r--r--lib/Support/CMakeLists.txt1
-rw-r--r--lib/Support/FormattedStream.cpp1
-rw-r--r--lib/Support/Triple.cpp18
7 files changed, 379 insertions, 60 deletions
diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp
index 17144522db82..2a916b14bc22 100644
--- a/lib/Support/APInt.cpp
+++ b/lib/Support/APInt.cpp
@@ -1398,8 +1398,8 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
DEBUG(dbgs() << '\n');
}
-void APInt::divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
- unsigned rhsWords, APInt *Quotient, APInt *Remainder) {
+void APInt::divide(const WordType *LHS, unsigned lhsWords, const WordType *RHS,
+ unsigned rhsWords, WordType *Quotient, WordType *Remainder) {
assert(lhsWords >= rhsWords && "Fractional result");
// First, compose the values into an array of 32-bit words instead of
@@ -1436,7 +1436,7 @@ void APInt::divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
// Initialize the dividend
memset(U, 0, (m+n+1)*sizeof(uint32_t));
for (unsigned i = 0; i < lhsWords; ++i) {
- uint64_t tmp = LHS.getRawData()[i];
+ uint64_t tmp = LHS[i];
U[i * 2] = Lo_32(tmp);
U[i * 2 + 1] = Hi_32(tmp);
}
@@ -1445,7 +1445,7 @@ void APInt::divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
// Initialize the divisor
memset(V, 0, (n)*sizeof(uint32_t));
for (unsigned i = 0; i < rhsWords; ++i) {
- uint64_t tmp = RHS.getRawData()[i];
+ uint64_t tmp = RHS[i];
V[i * 2] = Lo_32(tmp);
V[i * 2 + 1] = Hi_32(tmp);
}
@@ -1502,48 +1502,14 @@ void APInt::divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
// If the caller wants the quotient
if (Quotient) {
- // Set up the Quotient value's memory.
- Quotient->reallocate(LHS.BitWidth);
- // Clear out any previous bits.
- Quotient->clearAllBits();
-
- // The quotient is in Q. Reconstitute the quotient into Quotient's low
- // order words.
- // This case is currently dead as all users of divide() handle trivial cases
- // earlier.
- if (lhsWords == 1) {
- uint64_t tmp = Make_64(Q[1], Q[0]);
- if (Quotient->isSingleWord())
- Quotient->U.VAL = tmp;
- else
- Quotient->U.pVal[0] = tmp;
- } else {
- assert(!Quotient->isSingleWord() && "Quotient APInt not large enough");
- for (unsigned i = 0; i < lhsWords; ++i)
- Quotient->U.pVal[i] = Make_64(Q[i*2+1], Q[i*2]);
- }
+ for (unsigned i = 0; i < lhsWords; ++i)
+ Quotient[i] = Make_64(Q[i*2+1], Q[i*2]);
}
// If the caller wants the remainder
if (Remainder) {
- // Set up the Remainder value's memory.
- Remainder->reallocate(RHS.BitWidth);
- // Clear out any previous bits.
- Remainder->clearAllBits();
-
- // The remainder is in R. Reconstitute the remainder into Remainder's low
- // order words.
- if (rhsWords == 1) {
- uint64_t tmp = Make_64(R[1], R[0]);
- if (Remainder->isSingleWord())
- Remainder->U.VAL = tmp;
- else
- Remainder->U.pVal[0] = tmp;
- } else {
- assert(!Remainder->isSingleWord() && "Remainder APInt not large enough");
- for (unsigned i = 0; i < rhsWords; ++i)
- Remainder->U.pVal[i] = Make_64(R[i*2+1], R[i*2]);
- }
+ for (unsigned i = 0; i < rhsWords; ++i)
+ Remainder[i] = Make_64(R[i*2+1], R[i*2]);
}
// Clean up the memory we allocated.
@@ -1555,7 +1521,7 @@ void APInt::divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
}
}
-APInt APInt::udiv(const APInt& RHS) const {
+APInt APInt::udiv(const APInt &RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
// First, deal with the easy case
@@ -1588,8 +1554,41 @@ APInt APInt::udiv(const APInt& RHS) const {
return APInt(BitWidth, this->U.pVal[0] / RHS.U.pVal[0]);
// We have to compute it the hard way. Invoke the Knuth divide algorithm.
- APInt Quotient; // to hold result.
- divide(*this, lhsWords, RHS, rhsWords, &Quotient, nullptr);
+ APInt Quotient(BitWidth, 0); // to hold result.
+ divide(U.pVal, lhsWords, RHS.U.pVal, rhsWords, Quotient.U.pVal, nullptr);
+ return Quotient;
+}
+
+APInt APInt::udiv(uint64_t RHS) const {
+ assert(RHS != 0 && "Divide by zero?");
+
+ // First, deal with the easy case
+ if (isSingleWord())
+ return APInt(BitWidth, U.VAL / RHS);
+
+ // Get some facts about the LHS words.
+ unsigned lhsWords = getNumWords(getActiveBits());
+
+ // Deal with some degenerate cases
+ if (!lhsWords)
+ // 0 / X ===> 0
+ return APInt(BitWidth, 0);
+ if (RHS == 1)
+ // X / 1 ===> X
+ return *this;
+ if (this->ult(RHS))
+ // X / Y ===> 0, iff X < Y
+ return APInt(BitWidth, 0);
+ if (*this == RHS)
+ // X / X ===> 1
+ return APInt(BitWidth, 1);
+ if (lhsWords == 1) // rhsWords is 1 if lhsWords is 1.
+ // All high words are zero, just use native divide
+ return APInt(BitWidth, this->U.pVal[0] / RHS);
+
+ // We have to compute it the hard way. Invoke the Knuth divide algorithm.
+ APInt Quotient(BitWidth, 0); // to hold result.
+ divide(U.pVal, lhsWords, &RHS, 1, Quotient.U.pVal, nullptr);
return Quotient;
}
@@ -1604,7 +1603,18 @@ APInt APInt::sdiv(const APInt &RHS) const {
return this->udiv(RHS);
}
-APInt APInt::urem(const APInt& RHS) const {
+APInt APInt::sdiv(int64_t RHS) const {
+ if (isNegative()) {
+ if (RHS < 0)
+ return (-(*this)).udiv(-RHS);
+ return -((-(*this)).udiv(RHS));
+ }
+ if (RHS < 0)
+ return -(this->udiv(-RHS));
+ return this->udiv(RHS);
+}
+
+APInt APInt::urem(const APInt &RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord()) {
assert(RHS.U.VAL != 0 && "Remainder by zero?");
@@ -1637,8 +1647,40 @@ APInt APInt::urem(const APInt& RHS) const {
return APInt(BitWidth, U.pVal[0] % RHS.U.pVal[0]);
// We have to compute it the hard way. Invoke the Knuth divide algorithm.
- APInt Remainder;
- divide(*this, lhsWords, RHS, rhsWords, nullptr, &Remainder);
+ APInt Remainder(BitWidth, 0);
+ divide(U.pVal, lhsWords, RHS.U.pVal, rhsWords, nullptr, Remainder.U.pVal);
+ return Remainder;
+}
+
+uint64_t APInt::urem(uint64_t RHS) const {
+ assert(RHS != 0 && "Remainder by zero?");
+
+ if (isSingleWord())
+ return U.VAL % RHS;
+
+ // Get some facts about the LHS
+ unsigned lhsWords = getNumWords(getActiveBits());
+
+ // Check the degenerate cases
+ if (lhsWords == 0)
+ // 0 % Y ===> 0
+ return 0;
+ if (RHS == 1)
+ // X % 1 ===> 0
+ return 0;
+ if (this->ult(RHS))
+ // X % Y ===> X, iff X < Y
+ return getZExtValue();
+ if (*this == RHS)
+ // X % X == 0;
+ return 0;
+ if (lhsWords == 1)
+ // All high words are zero, just use native remainder
+ return U.pVal[0] % RHS;
+
+ // We have to compute it the hard way. Invoke the Knuth divide algorithm.
+ uint64_t Remainder;
+ divide(U.pVal, lhsWords, &RHS, 1, nullptr, &Remainder);
return Remainder;
}
@@ -1653,6 +1695,17 @@ APInt APInt::srem(const APInt &RHS) const {
return this->urem(RHS);
}
+int64_t APInt::srem(int64_t RHS) const {
+ if (isNegative()) {
+ if (RHS < 0)
+ return -((-(*this)).urem(-RHS));
+ return -((-(*this)).urem(RHS));
+ }
+ if (RHS < 0)
+ return this->urem(-RHS);
+ return this->urem(RHS);
+}
+
void APInt::udivrem(const APInt &LHS, const APInt &RHS,
APInt &Quotient, APInt &Remainder) {
assert(LHS.BitWidth == RHS.BitWidth && "Bit widths must be the same");
@@ -1698,20 +1751,90 @@ void APInt::udivrem(const APInt &LHS, const APInt &RHS,
return;
}
+ // Make sure there is enough space to hold the results.
+ // NOTE: This assumes that reallocate won't affect any bits if it doesn't
+ // change the size. This is necessary if Quotient or Remainder is aliased
+ // with LHS or RHS.
+ Quotient.reallocate(BitWidth);
+ Remainder.reallocate(BitWidth);
+
if (lhsWords == 1) { // rhsWords is 1 if lhsWords is 1.
// There is only one word to consider so use the native versions.
uint64_t lhsValue = LHS.U.pVal[0];
uint64_t rhsValue = RHS.U.pVal[0];
- // Make sure there is enough space to hold the results.
- Quotient.reallocate(BitWidth);
- Remainder.reallocate(BitWidth);
Quotient = lhsValue / rhsValue;
Remainder = lhsValue % rhsValue;
return;
}
// Okay, lets do it the long way
- divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder);
+ divide(LHS.U.pVal, lhsWords, RHS.U.pVal, rhsWords, Quotient.U.pVal,
+ Remainder.U.pVal);
+ // Clear the rest of the Quotient and Remainder.
+ std::memset(Quotient.U.pVal + lhsWords, 0,
+ (getNumWords(BitWidth) - lhsWords) * APINT_WORD_SIZE);
+ std::memset(Remainder.U.pVal + rhsWords, 0,
+ (getNumWords(BitWidth) - rhsWords) * APINT_WORD_SIZE);
+}
+
+void APInt::udivrem(const APInt &LHS, uint64_t RHS, APInt &Quotient,
+ uint64_t &Remainder) {
+ assert(RHS != 0 && "Divide by zero?");
+ unsigned BitWidth = LHS.BitWidth;
+
+ // First, deal with the easy case
+ if (LHS.isSingleWord()) {
+ uint64_t QuotVal = LHS.U.VAL / RHS;
+ Remainder = LHS.U.VAL % RHS;
+ Quotient = APInt(BitWidth, QuotVal);
+ return;
+ }
+
+ // Get some size facts about the dividend and divisor
+ unsigned lhsWords = getNumWords(LHS.getActiveBits());
+
+ // Check the degenerate cases
+ if (lhsWords == 0) {
+ Quotient = 0; // 0 / Y ===> 0
+ Remainder = 0; // 0 % Y ===> 0
+ return;
+ }
+
+ if (RHS == 1) {
+ Quotient = LHS; // X / 1 ===> X
+ Remainder = 0; // X % 1 ===> 0
+ }
+
+ if (LHS.ult(RHS)) {
+ Remainder = LHS.getZExtValue(); // X % Y ===> X, iff X < Y
+ Quotient = 0; // X / Y ===> 0, iff X < Y
+ return;
+ }
+
+ if (LHS == RHS) {
+ Quotient = 1; // X / X ===> 1
+ Remainder = 0; // X % X ===> 0;
+ return;
+ }
+
+ // Make sure there is enough space to hold the results.
+ // NOTE: This assumes that reallocate won't affect any bits if it doesn't
+ // change the size. This is necessary if Quotient is aliased with LHS.
+ Quotient.reallocate(BitWidth);
+
+ if (lhsWords == 1) { // rhsWords is 1 if lhsWords is 1.
+ // There is only one word to consider so use the native versions.
+ uint64_t lhsValue = LHS.U.pVal[0];
+ Quotient = lhsValue / RHS;
+ Remainder = lhsValue % RHS;
+ return;
+ }
+
+ // Okay, lets do it the long way
+ divide(LHS.U.pVal, lhsWords, &RHS, 1, Quotient.U.pVal, &Remainder);
+ // Clear the rest of the Quotient.
+ std::memset(Quotient.U.pVal + lhsWords, 0,
+ (getNumWords(BitWidth) - lhsWords) * APINT_WORD_SIZE);
}
void APInt::sdivrem(const APInt &LHS, const APInt &RHS,
@@ -1732,6 +1855,26 @@ void APInt::sdivrem(const APInt &LHS, const APInt &RHS,
}
}
+void APInt::sdivrem(const APInt &LHS, int64_t RHS,
+ APInt &Quotient, int64_t &Remainder) {
+ uint64_t R = Remainder;
+ if (LHS.isNegative()) {
+ if (RHS < 0)
+ APInt::udivrem(-LHS, -RHS, Quotient, R);
+ else {
+ APInt::udivrem(-LHS, RHS, Quotient, R);
+ Quotient.negate();
+ }
+ R = -R;
+ } else if (RHS < 0) {
+ APInt::udivrem(LHS, -RHS, Quotient, R);
+ Quotient.negate();
+ } else {
+ APInt::udivrem(LHS, RHS, Quotient, R);
+ }
+ Remainder = R;
+}
+
APInt APInt::sadd_ov(const APInt &RHS, bool &Overflow) const {
APInt Res = *this+RHS;
Overflow = isNonNegative() == RHS.isNonNegative() &&
@@ -1962,11 +2105,9 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix,
Tmp.lshrInPlace(ShiftAmt);
}
} else {
- APInt divisor(Tmp.getBitWidth(), Radix);
- APInt APdigit;
while (Tmp.getBoolValue()) {
- udivrem(Tmp, divisor, Tmp, APdigit);
- unsigned Digit = (unsigned)APdigit.getZExtValue();
+ uint64_t Digit;
+ udivrem(Tmp, Radix, Tmp, Digit);
assert(Digit < Radix && "divide failed");
Str.push_back(Digits[Digit]);
}
diff --git a/lib/Support/BinaryStreamReader.cpp b/lib/Support/BinaryStreamReader.cpp
index 702d98770e05..5c277448a765 100644
--- a/lib/Support/BinaryStreamReader.cpp
+++ b/lib/Support/BinaryStreamReader.cpp
@@ -13,9 +13,18 @@
#include "llvm/Support/BinaryStreamRef.h"
using namespace llvm;
+using endianness = llvm::support::endianness;
-BinaryStreamReader::BinaryStreamReader(BinaryStreamRef S)
- : Stream(S), Offset(0) {}
+BinaryStreamReader::BinaryStreamReader(BinaryStreamRef Ref) : Stream(Ref) {}
+
+BinaryStreamReader::BinaryStreamReader(BinaryStream &Stream) : Stream(Stream) {}
+
+BinaryStreamReader::BinaryStreamReader(ArrayRef<uint8_t> Data,
+ endianness Endian)
+ : Stream(Data, Endian) {}
+
+BinaryStreamReader::BinaryStreamReader(StringRef Data, endianness Endian)
+ : Stream(Data, Endian) {}
Error BinaryStreamReader::readLongestContiguousChunk(
ArrayRef<uint8_t> &Buffer) {
@@ -86,6 +95,11 @@ Error BinaryStreamReader::skip(uint32_t Amount) {
return Error::success();
}
+Error BinaryStreamReader::padToAlignment(uint32_t Align) {
+ uint32_t NewOffset = alignTo(Offset, Align);
+ return skip(NewOffset - Offset);
+}
+
uint8_t BinaryStreamReader::peek() const {
ArrayRef<uint8_t> Buffer;
auto EC = Stream.readBytes(Offset, 1, Buffer);
diff --git a/lib/Support/BinaryStreamRef.cpp b/lib/Support/BinaryStreamRef.cpp
new file mode 100644
index 000000000000..fe9a8171e146
--- /dev/null
+++ b/lib/Support/BinaryStreamRef.cpp
@@ -0,0 +1,137 @@
+//===- BinaryStreamRef.cpp - ----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/BinaryStreamRef.h"
+#include "llvm/Support/BinaryByteStream.h"
+
+using namespace llvm;
+using namespace llvm::support;
+
+namespace {
+
+class ArrayRefImpl : public BinaryStream {
+public:
+ ArrayRefImpl(ArrayRef<uint8_t> Data, endianness Endian) : BBS(Data, Endian) {}
+
+ llvm::support::endianness getEndian() const override {
+ return BBS.getEndian();
+ }
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) override {
+ return BBS.readBytes(Offset, Size, Buffer);
+ }
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) override {
+ return BBS.readLongestContiguousChunk(Offset, Buffer);
+ }
+ uint32_t getLength() override { return BBS.getLength(); }
+
+private:
+ BinaryByteStream BBS;
+};
+
+class MutableArrayRefImpl : public WritableBinaryStream {
+public:
+ MutableArrayRefImpl(MutableArrayRef<uint8_t> Data, endianness Endian)
+ : BBS(Data, Endian) {}
+
+ // Inherited via WritableBinaryStream
+ llvm::support::endianness getEndian() const override {
+ return BBS.getEndian();
+ }
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) override {
+ return BBS.readBytes(Offset, Size, Buffer);
+ }
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) override {
+ return BBS.readLongestContiguousChunk(Offset, Buffer);
+ }
+ uint32_t getLength() override { return BBS.getLength(); }
+
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) override {
+ return BBS.writeBytes(Offset, Data);
+ }
+ Error commit() override { return BBS.commit(); }
+
+private:
+ MutableBinaryByteStream BBS;
+};
+}
+
+BinaryStreamRef::BinaryStreamRef(BinaryStream &Stream)
+ : BinaryStreamRef(Stream, 0, Stream.getLength()) {}
+BinaryStreamRef::BinaryStreamRef(BinaryStream &Stream, uint32_t Offset,
+ uint32_t Length)
+ : BinaryStreamRefBase(Stream, Offset, Length) {}
+BinaryStreamRef::BinaryStreamRef(ArrayRef<uint8_t> Data, endianness Endian)
+ : BinaryStreamRefBase(std::make_shared<ArrayRefImpl>(Data, Endian), 0,
+ Data.size()) {}
+BinaryStreamRef::BinaryStreamRef(StringRef Data, endianness Endian)
+ : BinaryStreamRef(makeArrayRef(Data.bytes_begin(), Data.bytes_end()),
+ Endian) {}
+
+BinaryStreamRef::BinaryStreamRef(const BinaryStreamRef &Other)
+ : BinaryStreamRefBase(Other) {}
+
+Error BinaryStreamRef::readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const {
+ if (auto EC = checkOffset(Offset, Size))
+ return EC;
+ return BorrowedImpl->readBytes(ViewOffset + Offset, Size, Buffer);
+}
+
+Error BinaryStreamRef::readLongestContiguousChunk(
+ uint32_t Offset, ArrayRef<uint8_t> &Buffer) const {
+ if (auto EC = checkOffset(Offset, 1))
+ return EC;
+
+ if (auto EC =
+ BorrowedImpl->readLongestContiguousChunk(ViewOffset + Offset, Buffer))
+ return EC;
+ // This StreamRef might refer to a smaller window over a larger stream. In
+ // that case we will have read out more bytes than we should return, because
+ // we should not read past the end of the current view.
+ uint32_t MaxLength = Length - Offset;
+ if (Buffer.size() > MaxLength)
+ Buffer = Buffer.slice(0, MaxLength);
+ return Error::success();
+}
+
+WritableBinaryStreamRef::WritableBinaryStreamRef(WritableBinaryStream &Stream)
+ : WritableBinaryStreamRef(Stream, 0, Stream.getLength()) {}
+
+WritableBinaryStreamRef::WritableBinaryStreamRef(WritableBinaryStream &Stream,
+ uint32_t Offset,
+ uint32_t Length)
+ : BinaryStreamRefBase(Stream, Offset, Length) {}
+
+WritableBinaryStreamRef::WritableBinaryStreamRef(MutableArrayRef<uint8_t> Data,
+ endianness Endian)
+ : BinaryStreamRefBase(std::make_shared<MutableArrayRefImpl>(Data, Endian),
+ 0, Data.size()) {}
+
+WritableBinaryStreamRef::WritableBinaryStreamRef(
+ const WritableBinaryStreamRef &Other)
+ : BinaryStreamRefBase(Other) {}
+
+Error WritableBinaryStreamRef::writeBytes(uint32_t Offset,
+ ArrayRef<uint8_t> Data) const {
+ if (auto EC = checkOffset(Offset, Data.size()))
+ return EC;
+
+ return BorrowedImpl->writeBytes(ViewOffset + Offset, Data);
+}
+
+WritableBinaryStreamRef::operator BinaryStreamRef() const {
+ return BinaryStreamRef(*BorrowedImpl, ViewOffset, Length);
+}
+
+/// \brief For buffered streams, commits changes to the backing store.
+Error WritableBinaryStreamRef::commit() { return BorrowedImpl->commit(); }
diff --git a/lib/Support/BinaryStreamWriter.cpp b/lib/Support/BinaryStreamWriter.cpp
index d78dbc68f593..b22eb1ed12d0 100644
--- a/lib/Support/BinaryStreamWriter.cpp
+++ b/lib/Support/BinaryStreamWriter.cpp
@@ -15,8 +15,15 @@
using namespace llvm;
-BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStreamRef S)
- : Stream(S), Offset(0) {}
+BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStreamRef Ref)
+ : Stream(Ref) {}
+
+BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStream &Stream)
+ : Stream(Stream) {}
+
+BinaryStreamWriter::BinaryStreamWriter(MutableArrayRef<uint8_t> Data,
+ llvm::support::endianness Endian)
+ : Stream(Data, Endian) {}
Error BinaryStreamWriter::writeBytes(ArrayRef<uint8_t> Buffer) {
if (auto EC = Stream.writeBytes(Offset, Buffer))
diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt
index 83376284548f..a12ba4fbfda8 100644
--- a/lib/Support/CMakeLists.txt
+++ b/lib/Support/CMakeLists.txt
@@ -39,6 +39,7 @@ add_llvm_library(LLVMSupport
Allocator.cpp
BinaryStreamError.cpp
BinaryStreamReader.cpp
+ BinaryStreamRef.cpp
BinaryStreamWriter.cpp
BlockFrequency.cpp
BranchProbability.cpp
diff --git a/lib/Support/FormattedStream.cpp b/lib/Support/FormattedStream.cpp
index 2ed71c7e4311..c01659604444 100644
--- a/lib/Support/FormattedStream.cpp
+++ b/lib/Support/FormattedStream.cpp
@@ -32,6 +32,7 @@ static void UpdatePosition(std::pair<unsigned, unsigned> &Position, const char *
switch (*Ptr) {
case '\n':
Line += 1;
+ LLVM_FALLTHROUGH;
case '\r':
Column = 0;
break;
diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp
index eb8108908ac5..b0e3d6898cae 100644
--- a/lib/Support/Triple.cpp
+++ b/lib/Support/Triple.cpp
@@ -1472,6 +1472,24 @@ bool Triple::isLittleEndian() const {
}
}
+bool Triple::isCompatibleWith(const Triple &Other) const {
+ // If vendor is apple, ignore the version number.
+ if (getVendor() == Triple::Apple)
+ return getArch() == Other.getArch() && getSubArch() == Other.getSubArch() &&
+ getVendor() == Other.getVendor() && getOS() == Other.getOS();
+
+ return *this == Other;
+}
+
+std::string Triple::merge(const Triple &Other) const {
+ // If vendor is apple, pick the triple with the larger version number.
+ if (getVendor() == Triple::Apple)
+ if (Other.isOSVersionLT(*this))
+ return str();
+
+ return Other.str();
+}
+
StringRef Triple::getARMCPUForArch(StringRef MArch) const {
if (MArch.empty())
MArch = getArchName();