aboutsummaryrefslogtreecommitdiff
path: root/lib/Support
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-05-27 18:44:32 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-05-27 18:44:32 +0000
commit5a5ac124e1efaf208671f01c46edb15f29ed2a0b (patch)
treea6140557876943cdd800ee997c9317283394b22c /lib/Support
parentf03b5bed27d0d2eafd68562ce14f8b5e3f1f0801 (diff)
downloadsrc-5a5ac124e1efaf208671f01c46edb15f29ed2a0b.tar.gz
src-5a5ac124e1efaf208671f01c46edb15f29ed2a0b.zip
Notes
Diffstat (limited to 'lib/Support')
-rw-r--r--lib/Support/APFloat.cpp10
-rw-r--r--lib/Support/APInt.cpp109
-rw-r--r--lib/Support/Allocator.cpp5
-rw-r--r--lib/Support/CMakeLists.txt34
-rw-r--r--lib/Support/COM.cpp23
-rw-r--r--lib/Support/CommandLine.cpp444
-rw-r--r--lib/Support/Compression.cpp1
-rw-r--r--lib/Support/ConvertUTFWrapper.cpp45
-rw-r--r--lib/Support/CrashRecoveryContext.cpp2
-rw-r--r--lib/Support/DAGDeltaAlgorithm.cpp26
-rw-r--r--lib/Support/DataStream.cpp6
-rw-r--r--lib/Support/Debug.cpp72
-rw-r--r--lib/Support/Dwarf.cpp364
-rw-r--r--lib/Support/FileOutputBuffer.cpp14
-rw-r--r--lib/Support/FoldingSet.cpp11
-rw-r--r--lib/Support/FormattedStream.cpp1
-rw-r--r--lib/Support/GraphWriter.cpp28
-rw-r--r--lib/Support/Host.cpp237
-rw-r--r--lib/Support/IsInf.cpp49
-rw-r--r--lib/Support/IsNAN.cpp33
-rw-r--r--lib/Support/LockFileManager.cpp73
-rw-r--r--lib/Support/MemoryBuffer.cpp1
-rw-r--r--lib/Support/Path.cpp18
-rw-r--r--lib/Support/PrettyStackTrace.cpp50
-rw-r--r--lib/Support/Process.cpp21
-rw-r--r--lib/Support/Program.cpp1
-rw-r--r--lib/Support/RandomNumberGenerator.cpp6
-rw-r--r--lib/Support/Regex.cpp6
-rw-r--r--lib/Support/ScaledNumber.cpp1
-rw-r--r--lib/Support/SmallPtrSet.cpp19
-rw-r--r--lib/Support/SourceMgr.cpp2
-rw-r--r--lib/Support/SpecialCaseList.cpp60
-rw-r--r--lib/Support/StreamingMemoryObject.cpp24
-rw-r--r--lib/Support/StringExtras.cpp1
-rw-r--r--lib/Support/StringMap.cpp5
-rw-r--r--lib/Support/SystemUtils.cpp2
-rw-r--r--lib/Support/TargetParser.cpp467
-rw-r--r--lib/Support/TargetRegistry.cpp53
-rw-r--r--lib/Support/Timer.cpp2
-rw-r--r--lib/Support/Triple.cpp303
-rw-r--r--lib/Support/Twine.cpp13
-rw-r--r--lib/Support/Unix/COM.inc27
-rw-r--r--lib/Support/Unix/Host.inc24
-rw-r--r--lib/Support/Unix/Process.inc16
-rw-r--r--lib/Support/Unix/Program.inc18
-rw-r--r--lib/Support/Unix/Signals.inc70
-rw-r--r--lib/Support/Valgrind.cpp3
-rw-r--r--lib/Support/Windows/COM.inc37
-rw-r--r--lib/Support/Windows/Path.inc57
-rw-r--r--lib/Support/Windows/Process.inc19
-rw-r--r--lib/Support/Windows/Program.inc3
-rw-r--r--lib/Support/Windows/Signals.inc285
-rw-r--r--lib/Support/Windows/TimeValue.inc1
-rw-r--r--lib/Support/Windows/WindowsSupport.h7
-rw-r--r--lib/Support/YAMLParser.cpp356
-rw-r--r--lib/Support/YAMLTraits.cpp115
-rw-r--r--lib/Support/raw_ostream.cpp95
-rw-r--r--lib/Support/regcomp.c4
58 files changed, 2355 insertions, 1424 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index 393ecf4784cb..4b0a0e5d4819 100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -1248,10 +1248,10 @@ APFloat::roundAwayFromZero(roundingMode rounding_mode,
return false;
case rmTowardPositive:
- return sign == false;
+ return !sign;
case rmTowardNegative:
- return sign == true;
+ return sign;
}
llvm_unreachable("Invalid rounding mode found");
}
@@ -1430,7 +1430,7 @@ APFloat::addOrSubtractSignificand(const APFloat &rhs, bool subtract)
/* Determine if the operation on the absolute values is effectively
an addition or subtraction. */
- subtract ^= (sign ^ rhs.sign) ? true : false;
+ subtract ^= static_cast<bool>(sign ^ rhs.sign);
/* Are we bigger exponent-wise than the RHS? */
bits = exponent - rhs.exponent;
@@ -3920,7 +3920,7 @@ APFloat::makeZero(bool Negative) {
APFloat llvm::scalbn(APFloat X, int Exp) {
if (X.isInfinity() || X.isZero() || X.isNaN())
- return std::move(X);
+ return X;
auto MaxExp = X.getSemantics().maxExponent;
auto MinExp = X.getSemantics().minExponent;
@@ -3932,5 +3932,5 @@ APFloat llvm::scalbn(APFloat X, int Exp) {
return APFloat::getZero(X.getSemantics(), X.isNegative());
X.exponent += Exp;
- return std::move(X);
+ return X;
}
diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp
index 0ddc2ab8af30..23f89bb66f9e 100644
--- a/lib/Support/APInt.cpp
+++ b/lib/Support/APInt.cpp
@@ -162,7 +162,7 @@ APInt& APInt::operator=(uint64_t RHS) {
return clearUnusedBits();
}
-/// Profile - This method 'profiles' an APInt for use with FoldingSet.
+/// This method 'profiles' an APInt for use with FoldingSet.
void APInt::Profile(FoldingSetNodeID& ID) const {
ID.AddInteger(BitWidth);
@@ -176,7 +176,7 @@ void APInt::Profile(FoldingSetNodeID& ID) const {
ID.AddInteger(pVal[i]);
}
-/// add_1 - This function adds a single "digit" integer, y, to the multiple
+/// This function adds a single "digit" integer, y, to the multiple
/// "digit" integer array, x[]. x[] is modified to reflect the addition and
/// 1 is returned if there is a carry out, otherwise 0 is returned.
/// @returns the carry of the addition.
@@ -202,7 +202,7 @@ APInt& APInt::operator++() {
return clearUnusedBits();
}
-/// sub_1 - This function subtracts a single "digit" (64-bit word), y, from
+/// This function subtracts a single "digit" (64-bit word), y, from
/// the multi-digit integer array, x[], propagating the borrowed 1 value until
/// no further borrowing is neeeded or it runs out of "digits" in x. The result
/// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted.
@@ -231,7 +231,7 @@ APInt& APInt::operator--() {
return clearUnusedBits();
}
-/// add - This function adds the integer array x to the integer array Y and
+/// This function adds the integer array x to the integer array Y and
/// places the result in dest.
/// @returns the carry out from the addition
/// @brief General addition of 64-bit integer arrays
@@ -672,12 +672,20 @@ hash_code llvm::hash_value(const APInt &Arg) {
return hash_combine_range(Arg.pVal, Arg.pVal + Arg.getNumWords());
}
-/// HiBits - This function returns the high "numBits" bits of this APInt.
+bool APInt::isSplat(unsigned SplatSizeInBits) const {
+ assert(getBitWidth() % SplatSizeInBits == 0 &&
+ "SplatSizeInBits must divide width!");
+ // We can check that all parts of an integer are equal by making use of a
+ // little trick: rotate and check if it's still the same value.
+ return *this == rotl(SplatSizeInBits);
+}
+
+/// This function returns the high "numBits" bits of this APInt.
APInt APInt::getHiBits(unsigned numBits) const {
return APIntOps::lshr(*this, BitWidth - numBits);
}
-/// LoBits - This function returns the low "numBits" bits of this APInt.
+/// This function returns the low "numBits" bits of this APInt.
APInt APInt::getLoBits(unsigned numBits) const {
return APIntOps::lshr(APIntOps::shl(*this, BitWidth - numBits),
BitWidth - numBits);
@@ -713,7 +721,7 @@ unsigned APInt::countLeadingZerosSlowCase() const {
unsigned APInt::countLeadingOnes() const {
if (isSingleWord())
- return CountLeadingOnes_64(VAL << (APINT_BITS_PER_WORD - BitWidth));
+ return llvm::countLeadingOnes(VAL << (APINT_BITS_PER_WORD - BitWidth));
unsigned highWordBits = BitWidth % APINT_BITS_PER_WORD;
unsigned shift;
@@ -724,13 +732,13 @@ unsigned APInt::countLeadingOnes() const {
shift = APINT_BITS_PER_WORD - highWordBits;
}
int i = getNumWords() - 1;
- unsigned Count = CountLeadingOnes_64(pVal[i] << shift);
+ unsigned Count = llvm::countLeadingOnes(pVal[i] << shift);
if (Count == highWordBits) {
for (i--; i >= 0; --i) {
if (pVal[i] == -1ULL)
Count += APINT_BITS_PER_WORD;
else {
- Count += CountLeadingOnes_64(pVal[i]);
+ Count += llvm::countLeadingOnes(pVal[i]);
break;
}
}
@@ -756,14 +764,14 @@ unsigned APInt::countTrailingOnesSlowCase() const {
for (; i < getNumWords() && pVal[i] == -1ULL; ++i)
Count += APINT_BITS_PER_WORD;
if (i < getNumWords())
- Count += CountTrailingOnes_64(pVal[i]);
+ Count += llvm::countTrailingOnes(pVal[i]);
return std::min(Count, BitWidth);
}
unsigned APInt::countPopulationSlowCase() const {
unsigned Count = 0;
for (unsigned i = 0; i < getNumWords(); ++i)
- Count += CountPopulation_64(pVal[i]);
+ Count += llvm::countPopulation(pVal[i]);
return Count;
}
@@ -853,7 +861,7 @@ APInt llvm::APIntOps::RoundDoubleToAPInt(double Double, unsigned width) {
return isNeg ? -Tmp : Tmp;
}
-/// RoundToDouble - This function converts this APInt to a double.
+/// This function converts this APInt to a double.
/// The layout for double is as following (IEEE Standard 754):
/// --------------------------------------
/// | Sign Exponent Fraction Bias |
@@ -1310,13 +1318,8 @@ APInt APInt::sqrt() const {
// libc sqrt function which will probably use a hardware sqrt computation.
// This should be faster than the algorithm below.
if (magnitude < 52) {
-#if HAVE_ROUND
return APInt(BitWidth,
uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0])))));
-#else
- return APInt(BitWidth,
- uint64_t(::sqrt(double(isSingleWord()?VAL:pVal[0])) + 0.5));
-#endif
}
// Okay, all the short cuts are exhausted. We must compute it. The following
@@ -1508,21 +1511,18 @@ static void KnuthDiv(unsigned *u, unsigned *v, unsigned *q, unsigned* r,
assert(u && "Must provide dividend");
assert(v && "Must provide divisor");
assert(q && "Must provide quotient");
- assert(u != v && u != q && v != q && "Must us different memory");
+ assert(u != v && u != q && v != q && "Must use different memory");
assert(n>1 && "n must be > 1");
- // Knuth uses the value b as the base of the number system. In our case b
- // is 2^31 so we just set it to -1u.
- uint64_t b = uint64_t(1) << 32;
+ // b denotes the base of the number system. In our case b is 2^32.
+ LLVM_CONSTEXPR uint64_t b = uint64_t(1) << 32;
-#if 0
DEBUG(dbgs() << "KnuthDiv: m=" << m << " n=" << n << '\n');
DEBUG(dbgs() << "KnuthDiv: original:");
DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]);
DEBUG(dbgs() << " by");
DEBUG(for (int i = n; i >0; i--) dbgs() << " " << v[i-1]);
DEBUG(dbgs() << '\n');
-#endif
// D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of
// u and v by d. Note that we have taken Knuth's advice here to use a power
// of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of
@@ -1547,13 +1547,12 @@ static void KnuthDiv(unsigned *u, unsigned *v, unsigned *q, unsigned* r,
}
}
u[m+n] = u_carry;
-#if 0
+
DEBUG(dbgs() << "KnuthDiv: normal:");
DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]);
DEBUG(dbgs() << " by");
DEBUG(for (int i = n; i >0; i--) dbgs() << " " << v[i-1]);
DEBUG(dbgs() << '\n');
-#endif
// D2. [Initialize j.] Set j to m. This is the loop counter over the places.
int j = m;
@@ -1583,44 +1582,23 @@ static void KnuthDiv(unsigned *u, unsigned *v, unsigned *q, unsigned* r,
// (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation
// consists of a simple multiplication by a one-place number, combined with
// a subtraction.
- bool isNeg = false;
- for (unsigned i = 0; i < n; ++i) {
- uint64_t u_tmp = uint64_t(u[j+i]) | (uint64_t(u[j+i+1]) << 32);
- uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]);
- bool borrow = subtrahend > u_tmp;
- DEBUG(dbgs() << "KnuthDiv: u_tmp == " << u_tmp
- << ", subtrahend == " << subtrahend
- << ", borrow = " << borrow << '\n');
-
- uint64_t result = u_tmp - subtrahend;
- unsigned k = j + i;
- u[k++] = (unsigned)(result & (b-1)); // subtract low word
- u[k++] = (unsigned)(result >> 32); // subtract high word
- while (borrow && k <= m+n) { // deal with borrow to the left
- borrow = u[k] == 0;
- u[k]--;
- k++;
- }
- isNeg |= borrow;
- DEBUG(dbgs() << "KnuthDiv: u[j+i] == " << u[j+i] << ", u[j+i+1] == " <<
- u[j+i+1] << '\n');
- }
- DEBUG(dbgs() << "KnuthDiv: after subtraction:");
- DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]);
- DEBUG(dbgs() << '\n');
// The digits (u[j+n]...u[j]) should be kept positive; if the result of
// this step is actually negative, (u[j+n]...u[j]) should be left as the
// true value plus b**(n+1), namely as the b's complement of
// the true value, and a "borrow" to the left should be remembered.
- //
- if (isNeg) {
- bool carry = true; // true because b's complement is "complement + 1"
- for (unsigned i = 0; i <= m+n; ++i) {
- u[i] = ~u[i] + carry; // b's complement
- carry = carry && u[i] == 0;
- }
+ int64_t borrow = 0;
+ for (unsigned i = 0; i < n; ++i) {
+ uint64_t p = uint64_t(qp) * uint64_t(v[i]);
+ int64_t subres = int64_t(u[j+i]) - borrow - (unsigned)p;
+ u[j+i] = (unsigned)subres;
+ borrow = (p >> 32) - (subres >> 32);
+ DEBUG(dbgs() << "KnuthDiv: u[j+i] = " << u[j+i]
+ << ", borrow = " << borrow << '\n');
}
- DEBUG(dbgs() << "KnuthDiv: after complement:");
+ bool isNeg = u[j+n] < borrow;
+ u[j+n] -= (unsigned)borrow;
+
+ DEBUG(dbgs() << "KnuthDiv: after subtraction:");
DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]);
DEBUG(dbgs() << '\n');
@@ -1644,7 +1622,7 @@ static void KnuthDiv(unsigned *u, unsigned *v, unsigned *q, unsigned* r,
u[j+n] += carry;
}
DEBUG(dbgs() << "KnuthDiv: after correction:");
- DEBUG(for (int i = m+n; i >=0; i--) dbgs() <<" " << u[i]);
+ DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]);
DEBUG(dbgs() << "\nKnuthDiv: digit result = " << q[j] << '\n');
// D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3.
@@ -1677,9 +1655,7 @@ static void KnuthDiv(unsigned *u, unsigned *v, unsigned *q, unsigned* r,
}
DEBUG(dbgs() << '\n');
}
-#if 0
DEBUG(dbgs() << '\n');
-#endif
}
void APInt::divide(const APInt LHS, unsigned lhsWords,
@@ -1803,6 +1779,8 @@ void APInt::divide(const APInt LHS, unsigned lhsWords,
// 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 =
uint64_t(Q[0]) | (uint64_t(Q[1]) << (APINT_BITS_PER_WORD / 2));
@@ -2281,9 +2259,8 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix,
std::reverse(Str.begin()+StartDig, Str.end());
}
-/// toString - This returns the APInt as a std::string. Note that this is an
-/// inefficient method. It is better to pass in a SmallVector/SmallString
-/// to the methods above.
+/// Returns the APInt as a std::string. Note that this is an inefficient method.
+/// It is better to pass in a SmallVector/SmallString to the methods above.
std::string APInt::toString(unsigned Radix = 10, bool Signed = true) const {
SmallString<40> S;
toString(S, Radix, Signed, /* formatAsCLiteral = */false);
@@ -2296,13 +2273,13 @@ void APInt::dump() const {
this->toStringUnsigned(U);
this->toStringSigned(S);
dbgs() << "APInt(" << BitWidth << "b, "
- << U.str() << "u " << S.str() << "s)";
+ << U << "u " << S << "s)";
}
void APInt::print(raw_ostream &OS, bool isSigned) const {
SmallString<40> S;
this->toString(S, 10, isSigned, /* formatAsCLiteral = */false);
- OS << S.str();
+ OS << S;
}
// This implements a variety of operations on a representation of
diff --git a/lib/Support/Allocator.cpp b/lib/Support/Allocator.cpp
index 7c306b2370e6..f48edac0598c 100644
--- a/lib/Support/Allocator.cpp
+++ b/lib/Support/Allocator.cpp
@@ -12,12 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/Memory.h"
-#include "llvm/Support/Recycler.h"
#include "llvm/Support/raw_ostream.h"
-#include <cstring>
namespace llvm {
diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt
index fa62591191db..79aae1584357 100644
--- a/lib/Support/CMakeLists.txt
+++ b/lib/Support/CMakeLists.txt
@@ -1,7 +1,7 @@
set(system_libs)
if( NOT MSVC )
if( MINGW )
- set(system_libs ${system_libs} imagehlp psapi shell32)
+ set(system_libs ${system_libs} imagehlp psapi shell32 ole32)
elseif( CMAKE_HOST_UNIX )
if( HAVE_LIBRT )
set(system_libs ${system_libs} rt)
@@ -37,6 +37,7 @@ add_llvm_library(LLVMSupport
BlockFrequency.cpp
BranchProbability.cpp
circular_raw_ostream.cpp
+ COM.cpp
CommandLine.cpp
Compression.cpp
ConvertUTF.c
@@ -58,8 +59,6 @@ add_llvm_library(LLVMSupport
IntEqClasses.cpp
IntervalMap.cpp
IntrusiveRefCntPtr.cpp
- IsInf.cpp
- IsNAN.cpp
LEB128.cpp
LineIterator.cpp
Locale.cpp
@@ -86,6 +85,7 @@ add_llvm_library(LLVMSupport
StringPool.cpp
StringRef.cpp
SystemUtils.cpp
+ TargetParser.cpp
Timer.cpp
ToolOutputFile.cpp
Triple.cpp
@@ -121,30 +121,10 @@ add_llvm_library(LLVMSupport
Valgrind.cpp
Watchdog.cpp
- ADDITIONAL_HEADERS
- Unix/Host.inc
- Unix/Memory.inc
- Unix/Mutex.inc
- Unix/Path.inc
- Unix/Process.inc
- Unix/Program.inc
- Unix/RWMutex.inc
- Unix/Signals.inc
- Unix/ThreadLocal.inc
- Unix/TimeValue.inc
- Unix/Watchdog.inc
- Windows/DynamicLibrary.inc
- Windows/Host.inc
- Windows/Memory.inc
- Windows/Mutex.inc
- Windows/Path.inc
- Windows/Process.inc
- Windows/Program.inc
- Windows/RWMutex.inc
- Windows/Signals.inc
- Windows/ThreadLocal.inc
- Windows/TimeValue.inc
- Windows/Watchdog.inc
+ ADDITIONAL_HEADER_DIRS
+ Unix
+ Windows
+ ${LLVM_MAIN_INCLUDE_DIR}/llvm/Support
LINK_LIBS ${system_libs}
)
diff --git a/lib/Support/COM.cpp b/lib/Support/COM.cpp
new file mode 100644
index 000000000000..cf3a133fd9b4
--- /dev/null
+++ b/lib/Support/COM.cpp
@@ -0,0 +1,23 @@
+//===-- COM.cpp - Implement COM utility classes -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements utility classes related to COM.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/COM.h"
+
+#include "llvm/Config/config.h"
+
+// Include the platform-specific parts of this class.
+#ifdef LLVM_ON_UNIX
+#include "Unix/COM.inc"
+#elif LLVM_ON_WIN32
+#include "Windows/COM.inc"
+#endif
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp
index 40570cab7cc8..3cabc54a73aa 100644
--- a/lib/Support/CommandLine.cpp
+++ b/lib/Support/CommandLine.cpp
@@ -19,6 +19,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm-c/Support.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
@@ -32,10 +33,8 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
-#include <cerrno>
#include <cstdlib>
#include <map>
-#include <system_error>
using namespace llvm;
using namespace cl;
@@ -83,129 +82,172 @@ void StringSaver::anchor() {}
//===----------------------------------------------------------------------===//
-// Globals for name and overview of program. Program name is not a string to
-// avoid static ctor/dtor issues.
-static char ProgramName[80] = "<premain>";
-static const char *ProgramOverview = nullptr;
+namespace {
-// This collects additional help to be printed.
-static ManagedStatic<std::vector<const char *>> MoreHelp;
+class CommandLineParser {
+public:
+ // Globals for name and overview of program. Program name is not a string to
+ // avoid static ctor/dtor issues.
+ std::string ProgramName;
+ const char *ProgramOverview;
-extrahelp::extrahelp(const char *Help) : morehelp(Help) {
- MoreHelp->push_back(Help);
-}
+ // This collects additional help to be printed.
+ std::vector<const char *> MoreHelp;
-static bool OptionListChanged = false;
+ SmallVector<Option *, 4> PositionalOpts;
+ SmallVector<Option *, 4> SinkOpts;
+ StringMap<Option *> OptionsMap;
-// MarkOptionsChanged - Internal helper function.
-void cl::MarkOptionsChanged() { OptionListChanged = true; }
+ Option *ConsumeAfterOpt; // The ConsumeAfter option if it exists.
-/// RegisteredOptionList - This is the list of the command line options that
-/// have statically constructed themselves.
-static Option *RegisteredOptionList = nullptr;
+ // This collects the different option categories that have been registered.
+ SmallPtrSet<OptionCategory *, 16> RegisteredOptionCategories;
-void Option::addArgument() {
- assert(!NextRegistered && "argument multiply registered!");
+ CommandLineParser() : ProgramOverview(nullptr), ConsumeAfterOpt(nullptr) {}
- NextRegistered = RegisteredOptionList;
- RegisteredOptionList = this;
- MarkOptionsChanged();
-}
+ void ParseCommandLineOptions(int argc, const char *const *argv,
+ const char *Overview);
-void Option::removeArgument() {
- if (RegisteredOptionList == this) {
- RegisteredOptionList = NextRegistered;
- MarkOptionsChanged();
- return;
+ void addLiteralOption(Option &Opt, const char *Name) {
+ if (!Opt.hasArgStr()) {
+ if (!OptionsMap.insert(std::make_pair(Name, &Opt)).second) {
+ errs() << ProgramName << ": CommandLine Error: Option '" << Name
+ << "' registered more than once!\n";
+ report_fatal_error("inconsistency in registered CommandLine options");
+ }
+ }
}
- Option *O = RegisteredOptionList;
- for (; O->NextRegistered != this; O = O->NextRegistered)
- ;
- O->NextRegistered = NextRegistered;
- MarkOptionsChanged();
-}
-
-// This collects the different option categories that have been registered.
-typedef SmallPtrSet<OptionCategory *, 16> OptionCatSet;
-static ManagedStatic<OptionCatSet> RegisteredOptionCategories;
-// Initialise the general option category.
-OptionCategory llvm::cl::GeneralCategory("General options");
-
-void OptionCategory::registerCategory() {
- assert(std::count_if(RegisteredOptionCategories->begin(),
- RegisteredOptionCategories->end(),
- [this](const OptionCategory *Category) {
- return getName() == Category->getName();
- }) == 0 &&
- "Duplicate option categories");
-
- RegisteredOptionCategories->insert(this);
-}
-
-//===----------------------------------------------------------------------===//
-// Basic, shared command line option processing machinery.
-//
-
-/// GetOptionInfo - Scan the list of registered options, turning them into data
-/// structures that are easier to handle.
-static void GetOptionInfo(SmallVectorImpl<Option *> &PositionalOpts,
- SmallVectorImpl<Option *> &SinkOpts,
- StringMap<Option *> &OptionsMap) {
- bool HadErrors = false;
- SmallVector<const char *, 16> OptionNames;
- Option *CAOpt = nullptr; // The ConsumeAfter option if it exists.
- for (Option *O = RegisteredOptionList; O; O = O->getNextRegisteredOption()) {
- // If this option wants to handle multiple option names, get the full set.
- // This handles enum options like "-O1 -O2" etc.
- O->getExtraOptionNames(OptionNames);
- if (O->ArgStr[0])
- OptionNames.push_back(O->ArgStr);
-
- // Handle named options.
- for (size_t i = 0, e = OptionNames.size(); i != e; ++i) {
+ void addOption(Option *O) {
+ bool HadErrors = false;
+ if (O->ArgStr[0]) {
// Add argument to the argument map!
- if (!OptionsMap.insert(std::make_pair(OptionNames[i], O)).second) {
- errs() << ProgramName << ": CommandLine Error: Option '"
- << OptionNames[i] << "' registered more than once!\n";
+ if (!OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) {
+ errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr
+ << "' registered more than once!\n";
HadErrors = true;
}
}
- OptionNames.clear();
-
// Remember information about positional options.
if (O->getFormattingFlag() == cl::Positional)
PositionalOpts.push_back(O);
else if (O->getMiscFlags() & cl::Sink) // Remember sink options
SinkOpts.push_back(O);
else if (O->getNumOccurrencesFlag() == cl::ConsumeAfter) {
- if (CAOpt) {
+ if (ConsumeAfterOpt) {
O->error("Cannot specify more than one option with cl::ConsumeAfter!");
HadErrors = true;
}
- CAOpt = O;
+ ConsumeAfterOpt = O;
}
+
+ // Fail hard if there were errors. These are strictly unrecoverable and
+ // indicate serious issues such as conflicting option names or an
+ // incorrectly
+ // linked LLVM distribution.
+ if (HadErrors)
+ report_fatal_error("inconsistency in registered CommandLine options");
}
- if (CAOpt)
- PositionalOpts.push_back(CAOpt);
+ void removeOption(Option *O) {
+ SmallVector<const char *, 16> OptionNames;
+ O->getExtraOptionNames(OptionNames);
+ if (O->ArgStr[0])
+ OptionNames.push_back(O->ArgStr);
+ for (auto Name : OptionNames)
+ OptionsMap.erase(StringRef(Name));
- // Make sure that they are in order of registration not backwards.
- std::reverse(PositionalOpts.begin(), PositionalOpts.end());
+ if (O->getFormattingFlag() == cl::Positional)
+ for (auto Opt = PositionalOpts.begin(); Opt != PositionalOpts.end();
+ ++Opt) {
+ if (*Opt == O) {
+ PositionalOpts.erase(Opt);
+ break;
+ }
+ }
+ else if (O->getMiscFlags() & cl::Sink)
+ for (auto Opt = SinkOpts.begin(); Opt != SinkOpts.end(); ++Opt) {
+ if (*Opt == O) {
+ SinkOpts.erase(Opt);
+ break;
+ }
+ }
+ else if (O == ConsumeAfterOpt)
+ ConsumeAfterOpt = nullptr;
+ }
+
+ bool hasOptions() {
+ return (!OptionsMap.empty() || !PositionalOpts.empty() ||
+ nullptr != ConsumeAfterOpt);
+ }
+
+ void updateArgStr(Option *O, const char *NewName) {
+ if (!OptionsMap.insert(std::make_pair(NewName, O)).second) {
+ errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr
+ << "' registered more than once!\n";
+ report_fatal_error("inconsistency in registered CommandLine options");
+ }
+ OptionsMap.erase(StringRef(O->ArgStr));
+ }
+
+ void printOptionValues();
+
+ void registerCategory(OptionCategory *cat) {
+ assert(std::count_if(RegisteredOptionCategories.begin(),
+ RegisteredOptionCategories.end(),
+ [cat](const OptionCategory *Category) {
+ return cat->getName() == Category->getName();
+ }) == 0 &&
+ "Duplicate option categories");
+
+ RegisteredOptionCategories.insert(cat);
+ }
- // Fail hard if there were errors. These are strictly unrecoverable and
- // indicate serious issues such as conflicting option names or an incorrectly
- // linked LLVM distribution.
- if (HadErrors)
- report_fatal_error("inconsistency in registered CommandLine options");
+private:
+ Option *LookupOption(StringRef &Arg, StringRef &Value);
+};
+
+} // namespace
+
+static ManagedStatic<CommandLineParser> GlobalParser;
+
+void cl::AddLiteralOption(Option &O, const char *Name) {
+ GlobalParser->addLiteralOption(O, Name);
}
+extrahelp::extrahelp(const char *Help) : morehelp(Help) {
+ GlobalParser->MoreHelp.push_back(Help);
+}
+
+void Option::addArgument() {
+ GlobalParser->addOption(this);
+ FullyInitialized = true;
+}
+
+void Option::removeArgument() { GlobalParser->removeOption(this); }
+
+void Option::setArgStr(const char *S) {
+ if (FullyInitialized)
+ GlobalParser->updateArgStr(this, S);
+ ArgStr = S;
+}
+
+// Initialise the general option category.
+OptionCategory llvm::cl::GeneralCategory("General options");
+
+void OptionCategory::registerCategory() {
+ GlobalParser->registerCategory(this);
+}
+
+//===----------------------------------------------------------------------===//
+// Basic, shared command line option processing machinery.
+//
+
/// LookupOption - Lookup the option specified by the specified option on the
/// command line. If there is a value specified (after an equal sign) return
/// that as well. This assumes that leading dashes have already been stripped.
-static Option *LookupOption(StringRef &Arg, StringRef &Value,
- const StringMap<Option *> &OptionsMap) {
+Option *CommandLineParser::LookupOption(StringRef &Arg, StringRef &Value) {
// Reject all dashes.
if (Arg.empty())
return nullptr;
@@ -271,7 +313,7 @@ static Option *LookupNearestOption(StringRef Arg,
if (RHS.empty() || !PermitValue)
NearestString = OptionNames[i];
else
- NearestString = std::string(OptionNames[i]) + "=" + RHS.str();
+ NearestString = (Twine(OptionNames[i]) + "=" + RHS).str();
}
}
}
@@ -655,6 +697,12 @@ void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver,
NewArgv.push_back(nullptr);
}
+// It is called byte order marker but the UTF-8 BOM is actually not affected
+// by the host system's endianness.
+static bool hasUTF8ByteOrderMark(ArrayRef<char> S) {
+ return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf');
+}
+
static bool ExpandResponseFile(const char *FName, StringSaver &Saver,
TokenizerCallback Tokenizer,
SmallVectorImpl<const char *> &NewArgv,
@@ -674,6 +722,11 @@ static bool ExpandResponseFile(const char *FName, StringSaver &Saver,
return false;
Str = StringRef(UTF8Buf);
}
+ // If we see UTF-8 BOM sequence at the beginning of a file, we shall remove
+ // these bytes before parsing.
+ // Reference: http://en.wikipedia.org/wiki/UTF-8#Byte_order_mark
+ else if (hasUTF8ByteOrderMark(BufRef))
+ Str = StringRef(BufRef.data() + 3, BufRef.size() - 3);
// Tokenize the contents into NewArgv.
Tokenizer(Str, Saver, NewArgv, MarkEOLs);
@@ -731,7 +784,7 @@ class StrDupSaver : public StringSaver {
std::vector<char *> Dups;
public:
- ~StrDupSaver() {
+ ~StrDupSaver() override {
for (std::vector<char *>::iterator I = Dups.begin(), E = Dups.end(); I != E;
++I) {
char *Dup = *I;
@@ -777,28 +830,23 @@ void cl::ParseEnvironmentOptions(const char *progName, const char *envVar,
void cl::ParseCommandLineOptions(int argc, const char *const *argv,
const char *Overview) {
- // Process all registered options.
- SmallVector<Option *, 4> PositionalOpts;
- SmallVector<Option *, 4> SinkOpts;
- StringMap<Option *> Opts;
- GetOptionInfo(PositionalOpts, SinkOpts, Opts);
+ GlobalParser->ParseCommandLineOptions(argc, argv, Overview);
+}
- assert((!Opts.empty() || !PositionalOpts.empty()) && "No options specified!");
+void CommandLineParser::ParseCommandLineOptions(int argc,
+ const char *const *argv,
+ const char *Overview) {
+ assert(hasOptions() && "No options specified!");
// Expand response files.
- SmallVector<const char *, 20> newArgv;
- for (int i = 0; i != argc; ++i)
- newArgv.push_back(argv[i]);
+ SmallVector<const char *, 20> newArgv(argv, argv + argc);
StrDupSaver Saver;
ExpandResponseFiles(Saver, TokenizeGNUCommandLine, newArgv);
argv = &newArgv[0];
argc = static_cast<int>(newArgv.size());
// Copy the program name into ProgName, making sure not to overflow it.
- StringRef ProgName = sys::path::filename(argv[0]);
- size_t Len = std::min(ProgName.size(), size_t(79));
- memcpy(ProgramName, ProgName.data(), Len);
- ProgramName[Len] = '\0';
+ ProgramName = sys::path::filename(argv[0]);
ProgramOverview = Overview;
bool ErrorParsing = false;
@@ -809,25 +857,22 @@ void cl::ParseCommandLineOptions(int argc, const char *const *argv,
// Determine whether or not there are an unlimited number of positionals
bool HasUnlimitedPositionals = false;
- Option *ConsumeAfterOpt = nullptr;
+ if (ConsumeAfterOpt) {
+ assert(PositionalOpts.size() > 0 &&
+ "Cannot specify cl::ConsumeAfter without a positional argument!");
+ }
if (!PositionalOpts.empty()) {
- if (PositionalOpts[0]->getNumOccurrencesFlag() == cl::ConsumeAfter) {
- assert(PositionalOpts.size() > 1 &&
- "Cannot specify cl::ConsumeAfter without a positional argument!");
- ConsumeAfterOpt = PositionalOpts[0];
- }
// Calculate how many positional values are _required_.
bool UnboundedFound = false;
- for (size_t i = ConsumeAfterOpt ? 1 : 0, e = PositionalOpts.size(); i != e;
- ++i) {
+ for (size_t i = 0, e = PositionalOpts.size(); i != e; ++i) {
Option *Opt = PositionalOpts[i];
if (RequiresValue(Opt))
++NumPositionalRequired;
else if (ConsumeAfterOpt) {
// ConsumeAfter cannot be combined with "optional" positional options
// unless there is only one positional argument...
- if (PositionalOpts.size() > 2)
+ if (PositionalOpts.size() > 1)
ErrorParsing |= Opt->error(
"error - this positional option will never be matched, "
"because it does not Require a value, and a "
@@ -841,6 +886,9 @@ void cl::ParseCommandLineOptions(int argc, const char *const *argv,
"another positional argument will match an "
"unbounded number of values, and this option"
" does not require a value!");
+ errs() << ProgramName << ": CommandLine Error: Option '" << Opt->ArgStr
+ << "' is all messed up!\n";
+ errs() << PositionalOpts.size();
}
UnboundedFound |= EatsUnboundedNumberOfValues(Opt);
}
@@ -866,17 +914,6 @@ void cl::ParseCommandLineOptions(int argc, const char *const *argv,
StringRef Value;
StringRef ArgName = "";
- // If the option list changed, this means that some command line
- // option has just been registered or deregistered. This can occur in
- // response to things like -load, etc. If this happens, rescan the options.
- if (OptionListChanged) {
- PositionalOpts.clear();
- SinkOpts.clear();
- Opts.clear();
- GetOptionInfo(PositionalOpts, SinkOpts, Opts);
- OptionListChanged = false;
- }
-
// Check to see if this is a positional argument. This argument is
// considered to be positional if it doesn't start with '-', if it is "-"
// itself, or if we have seen "--" already.
@@ -917,7 +954,7 @@ void cl::ParseCommandLineOptions(int argc, const char *const *argv,
while (!ArgName.empty() && ArgName[0] == '-')
ArgName = ArgName.substr(1);
- Handler = LookupOption(ArgName, Value, Opts);
+ Handler = LookupOption(ArgName, Value);
if (!Handler || Handler->getFormattingFlag() != cl::Positional) {
ProvidePositionalOption(ActivePositionalArg, argv[i], i);
continue; // We are done!
@@ -929,18 +966,18 @@ void cl::ParseCommandLineOptions(int argc, const char *const *argv,
while (!ArgName.empty() && ArgName[0] == '-')
ArgName = ArgName.substr(1);
- Handler = LookupOption(ArgName, Value, Opts);
+ Handler = LookupOption(ArgName, Value);
// Check to see if this "option" is really a prefixed or grouped argument.
if (!Handler)
- Handler =
- HandlePrefixedOrGroupedOption(ArgName, Value, ErrorParsing, Opts);
+ Handler = HandlePrefixedOrGroupedOption(ArgName, Value, ErrorParsing,
+ OptionsMap);
// Otherwise, look for the closest available option to report to the user
// in the upcoming error.
if (!Handler && SinkOpts.empty())
NearestHandler =
- LookupNearestOption(ArgName, Opts, NearestHandlerString);
+ LookupNearestOption(ArgName, OptionsMap, NearestHandlerString);
}
if (!Handler) {
@@ -1037,8 +1074,8 @@ void cl::ParseCommandLineOptions(int argc, const char *const *argv,
// positional option and keep the rest for the consume after. The above
// loop would have assigned no values to positional options in this case.
//
- if (PositionalOpts.size() == 2 && ValNo == 0 && !PositionalVals.empty()) {
- ErrorParsing |= ProvidePositionalOption(PositionalOpts[1],
+ if (PositionalOpts.size() == 1 && ValNo == 0 && !PositionalVals.empty()) {
+ ErrorParsing |= ProvidePositionalOption(PositionalOpts[0],
PositionalVals[ValNo].first,
PositionalVals[ValNo].second);
ValNo++;
@@ -1053,7 +1090,7 @@ void cl::ParseCommandLineOptions(int argc, const char *const *argv,
}
// Loop over args and make sure all required args are specified!
- for (const auto &Opt : Opts) {
+ for (const auto &Opt : OptionsMap) {
switch (Opt.second->getNumOccurrencesFlag()) {
case Required:
case OneOrMore:
@@ -1076,9 +1113,7 @@ void cl::ParseCommandLineOptions(int argc, const char *const *argv,
// Free all of the memory allocated to the map. Command line options may only
// be processed once!
- Opts.clear();
- PositionalOpts.clear();
- MoreHelp->clear();
+ MoreHelp.clear();
// If we had an error processing our arguments, don't let the program execute
if (ErrorParsing)
@@ -1095,7 +1130,7 @@ bool Option::error(const Twine &Message, StringRef ArgName) {
if (ArgName.empty())
errs() << HelpStr; // Be nice for positional arguments
else
- errs() << ProgramName << ": for the -" << ArgName;
+ errs() << GlobalParser->ProgramName << ": for the -" << ArgName;
errs() << " option: " << Message << "\n";
return true;
@@ -1427,10 +1462,9 @@ void basic_parser_impl::printOptionNoValue(const Option &O,
// -help and -help-hidden option implementation
//
-static int OptNameCompare(const void *LHS, const void *RHS) {
- typedef std::pair<const char *, Option *> pair_ty;
-
- return strcmp(((const pair_ty *)LHS)->first, ((const pair_ty *)RHS)->first);
+static int OptNameCompare(const std::pair<const char *, Option *> *LHS,
+ const std::pair<const char *, Option *> *RHS) {
+ return strcmp(LHS->first, RHS->first);
}
// Copy Options into a vector so we can sort them as we like.
@@ -1458,7 +1492,7 @@ static void sortOpts(StringMap<Option *> &OptMap,
}
// Sort the options list alphabetically.
- qsort(Opts.data(), Opts.size(), sizeof(Opts[0]), OptNameCompare);
+ array_pod_sort(Opts.begin(), Opts.end(), OptNameCompare);
}
namespace {
@@ -1480,38 +1514,26 @@ public:
// Invoke the printer.
void operator=(bool Value) {
- if (Value == false)
+ if (!Value)
return;
- // Get all the options.
- SmallVector<Option *, 4> PositionalOpts;
- SmallVector<Option *, 4> SinkOpts;
- StringMap<Option *> OptMap;
- GetOptionInfo(PositionalOpts, SinkOpts, OptMap);
-
StrOptionPairVector Opts;
- sortOpts(OptMap, Opts, ShowHidden);
-
- if (ProgramOverview)
- outs() << "OVERVIEW: " << ProgramOverview << "\n";
+ sortOpts(GlobalParser->OptionsMap, Opts, ShowHidden);
- outs() << "USAGE: " << ProgramName << " [options]";
+ if (GlobalParser->ProgramOverview)
+ outs() << "OVERVIEW: " << GlobalParser->ProgramOverview << "\n";
- // Print out the positional options.
- Option *CAOpt = nullptr; // The cl::ConsumeAfter option, if it exists...
- if (!PositionalOpts.empty() &&
- PositionalOpts[0]->getNumOccurrencesFlag() == ConsumeAfter)
- CAOpt = PositionalOpts[0];
+ outs() << "USAGE: " << GlobalParser->ProgramName << " [options]";
- for (size_t i = CAOpt != nullptr, e = PositionalOpts.size(); i != e; ++i) {
- if (PositionalOpts[i]->ArgStr[0])
- outs() << " --" << PositionalOpts[i]->ArgStr;
- outs() << " " << PositionalOpts[i]->HelpStr;
+ for (auto Opt : GlobalParser->PositionalOpts) {
+ if (Opt->ArgStr[0])
+ outs() << " --" << Opt->ArgStr;
+ outs() << " " << Opt->HelpStr;
}
// Print the consume after option info if it exists...
- if (CAOpt)
- outs() << " " << CAOpt->HelpStr;
+ if (GlobalParser->ConsumeAfterOpt)
+ outs() << " " << GlobalParser->ConsumeAfterOpt->HelpStr;
outs() << "\n\n";
@@ -1524,11 +1546,9 @@ public:
printOptions(Opts, MaxArgLen);
// Print any extra help the user has declared.
- for (std::vector<const char *>::iterator I = MoreHelp->begin(),
- E = MoreHelp->end();
- I != E; ++I)
- outs() << *I;
- MoreHelp->clear();
+ for (auto I : GlobalParser->MoreHelp)
+ outs() << I;
+ GlobalParser->MoreHelp.clear();
// Halt the program since help information was printed
exit(0);
@@ -1540,10 +1560,11 @@ public:
explicit CategorizedHelpPrinter(bool showHidden) : HelpPrinter(showHidden) {}
// Helper function for printOptions().
- // It shall return true if A's name should be lexographically
- // ordered before B's name. It returns false otherwise.
- static bool OptionCategoryCompare(OptionCategory *A, OptionCategory *B) {
- return strcmp(A->getName(), B->getName()) < 0;
+ // It shall return a negative value if A's name should be lexicographically
+ // ordered before B's name. It returns a value greater equal zero otherwise.
+ static int OptionCategoryCompare(OptionCategory *const *A,
+ OptionCategory *const *B) {
+ return strcmp((*A)->getName(), (*B)->getName());
}
// Make sure we inherit our base class's operator=()
@@ -1556,16 +1577,16 @@ protected:
// Collect registered option categories into vector in preparation for
// sorting.
- for (OptionCatSet::const_iterator I = RegisteredOptionCategories->begin(),
- E = RegisteredOptionCategories->end();
+ for (auto I = GlobalParser->RegisteredOptionCategories.begin(),
+ E = GlobalParser->RegisteredOptionCategories.end();
I != E; ++I) {
SortedCategories.push_back(*I);
}
// Sort the different option categories alphabetically.
assert(SortedCategories.size() > 0 && "No option categories registered!");
- std::sort(SortedCategories.begin(), SortedCategories.end(),
- OptionCategoryCompare);
+ array_pod_sort(SortedCategories.begin(), SortedCategories.end(),
+ OptionCategoryCompare);
// Create map to empty vectors.
for (std::vector<OptionCategory *>::const_iterator
@@ -1653,48 +1674,54 @@ static HelpPrinterWrapper WrappedNormalPrinter(UncategorizedNormalPrinter,
static HelpPrinterWrapper WrappedHiddenPrinter(UncategorizedHiddenPrinter,
CategorizedHiddenPrinter);
+// Define a category for generic options that all tools should have.
+static cl::OptionCategory GenericCategory("Generic Options");
+
// Define uncategorized help printers.
// -help-list is hidden by default because if Option categories are being used
// then -help behaves the same as -help-list.
static cl::opt<HelpPrinter, true, parser<bool>> HLOp(
"help-list",
cl::desc("Display list of available options (-help-list-hidden for more)"),
- cl::location(UncategorizedNormalPrinter), cl::Hidden, cl::ValueDisallowed);
+ cl::location(UncategorizedNormalPrinter), cl::Hidden, cl::ValueDisallowed,
+ cl::cat(GenericCategory));
static cl::opt<HelpPrinter, true, parser<bool>>
HLHOp("help-list-hidden", cl::desc("Display list of all available options"),
cl::location(UncategorizedHiddenPrinter), cl::Hidden,
- cl::ValueDisallowed);
+ cl::ValueDisallowed, cl::cat(GenericCategory));
// Define uncategorized/categorized help printers. These printers change their
// behaviour at runtime depending on whether one or more Option categories have
// been declared.
static cl::opt<HelpPrinterWrapper, true, parser<bool>>
HOp("help", cl::desc("Display available options (-help-hidden for more)"),
- cl::location(WrappedNormalPrinter), cl::ValueDisallowed);
+ cl::location(WrappedNormalPrinter), cl::ValueDisallowed,
+ cl::cat(GenericCategory));
static cl::opt<HelpPrinterWrapper, true, parser<bool>>
HHOp("help-hidden", cl::desc("Display all available options"),
- cl::location(WrappedHiddenPrinter), cl::Hidden, cl::ValueDisallowed);
+ cl::location(WrappedHiddenPrinter), cl::Hidden, cl::ValueDisallowed,
+ cl::cat(GenericCategory));
static cl::opt<bool> PrintOptions(
"print-options",
cl::desc("Print non-default options after command line parsing"),
- cl::Hidden, cl::init(false));
+ cl::Hidden, cl::init(false), cl::cat(GenericCategory));
static cl::opt<bool> PrintAllOptions(
"print-all-options",
cl::desc("Print all option values after command line parsing"), cl::Hidden,
- cl::init(false));
+ cl::init(false), cl::cat(GenericCategory));
void HelpPrinterWrapper::operator=(bool Value) {
- if (Value == false)
+ if (!Value)
return;
// Decide which printer to invoke. If more than one option category is
// registered then it is useful to show the categorized help instead of
// uncategorized help.
- if (RegisteredOptionCategories->size() > 1) {
+ if (GlobalParser->RegisteredOptionCategories.size() > 1) {
// unhide -help-list option so user can have uncategorized output if they
// want it.
HLOp.setHiddenFlag(NotHidden);
@@ -1705,18 +1732,14 @@ void HelpPrinterWrapper::operator=(bool Value) {
}
// Print the value of each option.
-void cl::PrintOptionValues() {
+void cl::PrintOptionValues() { GlobalParser->printOptionValues(); }
+
+void CommandLineParser::printOptionValues() {
if (!PrintOptions && !PrintAllOptions)
return;
- // Get all the options.
- SmallVector<Option *, 4> PositionalOpts;
- SmallVector<Option *, 4> SinkOpts;
- StringMap<Option *> OptMap;
- GetOptionInfo(PositionalOpts, SinkOpts, OptMap);
-
SmallVector<std::pair<const char *, Option *>, 128> Opts;
- sortOpts(OptMap, Opts, /*ShowHidden*/ true);
+ sortOpts(OptionsMap, Opts, /*ShowHidden*/ true);
// Compute the maximum argument length...
size_t MaxArgLen = 0;
@@ -1790,7 +1813,8 @@ static VersionPrinter VersionPrinterInstance;
static cl::opt<VersionPrinter, true, parser<bool>>
VersOp("version", cl::desc("Display the version of this program"),
- cl::location(VersionPrinterInstance), cl::ValueDisallowed);
+ cl::location(VersionPrinterInstance), cl::ValueDisallowed,
+ cl::cat(GenericCategory));
// Utility function for printing the help message.
void cl::PrintHelpMessage(bool Hidden, bool Categorized) {
@@ -1823,13 +1847,27 @@ void cl::AddExtraVersionPrinter(void (*func)()) {
ExtraVersionPrinters->push_back(func);
}
-void cl::getRegisteredOptions(StringMap<Option *> &Map) {
- // Get all the options.
- SmallVector<Option *, 4> PositionalOpts; // NOT USED
- SmallVector<Option *, 4> SinkOpts; // NOT USED
- assert(Map.size() == 0 && "StringMap must be empty");
- GetOptionInfo(PositionalOpts, SinkOpts, Map);
- return;
+StringMap<Option *> &cl::getRegisteredOptions() {
+ return GlobalParser->OptionsMap;
+}
+
+void cl::HideUnrelatedOptions(cl::OptionCategory &Category) {
+ for (auto &I : GlobalParser->OptionsMap) {
+ if (I.second->Category != &Category &&
+ I.second->Category != &GenericCategory)
+ I.second->setHiddenFlag(cl::ReallyHidden);
+ }
+}
+
+void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories) {
+ auto CategoriesBegin = Categories.begin();
+ auto CategoriesEnd = Categories.end();
+ for (auto &I : GlobalParser->OptionsMap) {
+ if (std::find(CategoriesBegin, CategoriesEnd, I.second->Category) ==
+ CategoriesEnd &&
+ I.second->Category != &GenericCategory)
+ I.second->setHiddenFlag(cl::ReallyHidden);
+ }
}
void LLVMParseCommandLineOptions(int argc, const char *const *argv,
diff --git a/lib/Support/Compression.cpp b/lib/Support/Compression.cpp
index 17ae2957d12f..b54613e92b8b 100644
--- a/lib/Support/Compression.cpp
+++ b/lib/Support/Compression.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/Compression.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Compiler.h"
diff --git a/lib/Support/ConvertUTFWrapper.cpp b/lib/Support/ConvertUTFWrapper.cpp
index e45335ddcb6c..1bbef233b82f 100644
--- a/lib/Support/ConvertUTFWrapper.cpp
+++ b/lib/Support/ConvertUTFWrapper.cpp
@@ -109,8 +109,9 @@ bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out) {
if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_NATIVE)
Src++;
- // Just allocate enough space up front. We'll shrink it later.
- Out.resize(SrcBytes.size() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT);
+ // Just allocate enough space up front. We'll shrink it later. Allocate
+ // enough that we can fit a null terminator without reallocating.
+ Out.resize(SrcBytes.size() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1);
UTF8 *Dst = reinterpret_cast<UTF8 *>(&Out[0]);
UTF8 *DstEnd = Dst + Out.size();
@@ -124,6 +125,46 @@ bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out) {
}
Out.resize(reinterpret_cast<char *>(Dst) - &Out[0]);
+ Out.push_back(0);
+ Out.pop_back();
+ return true;
+}
+
+bool convertUTF8ToUTF16String(StringRef SrcUTF8,
+ SmallVectorImpl<UTF16> &DstUTF16) {
+ assert(DstUTF16.empty());
+
+ // Avoid OOB by returning early on empty input.
+ if (SrcUTF8.empty()) {
+ DstUTF16.push_back(0);
+ DstUTF16.pop_back();
+ return true;
+ }
+
+ const UTF8 *Src = reinterpret_cast<const UTF8 *>(SrcUTF8.begin());
+ const UTF8 *SrcEnd = reinterpret_cast<const UTF8 *>(SrcUTF8.end());
+
+ // Allocate the same number of UTF-16 code units as UTF-8 code units. Encoding
+ // as UTF-16 should always require the same amount or less code units than the
+ // UTF-8 encoding. Allocate one extra byte for the null terminator though,
+ // so that someone calling DstUTF16.data() gets a null terminated string.
+ // We resize down later so we don't have to worry that this over allocates.
+ DstUTF16.resize(SrcUTF8.size()+1);
+ UTF16 *Dst = &DstUTF16[0];
+ UTF16 *DstEnd = Dst + DstUTF16.size();
+
+ ConversionResult CR =
+ ConvertUTF8toUTF16(&Src, SrcEnd, &Dst, DstEnd, strictConversion);
+ assert(CR != targetExhausted);
+
+ if (CR != conversionOK) {
+ DstUTF16.clear();
+ return false;
+ }
+
+ DstUTF16.resize(Dst - &DstUTF16[0]);
+ DstUTF16.push_back(0);
+ DstUTF16.pop_back();
return true;
}
diff --git a/lib/Support/CrashRecoveryContext.cpp b/lib/Support/CrashRecoveryContext.cpp
index 9b0e44339d84..aba0f1ddeee8 100644
--- a/lib/Support/CrashRecoveryContext.cpp
+++ b/lib/Support/CrashRecoveryContext.cpp
@@ -8,13 +8,11 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/CrashRecoveryContext.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/Config/config.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/ThreadLocal.h"
-#include <cstdio>
#include <setjmp.h>
using namespace llvm;
diff --git a/lib/Support/DAGDeltaAlgorithm.cpp b/lib/Support/DAGDeltaAlgorithm.cpp
index 0d504ee86b43..f1a334bfc7be 100644
--- a/lib/Support/DAGDeltaAlgorithm.cpp
+++ b/lib/Support/DAGDeltaAlgorithm.cpp
@@ -63,9 +63,6 @@ private:
DAGDeltaAlgorithm &DDA;
- const changeset_ty &Changes;
- const std::vector<edge_ty> &Dependencies;
-
std::vector<change_ty> Roots;
/// Cache of failed test results. Successful test results are never cached
@@ -139,9 +136,8 @@ private:
}
public:
- DAGDeltaAlgorithmImpl(DAGDeltaAlgorithm &_DDA,
- const changeset_ty &_Changes,
- const std::vector<edge_ty> &_Dependencies);
+ DAGDeltaAlgorithmImpl(DAGDeltaAlgorithm &DDA, const changeset_ty &Changes,
+ const std::vector<edge_ty> &Dependencies);
changeset_ty Run();
@@ -174,21 +170,17 @@ protected:
}
public:
- DeltaActiveSetHelper(DAGDeltaAlgorithmImpl &_DDAI,
- const changeset_ty &_Required)
- : DDAI(_DDAI), Required(_Required) {}
+ DeltaActiveSetHelper(DAGDeltaAlgorithmImpl &DDAI,
+ const changeset_ty &Required)
+ : DDAI(DDAI), Required(Required) {}
};
}
-DAGDeltaAlgorithmImpl::DAGDeltaAlgorithmImpl(DAGDeltaAlgorithm &_DDA,
- const changeset_ty &_Changes,
- const std::vector<edge_ty>
- &_Dependencies)
- : DDA(_DDA),
- Changes(_Changes),
- Dependencies(_Dependencies)
-{
+DAGDeltaAlgorithmImpl::DAGDeltaAlgorithmImpl(
+ DAGDeltaAlgorithm &DDA, const changeset_ty &Changes,
+ const std::vector<edge_ty> &Dependencies)
+ : DDA(DDA) {
for (changeset_ty::const_iterator it = Changes.begin(),
ie = Changes.end(); it != ie; ++it) {
Predecessors.insert(std::make_pair(*it, std::vector<change_ty>()));
diff --git a/lib/Support/DataStream.cpp b/lib/Support/DataStream.cpp
index dbf6465189de..c24315526cff 100644
--- a/lib/Support/DataStream.cpp
+++ b/lib/Support/DataStream.cpp
@@ -18,8 +18,6 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Program.h"
-#include <cerrno>
-#include <cstdio>
#include <string>
#include <system_error>
#if !defined(_MSC_VER) && !defined(__MINGW32__)
@@ -56,9 +54,7 @@ class DataFileStreamer : public DataStreamer {
int Fd;
public:
DataFileStreamer() : Fd(0) {}
- virtual ~DataFileStreamer() {
- close(Fd);
- }
+ ~DataFileStreamer() override { close(Fd); }
size_t GetBytes(unsigned char *buf, size_t len) override {
NumStreamFetches++;
return read(Fd, buf, len);
diff --git a/lib/Support/Debug.cpp b/lib/Support/Debug.cpp
index cb86ea6a600a..eb99242914c2 100644
--- a/lib/Support/Debug.cpp
+++ b/lib/Support/Debug.cpp
@@ -28,12 +28,49 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/circular_raw_ostream.h"
+#include "llvm/Support/raw_ostream.h"
+
+#undef isCurrentDebugType
+#undef setCurrentDebugType
using namespace llvm;
+// Even though LLVM might be built with NDEBUG, define symbols that the code
+// built without NDEBUG can depend on via the llvm/Support/Debug.h header.
+namespace llvm {
+/// Exported boolean set by the -debug option.
+bool DebugFlag = false;
+
+static ManagedStatic<std::vector<std::string>> CurrentDebugType;
+
+/// Return true if the specified string is the debug type
+/// specified on the command line, or if none was specified on the command line
+/// with the -debug-only=X option.
+bool isCurrentDebugType(const char *DebugType) {
+ if (CurrentDebugType->empty())
+ return true;
+ // see if DebugType is in list. Note: do not use find() as that forces us to
+ // unnecessarily create an std::string instance.
+ for (auto d : *CurrentDebugType) {
+ if (d == DebugType)
+ return true;
+ }
+ return false;
+}
+
+/// Set the current debug type, as if the -debug-only=X
+/// option were specified. Note that DebugFlag also needs to be set to true for
+/// debug output to be produced.
+///
+void setCurrentDebugType(const char *Type) {
+ CurrentDebugType->clear();
+ CurrentDebugType->push_back(Type);
+}
+
+} // namespace llvm
+
// All Debug.h functionality is a no-op in NDEBUG mode.
#ifndef NDEBUG
-bool llvm::DebugFlag; // DebugFlag - Exported boolean set by the -debug option
// -debug - Command line option to enable the DEBUG statements in the passes.
// This flag may only be enabled in debug builds.
@@ -51,8 +88,6 @@ DebugBufferSize("debug-buffer-size",
cl::Hidden,
cl::init(0));
-static ManagedStatic<std::vector<std::string> > CurrentDebugType;
-
namespace {
struct DebugOnlyOpt {
@@ -79,34 +114,9 @@ static void debug_user_sig_handler(void *Cookie) {
// know that debug mode is enabled and dbgs() really is a
// circular_raw_ostream. If NDEBUG is defined, then dbgs() ==
// errs() but this will never be invoked.
- llvm::circular_raw_ostream *dbgout =
- static_cast<llvm::circular_raw_ostream *>(&llvm::dbgs());
- dbgout->flushBufferWithBanner();
-}
-
-// isCurrentDebugType - Return true if the specified string is the debug type
-// specified on the command line, or if none was specified on the command line
-// with the -debug-only=X option.
-//
-bool llvm::isCurrentDebugType(const char *DebugType) {
- if (CurrentDebugType->empty())
- return true;
- // see if DebugType is in list. Note: do not use find() as that forces us to
- // unnecessarily create an std::string instance.
- for (auto d : *CurrentDebugType) {
- if (d == DebugType)
- return true;
- }
- return false;
-}
-
-/// setCurrentDebugType - Set the current debug type, as if the -debug-only=X
-/// option were specified. Note that DebugFlag also needs to be set to true for
-/// debug output to be produced.
-///
-void llvm::setCurrentDebugType(const char *Type) {
- CurrentDebugType->clear();
- CurrentDebugType->push_back(Type);
+ llvm::circular_raw_ostream &dbgout =
+ static_cast<circular_raw_ostream &>(llvm::dbgs());
+ dbgout.flushBufferWithBanner();
}
/// dbgs - Return a circular-buffered debug stream.
diff --git a/lib/Support/Dwarf.cpp b/lib/Support/Dwarf.cpp
index 4b6337ecc52c..6229825a8ee2 100644
--- a/lib/Support/Dwarf.cpp
+++ b/lib/Support/Dwarf.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/Dwarf.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
@@ -19,87 +20,19 @@ using namespace dwarf;
const char *llvm::dwarf::TagString(unsigned Tag) {
switch (Tag) {
- case DW_TAG_array_type: return "DW_TAG_array_type";
- case DW_TAG_class_type: return "DW_TAG_class_type";
- case DW_TAG_entry_point: return "DW_TAG_entry_point";
- case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type";
- case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter";
- case DW_TAG_imported_declaration: return "DW_TAG_imported_declaration";
- case DW_TAG_label: return "DW_TAG_label";
- case DW_TAG_lexical_block: return "DW_TAG_lexical_block";
- case DW_TAG_member: return "DW_TAG_member";
- case DW_TAG_pointer_type: return "DW_TAG_pointer_type";
- case DW_TAG_reference_type: return "DW_TAG_reference_type";
- case DW_TAG_compile_unit: return "DW_TAG_compile_unit";
- case DW_TAG_string_type: return "DW_TAG_string_type";
- case DW_TAG_structure_type: return "DW_TAG_structure_type";
- case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type";
- case DW_TAG_typedef: return "DW_TAG_typedef";
- case DW_TAG_union_type: return "DW_TAG_union_type";
- case DW_TAG_unspecified_parameters: return "DW_TAG_unspecified_parameters";
- case DW_TAG_variant: return "DW_TAG_variant";
- case DW_TAG_common_block: return "DW_TAG_common_block";
- case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion";
- case DW_TAG_inheritance: return "DW_TAG_inheritance";
- case DW_TAG_inlined_subroutine: return "DW_TAG_inlined_subroutine";
- case DW_TAG_module: return "DW_TAG_module";
- case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type";
- case DW_TAG_set_type: return "DW_TAG_set_type";
- case DW_TAG_subrange_type: return "DW_TAG_subrange_type";
- case DW_TAG_with_stmt: return "DW_TAG_with_stmt";
- case DW_TAG_access_declaration: return "DW_TAG_access_declaration";
- case DW_TAG_base_type: return "DW_TAG_base_type";
- case DW_TAG_catch_block: return "DW_TAG_catch_block";
- case DW_TAG_const_type: return "DW_TAG_const_type";
- case DW_TAG_constant: return "DW_TAG_constant";
- case DW_TAG_enumerator: return "DW_TAG_enumerator";
- case DW_TAG_file_type: return "DW_TAG_file_type";
- case DW_TAG_friend: return "DW_TAG_friend";
- case DW_TAG_namelist: return "DW_TAG_namelist";
- case DW_TAG_namelist_item: return "DW_TAG_namelist_item";
- case DW_TAG_packed_type: return "DW_TAG_packed_type";
- case DW_TAG_subprogram: return "DW_TAG_subprogram";
- case DW_TAG_template_type_parameter: return "DW_TAG_template_type_parameter";
- case DW_TAG_template_value_parameter: return "DW_TAG_template_value_parameter";
- case DW_TAG_thrown_type: return "DW_TAG_thrown_type";
- case DW_TAG_try_block: return "DW_TAG_try_block";
- case DW_TAG_variant_part: return "DW_TAG_variant_part";
- case DW_TAG_variable: return "DW_TAG_variable";
- case DW_TAG_volatile_type: return "DW_TAG_volatile_type";
- case DW_TAG_dwarf_procedure: return "DW_TAG_dwarf_procedure";
- case DW_TAG_restrict_type: return "DW_TAG_restrict_type";
- case DW_TAG_interface_type: return "DW_TAG_interface_type";
- case DW_TAG_namespace: return "DW_TAG_namespace";
- case DW_TAG_imported_module: return "DW_TAG_imported_module";
- case DW_TAG_unspecified_type: return "DW_TAG_unspecified_type";
- case DW_TAG_partial_unit: return "DW_TAG_partial_unit";
- case DW_TAG_imported_unit: return "DW_TAG_imported_unit";
- case DW_TAG_condition: return "DW_TAG_condition";
- case DW_TAG_shared_type: return "DW_TAG_shared_type";
- case DW_TAG_lo_user: return "DW_TAG_lo_user";
- case DW_TAG_hi_user: return "DW_TAG_hi_user";
- case DW_TAG_auto_variable: return "DW_TAG_auto_variable";
- case DW_TAG_arg_variable: return "DW_TAG_arg_variable";
- case DW_TAG_expression: return "DW_TAG_expression";
- case DW_TAG_rvalue_reference_type: return "DW_TAG_rvalue_reference_type";
- case DW_TAG_template_alias: return "DW_TAG_template_alias";
- case DW_TAG_coarray_type: return "DW_TAG_coarray_type";
- case DW_TAG_generic_subrange: return "DW_TAG_generic_subrange";
- case DW_TAG_dynamic_type: return "DW_TAG_dynamic_type";
- case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop";
- case DW_TAG_type_unit: return "DW_TAG_type_unit";
- case DW_TAG_format_label: return "DW_TAG_format_label";
- case DW_TAG_function_template: return "DW_TAG_function_template";
- case DW_TAG_class_template: return "DW_TAG_class_template";
- case DW_TAG_GNU_template_template_param:
- return "DW_TAG_GNU_template_template_param";
- case DW_TAG_GNU_template_parameter_pack:
- return "DW_TAG_GNU_template_parameter_pack";
- case DW_TAG_GNU_formal_parameter_pack:
- return "DW_TAG_GNU_formal_parameter_pack";
- case DW_TAG_APPLE_property: return "DW_TAG_APPLE_property";
+ default: return nullptr;
+#define HANDLE_DW_TAG(ID, NAME) \
+ case DW_TAG_##NAME: \
+ return "DW_TAG_" #NAME;
+#include "llvm/Support/Dwarf.def"
}
- return nullptr;
+}
+
+unsigned llvm::dwarf::getTag(StringRef TagString) {
+ return StringSwitch<unsigned>(TagString)
+#define HANDLE_DW_TAG(ID, NAME) .Case("DW_TAG_" #NAME, DW_TAG_##NAME)
+#include "llvm/Support/Dwarf.def"
+ .Default(DW_TAG_invalid);
}
const char *llvm::dwarf::ChildrenString(unsigned Children) {
@@ -300,199 +233,46 @@ const char *llvm::dwarf::FormEncodingString(unsigned Encoding) {
// DWARF5 Fission Extension Forms
case DW_FORM_GNU_addr_index: return "DW_FORM_GNU_addr_index";
case DW_FORM_GNU_str_index: return "DW_FORM_GNU_str_index";
+
+ // Alternate debug sections proposal (output of "dwz" tool).
+ case DW_FORM_GNU_ref_alt: return "DW_FORM_GNU_ref_alt";
+ case DW_FORM_GNU_strp_alt: return "DW_FORM_GNU_strp_alt";
}
return nullptr;
}
const char *llvm::dwarf::OperationEncodingString(unsigned Encoding) {
switch (Encoding) {
- case DW_OP_addr: return "DW_OP_addr";
- case DW_OP_deref: return "DW_OP_deref";
- case DW_OP_const1u: return "DW_OP_const1u";
- case DW_OP_const1s: return "DW_OP_const1s";
- case DW_OP_const2u: return "DW_OP_const2u";
- case DW_OP_const2s: return "DW_OP_const2s";
- case DW_OP_const4u: return "DW_OP_const4u";
- case DW_OP_const4s: return "DW_OP_const4s";
- case DW_OP_const8u: return "DW_OP_const8u";
- case DW_OP_const8s: return "DW_OP_const8s";
- case DW_OP_constu: return "DW_OP_constu";
- case DW_OP_consts: return "DW_OP_consts";
- case DW_OP_dup: return "DW_OP_dup";
- case DW_OP_drop: return "DW_OP_drop";
- case DW_OP_over: return "DW_OP_over";
- case DW_OP_pick: return "DW_OP_pick";
- case DW_OP_swap: return "DW_OP_swap";
- case DW_OP_rot: return "DW_OP_rot";
- case DW_OP_xderef: return "DW_OP_xderef";
- case DW_OP_abs: return "DW_OP_abs";
- case DW_OP_and: return "DW_OP_and";
- case DW_OP_div: return "DW_OP_div";
- case DW_OP_minus: return "DW_OP_minus";
- case DW_OP_mod: return "DW_OP_mod";
- case DW_OP_mul: return "DW_OP_mul";
- case DW_OP_neg: return "DW_OP_neg";
- case DW_OP_not: return "DW_OP_not";
- case DW_OP_or: return "DW_OP_or";
- case DW_OP_plus: return "DW_OP_plus";
- case DW_OP_plus_uconst: return "DW_OP_plus_uconst";
- case DW_OP_shl: return "DW_OP_shl";
- case DW_OP_shr: return "DW_OP_shr";
- case DW_OP_shra: return "DW_OP_shra";
- case DW_OP_xor: return "DW_OP_xor";
- case DW_OP_skip: return "DW_OP_skip";
- case DW_OP_bra: return "DW_OP_bra";
- case DW_OP_eq: return "DW_OP_eq";
- case DW_OP_ge: return "DW_OP_ge";
- case DW_OP_gt: return "DW_OP_gt";
- case DW_OP_le: return "DW_OP_le";
- case DW_OP_lt: return "DW_OP_lt";
- case DW_OP_ne: return "DW_OP_ne";
- case DW_OP_lit0: return "DW_OP_lit0";
- case DW_OP_lit1: return "DW_OP_lit1";
- case DW_OP_lit2: return "DW_OP_lit2";
- case DW_OP_lit3: return "DW_OP_lit3";
- case DW_OP_lit4: return "DW_OP_lit4";
- case DW_OP_lit5: return "DW_OP_lit5";
- case DW_OP_lit6: return "DW_OP_lit6";
- case DW_OP_lit7: return "DW_OP_lit7";
- case DW_OP_lit8: return "DW_OP_lit8";
- case DW_OP_lit9: return "DW_OP_lit9";
- case DW_OP_lit10: return "DW_OP_lit10";
- case DW_OP_lit11: return "DW_OP_lit11";
- case DW_OP_lit12: return "DW_OP_lit12";
- case DW_OP_lit13: return "DW_OP_lit13";
- case DW_OP_lit14: return "DW_OP_lit14";
- case DW_OP_lit15: return "DW_OP_lit15";
- case DW_OP_lit16: return "DW_OP_lit16";
- case DW_OP_lit17: return "DW_OP_lit17";
- case DW_OP_lit18: return "DW_OP_lit18";
- case DW_OP_lit19: return "DW_OP_lit19";
- case DW_OP_lit20: return "DW_OP_lit20";
- case DW_OP_lit21: return "DW_OP_lit21";
- case DW_OP_lit22: return "DW_OP_lit22";
- case DW_OP_lit23: return "DW_OP_lit23";
- case DW_OP_lit24: return "DW_OP_lit24";
- case DW_OP_lit25: return "DW_OP_lit25";
- case DW_OP_lit26: return "DW_OP_lit26";
- case DW_OP_lit27: return "DW_OP_lit27";
- case DW_OP_lit28: return "DW_OP_lit28";
- case DW_OP_lit29: return "DW_OP_lit29";
- case DW_OP_lit30: return "DW_OP_lit30";
- case DW_OP_lit31: return "DW_OP_lit31";
- case DW_OP_reg0: return "DW_OP_reg0";
- case DW_OP_reg1: return "DW_OP_reg1";
- case DW_OP_reg2: return "DW_OP_reg2";
- case DW_OP_reg3: return "DW_OP_reg3";
- case DW_OP_reg4: return "DW_OP_reg4";
- case DW_OP_reg5: return "DW_OP_reg5";
- case DW_OP_reg6: return "DW_OP_reg6";
- case DW_OP_reg7: return "DW_OP_reg7";
- case DW_OP_reg8: return "DW_OP_reg8";
- case DW_OP_reg9: return "DW_OP_reg9";
- case DW_OP_reg10: return "DW_OP_reg10";
- case DW_OP_reg11: return "DW_OP_reg11";
- case DW_OP_reg12: return "DW_OP_reg12";
- case DW_OP_reg13: return "DW_OP_reg13";
- case DW_OP_reg14: return "DW_OP_reg14";
- case DW_OP_reg15: return "DW_OP_reg15";
- case DW_OP_reg16: return "DW_OP_reg16";
- case DW_OP_reg17: return "DW_OP_reg17";
- case DW_OP_reg18: return "DW_OP_reg18";
- case DW_OP_reg19: return "DW_OP_reg19";
- case DW_OP_reg20: return "DW_OP_reg20";
- case DW_OP_reg21: return "DW_OP_reg21";
- case DW_OP_reg22: return "DW_OP_reg22";
- case DW_OP_reg23: return "DW_OP_reg23";
- case DW_OP_reg24: return "DW_OP_reg24";
- case DW_OP_reg25: return "DW_OP_reg25";
- case DW_OP_reg26: return "DW_OP_reg26";
- case DW_OP_reg27: return "DW_OP_reg27";
- case DW_OP_reg28: return "DW_OP_reg28";
- case DW_OP_reg29: return "DW_OP_reg29";
- case DW_OP_reg30: return "DW_OP_reg30";
- case DW_OP_reg31: return "DW_OP_reg31";
- case DW_OP_breg0: return "DW_OP_breg0";
- case DW_OP_breg1: return "DW_OP_breg1";
- case DW_OP_breg2: return "DW_OP_breg2";
- case DW_OP_breg3: return "DW_OP_breg3";
- case DW_OP_breg4: return "DW_OP_breg4";
- case DW_OP_breg5: return "DW_OP_breg5";
- case DW_OP_breg6: return "DW_OP_breg6";
- case DW_OP_breg7: return "DW_OP_breg7";
- case DW_OP_breg8: return "DW_OP_breg8";
- case DW_OP_breg9: return "DW_OP_breg9";
- case DW_OP_breg10: return "DW_OP_breg10";
- case DW_OP_breg11: return "DW_OP_breg11";
- case DW_OP_breg12: return "DW_OP_breg12";
- case DW_OP_breg13: return "DW_OP_breg13";
- case DW_OP_breg14: return "DW_OP_breg14";
- case DW_OP_breg15: return "DW_OP_breg15";
- case DW_OP_breg16: return "DW_OP_breg16";
- case DW_OP_breg17: return "DW_OP_breg17";
- case DW_OP_breg18: return "DW_OP_breg18";
- case DW_OP_breg19: return "DW_OP_breg19";
- case DW_OP_breg20: return "DW_OP_breg20";
- case DW_OP_breg21: return "DW_OP_breg21";
- case DW_OP_breg22: return "DW_OP_breg22";
- case DW_OP_breg23: return "DW_OP_breg23";
- case DW_OP_breg24: return "DW_OP_breg24";
- case DW_OP_breg25: return "DW_OP_breg25";
- case DW_OP_breg26: return "DW_OP_breg26";
- case DW_OP_breg27: return "DW_OP_breg27";
- case DW_OP_breg28: return "DW_OP_breg28";
- case DW_OP_breg29: return "DW_OP_breg29";
- case DW_OP_breg30: return "DW_OP_breg30";
- case DW_OP_breg31: return "DW_OP_breg31";
- case DW_OP_regx: return "DW_OP_regx";
- case DW_OP_fbreg: return "DW_OP_fbreg";
- case DW_OP_bregx: return "DW_OP_bregx";
- case DW_OP_piece: return "DW_OP_piece";
- case DW_OP_deref_size: return "DW_OP_deref_size";
- case DW_OP_xderef_size: return "DW_OP_xderef_size";
- case DW_OP_nop: return "DW_OP_nop";
- case DW_OP_push_object_address: return "DW_OP_push_object_address";
- case DW_OP_call2: return "DW_OP_call2";
- case DW_OP_call4: return "DW_OP_call4";
- case DW_OP_call_ref: return "DW_OP_call_ref";
- case DW_OP_form_tls_address: return "DW_OP_form_tls_address";
- case DW_OP_call_frame_cfa: return "DW_OP_call_frame_cfa";
- case DW_OP_bit_piece: return "DW_OP_bit_piece";
- case DW_OP_implicit_value: return "DW_OP_implicit_value";
- case DW_OP_stack_value: return "DW_OP_stack_value";
-
- // GNU thread-local storage
- case DW_OP_GNU_push_tls_address: return "DW_OP_GNU_push_tls_address";
-
- // DWARF5 Fission Proposal Op Extensions
- case DW_OP_GNU_addr_index: return "DW_OP_GNU_addr_index";
- case DW_OP_GNU_const_index: return "DW_OP_GNU_const_index";
+ default: return nullptr;
+#define HANDLE_DW_OP(ID, NAME) \
+ case DW_OP_##NAME: \
+ return "DW_OP_" #NAME;
+#include "llvm/Support/Dwarf.def"
}
- return nullptr;
+}
+
+unsigned llvm::dwarf::getOperationEncoding(StringRef OperationEncodingString) {
+ return StringSwitch<unsigned>(OperationEncodingString)
+#define HANDLE_DW_OP(ID, NAME) .Case("DW_OP_" #NAME, DW_OP_##NAME)
+#include "llvm/Support/Dwarf.def"
+ .Default(0);
}
const char *llvm::dwarf::AttributeEncodingString(unsigned Encoding) {
switch (Encoding) {
- case DW_ATE_address: return "DW_ATE_address";
- case DW_ATE_boolean: return "DW_ATE_boolean";
- case DW_ATE_complex_float: return "DW_ATE_complex_float";
- case DW_ATE_float: return "DW_ATE_float";
- case DW_ATE_signed: return "DW_ATE_signed";
- case DW_ATE_signed_char: return "DW_ATE_signed_char";
- case DW_ATE_unsigned: return "DW_ATE_unsigned";
- case DW_ATE_unsigned_char: return "DW_ATE_unsigned_char";
- case DW_ATE_imaginary_float: return "DW_ATE_imaginary_float";
- case DW_ATE_UTF: return "DW_ATE_UTF";
- case DW_ATE_packed_decimal: return "DW_ATE_packed_decimal";
- case DW_ATE_numeric_string: return "DW_ATE_numeric_string";
- case DW_ATE_edited: return "DW_ATE_edited";
- case DW_ATE_signed_fixed: return "DW_ATE_signed_fixed";
- case DW_ATE_unsigned_fixed: return "DW_ATE_unsigned_fixed";
- case DW_ATE_decimal_float: return "DW_ATE_decimal_float";
- case DW_ATE_lo_user: return "DW_ATE_lo_user";
- case DW_ATE_hi_user: return "DW_ATE_hi_user";
+ default: return nullptr;
+#define HANDLE_DW_ATE(ID, NAME) \
+ case DW_ATE_##NAME: \
+ return "DW_ATE_" #NAME;
+#include "llvm/Support/Dwarf.def"
}
- return nullptr;
+}
+
+unsigned llvm::dwarf::getAttributeEncoding(StringRef EncodingString) {
+ return StringSwitch<unsigned>(EncodingString)
+#define HANDLE_DW_ATE(ID, NAME) .Case("DW_ATE_" #NAME, DW_ATE_##NAME)
+#include "llvm/Support/Dwarf.def"
+ .Default(0);
}
const char *llvm::dwarf::DecimalSignString(unsigned Sign) {
@@ -538,47 +318,39 @@ const char *llvm::dwarf::VisibilityString(unsigned Visibility) {
const char *llvm::dwarf::VirtualityString(unsigned Virtuality) {
switch (Virtuality) {
- case DW_VIRTUALITY_none: return "DW_VIRTUALITY_none";
- case DW_VIRTUALITY_virtual: return "DW_VIRTUALITY_virtual";
- case DW_VIRTUALITY_pure_virtual: return "DW_VIRTUALITY_pure_virtual";
+ default:
+ return nullptr;
+#define HANDLE_DW_VIRTUALITY(ID, NAME) \
+ case DW_VIRTUALITY_##NAME: \
+ return "DW_VIRTUALITY_" #NAME;
+#include "llvm/Support/Dwarf.def"
}
- return nullptr;
+}
+
+unsigned llvm::dwarf::getVirtuality(StringRef VirtualityString) {
+ return StringSwitch<unsigned>(VirtualityString)
+#define HANDLE_DW_VIRTUALITY(ID, NAME) \
+ .Case("DW_VIRTUALITY_" #NAME, DW_VIRTUALITY_##NAME)
+#include "llvm/Support/Dwarf.def"
+ .Default(DW_VIRTUALITY_invalid);
}
const char *llvm::dwarf::LanguageString(unsigned Language) {
switch (Language) {
- case DW_LANG_C89: return "DW_LANG_C89";
- case DW_LANG_C: return "DW_LANG_C";
- case DW_LANG_Ada83: return "DW_LANG_Ada83";
- case DW_LANG_C_plus_plus: return "DW_LANG_C_plus_plus";
- case DW_LANG_Cobol74: return "DW_LANG_Cobol74";
- case DW_LANG_Cobol85: return "DW_LANG_Cobol85";
- case DW_LANG_Fortran77: return "DW_LANG_Fortran77";
- case DW_LANG_Fortran90: return "DW_LANG_Fortran90";
- case DW_LANG_Pascal83: return "DW_LANG_Pascal83";
- case DW_LANG_Modula2: return "DW_LANG_Modula2";
- case DW_LANG_Java: return "DW_LANG_Java";
- case DW_LANG_C99: return "DW_LANG_C99";
- case DW_LANG_Ada95: return "DW_LANG_Ada95";
- case DW_LANG_Fortran95: return "DW_LANG_Fortran95";
- case DW_LANG_PLI: return "DW_LANG_PLI";
- case DW_LANG_ObjC: return "DW_LANG_ObjC";
- case DW_LANG_ObjC_plus_plus: return "DW_LANG_ObjC_plus_plus";
- case DW_LANG_UPC: return "DW_LANG_UPC";
- case DW_LANG_D: return "DW_LANG_D";
- case DW_LANG_Python: return "DW_LANG_Python";
- case DW_LANG_OpenCL: return "DW_LANG_OpenCL";
- case DW_LANG_Go: return "DW_LANG_Go";
- case DW_LANG_Modula3: return "DW_LANG_Modula3";
- case DW_LANG_Haskell: return "DW_LANG_Haskell";
- case DW_LANG_C_plus_plus_03: return "DW_LANG_C_plus_plus_03";
- case DW_LANG_C_plus_plus_11: return "DW_LANG_C_plus_plus_11";
- case DW_LANG_OCaml: return "DW_LANG_OCaml";
- case DW_LANG_lo_user: return "DW_LANG_lo_user";
- case DW_LANG_Mips_Assembler: return "DW_LANG_Mips_Assembler";
- case DW_LANG_hi_user: return "DW_LANG_hi_user";
+ default:
+ return nullptr;
+#define HANDLE_DW_LANG(ID, NAME) \
+ case DW_LANG_##NAME: \
+ return "DW_LANG_" #NAME;
+#include "llvm/Support/Dwarf.def"
}
- return nullptr;
+}
+
+unsigned llvm::dwarf::getLanguage(StringRef LanguageString) {
+ return StringSwitch<unsigned>(LanguageString)
+#define HANDLE_DW_LANG(ID, NAME) .Case("DW_LANG_" #NAME, DW_LANG_##NAME)
+#include "llvm/Support/Dwarf.def"
+ .Default(0);
}
const char *llvm::dwarf::CaseString(unsigned Case) {
diff --git a/lib/Support/FileOutputBuffer.cpp b/lib/Support/FileOutputBuffer.cpp
index b176a8b45ab3..307ff09afedc 100644
--- a/lib/Support/FileOutputBuffer.cpp
+++ b/lib/Support/FileOutputBuffer.cpp
@@ -11,11 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Support/Errc.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Errc.h"
#include <system_error>
#if !defined(_MSC_VER) && !defined(__MINGW32__)
@@ -77,9 +76,16 @@ FileOutputBuffer::create(StringRef FilePath, size_t Size,
if (EC)
return EC;
+#ifndef LLVM_ON_WIN32
+ // On Windows, CreateFileMapping (the mmap function on Windows)
+ // automatically extends the underlying file. We don't need to
+ // extend the file beforehand. _chsize (ftruncate on Windows) is
+ // pretty slow just like it writes specified amount of bytes,
+ // so we should avoid calling that.
EC = sys::fs::resize_file(FD, Size);
if (EC)
return EC;
+#endif
auto MappedFile = llvm::make_unique<mapped_file_region>(
FD, mapped_file_region::readwrite, Size, 0, EC);
diff --git a/lib/Support/FoldingSet.cpp b/lib/Support/FoldingSet.cpp
index 463511408759..b8538ffe1f9f 100644
--- a/lib/Support/FoldingSet.cpp
+++ b/lib/Support/FoldingSet.cpp
@@ -51,8 +51,8 @@ bool FoldingSetNodeIDRef::operator<(FoldingSetNodeIDRef RHS) const {
///
void FoldingSetNodeID::AddPointer(const void *Ptr) {
// Note: this adds pointers to the hash using sizes and endianness that
- // depend on the host. It doesn't matter however, because hashing on
- // pointer values in inherently unstable. Nothing should depend on the
+ // depend on the host. It doesn't matter, however, because hashing on
+ // pointer values is inherently unstable. Nothing should depend on the
// ordering of nodes in the folding set.
Bits.append(reinterpret_cast<unsigned *>(&Ptr),
reinterpret_cast<unsigned *>(&Ptr+1));
@@ -101,6 +101,8 @@ void FoldingSetNodeID::AddString(StringRef String) {
// Otherwise do it the hard way.
// To be compatible with above bulk transfer, we need to take endianness
// into account.
+ static_assert(sys::IsBigEndianHost || sys::IsLittleEndianHost,
+ "Unexpected host endianness");
if (sys::IsBigEndianHost) {
for (Pos += 4; Pos <= Size; Pos += 4) {
unsigned V = ((unsigned char)String[Pos - 4] << 24) |
@@ -109,8 +111,7 @@ void FoldingSetNodeID::AddString(StringRef String) {
(unsigned char)String[Pos - 1];
Bits.push_back(V);
}
- } else {
- assert(sys::IsLittleEndianHost && "Unexpected host endianness");
+ } else { // Little-endian host
for (Pos += 4; Pos <= Size; Pos += 4) {
unsigned V = ((unsigned char)String[Pos - 1] << 24) |
((unsigned char)String[Pos - 2] << 16) |
@@ -222,6 +223,8 @@ static void **AllocateBuckets(unsigned NumBuckets) {
//===----------------------------------------------------------------------===//
// FoldingSetImpl Implementation
+void FoldingSetImpl::anchor() {}
+
FoldingSetImpl::FoldingSetImpl(unsigned Log2InitSize) {
assert(5 < Log2InitSize && Log2InitSize < 32 &&
"Initial hash table size out of range");
diff --git a/lib/Support/FormattedStream.cpp b/lib/Support/FormattedStream.cpp
index 618ec2673a16..2ed71c7e4311 100644
--- a/lib/Support/FormattedStream.cpp
+++ b/lib/Support/FormattedStream.cpp
@@ -13,6 +13,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace llvm;
diff --git a/lib/Support/GraphWriter.cpp b/lib/Support/GraphWriter.cpp
index 054df528474e..97aedc88473a 100644
--- a/lib/Support/GraphWriter.cpp
+++ b/lib/Support/GraphWriter.cpp
@@ -15,7 +15,6 @@
#include "llvm/Config/config.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
using namespace llvm;
@@ -93,11 +92,12 @@ static bool ExecGraphViewer(StringRef ExecPath, std::vector<const char *> &args,
errs() << " done. \n";
} else {
sys::ExecuteNoWait(ExecPath, args.data(), nullptr, nullptr, 0, &ErrMsg);
- errs() << "Remember to erase graph file: " << Filename.str() << "\n";
+ errs() << "Remember to erase graph file: " << Filename << "\n";
}
return false;
}
+namespace {
struct GraphSession {
std::string LogBuffer;
bool TryFindProgram(StringRef Names, std::string &ProgramPath) {
@@ -114,6 +114,7 @@ struct GraphSession {
return false;
}
};
+} // namespace
static const char *getProgramName(GraphProgram::Name program) {
switch (program) {
@@ -139,6 +140,29 @@ bool llvm::DisplayGraph(StringRef FilenameRef, bool wait,
std::string ViewerPath;
GraphSession S;
+#ifdef __APPLE__
+ if (S.TryFindProgram("open", ViewerPath)) {
+ std::vector<const char *> args;
+ args.push_back(ViewerPath.c_str());
+ if (wait)
+ args.push_back("-W");
+ args.push_back(Filename.c_str());
+ args.push_back(nullptr);
+ errs() << "Trying 'open' program... ";
+ if (!ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg))
+ return false;
+ }
+#endif
+ if (S.TryFindProgram("xdg-open", ViewerPath)) {
+ std::vector<const char *> args;
+ args.push_back(ViewerPath.c_str());
+ args.push_back(Filename.c_str());
+ args.push_back(nullptr);
+ errs() << "Trying 'xdg-open' program... ";
+ if (!ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg))
+ return false;
+ }
+
// Graphviz
if (S.TryFindProgram("Graphviz", ViewerPath)) {
std::vector<const char *> args;
diff --git a/lib/Support/Host.cpp b/lib/Support/Host.cpp
index 2abbc1440a25..1bd1fe2bea0e 100644
--- a/lib/Support/Host.cpp
+++ b/lib/Support/Host.cpp
@@ -137,18 +137,13 @@ static bool GetX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
"c" (subleaf));
return false;
#elif defined(_MSC_VER)
- // __cpuidex was added in MSVC++ 9.0 SP1
- #if (_MSC_VER > 1500) || (_MSC_VER == 1500 && _MSC_FULL_VER >= 150030729)
- int registers[4];
- __cpuidex(registers, value, subleaf);
- *rEAX = registers[0];
- *rEBX = registers[1];
- *rECX = registers[2];
- *rEDX = registers[3];
- return false;
- #else
- return true;
- #endif
+ int registers[4];
+ __cpuidex(registers, value, subleaf);
+ *rEAX = registers[0];
+ *rEBX = registers[1];
+ *rECX = registers[2];
+ *rEDX = registers[3];
+ return false;
#else
return true;
#endif
@@ -187,19 +182,21 @@ static bool GetX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
#endif
}
-static bool OSHasAVXSupport() {
+static bool GetX86XCR0(unsigned *rEAX, unsigned *rEDX) {
#if defined(__GNUC__)
// Check xgetbv; this uses a .byte sequence instead of the instruction
// directly because older assemblers do not include support for xgetbv and
// there is no easy way to conditionally compile based on the assembler used.
- int rEAX, rEDX;
- __asm__ (".byte 0x0f, 0x01, 0xd0" : "=a" (rEAX), "=d" (rEDX) : "c" (0));
+ __asm__ (".byte 0x0f, 0x01, 0xd0" : "=a" (*rEAX), "=d" (*rEDX) : "c" (0));
+ return false;
#elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
- unsigned long long rEAX = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
+ unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
+ *rEAX = Result;
+ *rEDX = Result >> 32;
+ return false;
#else
- int rEAX = 0; // Ensures we return false
+ return true;
#endif
- return (rEAX & 6) == 6;
}
static void DetectX86FamilyModel(unsigned EAX, unsigned &Family,
@@ -228,19 +225,30 @@ StringRef sys::getHostCPUName() {
char c[12];
} text;
- GetX86CpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1);
-
- unsigned MaxLeaf = EAX;
- bool HasSSE3 = (ECX & 0x1);
- bool HasSSE41 = (ECX & 0x80000);
- // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
+ unsigned MaxLeaf;
+ GetX86CpuIDAndInfo(0, &MaxLeaf, text.u+0, text.u+2, text.u+1);
+
+ bool HasMMX = (EDX >> 23) & 1;
+ bool HasSSE = (EDX >> 25) & 1;
+ bool HasSSE2 = (EDX >> 26) & 1;
+ bool HasSSE3 = (ECX >> 0) & 1;
+ bool HasSSSE3 = (ECX >> 9) & 1;
+ bool HasSSE41 = (ECX >> 19) & 1;
+ bool HasSSE42 = (ECX >> 20) & 1;
+ bool HasMOVBE = (ECX >> 22) & 1;
+ // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
// indicates that the AVX registers will be saved and restored on context
// switch, then we have full AVX support.
const unsigned AVXBits = (1 << 27) | (1 << 28);
- bool HasAVX = ((ECX & AVXBits) == AVXBits) && OSHasAVXSupport();
- bool HasAVX2 = HasAVX && MaxLeaf >= 0x7 &&
- !GetX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX) &&
- (EBX & 0x20);
+ bool HasAVX = ((ECX & AVXBits) == AVXBits) && !GetX86XCR0(&EAX, &EDX) &&
+ ((EAX & 0x6) == 0x6);
+ bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
+ bool HasLeaf7 = MaxLeaf >= 0x7 &&
+ !GetX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
+ bool HasADX = HasLeaf7 && ((EBX >> 19) & 1);
+ bool HasAVX2 = HasAVX && HasLeaf7 && (EBX & 0x20);
+ bool HasAVX512 = HasLeaf7 && HasAVX512Save && ((EBX >> 16) & 1);
+
GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
bool Em64T = (EDX >> 29) & 0x1;
bool HasTBM = (ECX >> 21) & 0x1;
@@ -303,6 +311,8 @@ StringRef sys::getHostCPUName() {
case 9: // Intel Pentium M processor, Intel Celeron M processor model 09.
case 13: // Intel Pentium M processor, Intel Celeron M processor, model
// 0Dh. All processors are manufactured using the 90 nm process.
+ case 21: // Intel EP80579 Integrated Processor and Intel EP80579
+ // Integrated Processor with Intel QuickAssist Technology
return "pentium-m";
case 14: // Intel Core Duo processor, Intel Core Solo processor, model
@@ -318,68 +328,85 @@ StringRef sys::getHostCPUName() {
// manufactured using the 65 nm process
return "core2";
- case 21: // Intel EP80579 Integrated Processor and Intel EP80579
- // Integrated Processor with Intel QuickAssist Technology
- return "i686"; // FIXME: ???
-
case 23: // Intel Core 2 Extreme processor, Intel Xeon processor, model
// 17h. All processors are manufactured using the 45 nm process.
//
// 45nm: Penryn , Wolfdale, Yorkfield (XE)
- // Not all Penryn processors support SSE 4.1 (such as the Pentium brand)
- return HasSSE41 ? "penryn" : "core2";
+ case 29: // Intel Xeon processor MP. All processors are manufactured using
+ // the 45 nm process.
+ return "penryn";
case 26: // Intel Core i7 processor and Intel Xeon processor. All
// processors are manufactured using the 45 nm process.
- case 29: // Intel Xeon processor MP. All processors are manufactured using
- // the 45 nm process.
case 30: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz.
// As found in a Summer 2010 model iMac.
+ case 46: // Nehalem EX
+ return "nehalem";
case 37: // Intel Core i7, laptop version.
case 44: // Intel Core i7 processor and Intel Xeon processor. All
// processors are manufactured using the 32 nm process.
- case 46: // Nehalem EX
case 47: // Westmere EX
- return "corei7";
+ return "westmere";
// SandyBridge:
case 42: // Intel Core i7 processor. All processors are manufactured
// using the 32 nm process.
case 45:
- // Not all Sandy Bridge processors support AVX (such as the Pentium
- // versions instead of the i7 versions).
- return HasAVX ? "corei7-avx" : "corei7";
+ return "sandybridge";
// Ivy Bridge:
case 58:
case 62: // Ivy Bridge EP
- // Not all Ivy Bridge processors support AVX (such as the Pentium
- // versions instead of the i7 versions).
- return HasAVX ? "core-avx-i" : "corei7";
+ return "ivybridge";
// Haswell:
case 60:
case 63:
case 69:
case 70:
- // Not all Haswell processors support AVX too (such as the Pentium
- // versions instead of the i7 versions).
- return HasAVX2 ? "core-avx2" : "corei7";
+ return "haswell";
+
+ // Broadwell:
+ case 61:
+ return "broadwell";
case 28: // Most 45 nm Intel Atom processors
case 38: // 45 nm Atom Lincroft
case 39: // 32 nm Atom Medfield
case 53: // 32 nm Atom Midview
case 54: // 32 nm Atom Midview
- return "atom";
+ return "bonnell";
// Atom Silvermont codes from the Intel software optimization guide.
case 55:
case 74:
case 77:
- return "slm";
-
- default: return (Em64T) ? "x86-64" : "i686";
+ return "silvermont";
+
+ default: // Unknown family 6 CPU, try to guess.
+ if (HasAVX512)
+ return "knl";
+ if (HasADX)
+ return "broadwell";
+ if (HasAVX2)
+ return "haswell";
+ if (HasAVX)
+ return "sandybridge";
+ if (HasSSE42)
+ return HasMOVBE ? "silvermont" : "nehalem";
+ if (HasSSE41)
+ return "penryn";
+ if (HasSSSE3)
+ return HasMOVBE ? "bonnell" : "core2";
+ if (Em64T)
+ return "x86-64";
+ if (HasSSE2)
+ return "pentium-m";
+ if (HasSSE)
+ return "pentium3";
+ if (HasMMX)
+ return "pentium2";
+ return "pentiumpro";
}
case 15: {
switch (Model) {
@@ -655,6 +682,28 @@ StringRef sys::getHostCPUName() {
StringRef Str(buffer, CPUInfoSize);
SmallVector<StringRef, 32> Lines;
Str.split(Lines, "\n");
+
+ // Look for the CPU features.
+ SmallVector<StringRef, 32> CPUFeatures;
+ for (unsigned I = 0, E = Lines.size(); I != E; ++I)
+ if (Lines[I].startswith("features")) {
+ size_t Pos = Lines[I].find(":");
+ if (Pos != StringRef::npos) {
+ Lines[I].drop_front(Pos + 1).split(CPUFeatures, " ");
+ break;
+ }
+ }
+
+ // We need to check for the presence of vector support independently of
+ // the machine type, since we may only use the vector register set when
+ // supported by the kernel (and hypervisor).
+ bool HaveVectorSupport = false;
+ for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
+ if (CPUFeatures[I] == "vx")
+ HaveVectorSupport = true;
+ }
+
+ // Now check the processor machine type.
for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
if (Lines[I].startswith("processor ")) {
size_t Pos = Lines[I].find("machine = ");
@@ -662,6 +711,8 @@ StringRef sys::getHostCPUName() {
Pos += sizeof("machine = ") - 1;
unsigned int Id;
if (!Lines[I].drop_front(Pos).getAsInteger(10, Id)) {
+ if (Id >= 2964 && HaveVectorSupport)
+ return "z13";
if (Id >= 2827)
return "zEC12";
if (Id >= 2817)
@@ -680,7 +731,89 @@ StringRef sys::getHostCPUName() {
}
#endif
-#if defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
+#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)\
+ || defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
+bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
+ unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
+ unsigned MaxLevel;
+ union {
+ unsigned u[3];
+ char c[12];
+ } text;
+
+ if (GetX86CpuIDAndInfo(0, &MaxLevel, text.u+0, text.u+2, text.u+1) ||
+ MaxLevel < 1)
+ return false;
+
+ GetX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);
+
+ Features["cmov"] = (EDX >> 15) & 1;
+ Features["mmx"] = (EDX >> 23) & 1;
+ Features["sse"] = (EDX >> 25) & 1;
+ Features["sse2"] = (EDX >> 26) & 1;
+ Features["sse3"] = (ECX >> 0) & 1;
+ Features["ssse3"] = (ECX >> 9) & 1;
+ Features["sse4.1"] = (ECX >> 19) & 1;
+ Features["sse4.2"] = (ECX >> 20) & 1;
+
+ Features["pclmul"] = (ECX >> 1) & 1;
+ Features["cx16"] = (ECX >> 13) & 1;
+ Features["movbe"] = (ECX >> 22) & 1;
+ Features["popcnt"] = (ECX >> 23) & 1;
+ Features["aes"] = (ECX >> 25) & 1;
+ Features["rdrnd"] = (ECX >> 30) & 1;
+
+ // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
+ // indicates that the AVX registers will be saved and restored on context
+ // switch, then we have full AVX support.
+ bool HasAVX = ((ECX >> 27) & 1) && ((ECX >> 28) & 1) &&
+ !GetX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6);
+ Features["avx"] = HasAVX;
+ Features["fma"] = HasAVX && (ECX >> 12) & 1;
+ Features["f16c"] = HasAVX && (ECX >> 29) & 1;
+
+ // AVX512 requires additional context to be saved by the OS.
+ bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
+
+ unsigned MaxExtLevel;
+ GetX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
+
+ bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
+ !GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
+ Features["lzcnt"] = HasExtLeaf1 && ((ECX >> 5) & 1);
+ Features["sse4a"] = HasExtLeaf1 && ((ECX >> 6) & 1);
+ Features["prfchw"] = HasExtLeaf1 && ((ECX >> 8) & 1);
+ Features["xop"] = HasAVX && HasExtLeaf1 && ((ECX >> 11) & 1);
+ Features["fma4"] = HasAVX && HasExtLeaf1 && ((ECX >> 16) & 1);
+ Features["tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1);
+
+ bool HasLeaf7 = MaxLevel >= 7 &&
+ !GetX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
+
+ // AVX2 is only supported if we have the OS save support from AVX.
+ Features["avx2"] = HasAVX && HasLeaf7 && (EBX >> 5) & 1;
+
+ Features["fsgsbase"] = HasLeaf7 && ((EBX >> 0) & 1);
+ Features["bmi"] = HasLeaf7 && ((EBX >> 3) & 1);
+ Features["hle"] = HasLeaf7 && ((EBX >> 4) & 1);
+ Features["bmi2"] = HasLeaf7 && ((EBX >> 8) & 1);
+ Features["rtm"] = HasLeaf7 && ((EBX >> 11) & 1);
+ Features["rdseed"] = HasLeaf7 && ((EBX >> 18) & 1);
+ Features["adx"] = HasLeaf7 && ((EBX >> 19) & 1);
+ Features["sha"] = HasLeaf7 && ((EBX >> 29) & 1);
+
+ // AVX512 is only supported if the OS supports the context save for it.
+ Features["avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;
+ Features["avx512dq"] = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save;
+ Features["avx512pf"] = HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save;
+ Features["avx512er"] = HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save;
+ Features["avx512cd"] = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save;
+ Features["avx512bw"] = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save;
+ Features["avx512vl"] = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save;
+
+ return true;
+}
+#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
// Read 1024 bytes from /proc/cpuinfo, which should contain the Features line
// in all cases.
diff --git a/lib/Support/IsInf.cpp b/lib/Support/IsInf.cpp
deleted file mode 100644
index d6da0c99e8d8..000000000000
--- a/lib/Support/IsInf.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-//===-- IsInf.cpp - Platform-independent wrapper around C99 isinf() -------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Platform-independent wrapper around C99 isinf()
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Config/config.h"
-
-#if HAVE_ISINF_IN_MATH_H
-# include <math.h>
-#elif HAVE_ISINF_IN_CMATH
-# include <cmath>
-#elif HAVE_STD_ISINF_IN_CMATH
-# include <cmath>
-using std::isinf;
-#elif HAVE_FINITE_IN_IEEEFP_H
-// A handy workaround I found at http://www.unixguide.net/sun/faq ...
-// apparently this has been a problem with Solaris for years.
-# include <ieeefp.h>
-static int isinf(double x) { return !finite(x) && x==x; }
-#elif defined(_MSC_VER)
-#include <float.h>
-#define isinf(X) (!_finite(X))
-#elif defined(_AIX) && defined(__GNUC__)
-// GCC's fixincludes seems to be removing the isinf() declaration from the
-// system header /usr/include/math.h
-# include <math.h>
-static int isinf(double x) { return !finite(x) && x==x; }
-#elif defined(__hpux)
-// HP-UX is "special"
-#include <math.h>
-static int isinf(double x) { return ((x) == INFINITY) || ((x) == -INFINITY); }
-#else
-# error "Don't know how to get isinf()"
-#endif
-
-namespace llvm {
-
-int IsInf(float f) { return isinf(f); }
-int IsInf(double d) { return isinf(d); }
-
-} // end namespace llvm;
diff --git a/lib/Support/IsNAN.cpp b/lib/Support/IsNAN.cpp
deleted file mode 100644
index bdfdfbf3155d..000000000000
--- a/lib/Support/IsNAN.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//===-- IsNAN.cpp ---------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Platform-independent wrapper around C99 isnan().
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Config/config.h"
-
-#if HAVE_ISNAN_IN_MATH_H
-# include <math.h>
-#elif HAVE_ISNAN_IN_CMATH
-# include <cmath>
-#elif HAVE_STD_ISNAN_IN_CMATH
-# include <cmath>
-using std::isnan;
-#elif defined(_MSC_VER)
-#include <float.h>
-#define isnan _isnan
-#else
-# error "Don't know how to get isnan()"
-#endif
-
-namespace llvm {
- int IsNAN(float f) { return isnan(f); }
- int IsNAN(double d) { return isnan(d); }
-} // end namespace llvm;
diff --git a/lib/Support/LockFileManager.cpp b/lib/Support/LockFileManager.cpp
index 5b82c367c0ad..d07c5f0f682f 100644
--- a/lib/Support/LockFileManager.cpp
+++ b/lib/Support/LockFileManager.cpp
@@ -7,12 +7,10 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/LockFileManager.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <sys/stat.h>
#include <sys/types.h>
@@ -91,7 +89,7 @@ LockFileManager::LockFileManager(StringRef FileName)
UniqueLockFileName += "-%%%%%%%%";
int UniqueLockFileID;
if (std::error_code EC = sys::fs::createUniqueFile(
- UniqueLockFileName.str(), UniqueLockFileID, UniqueLockFileName)) {
+ UniqueLockFileName, UniqueLockFileID, UniqueLockFileName)) {
Error = EC;
return;
}
@@ -116,7 +114,7 @@ LockFileManager::LockFileManager(StringRef FileName)
// We failed to write out PID, so make up an excuse, remove the
// unique lock file, and fail.
Error = make_error_code(errc::no_space_on_device);
- sys::fs::remove(UniqueLockFileName.c_str());
+ sys::fs::remove(UniqueLockFileName);
return;
}
}
@@ -124,7 +122,7 @@ LockFileManager::LockFileManager(StringRef FileName)
while (1) {
// Create a link from the lock file name. If this succeeds, we're done.
std::error_code EC =
- sys::fs::create_link(UniqueLockFileName.str(), LockFileName.str());
+ sys::fs::create_link(UniqueLockFileName, LockFileName);
if (!EC)
return;
@@ -137,11 +135,11 @@ LockFileManager::LockFileManager(StringRef FileName)
// from the lock file.
if ((Owner = readLockFile(LockFileName))) {
// Wipe out our unique lock file (it's useless now)
- sys::fs::remove(UniqueLockFileName.str());
+ sys::fs::remove(UniqueLockFileName);
return;
}
- if (!sys::fs::exists(LockFileName.str())) {
+ if (!sys::fs::exists(LockFileName)) {
// The previous owner released the lock file before we could read it.
// Try to get ownership again.
continue;
@@ -149,7 +147,7 @@ LockFileManager::LockFileManager(StringRef FileName)
// There is a lock file that nobody owns; try to clean it up and get
// ownership.
- if ((EC = sys::fs::remove(LockFileName.str()))) {
+ if ((EC = sys::fs::remove(LockFileName))) {
Error = EC;
return;
}
@@ -171,8 +169,8 @@ LockFileManager::~LockFileManager() {
return;
// Since we own the lock, remove the lock file and our own unique lock file.
- sys::fs::remove(LockFileName.str());
- sys::fs::remove(UniqueLockFileName.str());
+ sys::fs::remove(LockFileName);
+ sys::fs::remove(UniqueLockFileName);
}
LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock() {
@@ -186,9 +184,9 @@ LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock() {
Interval.tv_sec = 0;
Interval.tv_nsec = 1000000;
#endif
- // Don't wait more than five minutes for the file to appear.
- unsigned MaxSeconds = 300;
- bool LockFileGone = false;
+ // Don't wait more than five minutes per iteration. Total timeout for the file
+ // to appear is ~8.5 mins.
+ const unsigned MaxSeconds = 5*60;
do {
// Sleep for the designated interval, to allow the owning process time to
// finish up and remove the lock file.
@@ -199,47 +197,18 @@ LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock() {
#else
nanosleep(&Interval, nullptr);
#endif
- bool LockFileJustDisappeared = false;
- // If the lock file is still expected to be there, check whether it still
- // is.
- if (!LockFileGone) {
- if (sys::fs::access(LockFileName.c_str(), sys::fs::AccessMode::Exist) ==
- errc::no_such_file_or_directory) {
- LockFileGone = true;
- LockFileJustDisappeared = true;
- }
+ if (sys::fs::access(LockFileName.c_str(), sys::fs::AccessMode::Exist) ==
+ errc::no_such_file_or_directory) {
+ // If the original file wasn't created, somone thought the lock was dead.
+ if (!sys::fs::exists(FileName))
+ return Res_OwnerDied;
+ return Res_Success;
}
- // If the lock file is no longer there, check if the original file is
- // available now.
- if (LockFileGone) {
- if (sys::fs::exists(FileName.str())) {
- return Res_Success;
- }
-
- // The lock file is gone, so now we're waiting for the original file to
- // show up. If this just happened, reset our waiting intervals and keep
- // waiting.
- if (LockFileJustDisappeared) {
- MaxSeconds = 5;
-
-#if LLVM_ON_WIN32
- Interval = 1;
-#else
- Interval.tv_sec = 0;
- Interval.tv_nsec = 1000000;
-#endif
- continue;
- }
- }
-
- // If we're looking for the lock file to disappear, but the process
- // owning the lock died without cleaning up, just bail out.
- if (!LockFileGone &&
- !processStillExecuting((*Owner).first, (*Owner).second)) {
+ // If the process owning the lock died without cleaning up, just bail out.
+ if (!processStillExecuting((*Owner).first, (*Owner).second))
return Res_OwnerDied;
- }
// Exponentially increase the time we wait for the lock to be removed.
#if LLVM_ON_WIN32
@@ -263,3 +232,7 @@ LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock() {
// Give up.
return Res_Timeout;
}
+
+std::error_code LockFileManager::unsafeRemoveLockFile() {
+ return sys::fs::remove(LockFileName);
+}
diff --git a/lib/Support/MemoryBuffer.cpp b/lib/Support/MemoryBuffer.cpp
index 379db8811d4d..98862e96b749 100644
--- a/lib/Support/MemoryBuffer.cpp
+++ b/lib/Support/MemoryBuffer.cpp
@@ -23,7 +23,6 @@
#include "llvm/Support/Program.h"
#include <cassert>
#include <cerrno>
-#include <cstdio>
#include <cstring>
#include <new>
#include <sys/types.h>
diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp
index fdb27e6aa664..cf467381db8c 100644
--- a/lib/Support/Path.cpp
+++ b/lib/Support/Path.cpp
@@ -19,9 +19,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include <cctype>
-#include <cstdio>
#include <cstring>
-#include <fcntl.h>
#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
@@ -30,6 +28,7 @@
#endif
using namespace llvm;
+using namespace llvm::support::endian;
namespace {
using llvm::StringRef;
@@ -48,7 +47,6 @@ namespace {
// * empty (in this case we return an empty string)
// * either C: or {//,\\}net.
// * {/,\}
- // * {.,..}
// * {file,directory}name
if (path.empty())
@@ -75,12 +73,6 @@ namespace {
if (is_separator(path[0]))
return path.substr(0, 1);
- if (path.startswith(".."))
- return path.substr(0, 2);
-
- if (path[0] == '.')
- return path.substr(0, 1);
-
// * {file,directory}name
size_t end = path.find_first_of(separators);
return path.substr(0, end);
@@ -917,7 +909,7 @@ file_magic identify_magic(StringRef Magic) {
if (Magic.size() < MinSize)
return file_magic::coff_import_library;
- int BigObjVersion = *reinterpret_cast<const support::ulittle16_t*>(
+ int BigObjVersion = read16le(
Magic.data() + offsetof(COFF::BigObjHeader, Version));
if (BigObjVersion < COFF::BigObjHeader::MinBigObjectVersion)
return file_magic::coff_import_library;
@@ -960,7 +952,7 @@ file_magic identify_magic(StringRef Magic) {
unsigned low = Data2MSB ? 17 : 16;
if (Magic[high] == 0)
switch (Magic[low]) {
- default: break;
+ default: return file_magic::elf;
case 1: return file_magic::elf_relocatable;
case 2: return file_magic::elf_executable;
case 3: return file_magic::elf_shared_object;
@@ -1012,6 +1004,7 @@ file_magic identify_magic(StringRef Magic) {
case 8: return file_magic::macho_bundle;
case 9: return file_magic::macho_dynamically_linked_shared_lib_stub;
case 10: return file_magic::macho_dsym_companion;
+ case 11: return file_magic::macho_kext_bundle;
}
break;
}
@@ -1033,8 +1026,7 @@ file_magic identify_magic(StringRef Magic) {
case 'M': // Possible MS-DOS stub on Windows PE file
if (Magic[1] == 'Z') {
- uint32_t off =
- *reinterpret_cast<const support::ulittle32_t*>(Magic.data() + 0x3c);
+ uint32_t off = read32le(Magic.data() + 0x3c);
// PE/COFF file, either EXE or DLL.
if (off < Magic.size() &&
memcmp(Magic.data()+off, COFF::PEMagic, sizeof(COFF::PEMagic)) == 0)
diff --git a/lib/Support/PrettyStackTrace.cpp b/lib/Support/PrettyStackTrace.cpp
index 987778a1bde6..f9f8cab9d933 100644
--- a/lib/Support/PrettyStackTrace.cpp
+++ b/lib/Support/PrettyStackTrace.cpp
@@ -16,9 +16,8 @@
#include "llvm-c/Core.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Config/config.h" // Get autoconf configuration settings
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Signals.h"
-#include "llvm/Support/ThreadLocal.h"
#include "llvm/Support/Watchdog.h"
#include "llvm/Support/raw_ostream.h"
@@ -28,7 +27,17 @@
using namespace llvm;
-static ManagedStatic<sys::ThreadLocal<const PrettyStackTraceEntry> > PrettyStackTraceHead;
+// If backtrace support is not enabled, compile out support for pretty stack
+// traces. This has the secondary effect of not requiring thread local storage
+// when backtrace support is disabled.
+#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
+
+// We need a thread local pointer to manage the stack of our stack trace
+// objects, but we *really* cannot tolerate destructors running and do not want
+// to pay any overhead of synchronizing. As a consequence, we use a raw
+// thread-local variable.
+static LLVM_THREAD_LOCAL const PrettyStackTraceEntry *PrettyStackTraceHead =
+ nullptr;
static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){
unsigned NextID = 0;
@@ -46,12 +55,12 @@ static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){
/// PrintCurStackTrace - Print the current stack trace to the specified stream.
static void PrintCurStackTrace(raw_ostream &OS) {
// Don't print an empty trace.
- if (!PrettyStackTraceHead->get()) return;
+ if (!PrettyStackTraceHead) return;
// If there are pretty stack frames registered, walk and emit them.
OS << "Stack dump:\n";
- PrintStack(PrettyStackTraceHead->get(), OS);
+ PrintStack(PrettyStackTraceHead, OS);
OS.flush();
}
@@ -99,28 +108,23 @@ static void CrashHandler(void *) {
#endif
}
+// defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
+#endif
+
PrettyStackTraceEntry::PrettyStackTraceEntry() {
+#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
// Link ourselves.
- NextEntry = PrettyStackTraceHead->get();
- PrettyStackTraceHead->set(this);
+ NextEntry = PrettyStackTraceHead;
+ PrettyStackTraceHead = this;
+#endif
}
PrettyStackTraceEntry::~PrettyStackTraceEntry() {
- // Do nothing if PrettyStackTraceHead is uninitialized. This can only happen
- // if a shutdown occurred after we created the PrettyStackTraceEntry. That
- // does occur in the following idiom:
- //
- // PrettyStackTraceProgram X(...);
- // llvm_shutdown_obj Y;
- //
- // Without this check, we may end up removing ourselves from the stack trace
- // after PrettyStackTraceHead has already been destroyed.
- if (!PrettyStackTraceHead.isConstructed())
- return;
-
- assert(PrettyStackTraceHead->get() == this &&
+#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
+ assert(PrettyStackTraceHead == this &&
"Pretty stack trace entry destruction is out of order");
- PrettyStackTraceHead->set(getNextEntry());
+ PrettyStackTraceHead = getNextEntry();
+#endif
}
void PrettyStackTraceString::print(raw_ostream &OS) const {
@@ -135,15 +139,19 @@ void PrettyStackTraceProgram::print(raw_ostream &OS) const {
OS << '\n';
}
+#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
static bool RegisterCrashPrinter() {
sys::AddSignalHandler(CrashHandler, nullptr);
return false;
}
+#endif
void llvm::EnablePrettyStackTrace() {
+#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
// The first time this is called, we register the crash printer.
static bool HandlerRegistered = RegisterCrashPrinter();
(void)HandlerRegistered;
+#endif
}
void LLVMEnablePrettyStackTrace() {
diff --git a/lib/Support/Process.cpp b/lib/Support/Process.cpp
index ad67e1b10b48..6dcbb47e87d0 100644
--- a/lib/Support/Process.cpp
+++ b/lib/Support/Process.cpp
@@ -13,8 +13,8 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
-#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
@@ -26,27 +26,10 @@ using namespace sys;
//=== independent code.
//===----------------------------------------------------------------------===//
-/// \brief A helper function to compute the elapsed wall-time since the program
-/// started.
-///
-/// Note that this routine actually computes the elapsed wall time since the
-/// first time it was called. However, we arrange to have it called during the
-/// startup of the process to get approximately correct results.
-static TimeValue getElapsedWallTime() {
- static TimeValue &StartTime = *new TimeValue(TimeValue::now());
- return TimeValue::now() - StartTime;
-}
-
-/// \brief A special global variable to ensure we call \c getElapsedWallTime
-/// during global initialization of the program.
-///
-/// Note that this variable is never referenced elsewhere. Doing so could
-/// create race conditions during program startup or shutdown.
-static volatile TimeValue DummyTimeValue = getElapsedWallTime();
-
Optional<std::string> Process::FindInEnvPath(const std::string& EnvName,
const std::string& FileName)
{
+ assert(!path::is_absolute(FileName));
Optional<std::string> FoundPath;
Optional<std::string> OptPath = Process::GetEnv(EnvName);
if (!OptPath.hasValue())
diff --git a/lib/Support/Program.cpp b/lib/Support/Program.cpp
index b84b82b1f10b..34e336b354d6 100644
--- a/lib/Support/Program.cpp
+++ b/lib/Support/Program.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/Program.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Config/config.h"
#include <system_error>
using namespace llvm;
diff --git a/lib/Support/RandomNumberGenerator.cpp b/lib/Support/RandomNumberGenerator.cpp
index 294313769bf9..81d0411d60b4 100644
--- a/lib/Support/RandomNumberGenerator.cpp
+++ b/lib/Support/RandomNumberGenerator.cpp
@@ -13,13 +13,15 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "rng"
+#include "llvm/Support/RandomNumberGenerator.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/RandomNumberGenerator.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
+#define DEBUG_TYPE "rng"
+
// Tracking BUG: 19665
// http://llvm.org/bugs/show_bug.cgi?id=19665
//
diff --git a/lib/Support/Regex.cpp b/lib/Support/Regex.cpp
index f7fe1e4c7925..e8344ef74d9c 100644
--- a/lib/Support/Regex.cpp
+++ b/lib/Support/Regex.cpp
@@ -14,8 +14,8 @@
#include "llvm/Support/Regex.h"
#include "regex_impl.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
#include <string>
using namespace llvm;
@@ -159,7 +159,7 @@ std::string Regex::sub(StringRef Repl, StringRef String,
RefValue < Matches.size())
Res += Matches[RefValue];
else if (Error && Error->empty())
- *Error = "invalid backreference string '" + Ref.str() + "'";
+ *Error = ("invalid backreference string '" + Twine(Ref) + "'").str();
break;
}
}
diff --git a/lib/Support/ScaledNumber.cpp b/lib/Support/ScaledNumber.cpp
index 6f6699cfa7c4..987c2d803b7e 100644
--- a/lib/Support/ScaledNumber.cpp
+++ b/lib/Support/ScaledNumber.cpp
@@ -14,6 +14,7 @@
#include "llvm/Support/ScaledNumber.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace llvm::ScaledNumbers;
diff --git a/lib/Support/SmallPtrSet.cpp b/lib/Support/SmallPtrSet.cpp
index c87ee7d106e2..358c8e8abbe9 100644
--- a/lib/Support/SmallPtrSet.cpp
+++ b/lib/Support/SmallPtrSet.cpp
@@ -50,11 +50,12 @@ SmallPtrSetImplBase::insert_imp(const void *Ptr) {
}
// Otherwise, hit the big set case, which will call grow.
}
-
- if (NumElements*4 >= CurArraySize*3) {
+
+ if (LLVM_UNLIKELY(NumElements * 4 >= CurArraySize * 3)) {
// If more than 3/4 of the array is full, grow.
Grow(CurArraySize < 64 ? 128 : CurArraySize*2);
- } else if (CurArraySize-(NumElements+NumTombstones) < CurArraySize/8) {
+ } else if (LLVM_UNLIKELY(CurArraySize - (NumElements + NumTombstones) <
+ CurArraySize / 8)) {
// If fewer of 1/8 of the array is empty (meaning that many are filled with
// tombstones), rehash.
Grow(CurArraySize);
@@ -107,16 +108,16 @@ const void * const *SmallPtrSetImplBase::FindBucketFor(const void *Ptr) const {
const void *const *Array = CurArray;
const void *const *Tombstone = nullptr;
while (1) {
- // Found Ptr's bucket?
- if (Array[Bucket] == Ptr)
- return Array+Bucket;
-
// If we found an empty bucket, the pointer doesn't exist in the set.
// Return a tombstone if we've seen one so far, or the empty bucket if
// not.
- if (Array[Bucket] == getEmptyMarker())
+ if (LLVM_LIKELY(Array[Bucket] == getEmptyMarker()))
return Tombstone ? Tombstone : Array+Bucket;
-
+
+ // Found Ptr's bucket?
+ if (LLVM_LIKELY(Array[Bucket] == Ptr))
+ return Array+Bucket;
+
// If this is a tombstone, remember it. If Ptr ends up not in the set, we
// prefer to return it than something that would require more probing.
if (Array[Bucket] == getTombstoneMarker() && !Tombstone)
diff --git a/lib/Support/SourceMgr.cpp b/lib/Support/SourceMgr.cpp
index b50a66b2974f..d5e3157b064e 100644
--- a/lib/Support/SourceMgr.cpp
+++ b/lib/Support/SourceMgr.cpp
@@ -14,13 +14,11 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/SourceMgr.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Locale.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
-#include <system_error>
using namespace llvm;
static const size_t TabStop = 8;
diff --git a/lib/Support/SpecialCaseList.cpp b/lib/Support/SpecialCaseList.cpp
index 785cc609f48c..ea417c41c0a7 100644
--- a/lib/Support/SpecialCaseList.cpp
+++ b/lib/Support/SpecialCaseList.cpp
@@ -15,13 +15,11 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/SpecialCaseList.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Regex.h"
-#include "llvm/Support/raw_ostream.h"
#include <string>
#include <system_error>
#include <utility>
@@ -46,19 +44,27 @@ struct SpecialCaseList::Entry {
}
};
-SpecialCaseList::SpecialCaseList() : Entries() {}
+SpecialCaseList::SpecialCaseList() : Entries(), Regexps(), IsCompiled(false) {}
-std::unique_ptr<SpecialCaseList> SpecialCaseList::create(StringRef Path,
- std::string &Error) {
- if (Path.empty())
- return std::unique_ptr<SpecialCaseList>(new SpecialCaseList());
- ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
- MemoryBuffer::getFile(Path);
- if (std::error_code EC = FileOrErr.getError()) {
- Error = (Twine("Can't open file '") + Path + "': " + EC.message()).str();
- return nullptr;
+std::unique_ptr<SpecialCaseList>
+SpecialCaseList::create(const std::vector<std::string> &Paths,
+ std::string &Error) {
+ std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
+ for (auto Path : Paths) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
+ MemoryBuffer::getFile(Path);
+ if (std::error_code EC = FileOrErr.getError()) {
+ Error = (Twine("can't open file '") + Path + "': " + EC.message()).str();
+ return nullptr;
+ }
+ std::string ParseError;
+ if (!SCL->parse(FileOrErr.get().get(), ParseError)) {
+ Error = (Twine("error parsing file '") + Path + "': " + ParseError).str();
+ return nullptr;
+ }
}
- return create(FileOrErr.get().get(), Error);
+ SCL->compile();
+ return SCL;
}
std::unique_ptr<SpecialCaseList> SpecialCaseList::create(const MemoryBuffer *MB,
@@ -66,12 +72,14 @@ std::unique_ptr<SpecialCaseList> SpecialCaseList::create(const MemoryBuffer *MB,
std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
if (!SCL->parse(MB, Error))
return nullptr;
+ SCL->compile();
return SCL;
}
-std::unique_ptr<SpecialCaseList> SpecialCaseList::createOrDie(StringRef Path) {
+std::unique_ptr<SpecialCaseList>
+SpecialCaseList::createOrDie(const std::vector<std::string> &Paths) {
std::string Error;
- if (auto SCL = create(Path, Error))
+ if (auto SCL = create(Paths, Error))
return SCL;
report_fatal_error(Error);
}
@@ -80,12 +88,8 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) {
// Iterate through each line in the blacklist file.
SmallVector<StringRef, 16> Lines;
SplitString(MB->getBuffer(), Lines, "\n\r");
- StringMap<StringMap<std::string> > Regexps;
- assert(Entries.empty() &&
- "parse() should be called on an empty SpecialCaseList");
int LineNo = 1;
- for (SmallVectorImpl<StringRef>::iterator I = Lines.begin(), E = Lines.end();
- I != E; ++I, ++LineNo) {
+ for (auto I = Lines.begin(), E = Lines.end(); I != E; ++I, ++LineNo) {
// Ignore empty lines and lines starting with "#"
if (I->empty() || I->startswith("#"))
continue;
@@ -94,7 +98,7 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) {
StringRef Prefix = SplitLine.first;
if (SplitLine.second.empty()) {
// Missing ':' in the line.
- Error = (Twine("Malformed line ") + Twine(LineNo) + ": '" +
+ Error = (Twine("malformed line ") + Twine(LineNo) + ": '" +
SplitLine.first + "'").str();
return false;
}
@@ -119,7 +123,7 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) {
Regex CheckRE(Regexp);
std::string REError;
if (!CheckRE.isValid(REError)) {
- Error = (Twine("Malformed regex in line ") + Twine(LineNo) + ": '" +
+ Error = (Twine("malformed regex in line ") + Twine(LineNo) + ": '" +
SplitLine.second + "': " + REError).str();
return false;
}
@@ -129,10 +133,14 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) {
Regexps[Prefix][Category] += "|";
Regexps[Prefix][Category] += "^" + Regexp + "$";
}
+ return true;
+}
+void SpecialCaseList::compile() {
+ assert(!IsCompiled && "compile() should only be called once");
// Iterate through each of the prefixes, and create Regexs for them.
- for (StringMap<StringMap<std::string> >::const_iterator I = Regexps.begin(),
- E = Regexps.end();
+ for (StringMap<StringMap<std::string>>::const_iterator I = Regexps.begin(),
+ E = Regexps.end();
I != E; ++I) {
for (StringMap<std::string>::const_iterator II = I->second.begin(),
IE = I->second.end();
@@ -140,13 +148,15 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) {
Entries[I->getKey()][II->getKey()].RegEx.reset(new Regex(II->getValue()));
}
}
- return true;
+ Regexps.clear();
+ IsCompiled = true;
}
SpecialCaseList::~SpecialCaseList() {}
bool SpecialCaseList::inSection(StringRef Section, StringRef Query,
StringRef Category) const {
+ assert(IsCompiled && "SpecialCaseList::compile() was not called!");
StringMap<StringMap<Entry> >::const_iterator I = Entries.find(Section);
if (I == Entries.end()) return false;
StringMap<Entry>::const_iterator II = I->second.find(Category);
diff --git a/lib/Support/StreamingMemoryObject.cpp b/lib/Support/StreamingMemoryObject.cpp
index 68beeef4dc7f..6c5652af04c2 100644
--- a/lib/Support/StreamingMemoryObject.cpp
+++ b/lib/Support/StreamingMemoryObject.cpp
@@ -8,12 +8,9 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/StreamingMemoryObject.h"
-#include "llvm/Support/Compiler.h"
#include <cassert>
#include <cstddef>
#include <cstring>
-
-
using namespace llvm;
namespace {
@@ -45,8 +42,8 @@ private:
return static_cast<std::ptrdiff_t>(address) < LastChar - FirstChar;
}
- RawMemoryObject(const RawMemoryObject&) LLVM_DELETED_FUNCTION;
- void operator=(const RawMemoryObject&) LLVM_DELETED_FUNCTION;
+ RawMemoryObject(const RawMemoryObject&) = delete;
+ void operator=(const RawMemoryObject&) = delete;
};
uint64_t RawMemoryObject::readBytes(uint8_t *Buf, uint64_t Size,
@@ -76,7 +73,7 @@ namespace llvm {
// block until we actually want to read it.
bool StreamingMemoryObject::isValidAddress(uint64_t address) const {
if (ObjectSize && address < ObjectSize) return true;
- return fetchToPos(address);
+ return fetchToPos(address);
}
uint64_t StreamingMemoryObject::getExtent() const {
@@ -90,13 +87,18 @@ uint64_t StreamingMemoryObject::getExtent() const {
uint64_t StreamingMemoryObject::readBytes(uint8_t *Buf, uint64_t Size,
uint64_t Address) const {
fetchToPos(Address + Size - 1);
- if (Address >= BytesRead)
+ // Note: For wrapped bitcode files will set ObjectSize after the
+ // first call to fetchToPos. In such cases, ObjectSize can be
+ // smaller than BytesRead.
+ size_t MaxAddress =
+ (ObjectSize && ObjectSize < BytesRead) ? ObjectSize : BytesRead;
+ if (Address >= MaxAddress)
return 0;
uint64_t End = Address + Size;
- if (End > BytesRead)
- End = BytesRead;
- assert(static_cast<int64_t>(End - Address) >= 0);
+ if (End > MaxAddress)
+ End = MaxAddress;
+ assert(End >= Address);
Size = End - Address;
memcpy(Buf, &Bytes[Address + BytesSkipped], Size);
return Size;
@@ -112,6 +114,8 @@ bool StreamingMemoryObject::dropLeadingBytes(size_t s) {
void StreamingMemoryObject::setKnownObjectSize(size_t size) {
ObjectSize = size;
Bytes.reserve(size);
+ if (ObjectSize <= BytesRead)
+ EOFReached = true;
}
MemoryObject *getNonStreamedMemoryObject(const unsigned char *Start,
diff --git a/lib/Support/StringExtras.cpp b/lib/Support/StringExtras.cpp
index d77ad7f55a18..3e2420f67760 100644
--- a/lib/Support/StringExtras.cpp
+++ b/lib/Support/StringExtras.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;
diff --git a/lib/Support/StringMap.cpp b/lib/Support/StringMap.cpp
index ddb73494ff5d..7be946642d90 100644
--- a/lib/Support/StringMap.cpp
+++ b/lib/Support/StringMap.cpp
@@ -188,9 +188,10 @@ unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
// If the hash table is now more than 3/4 full, or if fewer than 1/8 of
// the buckets are empty (meaning that many are filled with tombstones),
// grow/rehash the table.
- if (NumItems*4 > NumBuckets*3) {
+ if (LLVM_UNLIKELY(NumItems * 4 > NumBuckets * 3)) {
NewSize = NumBuckets*2;
- } else if (NumBuckets-(NumItems+NumTombstones) <= NumBuckets/8) {
+ } else if (LLVM_UNLIKELY(NumBuckets - (NumItems + NumTombstones) <=
+ NumBuckets / 8)) {
NewSize = NumBuckets;
} else {
return BucketNo;
diff --git a/lib/Support/SystemUtils.cpp b/lib/Support/SystemUtils.cpp
index 2036364dc51d..7fa6ae3f6199 100644
--- a/lib/Support/SystemUtils.cpp
+++ b/lib/Support/SystemUtils.cpp
@@ -13,8 +13,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/SystemUtils.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
diff --git a/lib/Support/TargetParser.cpp b/lib/Support/TargetParser.cpp
new file mode 100644
index 000000000000..a3998d2d13ea
--- /dev/null
+++ b/lib/Support/TargetParser.cpp
@@ -0,0 +1,467 @@
+//===-- TargetParser - Parser for target features ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a target parser to recognise hardware features such as
+// FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ARMBuildAttributes.h"
+#include "llvm/Support/TargetParser.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include <cctype>
+
+using namespace llvm;
+
+namespace {
+
+// List of canonical FPU names (use getFPUSynonym)
+// FIXME: TableGen this.
+struct {
+ const char * Name;
+ ARM::FPUKind ID;
+} FPUNames[] = {
+ { "invalid", ARM::FK_INVALID },
+ { "vfp", ARM::FK_VFP },
+ { "vfpv2", ARM::FK_VFPV2 },
+ { "vfpv3", ARM::FK_VFPV3 },
+ { "vfpv3-d16", ARM::FK_VFPV3_D16 },
+ { "vfpv4", ARM::FK_VFPV4 },
+ { "vfpv4-d16", ARM::FK_VFPV4_D16 },
+ { "fpv5-d16", ARM::FK_FPV5_D16 },
+ { "fp-armv8", ARM::FK_FP_ARMV8 },
+ { "neon", ARM::FK_NEON },
+ { "neon-vfpv4", ARM::FK_NEON_VFPV4 },
+ { "neon-fp-armv8", ARM::FK_NEON_FP_ARMV8 },
+ { "crypto-neon-fp-armv8", ARM::FK_CRYPTO_NEON_FP_ARMV8 },
+ { "softvfp", ARM::FK_SOFTVFP }
+};
+// List of canonical arch names (use getArchSynonym)
+// FIXME: TableGen this.
+struct {
+ const char *Name;
+ ARM::ArchKind ID;
+ const char *DefaultCPU;
+ ARMBuildAttrs::CPUArch DefaultArch;
+} ARCHNames[] = {
+ { "invalid", ARM::AK_INVALID, nullptr, ARMBuildAttrs::CPUArch::Pre_v4 },
+ { "armv2", ARM::AK_ARMV2, "2", ARMBuildAttrs::CPUArch::v4 },
+ { "armv2a", ARM::AK_ARMV2A, "2A", ARMBuildAttrs::CPUArch::v4 },
+ { "armv3", ARM::AK_ARMV3, "3", ARMBuildAttrs::CPUArch::v4 },
+ { "armv3m", ARM::AK_ARMV3M, "3M", ARMBuildAttrs::CPUArch::v4 },
+ { "armv4", ARM::AK_ARMV4, "4", ARMBuildAttrs::CPUArch::v4 },
+ { "armv4t", ARM::AK_ARMV4T, "4T", ARMBuildAttrs::CPUArch::v4T },
+ { "armv5", ARM::AK_ARMV5, "5", ARMBuildAttrs::CPUArch::v5T },
+ { "armv5t", ARM::AK_ARMV5T, "5T", ARMBuildAttrs::CPUArch::v5T },
+ { "armv5te", ARM::AK_ARMV5TE, "5TE", ARMBuildAttrs::CPUArch::v5TE },
+ { "armv6", ARM::AK_ARMV6, "6", ARMBuildAttrs::CPUArch::v6 },
+ { "armv6j", ARM::AK_ARMV6J, "6J", ARMBuildAttrs::CPUArch::v6 },
+ { "armv6k", ARM::AK_ARMV6K, "6K", ARMBuildAttrs::CPUArch::v6K },
+ { "armv6t2", ARM::AK_ARMV6T2, "6T2", ARMBuildAttrs::CPUArch::v6T2 },
+ { "armv6z", ARM::AK_ARMV6Z, "6Z", ARMBuildAttrs::CPUArch::v6KZ },
+ { "armv6zk", ARM::AK_ARMV6ZK, "6ZK", ARMBuildAttrs::CPUArch::v6KZ },
+ { "armv6-m", ARM::AK_ARMV6M, "6-M", ARMBuildAttrs::CPUArch::v6_M },
+ { "armv7", ARM::AK_ARMV7, "7", ARMBuildAttrs::CPUArch::v7 },
+ { "armv7-a", ARM::AK_ARMV7A, "7-A", ARMBuildAttrs::CPUArch::v7 },
+ { "armv7-r", ARM::AK_ARMV7R, "7-R", ARMBuildAttrs::CPUArch::v7 },
+ { "armv7-m", ARM::AK_ARMV7M, "7-M", ARMBuildAttrs::CPUArch::v7 },
+ { "armv8-a", ARM::AK_ARMV8A, "8-A", ARMBuildAttrs::CPUArch::v8 },
+ { "armv8.1-a", ARM::AK_ARMV8_1A, "8.1-A", ARMBuildAttrs::CPUArch::v8 },
+ // Non-standard Arch names.
+ { "iwmmxt", ARM::AK_IWMMXT, "iwmmxt", ARMBuildAttrs::CPUArch::v5TE },
+ { "iwmmxt2", ARM::AK_IWMMXT2, "iwmmxt2", ARMBuildAttrs::CPUArch::v5TE },
+ { "xscale", ARM::AK_XSCALE, "xscale", ARMBuildAttrs::CPUArch::v5TE },
+ { "armv5e", ARM::AK_ARMV5E, "5E", ARMBuildAttrs::CPUArch::v5TE },
+ { "armv5tej", ARM::AK_ARMV5TEJ, "5TE", ARMBuildAttrs::CPUArch::v5TE },
+ { "armv6sm", ARM::AK_ARMV6SM, "6-M", ARMBuildAttrs::CPUArch::v6_M },
+ { "armv6hl", ARM::AK_ARMV6HL, "6-M", ARMBuildAttrs::CPUArch::v6_M },
+ { "armv7e-m", ARM::AK_ARMV7EM, "7E-M", ARMBuildAttrs::CPUArch::v7E_M },
+ { "armv7l", ARM::AK_ARMV7L, "7-L", ARMBuildAttrs::CPUArch::v7 },
+ { "armv7hl", ARM::AK_ARMV7HL, "7H-L", ARMBuildAttrs::CPUArch::v7 },
+ { "armv7s", ARM::AK_ARMV7S, "7-S", ARMBuildAttrs::CPUArch::v7 }
+};
+// List of canonical ARCH names (use getARCHSynonym)
+// FIXME: TableGen this.
+struct {
+ const char *Name;
+ ARM::ArchExtKind ID;
+} ARCHExtNames[] = {
+ { "invalid", ARM::AEK_INVALID },
+ { "crc", ARM::AEK_CRC },
+ { "crypto", ARM::AEK_CRYPTO },
+ { "fp", ARM::AEK_FP },
+ { "idiv", ARM::AEK_HWDIV },
+ { "mp", ARM::AEK_MP },
+ { "sec", ARM::AEK_SEC },
+ { "virt", ARM::AEK_VIRT }
+};
+// List of CPU names and their arches.
+// The same CPU can have multiple arches and can be default on multiple arches.
+// When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
+// FIXME: TableGen this.
+struct {
+ const char *Name;
+ ARM::ArchKind ArchID;
+ bool Default;
+} CPUNames[] = {
+ { "arm2", ARM::AK_ARMV2, true },
+ { "arm6", ARM::AK_ARMV3, true },
+ { "arm7m", ARM::AK_ARMV3M, true },
+ { "strongarm", ARM::AK_ARMV4, true },
+ { "arm7tdmi", ARM::AK_ARMV4T, true },
+ { "arm7tdmi-s", ARM::AK_ARMV4T, false },
+ { "arm710t", ARM::AK_ARMV4T, false },
+ { "arm720t", ARM::AK_ARMV4T, false },
+ { "arm9", ARM::AK_ARMV4T, false },
+ { "arm9tdmi", ARM::AK_ARMV4T, false },
+ { "arm920", ARM::AK_ARMV4T, false },
+ { "arm920t", ARM::AK_ARMV4T, false },
+ { "arm922t", ARM::AK_ARMV4T, false },
+ { "arm9312", ARM::AK_ARMV4T, false },
+ { "arm940t", ARM::AK_ARMV4T, false },
+ { "ep9312", ARM::AK_ARMV4T, false },
+ { "arm10tdmi", ARM::AK_ARMV5, true },
+ { "arm10tdmi", ARM::AK_ARMV5T, true },
+ { "arm1020t", ARM::AK_ARMV5T, false },
+ { "xscale", ARM::AK_XSCALE, true },
+ { "xscale", ARM::AK_ARMV5TE, false },
+ { "arm9e", ARM::AK_ARMV5TE, false },
+ { "arm926ej-s", ARM::AK_ARMV5TE, false },
+ { "arm946ej-s", ARM::AK_ARMV5TE, false },
+ { "arm966e-s", ARM::AK_ARMV5TE, false },
+ { "arm968e-s", ARM::AK_ARMV5TE, false },
+ { "arm1020e", ARM::AK_ARMV5TE, false },
+ { "arm1022e", ARM::AK_ARMV5TE, true },
+ { "iwmmxt", ARM::AK_ARMV5TE, false },
+ { "iwmmxt", ARM::AK_IWMMXT, true },
+ { "arm1136jf-s", ARM::AK_ARMV6, true },
+ { "arm1136j-s", ARM::AK_ARMV6J, true },
+ { "arm1136jz-s", ARM::AK_ARMV6J, false },
+ { "arm1176j-s", ARM::AK_ARMV6K, false },
+ { "mpcore", ARM::AK_ARMV6K, false },
+ { "mpcorenovfp", ARM::AK_ARMV6K, false },
+ { "arm1176jzf-s", ARM::AK_ARMV6K, true },
+ { "arm1176jzf-s", ARM::AK_ARMV6Z, true },
+ { "arm1176jzf-s", ARM::AK_ARMV6ZK, true },
+ { "arm1156t2-s", ARM::AK_ARMV6T2, true },
+ { "arm1156t2f-s", ARM::AK_ARMV6T2, false },
+ { "cortex-m0", ARM::AK_ARMV6M, true },
+ { "cortex-m0plus", ARM::AK_ARMV6M, false },
+ { "cortex-m1", ARM::AK_ARMV6M, false },
+ { "sc000", ARM::AK_ARMV6M, false },
+ { "cortex-a8", ARM::AK_ARMV7, true },
+ { "cortex-a5", ARM::AK_ARMV7A, false },
+ { "cortex-a7", ARM::AK_ARMV7A, false },
+ { "cortex-a8", ARM::AK_ARMV7A, true },
+ { "cortex-a9", ARM::AK_ARMV7A, false },
+ { "cortex-a12", ARM::AK_ARMV7A, false },
+ { "cortex-a15", ARM::AK_ARMV7A, false },
+ { "cortex-a17", ARM::AK_ARMV7A, false },
+ { "krait", ARM::AK_ARMV7A, false },
+ { "cortex-r4", ARM::AK_ARMV7R, true },
+ { "cortex-r4f", ARM::AK_ARMV7R, false },
+ { "cortex-r5", ARM::AK_ARMV7R, false },
+ { "cortex-r7", ARM::AK_ARMV7R, false },
+ { "sc300", ARM::AK_ARMV7M, false },
+ { "cortex-m3", ARM::AK_ARMV7M, true },
+ { "cortex-m4", ARM::AK_ARMV7M, false },
+ { "cortex-m7", ARM::AK_ARMV7M, false },
+ { "cortex-a53", ARM::AK_ARMV8A, true },
+ { "cortex-a57", ARM::AK_ARMV8A, false },
+ { "cortex-a72", ARM::AK_ARMV8A, false },
+ { "cyclone", ARM::AK_ARMV8A, false },
+ { "generic", ARM::AK_ARMV8_1A, true },
+ // Non-standard Arch names.
+ { "arm1022e", ARM::AK_ARMV5E, true },
+ { "arm926ej-s", ARM::AK_ARMV5TEJ, true },
+ { "cortex-m0", ARM::AK_ARMV6SM, true },
+ { "arm1176jzf-s", ARM::AK_ARMV6HL, true },
+ { "cortex-a8", ARM::AK_ARMV7L, true },
+ { "cortex-a8", ARM::AK_ARMV7HL, true },
+ { "cortex-m4", ARM::AK_ARMV7EM, true },
+ { "swift", ARM::AK_ARMV7S, true },
+ // Invalid CPU
+ { "invalid", ARM::AK_INVALID, true }
+};
+
+} // namespace
+
+namespace llvm {
+
+// ======================================================= //
+// Information by ID
+// ======================================================= //
+
+const char *ARMTargetParser::getFPUName(unsigned FPUKind) {
+ if (FPUKind >= ARM::FK_LAST)
+ return nullptr;
+ return FPUNames[FPUKind].Name;
+}
+
+const char *ARMTargetParser::getArchName(unsigned ArchKind) {
+ if (ArchKind >= ARM::AK_LAST)
+ return nullptr;
+ return ARCHNames[ArchKind].Name;
+}
+
+const char *ARMTargetParser::getArchDefaultCPUName(unsigned ArchKind) {
+ if (ArchKind >= ARM::AK_LAST)
+ return nullptr;
+ return ARCHNames[ArchKind].DefaultCPU;
+}
+
+unsigned ARMTargetParser::getArchDefaultCPUArch(unsigned ArchKind) {
+ if (ArchKind >= ARM::AK_LAST)
+ return ARMBuildAttrs::CPUArch::Pre_v4;
+ return ARCHNames[ArchKind].DefaultArch;
+}
+
+const char *ARMTargetParser::getArchExtName(unsigned ArchExtKind) {
+ if (ArchExtKind >= ARM::AEK_LAST)
+ return nullptr;
+ return ARCHExtNames[ArchExtKind].Name;
+}
+
+const char *ARMTargetParser::getDefaultCPU(StringRef Arch) {
+ unsigned AK = parseArch(Arch);
+ if (AK == ARM::AK_INVALID)
+ return nullptr;
+
+ // Look for multiple AKs to find the default for pair AK+Name.
+ for (const auto CPU : CPUNames) {
+ if (CPU.ArchID == AK && CPU.Default)
+ return CPU.Name;
+ }
+ return nullptr;
+}
+
+// ======================================================= //
+// Parsers
+// ======================================================= //
+
+StringRef ARMTargetParser::getFPUSynonym(StringRef FPU) {
+ return StringSwitch<StringRef>(FPU)
+ .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
+ .Case("vfp2", "vfpv2")
+ .Case("vfp3", "vfpv3")
+ .Case("vfp4", "vfpv4")
+ .Case("vfp3-d16", "vfpv3-d16")
+ .Case("vfp4-d16", "vfpv4-d16")
+ // FIXME: sp-16 is NOT the same as d16
+ .Cases("fp4-sp-d16", "fpv4-sp-d16", "vfpv4-d16")
+ .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
+ .Cases("fp5-sp-d16", "fpv5-sp-d16", "fpv5-d16")
+ .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
+ // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
+ .Case("neon-vfpv3", "neon")
+ .Default(FPU);
+}
+
+StringRef ARMTargetParser::getArchSynonym(StringRef Arch) {
+ return StringSwitch<StringRef>(Arch)
+ .Cases("armv6m", "v6m", "armv6-m")
+ .Cases("armv7a", "v7a", "armv7-a")
+ .Cases("armv7r", "v7r", "armv7-r")
+ .Cases("armv7m", "v7m", "armv7-m")
+ .Cases("armv7em", "v7em", "armv7e-m")
+ .Cases("armv8", "v8", "armv8-a")
+ .Cases("armv8a", "v8a", "armv8-a")
+ .Cases("armv8.1a", "v8.1a", "armv8.1-a")
+ .Cases("aarch64", "arm64", "armv8-a")
+ .Default(Arch);
+}
+
+// MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
+// (iwmmxt|xscale)(eb)? is also permitted. If the former, return
+// "v.+", if the latter, return unmodified string, minus 'eb'.
+// If invalid, return empty string.
+StringRef ARMTargetParser::getCanonicalArchName(StringRef Arch) {
+ size_t offset = StringRef::npos;
+ StringRef A = Arch;
+ StringRef Error = "";
+
+ // Begins with "arm" / "thumb", move past it.
+ if (A.startswith("arm64"))
+ offset = 5;
+ else if (A.startswith("arm"))
+ offset = 3;
+ else if (A.startswith("thumb"))
+ offset = 5;
+ else if (A.startswith("aarch64")) {
+ offset = 7;
+ // AArch64 uses "_be", not "eb" suffix.
+ if (A.find("eb") != StringRef::npos)
+ return Error;
+ if (A.substr(offset,3) == "_be")
+ offset += 3;
+ }
+
+ // Ex. "armebv7", move past the "eb".
+ if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
+ offset += 2;
+ // Or, if it ends with eb ("armv7eb"), chop it off.
+ else if (A.endswith("eb"))
+ A = A.substr(0, A.size() - 2);
+ // Trim the head
+ if (offset != StringRef::npos)
+ A = A.substr(offset);
+
+ // Empty string means offset reached the end, which means it's valid.
+ if (A.empty())
+ return Arch;
+
+ // Only match non-marketing names
+ if (offset != StringRef::npos) {
+ // Must start with 'vN'.
+ if (A[0] != 'v' || !std::isdigit(A[1]))
+ return Error;
+ // Can't have an extra 'eb'.
+ if (A.find("eb") != StringRef::npos)
+ return Error;
+ }
+
+ // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
+ return A;
+}
+
+unsigned ARMTargetParser::parseFPU(StringRef FPU) {
+ StringRef Syn = getFPUSynonym(FPU);
+ for (const auto F : FPUNames) {
+ if (Syn == F.Name)
+ return F.ID;
+ }
+ return ARM::FK_INVALID;
+}
+
+// Allows partial match, ex. "v7a" matches "armv7a".
+unsigned ARMTargetParser::parseArch(StringRef Arch) {
+ StringRef Syn = getArchSynonym(Arch);
+ for (const auto A : ARCHNames) {
+ if (StringRef(A.Name).endswith(Syn))
+ return A.ID;
+ }
+ return ARM::AK_INVALID;
+}
+
+unsigned ARMTargetParser::parseArchExt(StringRef ArchExt) {
+ for (const auto A : ARCHExtNames) {
+ if (ArchExt == A.Name)
+ return A.ID;
+ }
+ return ARM::AEK_INVALID;
+}
+
+unsigned ARMTargetParser::parseCPUArch(StringRef CPU) {
+ for (const auto C : CPUNames) {
+ if (CPU == C.Name)
+ return C.ArchID;
+ }
+ return ARM::AK_INVALID;
+}
+
+// ARM, Thumb, AArch64
+unsigned ARMTargetParser::parseArchISA(StringRef Arch) {
+ return StringSwitch<unsigned>(Arch)
+ .StartsWith("aarch64", ARM::IK_AARCH64)
+ .StartsWith("arm64", ARM::IK_AARCH64)
+ .StartsWith("thumb", ARM::IK_THUMB)
+ .StartsWith("arm", ARM::IK_ARM)
+ .Default(ARM::EK_INVALID);
+}
+
+// Little/Big endian
+unsigned ARMTargetParser::parseArchEndian(StringRef Arch) {
+ if (Arch.startswith("armeb") ||
+ Arch.startswith("thumbeb") ||
+ Arch.startswith("aarch64_be"))
+ return ARM::EK_BIG;
+
+ if (Arch.startswith("arm") || Arch.startswith("thumb")) {
+ if (Arch.endswith("eb"))
+ return ARM::EK_BIG;
+ else
+ return ARM::EK_LITTLE;
+ }
+
+ if (Arch.startswith("aarch64"))
+ return ARM::EK_LITTLE;
+
+ return ARM::EK_INVALID;
+}
+
+// Profile A/R/M
+unsigned ARMTargetParser::parseArchProfile(StringRef Arch) {
+ Arch = getCanonicalArchName(Arch);
+ switch(parseArch(Arch)) {
+ case ARM::AK_ARMV6M:
+ case ARM::AK_ARMV7M:
+ case ARM::AK_ARMV6SM:
+ case ARM::AK_ARMV7EM:
+ return ARM::PK_M;
+ case ARM::AK_ARMV7R:
+ return ARM::PK_R;
+ case ARM::AK_ARMV7:
+ case ARM::AK_ARMV7A:
+ case ARM::AK_ARMV8A:
+ case ARM::AK_ARMV8_1A:
+ return ARM::PK_A;
+ }
+ return ARM::PK_INVALID;
+}
+
+// Version number (ex. v7 = 7).
+unsigned ARMTargetParser::parseArchVersion(StringRef Arch) {
+ Arch = getCanonicalArchName(Arch);
+ switch(parseArch(Arch)) {
+ case ARM::AK_ARMV2:
+ case ARM::AK_ARMV2A:
+ return 2;
+ case ARM::AK_ARMV3:
+ case ARM::AK_ARMV3M:
+ return 3;
+ case ARM::AK_ARMV4:
+ case ARM::AK_ARMV4T:
+ return 4;
+ case ARM::AK_ARMV5:
+ case ARM::AK_ARMV5T:
+ case ARM::AK_ARMV5TE:
+ case ARM::AK_IWMMXT:
+ case ARM::AK_IWMMXT2:
+ case ARM::AK_XSCALE:
+ case ARM::AK_ARMV5E:
+ case ARM::AK_ARMV5TEJ:
+ return 5;
+ case ARM::AK_ARMV6:
+ case ARM::AK_ARMV6J:
+ case ARM::AK_ARMV6K:
+ case ARM::AK_ARMV6T2:
+ case ARM::AK_ARMV6Z:
+ case ARM::AK_ARMV6ZK:
+ case ARM::AK_ARMV6M:
+ case ARM::AK_ARMV6SM:
+ case ARM::AK_ARMV6HL:
+ return 6;
+ case ARM::AK_ARMV7:
+ case ARM::AK_ARMV7A:
+ case ARM::AK_ARMV7R:
+ case ARM::AK_ARMV7M:
+ case ARM::AK_ARMV7L:
+ case ARM::AK_ARMV7HL:
+ case ARM::AK_ARMV7S:
+ case ARM::AK_ARMV7EM:
+ return 7;
+ case ARM::AK_ARMV8A:
+ case ARM::AK_ARMV8_1A:
+ return 8;
+ }
+ return 0;
+}
+
+} // namespace llvm
diff --git a/lib/Support/TargetRegistry.cpp b/lib/Support/TargetRegistry.cpp
index f6918835f74b..eefef8ad8eaa 100644
--- a/lib/Support/TargetRegistry.cpp
+++ b/lib/Support/TargetRegistry.cpp
@@ -10,7 +10,6 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <vector>
@@ -19,8 +18,8 @@ using namespace llvm;
// Clients are responsible for avoid race conditions in registration.
static Target *FirstTarget = nullptr;
-TargetRegistry::iterator TargetRegistry::begin() {
- return iterator(FirstTarget);
+iterator_range<TargetRegistry::iterator> TargetRegistry::targets() {
+ return make_range(iterator(FirstTarget), iterator());
}
const Target *TargetRegistry::lookupTarget(const std::string &ArchName,
@@ -31,19 +30,17 @@ const Target *TargetRegistry::lookupTarget(const std::string &ArchName,
// name, because it might be a backend that has no mapping to a target triple.
const Target *TheTarget = nullptr;
if (!ArchName.empty()) {
- for (TargetRegistry::iterator it = TargetRegistry::begin(),
- ie = TargetRegistry::end(); it != ie; ++it) {
- if (ArchName == it->getName()) {
- TheTarget = &*it;
- break;
- }
- }
+ auto I =
+ std::find_if(targets().begin(), targets().end(),
+ [&](const Target &T) { return ArchName == T.getName(); });
- if (!TheTarget) {
+ if (I == targets().end()) {
Error = "error: invalid target '" + ArchName + "'.\n";
return nullptr;
}
+ TheTarget = &*I;
+
// Adjust the triple to match (if known), otherwise stick with the
// given triple.
Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName);
@@ -67,30 +64,28 @@ const Target *TargetRegistry::lookupTarget(const std::string &ArchName,
const Target *TargetRegistry::lookupTarget(const std::string &TT,
std::string &Error) {
// Provide special warning when no targets are initialized.
- if (begin() == end()) {
+ if (targets().begin() == targets().end()) {
Error = "Unable to find target for this triple (no targets are registered)";
return nullptr;
}
- const Target *Matching = nullptr;
- Triple::ArchType Arch = Triple(TT).getArch();
- for (iterator it = begin(), ie = end(); it != ie; ++it) {
- if (it->ArchMatchFn(Arch)) {
- if (Matching) {
- Error = std::string("Cannot choose between targets \"") +
- Matching->Name + "\" and \"" + it->Name + "\"";
- return nullptr;
- }
- Matching = &*it;
- }
- }
+ Triple::ArchType Arch = Triple(TT).getArch();
+ auto ArchMatch = [&](const Target &T) { return T.ArchMatchFn(Arch); };
+ auto I = std::find_if(targets().begin(), targets().end(), ArchMatch);
- if (!Matching) {
+ if (I == targets().end()) {
Error = "No available targets are compatible with this triple, "
"see -version for the available targets.";
return nullptr;
}
- return Matching;
+ auto J = std::find_if(std::next(I), targets().end(), ArchMatch);
+ if (J != targets().end()) {
+ Error = std::string("Cannot choose between targets \"") + I->Name +
+ "\" and \"" + J->Name + "\"";
+ return nullptr;
+ }
+
+ return &*I;
}
void TargetRegistry::RegisterTarget(Target &T,
@@ -124,10 +119,8 @@ static int TargetArraySortFn(const std::pair<StringRef, const Target *> *LHS,
void TargetRegistry::printRegisteredTargetsForVersion() {
std::vector<std::pair<StringRef, const Target*> > Targets;
size_t Width = 0;
- for (TargetRegistry::iterator I = TargetRegistry::begin(),
- E = TargetRegistry::end();
- I != E; ++I) {
- Targets.push_back(std::make_pair(I->getName(), &*I));
+ for (const auto &T : TargetRegistry::targets()) {
+ Targets.push_back(std::make_pair(T.getName(), &T));
Width = std::max(Width, Targets.back().first.size());
}
array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn);
diff --git a/lib/Support/Timer.cpp b/lib/Support/Timer.cpp
index e1a531a0af25..d7b65155d6ef 100644
--- a/lib/Support/Timer.cpp
+++ b/lib/Support/Timer.cpp
@@ -14,12 +14,10 @@
#include "llvm/Support/Timer.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Mutex.h"
-#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp
index 0838e90baaec..a63426f88571 100644
--- a/lib/Support/Triple.cpp
+++ b/lib/Support/Triple.cpp
@@ -12,6 +12,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetParser.h"
#include <cstring>
using namespace llvm;
@@ -23,6 +24,7 @@ const char *Triple::getArchTypeName(ArchType Kind) {
case aarch64_be: return "aarch64_be";
case arm: return "arm";
case armeb: return "armeb";
+ case bpf: return "bpf";
case hexagon: return "hexagon";
case mips: return "mips";
case mipsel: return "mipsel";
@@ -36,6 +38,7 @@ const char *Triple::getArchTypeName(ArchType Kind) {
case amdgcn: return "amdgcn";
case sparc: return "sparc";
case sparcv9: return "sparcv9";
+ case sparcel: return "sparcel";
case systemz: return "s390x";
case tce: return "tce";
case thumb: return "thumb";
@@ -86,10 +89,13 @@ const char *Triple::getArchTypePrefix(ArchType Kind) {
case amdgcn:
case r600: return "amdgpu";
+ case bpf: return "bpf";
+
case sparcv9:
+ case sparcel:
case sparc: return "sparc";
- case systemz: return "systemz";
+ case systemz: return "s390";
case x86:
case x86_64: return "x86";
@@ -138,6 +144,7 @@ const char *Triple::getOSTypeName(OSType Kind) {
switch (Kind) {
case UnknownOS: return "unknown";
+ case CloudABI: return "cloudabi";
case Darwin: return "darwin";
case DragonFly: return "dragonfly";
case FreeBSD: return "freebsd";
@@ -160,6 +167,7 @@ const char *Triple::getOSTypeName(OSType Kind) {
case CUDA: return "cuda";
case NVCL: return "nvcl";
case AMDHSA: return "amdhsa";
+ case PS4: return "ps4";
}
llvm_unreachable("Invalid OSType");
@@ -191,6 +199,7 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
.Case("arm64", aarch64) // "arm64" is an alias for "aarch64"
.Case("arm", arm)
.Case("armeb", armeb)
+ .Case("bpf", bpf)
.Case("mips", mips)
.Case("mipsel", mipsel)
.Case("mips64", mips64)
@@ -204,6 +213,7 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
.Case("amdgcn", amdgcn)
.Case("hexagon", hexagon)
.Case("sparc", sparc)
+ .Case("sparcel", sparcel)
.Case("sparcv9", sparcv9)
.Case("systemz", systemz)
.Case("tce", tce)
@@ -227,55 +237,61 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
}
static Triple::ArchType parseARMArch(StringRef ArchName) {
- size_t offset = StringRef::npos;
+ unsigned ISA = ARMTargetParser::parseArchISA(ArchName);
+ unsigned ENDIAN = ARMTargetParser::parseArchEndian(ArchName);
+
Triple::ArchType arch = Triple::UnknownArch;
- bool isThumb = ArchName.startswith("thumb");
-
- if (ArchName.equals("arm"))
- return Triple::arm;
- if (ArchName.equals("armeb"))
- return Triple::armeb;
- if (ArchName.equals("thumb"))
- return Triple::thumb;
- if (ArchName.equals("thumbeb"))
- return Triple::thumbeb;
- if (ArchName.equals("arm64") || ArchName.equals("aarch64"))
- return Triple::aarch64;
- if (ArchName.equals("aarch64_be"))
- return Triple::aarch64_be;
-
- if (ArchName.startswith("armv")) {
- offset = 3;
- if (ArchName.endswith("eb")) {
- arch = Triple::armeb;
- ArchName = ArchName.substr(0, ArchName.size() - 2);
- } else
+ switch (ENDIAN) {
+ case ARM::EK_LITTLE: {
+ switch (ISA) {
+ case ARM::IK_ARM:
arch = Triple::arm;
- } else if (ArchName.startswith("armebv")) {
- offset = 5;
- arch = Triple::armeb;
- } else if (ArchName.startswith("thumbv")) {
- offset = 5;
- if (ArchName.endswith("eb")) {
- arch = Triple::thumbeb;
- ArchName = ArchName.substr(0, ArchName.size() - 2);
- } else
+ break;
+ case ARM::IK_THUMB:
arch = Triple::thumb;
- } else if (ArchName.startswith("thumbebv")) {
- offset = 7;
- arch = Triple::thumbeb;
+ break;
+ case ARM::IK_AARCH64:
+ arch = Triple::aarch64;
+ break;
+ }
+ break;
}
- return StringSwitch<Triple::ArchType>(ArchName.substr(offset))
- .Cases("v2", "v2a", isThumb ? Triple::UnknownArch : arch)
- .Cases("v3", "v3m", isThumb ? Triple::UnknownArch : arch)
- .Cases("v4", "v4t", arch)
- .Cases("v5", "v5e", "v5t", "v5te", "v5tej", arch)
- .Cases("v6", "v6j", "v6k", "v6m", arch)
- .Cases("v6t2", "v6z", "v6zk", arch)
- .Cases("v7", "v7a", "v7em", "v7l", arch)
- .Cases("v7m", "v7r", "v7s", arch)
- .Cases("v8", "v8a", arch)
- .Default(Triple::UnknownArch);
+ case ARM::EK_BIG: {
+ switch (ISA) {
+ case ARM::IK_ARM:
+ arch = Triple::armeb;
+ break;
+ case ARM::IK_THUMB:
+ arch = Triple::thumbeb;
+ break;
+ case ARM::IK_AARCH64:
+ arch = Triple::aarch64_be;
+ break;
+ }
+ break;
+ }
+ }
+
+ ArchName = ARMTargetParser::getCanonicalArchName(ArchName);
+ if (ArchName.empty())
+ return Triple::UnknownArch;
+
+ // Thumb only exists in v4+
+ if (ISA == ARM::IK_THUMB &&
+ (ArchName.startswith("v2") || ArchName.startswith("v3")))
+ return Triple::UnknownArch;
+
+ // Thumb only for v6m
+ unsigned Profile = ARMTargetParser::parseArchProfile(ArchName);
+ unsigned Version = ARMTargetParser::parseArchVersion(ArchName);
+ if (Profile == ARM::PK_M && Version == 6) {
+ if (ENDIAN == ARM::EK_BIG)
+ return Triple::thumbeb;
+ else
+ return Triple::thumb;
+ }
+
+ return arch;
}
static Triple::ArchType parseArch(StringRef ArchName) {
@@ -301,9 +317,11 @@ static Triple::ArchType parseArch(StringRef ArchName) {
.Case("mips64el", Triple::mips64el)
.Case("r600", Triple::r600)
.Case("amdgcn", Triple::amdgcn)
+ .Case("bpf", Triple::bpf)
.Case("hexagon", Triple::hexagon)
.Case("s390x", Triple::systemz)
.Case("sparc", Triple::sparc)
+ .Case("sparcel", Triple::sparcel)
.Cases("sparcv9", "sparc64", Triple::sparcv9)
.Case("tce", Triple::tce)
.Case("xcore", Triple::xcore)
@@ -339,6 +357,7 @@ static Triple::VendorType parseVendor(StringRef VendorName) {
static Triple::OSType parseOS(StringRef OSName) {
return StringSwitch<Triple::OSType>(OSName)
+ .StartsWith("cloudabi", Triple::CloudABI)
.StartsWith("darwin", Triple::Darwin)
.StartsWith("dragonfly", Triple::DragonFly)
.StartsWith("freebsd", Triple::FreeBSD)
@@ -362,6 +381,7 @@ static Triple::OSType parseOS(StringRef OSName) {
.StartsWith("cuda", Triple::CUDA)
.StartsWith("nvcl", Triple::NVCL)
.StartsWith("amdhsa", Triple::AMDHSA)
+ .StartsWith("ps4", Triple::PS4)
.Default(Triple::UnknownOS);
}
@@ -390,31 +410,64 @@ static Triple::ObjectFormatType parseFormat(StringRef EnvironmentName) {
}
static Triple::SubArchType parseSubArch(StringRef SubArchName) {
- if (SubArchName.endswith("eb"))
- SubArchName = SubArchName.substr(0, SubArchName.size() - 2);
-
- return StringSwitch<Triple::SubArchType>(SubArchName)
- .EndsWith("v8", Triple::ARMSubArch_v8)
- .EndsWith("v8a", Triple::ARMSubArch_v8)
- .EndsWith("v7", Triple::ARMSubArch_v7)
- .EndsWith("v7a", Triple::ARMSubArch_v7)
- .EndsWith("v7em", Triple::ARMSubArch_v7em)
- .EndsWith("v7l", Triple::ARMSubArch_v7)
- .EndsWith("v7m", Triple::ARMSubArch_v7m)
- .EndsWith("v7r", Triple::ARMSubArch_v7)
- .EndsWith("v7s", Triple::ARMSubArch_v7s)
- .EndsWith("v6", Triple::ARMSubArch_v6)
- .EndsWith("v6m", Triple::ARMSubArch_v6m)
- .EndsWith("v6t2", Triple::ARMSubArch_v6t2)
- .EndsWith("v5", Triple::ARMSubArch_v5)
- .EndsWith("v5e", Triple::ARMSubArch_v5)
- .EndsWith("v5t", Triple::ARMSubArch_v5)
- .EndsWith("v5te", Triple::ARMSubArch_v5te)
- .EndsWith("v4t", Triple::ARMSubArch_v4t)
- .EndsWith("kalimba3", Triple::KalimbaSubArch_v3)
- .EndsWith("kalimba4", Triple::KalimbaSubArch_v4)
- .EndsWith("kalimba5", Triple::KalimbaSubArch_v5)
- .Default(Triple::NoSubArch);
+ StringRef ARMSubArch = ARMTargetParser::getCanonicalArchName(SubArchName);
+
+ // For now, this is the small part. Early return.
+ if (ARMSubArch.empty())
+ return StringSwitch<Triple::SubArchType>(SubArchName)
+ .EndsWith("kalimba3", Triple::KalimbaSubArch_v3)
+ .EndsWith("kalimba4", Triple::KalimbaSubArch_v4)
+ .EndsWith("kalimba5", Triple::KalimbaSubArch_v5)
+ .Default(Triple::NoSubArch);
+
+ // ARM sub arch.
+ switch(ARMTargetParser::parseArch(ARMSubArch)) {
+ case ARM::AK_ARMV4:
+ return Triple::NoSubArch;
+ case ARM::AK_ARMV4T:
+ return Triple::ARMSubArch_v4t;
+ case ARM::AK_ARMV5:
+ case ARM::AK_ARMV5T:
+ case ARM::AK_ARMV5E:
+ return Triple::ARMSubArch_v5;
+ case ARM::AK_ARMV5TE:
+ case ARM::AK_IWMMXT:
+ case ARM::AK_IWMMXT2:
+ case ARM::AK_XSCALE:
+ case ARM::AK_ARMV5TEJ:
+ return Triple::ARMSubArch_v5te;
+ case ARM::AK_ARMV6:
+ case ARM::AK_ARMV6J:
+ case ARM::AK_ARMV6Z:
+ return Triple::ARMSubArch_v6;
+ case ARM::AK_ARMV6K:
+ case ARM::AK_ARMV6ZK:
+ case ARM::AK_ARMV6HL:
+ return Triple::ARMSubArch_v6k;
+ case ARM::AK_ARMV6T2:
+ return Triple::ARMSubArch_v6t2;
+ case ARM::AK_ARMV6M:
+ case ARM::AK_ARMV6SM:
+ return Triple::ARMSubArch_v6m;
+ case ARM::AK_ARMV7:
+ case ARM::AK_ARMV7A:
+ case ARM::AK_ARMV7R:
+ case ARM::AK_ARMV7L:
+ case ARM::AK_ARMV7HL:
+ return Triple::ARMSubArch_v7;
+ case ARM::AK_ARMV7M:
+ return Triple::ARMSubArch_v7m;
+ case ARM::AK_ARMV7S:
+ return Triple::ARMSubArch_v7s;
+ case ARM::AK_ARMV7EM:
+ return Triple::ARMSubArch_v7em;
+ case ARM::AK_ARMV8A:
+ return Triple::ARMSubArch_v8;
+ case ARM::AK_ARMV8_1A:
+ return Triple::ARMSubArch_v8_1a;
+ default:
+ return Triple::NoSubArch;
+ }
}
static const char *getObjectFormatTypeName(Triple::ObjectFormatType Kind) {
@@ -428,6 +481,30 @@ static const char *getObjectFormatTypeName(Triple::ObjectFormatType Kind) {
}
static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
+ switch (T.getArch()) {
+ default:
+ break;
+ case Triple::hexagon:
+ case Triple::mips:
+ case Triple::mipsel:
+ case Triple::mips64:
+ case Triple::mips64el:
+ case Triple::r600:
+ case Triple::amdgcn:
+ case Triple::sparc:
+ case Triple::sparcv9:
+ case Triple::systemz:
+ case Triple::xcore:
+ case Triple::ppc64le:
+ return Triple::ELF;
+
+ case Triple::ppc:
+ case Triple::ppc64:
+ if (T.isOSDarwin())
+ return Triple::MachO;
+ return Triple::ELF;
+ }
+
if (T.isOSDarwin())
return Triple::MachO;
else if (T.isOSWindows())
@@ -706,6 +783,14 @@ void Triple::getOSVersion(unsigned &Major, unsigned &Minor,
unsigned &Micro) const {
StringRef OSName = getOSName();
+ // For Android, we care about the Android version rather than the Linux
+ // version.
+ if (getEnvironment() == Android) {
+ OSName = getEnvironmentName().substr(strlen("android"));
+ if (OSName.startswith("eabi"))
+ OSName = OSName.substr(strlen("eabi"));
+ }
+
// Assume that the OS portion of the triple starts with the canonical name.
StringRef OSTypeName = getOSTypeName(getOS());
if (OSName.startswith(OSTypeName))
@@ -808,7 +893,11 @@ void Triple::setOS(OSType Kind) {
}
void Triple::setEnvironment(EnvironmentType Kind) {
- setEnvironmentName(getEnvironmentTypeName(Kind));
+ if (ObjectFormat == getDefaultFormat(*this))
+ return setEnvironmentName(getEnvironmentTypeName(Kind));
+
+ setEnvironmentName((getEnvironmentTypeName(Kind) + Twine("-") +
+ getObjectFormatTypeName(ObjectFormat)).str());
}
void Triple::setObjectFormat(ObjectFormatType Kind) {
@@ -827,7 +916,7 @@ void Triple::setArchName(StringRef Str) {
Triple += getVendorName();
Triple += "-";
Triple += getOSAndEnvironmentName();
- setTriple(Triple.str());
+ setTriple(Triple);
}
void Triple::setVendorName(StringRef Str) {
@@ -869,6 +958,7 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
case llvm::Triple::ppc:
case llvm::Triple::r600:
case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
case llvm::Triple::tce:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
@@ -883,6 +973,7 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
case llvm::Triple::amdgcn:
+ case llvm::Triple::bpf:
case llvm::Triple::le64:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
@@ -919,6 +1010,7 @@ Triple Triple::get32BitArchVariant() const {
case Triple::aarch64:
case Triple::aarch64_be:
case Triple::amdgcn:
+ case Triple::bpf:
case Triple::msp430:
case Triple::systemz:
case Triple::ppc64le:
@@ -939,6 +1031,7 @@ Triple Triple::get32BitArchVariant() const {
case Triple::ppc:
case Triple::r600:
case Triple::sparc:
+ case Triple::sparcel:
case Triple::tce:
case Triple::thumb:
case Triple::thumbeb:
@@ -975,11 +1068,13 @@ Triple Triple::get64BitArchVariant() const {
case Triple::thumb:
case Triple::thumbeb:
case Triple::xcore:
+ case Triple::sparcel:
T.setArch(UnknownArch);
break;
case Triple::aarch64:
case Triple::aarch64_be:
+ case Triple::bpf:
case Triple::le64:
case Triple::amdil64:
case Triple::amdgcn:
@@ -1010,14 +1105,15 @@ Triple Triple::get64BitArchVariant() const {
return T;
}
-// FIXME: tblgen this.
const char *Triple::getARMCPUForArch(StringRef MArch) const {
if (MArch.empty())
MArch = getArchName();
+ // Some defaults are forced.
switch (getOS()) {
case llvm::Triple::FreeBSD:
case llvm::Triple::NetBSD:
+ // FIXME: This doesn't work on BE/thumb variants.
if (MArch == "armv6")
return "arm1176jzf-s";
break;
@@ -1028,51 +1124,16 @@ const char *Triple::getARMCPUForArch(StringRef MArch) const {
break;
}
- const char *result = nullptr;
- size_t offset = StringRef::npos;
- if (MArch.startswith("arm"))
- offset = 3;
- if (MArch.startswith("thumb"))
- offset = 5;
- if (offset != StringRef::npos && MArch.substr(offset, 2) == "eb")
- offset += 2;
- if (MArch.endswith("eb"))
- MArch = MArch.substr(0, MArch.size() - 2);
- if (offset != StringRef::npos)
- result = llvm::StringSwitch<const char *>(MArch.substr(offset))
- .Cases("v2", "v2a", "arm2")
- .Case("v3", "arm6")
- .Case("v3m", "arm7m")
- .Case("v4", "strongarm")
- .Case("v4t", "arm7tdmi")
- .Cases("v5", "v5t", "arm10tdmi")
- .Cases("v5e", "v5te", "arm1022e")
- .Case("v5tej", "arm926ej-s")
- .Cases("v6", "v6k", "arm1136jf-s")
- .Case("v6j", "arm1136j-s")
- .Cases("v6z", "v6zk", "arm1176jzf-s")
- .Case("v6t2", "arm1156t2-s")
- .Cases("v6m", "v6-m", "cortex-m0")
- .Cases("v7", "v7a", "v7-a", "v7l", "v7-l", "cortex-a8")
- .Cases("v7s", "v7-s", "swift")
- .Cases("v7r", "v7-r", "cortex-r4")
- .Cases("v7m", "v7-m", "cortex-m3")
- .Cases("v7em", "v7e-m", "cortex-m4")
- .Cases("v8", "v8a", "v8-a", "cortex-a53")
- .Default(nullptr);
- else
- result = llvm::StringSwitch<const char *>(MArch)
- .Case("ep9312", "ep9312")
- .Case("iwmmxt", "iwmmxt")
- .Case("xscale", "xscale")
- .Default(nullptr);
-
- if (result)
- return result;
-
- // If all else failed, return the most base CPU with thumb interworking
- // supported by LLVM.
- // FIXME: Should warn once that we're falling back.
+ MArch = ARMTargetParser::getCanonicalArchName(MArch);
+ if (MArch.empty())
+ return nullptr;
+
+ const char *CPU = ARMTargetParser::getDefaultCPU(MArch);
+ if (CPU)
+ return CPU;
+
+ // If no specific architecture version is requested, return the minimum CPU
+ // required by the OS and environment.
switch (getOS()) {
case llvm::Triple::NetBSD:
switch (getEnvironment()) {
@@ -1084,6 +1145,8 @@ const char *Triple::getARMCPUForArch(StringRef MArch) const {
default:
return "strongarm";
}
+ case llvm::Triple::NaCl:
+ return "cortex-a8";
default:
switch (getEnvironment()) {
case llvm::Triple::EABIHF:
@@ -1093,4 +1156,6 @@ const char *Triple::getARMCPUForArch(StringRef MArch) const {
return "arm7tdmi";
}
}
+
+ llvm_unreachable("invalid arch name");
}
diff --git a/lib/Support/Twine.cpp b/lib/Support/Twine.cpp
index 56ed964a50eb..020dd9596d9c 100644
--- a/lib/Support/Twine.cpp
+++ b/lib/Support/Twine.cpp
@@ -28,13 +28,6 @@ void Twine::toVector(SmallVectorImpl<char> &Out) const {
print(OS);
}
-StringRef Twine::toStringRef(SmallVectorImpl<char> &Out) const {
- if (isSingleStringRef())
- return getSingleStringRef();
- toVector(Out);
- return StringRef(Out.data(), Out.size());
-}
-
StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const {
if (isUnary()) {
switch (getLHSKind()) {
@@ -72,6 +65,9 @@ void Twine::printOneChild(raw_ostream &OS, Child Ptr,
case Twine::StringRefKind:
OS << *Ptr.stringRef;
break;
+ case Twine::SmallStringKind:
+ OS << *Ptr.smallString;
+ break;
case Twine::CharKind:
OS << Ptr.character;
break;
@@ -122,6 +118,9 @@ void Twine::printOneChildRepr(raw_ostream &OS, Child Ptr,
OS << "stringref:\""
<< Ptr.stringRef << "\"";
break;
+ case Twine::SmallStringKind:
+ OS << "smallstring:\"" << *Ptr.smallString << "\"";
+ break;
case Twine::CharKind:
OS << "char:\"" << Ptr.character << "\"";
break;
diff --git a/lib/Support/Unix/COM.inc b/lib/Support/Unix/COM.inc
new file mode 100644
index 000000000000..5b71de74ebf3
--- /dev/null
+++ b/lib/Support/Unix/COM.inc
@@ -0,0 +1,27 @@
+//===- llvm/Support/Unix/COM.inc - Unix COM Implementation -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Unix portion of COM support.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic UNIX code that
+//=== is guaranteed to work on *all* UNIX variants.
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+namespace sys {
+
+InitializeCOMRAII::InitializeCOMRAII(COMThreadingMode Threading,
+ bool SpeedOverMemory) {}
+
+InitializeCOMRAII::~InitializeCOMRAII() {}
+}
+}
diff --git a/lib/Support/Unix/Host.inc b/lib/Support/Unix/Host.inc
index 519f2a1fe687..457217125a22 100644
--- a/lib/Support/Unix/Host.inc
+++ b/lib/Support/Unix/Host.inc
@@ -35,29 +35,15 @@ static std::string getOSVersion() {
}
std::string sys::getDefaultTargetTriple() {
- StringRef TargetTripleString(LLVM_DEFAULT_TARGET_TRIPLE);
- std::pair<StringRef, StringRef> ArchSplit = TargetTripleString.split('-');
-
- // Normalize the arch, since the target triple may not actually match the
- // target.
- std::string Arch = ArchSplit.first;
-
- std::string Triple(Arch);
- Triple += '-';
- Triple += ArchSplit.second;
-
- // Force i<N>86 to i386.
- if (Triple[0] == 'i' && isdigit(Triple[1]) &&
- Triple[2] == '8' && Triple[3] == '6')
- Triple[1] = '3';
+ std::string TargetTripleString(LLVM_DEFAULT_TARGET_TRIPLE);
// On darwin, we want to update the version to match that of the
// target.
- std::string::size_type DarwinDashIdx = Triple.find("-darwin");
+ std::string::size_type DarwinDashIdx = TargetTripleString.find("-darwin");
if (DarwinDashIdx != std::string::npos) {
- Triple.resize(DarwinDashIdx + strlen("-darwin"));
- Triple += getOSVersion();
+ TargetTripleString.resize(DarwinDashIdx + strlen("-darwin"));
+ TargetTripleString += getOSVersion();
}
- return Triple::normalize(Triple);
+ return Triple::normalize(TargetTripleString);
}
diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc
index 530f86cf9070..df13bd221739 100644
--- a/lib/Support/Unix/Process.inc
+++ b/lib/Support/Unix/Process.inc
@@ -39,6 +39,9 @@
!defined(__OpenBSD__) && !defined(__Bitrig__)
#include <malloc.h>
#endif
+#if defined(HAVE_MALLCTL)
+#include <malloc_np.h>
+#endif
#ifdef HAVE_MALLOC_MALLOC_H
#include <malloc/malloc.h>
#endif
@@ -98,6 +101,12 @@ size_t Process::GetMallocUsage() {
malloc_statistics_t Stats;
malloc_zone_statistics(malloc_default_zone(), &Stats);
return Stats.size_in_use; // darwin
+#elif defined(HAVE_MALLCTL)
+ size_t alloc, sz;
+ sz = sizeof(size_t);
+ if (mallctl("stats.allocated", &alloc, &sz, NULL, 0) == 0)
+ return alloc;
+ return 0;
#elif defined(HAVE_SBRK)
// Note this is only an approximation and more closely resembles
// the value returned by mallinfo in the arena field.
@@ -105,8 +114,7 @@ size_t Process::GetMallocUsage() {
char *EndOfMemory = (char*)sbrk(0);
if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
return EndOfMemory - StartOfMemory;
- else
- return 0;
+ return 0;
#else
#warning Cannot get malloc info on this platform
return 0;
@@ -191,8 +199,8 @@ public:
}
private:
- FDCloser(const FDCloser &) LLVM_DELETED_FUNCTION;
- void operator=(const FDCloser &) LLVM_DELETED_FUNCTION;
+ FDCloser(const FDCloser &) = delete;
+ void operator=(const FDCloser &) = delete;
int &FD;
bool KeepOpen;
diff --git a/lib/Support/Unix/Program.inc b/lib/Support/Unix/Program.inc
index 0f45df1a0da0..5816fb812e9f 100644
--- a/lib/Support/Unix/Program.inc
+++ b/lib/Support/Unix/Program.inc
@@ -18,10 +18,11 @@
#include "Unix.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
-#include <llvm/Config/config.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
@@ -42,7 +43,18 @@
#define _RESTRICT_KYWD
#endif
#include <spawn.h>
-#if !defined(__APPLE__)
+
+#if defined(__APPLE__)
+#include <TargetConditionals.h>
+#endif
+
+#if defined(__APPLE__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
+#define USE_NSGETENVIRON 1
+#else
+#define USE_NSGETENVIRON 0
+#endif
+
+#if !USE_NSGETENVIRON
extern char **environ;
#else
#include <crt_externs.h> // _NSGetEnviron
@@ -217,7 +229,7 @@ static bool Execute(ProcessInfo &PI, StringRef Program, const char **args,
}
if (!envp)
-#if !defined(__APPLE__)
+#if !USE_NSGETENVIRON
envp = const_cast<const char **>(environ);
#else
// environ is missing in dylibs.
diff --git a/lib/Support/Unix/Signals.inc b/lib/Support/Unix/Signals.inc
index e8f4643dc8a7..bfe2a3a380ed 100644
--- a/lib/Support/Unix/Signals.inc
+++ b/lib/Support/Unix/Signals.inc
@@ -14,6 +14,7 @@
#include "Unix.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/ManagedStatic.h"
@@ -111,6 +112,12 @@ static void RegisterHandler(int Signal) {
}
static void RegisterHandlers() {
+ // We need to dereference the signals mutex during handler registration so
+ // that we force its construction. This is to prevent the first use being
+ // during handling an actual signal because you can't safely call new in a
+ // signal handler.
+ *SignalsMutex;
+
// If the handlers are already registered, we're done.
if (NumRegisteredSignals != 0) return;
@@ -132,6 +139,11 @@ static void UnregisterHandlers() {
/// NB: This must be an async signal safe function. It cannot allocate or free
/// memory, even in debug builds.
static void RemoveFilesToRemove() {
+ // Avoid constructing ManagedStatic in the signal handler.
+ // If FilesToRemove is not constructed, there are no files to remove.
+ if (!FilesToRemove.isConstructed())
+ return;
+
// We avoid iterators in case of debug iterators that allocate or release
// memory.
std::vector<std::string>& FilesToRemoveRef = *FilesToRemove;
@@ -193,10 +205,11 @@ static RETSIGTYPE SignalHandler(int Sig) {
}
// Otherwise if it is a fault (like SEGV) run any handler.
- std::vector<std::pair<void (*)(void *), void *>>& CallBacksToRunRef =
- *CallBacksToRun;
- for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i)
- CallBacksToRunRef[i].first(CallBacksToRunRef[i].second);
+ if (CallBacksToRun.isConstructed()) {
+ auto &CallBacksToRunRef = *CallBacksToRun;
+ for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i)
+ CallBacksToRunRef[i].first(CallBacksToRunRef[i].second);
+ }
#ifdef __s390__
// On S/390, certain signals are delivered with PSW Address pointing to
@@ -324,7 +337,8 @@ static bool findModulesAndOffsets(void **StackTrace, int Depth,
}
#endif
-static bool printSymbolizedStackTrace(void **StackTrace, int Depth, FILE *FD) {
+static bool printSymbolizedStackTrace(void **StackTrace, int Depth,
+ llvm::raw_ostream &OS) {
// FIXME: Subtract necessary number from StackTrace entries to turn return addresses
// into actual instruction addresses.
// Use llvm-symbolizer tool to symbolize the stack traces.
@@ -382,7 +396,7 @@ static bool printSymbolizedStackTrace(void **StackTrace, int Depth, FILE *FD) {
int frame_no = 0;
for (int i = 0; i < Depth; i++) {
if (!Modules[i]) {
- fprintf(FD, "#%d %p\n", frame_no++, StackTrace[i]);
+ OS << format("#%d %p\n", frame_no++, StackTrace[i]);
continue;
}
// Read pairs of lines (function name and file/line info) until we
@@ -393,17 +407,17 @@ static bool printSymbolizedStackTrace(void **StackTrace, int Depth, FILE *FD) {
StringRef FunctionName = *CurLine++;
if (FunctionName.empty())
break;
- fprintf(FD, "#%d %p ", frame_no++, StackTrace[i]);
+ OS << format("#%d %p ", frame_no++, StackTrace[i]);
if (!FunctionName.startswith("??"))
- fprintf(FD, "%s ", FunctionName.str().c_str());
+ OS << format("%s ", FunctionName.str().c_str());
if (CurLine == Lines.end())
return false;
StringRef FileLineInfo = *CurLine++;
if (!FileLineInfo.startswith("??"))
- fprintf(FD, "%s", FileLineInfo.str().c_str());
+ OS << format("%s", FileLineInfo.str().c_str());
else
- fprintf(FD, "(%s+%p)", Modules[i], (void *)Offsets[i]);
- fprintf(FD, "\n");
+ OS << format("(%s+%p)", Modules[i], (void *)Offsets[i]);
+ OS << "\n";
}
}
return true;
@@ -415,13 +429,13 @@ static bool printSymbolizedStackTrace(void **StackTrace, int Depth, FILE *FD) {
//
// On glibc systems we have the 'backtrace' function, which works nicely, but
// doesn't demangle symbols.
-void llvm::sys::PrintStackTrace(FILE *FD) {
+void llvm::sys::PrintStackTrace(raw_ostream &OS) {
#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
static void* StackTrace[256];
// Use backtrace() to output a backtrace on Linux systems with glibc.
int depth = backtrace(StackTrace,
static_cast<int>(array_lengthof(StackTrace)));
- if (printSymbolizedStackTrace(StackTrace, depth, FD))
+ if (printSymbolizedStackTrace(StackTrace, depth, OS))
return;
#if HAVE_DLFCN_H && __GNUG__
int width = 0;
@@ -441,34 +455,34 @@ void llvm::sys::PrintStackTrace(FILE *FD) {
Dl_info dlinfo;
dladdr(StackTrace[i], &dlinfo);
- fprintf(FD, "%-2d", i);
+ OS << format("%-2d", i);
const char* name = strrchr(dlinfo.dli_fname, '/');
- if (!name) fprintf(FD, " %-*s", width, dlinfo.dli_fname);
- else fprintf(FD, " %-*s", width, name+1);
+ if (!name) OS << format(" %-*s", width, dlinfo.dli_fname);
+ else OS << format(" %-*s", width, name+1);
- fprintf(FD, " %#0*lx",
- (int)(sizeof(void*) * 2) + 2, (unsigned long)StackTrace[i]);
+ OS << format(" %#0*lx", (int)(sizeof(void*) * 2) + 2,
+ (unsigned long)StackTrace[i]);
if (dlinfo.dli_sname != nullptr) {
- fputc(' ', FD);
+ OS << ' ';
# if HAVE_CXXABI_H
int res;
char* d = abi::__cxa_demangle(dlinfo.dli_sname, nullptr, nullptr, &res);
# else
char* d = NULL;
# endif
- if (!d) fputs(dlinfo.dli_sname, FD);
- else fputs(d, FD);
+ if (!d) OS << dlinfo.dli_sname;
+ else OS << d;
free(d);
// FIXME: When we move to C++11, use %t length modifier. It's not in
// C++03 and causes gcc to issue warnings. Losing the upper 32 bits of
// the stack offset for a stack dump isn't likely to cause any problems.
- fprintf(FD, " + %u",(unsigned)((char*)StackTrace[i]-
- (char*)dlinfo.dli_saddr));
+ OS << format(" + %u",(unsigned)((char*)StackTrace[i]-
+ (char*)dlinfo.dli_saddr));
}
- fputc('\n', FD);
+ OS << '\n';
}
#else
backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
@@ -477,17 +491,19 @@ void llvm::sys::PrintStackTrace(FILE *FD) {
}
static void PrintStackTraceSignalHandler(void *) {
- PrintStackTrace(stderr);
+ PrintStackTrace(llvm::errs());
}
+void llvm::sys::DisableSystemDialogsOnCrash() {}
+
/// PrintStackTraceOnErrorSignal - When an error signal (such as SIGABRT or
/// SIGSEGV) is delivered to the process, print a stack trace and then exit.
-void llvm::sys::PrintStackTraceOnErrorSignal() {
+void llvm::sys::PrintStackTraceOnErrorSignal(bool DisableCrashReporting) {
AddSignalHandler(PrintStackTraceSignalHandler, nullptr);
#if defined(__APPLE__) && defined(ENABLE_CRASH_OVERRIDES)
// Environment variable to disable any kind of crash dialog.
- if (getenv("LLVM_DISABLE_CRASH_REPORT")) {
+ if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT")) {
mach_port_t self = mach_task_self();
exception_mask_t mask = EXC_MASK_CRASH;
diff --git a/lib/Support/Valgrind.cpp b/lib/Support/Valgrind.cpp
index 2c6d6aaadfff..facf8d927ecd 100644
--- a/lib/Support/Valgrind.cpp
+++ b/lib/Support/Valgrind.cpp
@@ -53,7 +53,6 @@ void llvm::sys::ValgrindDiscardTranslations(const void *Addr, size_t Len) {
#endif // !HAVE_VALGRIND_VALGRIND_H
-#if LLVM_ENABLE_THREADS != 0 && !defined(NDEBUG)
// These functions require no implementation, tsan just looks at the arguments
// they're called with. However, they are required to be weak as some other
// application or library may already be providing these definitions for the
@@ -72,4 +71,4 @@ void AnnotateIgnoreWritesBegin(const char *file, int line) {}
LLVM_ATTRIBUTE_WEAK void AnnotateIgnoreWritesEnd(const char *file, int line);
void AnnotateIgnoreWritesEnd(const char *file, int line) {}
}
-#endif
+
diff --git a/lib/Support/Windows/COM.inc b/lib/Support/Windows/COM.inc
new file mode 100644
index 000000000000..0c50d6f74ea3
--- /dev/null
+++ b/lib/Support/Windows/COM.inc
@@ -0,0 +1,37 @@
+//===- llvm/Support/Windows/COM.inc - Windows COM Implementation *- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Windows portion of COM support.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only Windows code.
+//===----------------------------------------------------------------------===//
+
+#include <objbase.h>
+
+namespace llvm {
+namespace sys {
+
+InitializeCOMRAII::InitializeCOMRAII(COMThreadingMode Threading,
+ bool SpeedOverMemory) {
+ DWORD Coinit = 0;
+ if (Threading == COMThreadingMode::SingleThreaded)
+ Coinit |= COINIT_APARTMENTTHREADED;
+ else
+ Coinit |= COINIT_MULTITHREADED;
+ if (SpeedOverMemory)
+ Coinit |= COINIT_SPEED_OVER_MEMORY;
+ ::CoInitializeEx(nullptr, Coinit);
+}
+
+InitializeCOMRAII::~InitializeCOMRAII() { ::CoUninitialize(); }
+}
+}
diff --git a/lib/Support/Windows/Path.inc b/lib/Support/Windows/Path.inc
index d8b5702bf156..72da7c5fec32 100644
--- a/lib/Support/Windows/Path.inc
+++ b/lib/Support/Windows/Path.inc
@@ -46,10 +46,6 @@ using llvm::sys::windows::UTF8ToUTF16;
using llvm::sys::windows::UTF16ToUTF8;
using llvm::sys::path::widenPath;
-static std::error_code windows_error(DWORD E) {
- return mapWindowsError(E);
-}
-
static bool is_separator(const wchar_t value) {
switch (value) {
case L'\\':
@@ -83,7 +79,7 @@ std::error_code widenPath(const Twine &Path8,
else {
CurPathLen = ::GetCurrentDirectoryW(0, NULL);
if (CurPathLen == 0)
- return windows_error(::GetLastError());
+ return mapWindowsError(::GetLastError());
}
// Would the absolute path be longer than our limit?
@@ -174,7 +170,7 @@ std::error_code current_path(SmallVectorImpl<char> &result) {
// A zero return value indicates a failure other than insufficient space.
if (len == 0)
- return windows_error(::GetLastError());
+ return mapWindowsError(::GetLastError());
// If there's insufficient space, the len returned is larger than the len
// given.
@@ -195,7 +191,7 @@ std::error_code create_directory(const Twine &path, bool IgnoreExisting) {
if (!::CreateDirectoryW(path_utf16.begin(), NULL)) {
DWORD LastError = ::GetLastError();
if (LastError != ERROR_ALREADY_EXISTS || !IgnoreExisting)
- return windows_error(LastError);
+ return mapWindowsError(LastError);
}
return std::error_code();
@@ -212,7 +208,7 @@ std::error_code create_link(const Twine &to, const Twine &from) {
return ec;
if (!::CreateHardLinkW(wide_from.begin(), wide_to.begin(), NULL))
- return windows_error(::GetLastError());
+ return mapWindowsError(::GetLastError());
return std::error_code();
}
@@ -232,14 +228,14 @@ std::error_code remove(const Twine &path, bool IgnoreNonExisting) {
if (ST.type() == file_type::directory_file) {
if (!::RemoveDirectoryW(c_str(path_utf16))) {
- std::error_code EC = windows_error(::GetLastError());
+ std::error_code EC = mapWindowsError(::GetLastError());
if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting)
return EC;
}
return std::error_code();
}
if (!::DeleteFileW(c_str(path_utf16))) {
- std::error_code EC = windows_error(::GetLastError());
+ std::error_code EC = mapWindowsError(::GetLastError());
if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting)
return EC;
}
@@ -261,6 +257,7 @@ std::error_code rename(const Twine &from, const Twine &to) {
MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
return std::error_code();
DWORD LastError = ::GetLastError();
+ ec = mapWindowsError(LastError);
if (LastError != ERROR_ACCESS_DENIED)
break;
// Retry MoveFile() at ACCESS_DENIED.
@@ -294,7 +291,7 @@ std::error_code access(const Twine &Path, AccessMode Mode) {
DWORD LastError = ::GetLastError();
if (LastError != ERROR_FILE_NOT_FOUND &&
LastError != ERROR_PATH_NOT_FOUND)
- return windows_error(LastError);
+ return mapWindowsError(LastError);
return errc::no_such_file_or_directory;
}
@@ -358,7 +355,7 @@ static std::error_code getStatus(HANDLE FileHandle, file_status &Result) {
case FILE_TYPE_UNKNOWN: {
DWORD Err = ::GetLastError();
if (Err != NO_ERROR)
- return windows_error(Err);
+ return mapWindowsError(Err);
Result = file_status(file_type::type_unknown);
return std::error_code();
}
@@ -397,7 +394,7 @@ handle_status_error:
Result = file_status(file_type::type_unknown);
else
Result = file_status(file_type::status_error);
- return windows_error(LastError);
+ return mapWindowsError(LastError);
}
std::error_code status(const Twine &path, file_status &result) {
@@ -454,7 +451,7 @@ std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time) {
FT.dwHighDateTime = UI.HighPart;
HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
if (!SetFileTime(FileHandle, NULL, &FT, &FT))
- return windows_error(::GetLastError());
+ return mapWindowsError(::GetLastError());
return std::error_code();
}
@@ -481,7 +478,7 @@ std::error_code mapped_file_region::init(int FD, uint64_t Offset,
(Offset + Size) & 0xffffffff,
0);
if (FileMappingHandle == NULL) {
- std::error_code ec = windows_error(GetLastError());
+ std::error_code ec = mapWindowsError(GetLastError());
return ec;
}
@@ -497,7 +494,7 @@ std::error_code mapped_file_region::init(int FD, uint64_t Offset,
Offset & 0xffffffff,
Size);
if (Mapping == NULL) {
- std::error_code ec = windows_error(GetLastError());
+ std::error_code ec = mapWindowsError(GetLastError());
::CloseHandle(FileMappingHandle);
return ec;
}
@@ -506,7 +503,7 @@ std::error_code mapped_file_region::init(int FD, uint64_t Offset,
MEMORY_BASIC_INFORMATION mbi;
SIZE_T Result = VirtualQuery(Mapping, &mbi, sizeof(mbi));
if (Result == 0) {
- std::error_code ec = windows_error(GetLastError());
+ std::error_code ec = mapWindowsError(GetLastError());
::UnmapViewOfFile(Mapping);
::CloseHandle(FileMappingHandle);
return ec;
@@ -575,7 +572,7 @@ std::error_code detail::directory_iterator_construct(detail::DirIterState &it,
WIN32_FIND_DATAW FirstFind;
ScopedFindHandle FindHandle(::FindFirstFileW(c_str(path_utf16), &FirstFind));
if (!FindHandle)
- return windows_error(::GetLastError());
+ return mapWindowsError(::GetLastError());
size_t FilenameLen = ::wcslen(FirstFind.cFileName);
while ((FilenameLen == 1 && FirstFind.cFileName[0] == L'.') ||
@@ -586,7 +583,7 @@ std::error_code detail::directory_iterator_construct(detail::DirIterState &it,
// Check for end.
if (LastError == ERROR_NO_MORE_FILES)
return detail::directory_iterator_destruct(it);
- return windows_error(LastError);
+ return mapWindowsError(LastError);
} else
FilenameLen = ::wcslen(FirstFind.cFileName);
@@ -599,8 +596,8 @@ std::error_code detail::directory_iterator_construct(detail::DirIterState &it,
it.IterationHandle = intptr_t(FindHandle.take());
SmallString<128> directory_entry_path(path);
- path::append(directory_entry_path, directory_entry_name_utf8.str());
- it.CurrentEntry = directory_entry(directory_entry_path.str());
+ path::append(directory_entry_path, directory_entry_name_utf8);
+ it.CurrentEntry = directory_entry(directory_entry_path);
return std::error_code();
}
@@ -621,7 +618,7 @@ std::error_code detail::directory_iterator_increment(detail::DirIterState &it) {
// Check for end.
if (LastError == ERROR_NO_MORE_FILES)
return detail::directory_iterator_destruct(it);
- return windows_error(LastError);
+ return mapWindowsError(LastError);
}
size_t FilenameLen = ::wcslen(FindData.cFileName);
@@ -651,7 +648,7 @@ std::error_code openFileForRead(const Twine &Name, int &ResultFD) {
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (H == INVALID_HANDLE_VALUE) {
DWORD LastError = ::GetLastError();
- std::error_code EC = windows_error(LastError);
+ std::error_code EC = mapWindowsError(LastError);
// Provide a better error message when trying to open directories.
// This only runs if we failed to open the file, so there is probably
// no performances issues.
@@ -665,7 +662,7 @@ std::error_code openFileForRead(const Twine &Name, int &ResultFD) {
int FD = ::_open_osfhandle(intptr_t(H), 0);
if (FD == -1) {
::CloseHandle(H);
- return windows_error(ERROR_INVALID_HANDLE);
+ return mapWindowsError(ERROR_INVALID_HANDLE);
}
ResultFD = FD;
@@ -701,7 +698,7 @@ std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
if (H == INVALID_HANDLE_VALUE) {
DWORD LastError = ::GetLastError();
- std::error_code EC = windows_error(LastError);
+ std::error_code EC = mapWindowsError(LastError);
// Provide a better error message when trying to open directories.
// This only runs if we failed to open the file, so there is probably
// no performances issues.
@@ -722,7 +719,7 @@ std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
int FD = ::_open_osfhandle(intptr_t(H), OpenFlags);
if (FD == -1) {
::CloseHandle(H);
- return windows_error(ERROR_INVALID_HANDLE);
+ return mapWindowsError(ERROR_INVALID_HANDLE);
}
ResultFD = FD;
@@ -799,7 +796,7 @@ std::error_code UTF8ToUTF16(llvm::StringRef utf8,
utf8.size(), utf16.begin(), 0);
if (len == 0)
- return windows_error(::GetLastError());
+ return mapWindowsError(::GetLastError());
utf16.reserve(len + 1);
utf16.set_size(len);
@@ -808,7 +805,7 @@ std::error_code UTF8ToUTF16(llvm::StringRef utf8,
utf8.size(), utf16.begin(), utf16.size());
if (len == 0)
- return windows_error(::GetLastError());
+ return mapWindowsError(::GetLastError());
}
// Make utf16 null terminated.
@@ -828,7 +825,7 @@ std::error_code UTF16ToCodePage(unsigned codepage, const wchar_t *utf16,
0, NULL, NULL);
if (len == 0)
- return windows_error(::GetLastError());
+ return mapWindowsError(::GetLastError());
utf8.reserve(len);
utf8.set_size(len);
@@ -838,7 +835,7 @@ std::error_code UTF16ToCodePage(unsigned codepage, const wchar_t *utf16,
utf8.size(), NULL, NULL);
if (len == 0)
- return windows_error(::GetLastError());
+ return mapWindowsError(::GetLastError());
}
// Make utf8 null terminated.
diff --git a/lib/Support/Windows/Process.inc b/lib/Support/Windows/Process.inc
index 854eac73f230..8164956d1511 100644
--- a/lib/Support/Windows/Process.inc
+++ b/lib/Support/Windows/Process.inc
@@ -156,10 +156,6 @@ Optional<std::string> Process::GetEnv(StringRef Name) {
return std::string(Res.data());
}
-static std::error_code windows_error(DWORD E) {
- return mapWindowsError(E);
-}
-
static void AllocateAndPush(const SmallVectorImpl<char> &S,
SmallVectorImpl<const char *> &Vector,
SpecificBumpPtrAllocator<char> &Allocator) {
@@ -235,7 +231,7 @@ Process::GetArgumentVector(SmallVectorImpl<const char *> &Args,
wchar_t **UnicodeCommandLine =
CommandLineToArgvW(GetCommandLineW(), &ArgCount);
if (!UnicodeCommandLine)
- return windows_error(::GetLastError());
+ return mapWindowsError(::GetLastError());
Args.reserve(ArgCount);
std::error_code ec;
@@ -329,6 +325,16 @@ class DefaultColors
};
DefaultColors defaultColors;
+
+WORD fg_color(WORD color) {
+ return color & (FOREGROUND_BLUE | FOREGROUND_GREEN |
+ FOREGROUND_INTENSITY | FOREGROUND_RED);
+}
+
+WORD bg_color(WORD color) {
+ return color & (BACKGROUND_BLUE | BACKGROUND_GREEN |
+ BACKGROUND_INTENSITY | BACKGROUND_RED);
+}
}
bool Process::ColorNeedsFlush() {
@@ -350,6 +356,7 @@ const char *Process::OutputBold(bool bg) {
const char *Process::OutputColor(char code, bool bold, bool bg) {
if (UseANSI) return colorcodes[bg?1:0][bold?1:0][code&7];
+ WORD current = DefaultColors::GetCurrentColor();
WORD colors;
if (bg) {
colors = ((code&1) ? BACKGROUND_RED : 0) |
@@ -357,12 +364,14 @@ const char *Process::OutputColor(char code, bool bold, bool bg) {
((code&4) ? BACKGROUND_BLUE : 0);
if (bold)
colors |= BACKGROUND_INTENSITY;
+ colors |= fg_color(current);
} else {
colors = ((code&1) ? FOREGROUND_RED : 0) |
((code&2) ? FOREGROUND_GREEN : 0 ) |
((code&4) ? FOREGROUND_BLUE : 0);
if (bold)
colors |= FOREGROUND_INTENSITY;
+ colors |= bg_color(current);
}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
return 0;
diff --git a/lib/Support/Windows/Program.inc b/lib/Support/Windows/Program.inc
index c3700774514c..75685de45547 100644
--- a/lib/Support/Windows/Program.inc
+++ b/lib/Support/Windows/Program.inc
@@ -434,7 +434,8 @@ ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
DWORD status;
BOOL rc = GetExitCodeProcess(PI.ProcessHandle, &status);
DWORD err = GetLastError();
- CloseHandle(PI.ProcessHandle);
+ if (err != ERROR_INVALID_HANDLE)
+ CloseHandle(PI.ProcessHandle);
if (!rc) {
SetLastError(err);
diff --git a/lib/Support/Windows/Signals.inc b/lib/Support/Windows/Signals.inc
index 35ba6f8e1bba..6006499f4da2 100644
--- a/lib/Support/Windows/Signals.inc
+++ b/lib/Support/Windows/Signals.inc
@@ -10,12 +10,15 @@
// This file provides the Win32 specific implementation of the Signals class.
//
//===----------------------------------------------------------------------===//
-
#include "llvm/Support/FileSystem.h"
#include <algorithm>
+#include <signal.h>
#include <stdio.h>
#include <vector>
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
// The Windows.h header must be after LLVM and standard headers.
#include "WindowsSupport.h"
@@ -165,13 +168,97 @@ static std::vector<std::string> *FilesToRemove = NULL;
static std::vector<std::pair<void(*)(void*), void*> > *CallBacksToRun = 0;
static bool RegisteredUnhandledExceptionFilter = false;
static bool CleanupExecuted = false;
-static bool ExitOnUnhandledExceptions = false;
static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL;
// Windows creates a new thread to execute the console handler when an event
// (such as CTRL/C) occurs. This causes concurrency issues with the above
// globals which this critical section addresses.
static CRITICAL_SECTION CriticalSection;
+static bool CriticalSectionInitialized = false;
+
+static void PrintStackTraceForThread(llvm::raw_ostream &OS, HANDLE hProcess,
+ HANDLE hThread, STACKFRAME64 &StackFrame,
+ CONTEXT *Context) {
+ DWORD machineType;
+#if defined(_M_X64)
+ machineType = IMAGE_FILE_MACHINE_AMD64;
+#else
+ machineType = IMAGE_FILE_MACHINE_I386;
+#endif
+
+ // Initialize the symbol handler.
+ SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);
+ SymInitialize(hProcess, NULL, TRUE);
+
+ while (true) {
+ if (!StackWalk64(machineType, hProcess, hThread, &StackFrame, Context, NULL,
+ SymFunctionTableAccess64, SymGetModuleBase64, NULL)) {
+ break;
+ }
+
+ if (StackFrame.AddrFrame.Offset == 0)
+ break;
+
+ using namespace llvm;
+ // Print the PC in hexadecimal.
+ DWORD64 PC = StackFrame.AddrPC.Offset;
+#if defined(_M_X64)
+ OS << format("0x%016llX", PC);
+#elif defined(_M_IX86)
+ OS << format("0x%08lX", static_cast<DWORD>(PC));
+#endif
+
+// Print the parameters. Assume there are four.
+#if defined(_M_X64)
+ OS << format(" (0x%016llX 0x%016llX 0x%016llX 0x%016llX)",
+ StackFrame.Params[0], StackFrame.Params[1], StackFrame.Params[2],
+ StackFrame.Params[3]);
+#elif defined(_M_IX86)
+ OS << format(" (0x%08lX 0x%08lX 0x%08lX 0x%08lX)",
+ static_cast<DWORD>(StackFrame.Params[0]),
+ static_cast<DWORD>(StackFrame.Params[1]),
+ static_cast<DWORD>(StackFrame.Params[2]),
+ static_cast<DWORD>(StackFrame.Params[3]));
+#endif
+ // Verify the PC belongs to a module in this process.
+ if (!SymGetModuleBase64(hProcess, PC)) {
+ OS << " <unknown module>\n";
+ continue;
+ }
+
+ // Print the symbol name.
+ char buffer[512];
+ IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer);
+ memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64));
+ symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
+ symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64);
+
+ DWORD64 dwDisp;
+ if (!SymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) {
+ OS << '\n';
+ continue;
+ }
+
+ buffer[511] = 0;
+ if (dwDisp > 0)
+ OS << format(", %s() + 0x%llX bytes(s)", (const char*)symbol->Name,
+ dwDisp);
+ else
+ OS << format(", %s", (const char*)symbol->Name);
+
+ // Print the source file and line number information.
+ IMAGEHLP_LINE64 line = {};
+ DWORD dwLineDisp;
+ line.SizeOfStruct = sizeof(line);
+ if (SymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) {
+ OS << format(", %s, line %lu", line.FileName, line.LineNumber);
+ if (dwLineDisp > 0)
+ OS << format(" + 0x%lX byte(s)", dwLineDisp);
+ }
+
+ OS << '\n';
+ }
+}
namespace llvm {
@@ -184,7 +271,8 @@ namespace llvm {
/// AvoidMessageBoxHook - Emulates hitting "retry" from an "abort, retry,
/// ignore" CRT debug report dialog. "retry" raises an exception which
/// ultimately triggers our stack dumper.
-static int AvoidMessageBoxHook(int ReportType, char *Message, int *Return) {
+static LLVM_ATTRIBUTE_UNUSED int
+AvoidMessageBoxHook(int ReportType, char *Message, int *Return) {
// Set *Return to the retry code for the return value of _CrtDbgReport:
// http://msdn.microsoft.com/en-us/library/8hyw4sy7(v=vs.71).aspx
// This may also trigger just-in-time debugging via DebugBreak().
@@ -196,6 +284,22 @@ static int AvoidMessageBoxHook(int ReportType, char *Message, int *Return) {
#endif
+extern "C" void HandleAbort(int Sig) {
+ if (Sig == SIGABRT) {
+ LLVM_BUILTIN_TRAP;
+ }
+}
+
+static void InitializeThreading() {
+ if (CriticalSectionInitialized)
+ return;
+
+ // Now's the time to create the critical section. This is the first time
+ // through here, and there's only one thread.
+ InitializeCriticalSection(&CriticalSection);
+ CriticalSectionInitialized = true;
+}
+
static void RegisterHandler() {
#if __MINGW32__ && !defined(__MINGW64_VERSION_MAJOR)
// On MinGW.org, we need to load up the symbols explicitly, because the
@@ -214,9 +318,7 @@ static void RegisterHandler() {
return;
}
- // Now's the time to create the critical section. This is the first time
- // through here, and there's only one thread.
- InitializeCriticalSection(&CriticalSection);
+ InitializeThreading();
// Enter it immediately. Now if someone hits CTRL/C, the console handler
// can't proceed until the globals are updated.
@@ -226,17 +328,6 @@ static void RegisterHandler() {
OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter);
SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE);
- // Environment variable to disable any kind of crash dialog.
- if (getenv("LLVM_DISABLE_CRASH_REPORT")) {
-#ifdef _MSC_VER
- _CrtSetReportHook(AvoidMessageBoxHook);
-#endif
- SetErrorMode(SEM_FAILCRITICALERRORS |
- SEM_NOGPFAULTERRORBOX |
- SEM_NOOPENFILEERRORBOX);
- ExitOnUnhandledExceptions = true;
- }
-
// IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or
// else multi-threading problems will ensue.
}
@@ -267,7 +358,6 @@ void sys::DontRemoveFileOnSignal(StringRef Filename) {
RegisterHandler();
- FilesToRemove->push_back(Filename);
std::vector<std::string>::reverse_iterator I =
std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), Filename);
if (I != FilesToRemove->rend())
@@ -276,19 +366,63 @@ void sys::DontRemoveFileOnSignal(StringRef Filename) {
LeaveCriticalSection(&CriticalSection);
}
+void sys::DisableSystemDialogsOnCrash() {
+ // Crash to stack trace handler on abort.
+ signal(SIGABRT, HandleAbort);
+
+ // The following functions are not reliably accessible on MinGW.
+#ifdef _MSC_VER
+ // We're already handling writing a "something went wrong" message.
+ _set_abort_behavior(0, _WRITE_ABORT_MSG);
+ // Disable Dr. Watson.
+ _set_abort_behavior(0, _CALL_REPORTFAULT);
+ _CrtSetReportHook(AvoidMessageBoxHook);
+#endif
+
+ // Disable standard error dialog box.
+ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
+ SEM_NOOPENFILEERRORBOX);
+ _set_error_mode(_OUT_TO_STDERR);
+}
+
/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or
/// SIGSEGV) is delivered to the process, print a stack trace and then exit.
-void sys::PrintStackTraceOnErrorSignal() {
+void sys::PrintStackTraceOnErrorSignal(bool DisableCrashReporting) {
+ DisableSystemDialogsOnCrash();
RegisterHandler();
LeaveCriticalSection(&CriticalSection);
}
+}
+
+#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+// Provide a prototype for RtlCaptureContext, mingw32 from mingw.org is
+// missing it but mingw-w64 has it.
+extern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord);
+#endif
-void llvm::sys::PrintStackTrace(FILE *) {
- // FIXME: Implement.
+void llvm::sys::PrintStackTrace(raw_ostream &OS) {
+
+ STACKFRAME64 StackFrame = {};
+ CONTEXT Context = {};
+ ::RtlCaptureContext(&Context);
+#if defined(_M_X64)
+ StackFrame.AddrPC.Offset = Context.Rip;
+ StackFrame.AddrStack.Offset = Context.Rsp;
+ StackFrame.AddrFrame.Offset = Context.Rbp;
+#else
+ StackFrame.AddrPC.Offset = Context.Eip;
+ StackFrame.AddrStack.Offset = Context.Esp;
+ StackFrame.AddrFrame.Offset = Context.Ebp;
+#endif
+ StackFrame.AddrPC.Mode = AddrModeFlat;
+ StackFrame.AddrStack.Mode = AddrModeFlat;
+ StackFrame.AddrFrame.Mode = AddrModeFlat;
+ PrintStackTraceForThread(OS, GetCurrentProcess(), GetCurrentThread(),
+ StackFrame, &Context);
}
-void sys::SetInterruptFunction(void (*IF)()) {
+void llvm::sys::SetInterruptFunction(void (*IF)()) {
RegisterHandler();
InterruptFunction = IF;
LeaveCriticalSection(&CriticalSection);
@@ -298,16 +432,18 @@ void sys::SetInterruptFunction(void (*IF)()) {
/// AddSignalHandler - Add a function to be called when a signal is delivered
/// to the process. The handler can have a cookie passed to it to identify
/// what instance of the handler it is.
-void sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) {
+void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) {
if (CallBacksToRun == 0)
CallBacksToRun = new std::vector<std::pair<void(*)(void*), void*> >();
CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie));
RegisterHandler();
LeaveCriticalSection(&CriticalSection);
}
-}
static void Cleanup() {
+ if (CleanupExecuted)
+ return;
+
EnterCriticalSection(&CriticalSection);
// Prevent other thread from registering new files and directories for
@@ -323,13 +459,18 @@ static void Cleanup() {
}
if (CallBacksToRun)
- for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i)
- (*CallBacksToRun)[i].first((*CallBacksToRun)[i].second);
+ for (auto &I : *CallBacksToRun)
+ I.first(I.second);
LeaveCriticalSection(&CriticalSection);
}
void llvm::sys::RunInterruptHandlers() {
+ // The interrupt handler may be called from an interrupt, but it may also be
+ // called manually (such as the case of report_fatal_error with no registered
+ // error handler). We must ensure that the critical section is properly
+ // initialized.
+ InitializeThreading();
Cleanup();
}
@@ -337,12 +478,9 @@ static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
Cleanup();
// Initialize the STACKFRAME structure.
- STACKFRAME64 StackFrame;
- memset(&StackFrame, 0, sizeof(StackFrame));
+ STACKFRAME64 StackFrame = {};
- DWORD machineType;
#if defined(_M_X64)
- machineType = IMAGE_FILE_MACHINE_AMD64;
StackFrame.AddrPC.Offset = ep->ContextRecord->Rip;
StackFrame.AddrPC.Mode = AddrModeFlat;
StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp;
@@ -350,7 +488,6 @@ static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp;
StackFrame.AddrFrame.Mode = AddrModeFlat;
#elif defined(_M_IX86)
- machineType = IMAGE_FILE_MACHINE_I386;
StackFrame.AddrPC.Offset = ep->ContextRecord->Eip;
StackFrame.AddrPC.Mode = AddrModeFlat;
StackFrame.AddrStack.Offset = ep->ContextRecord->Esp;
@@ -361,90 +498,10 @@ static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
HANDLE hProcess = GetCurrentProcess();
HANDLE hThread = GetCurrentThread();
+ PrintStackTraceForThread(llvm::errs(), hProcess, hThread, StackFrame,
+ ep->ContextRecord);
- // Initialize the symbol handler.
- SymSetOptions(SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES);
- SymInitialize(hProcess, NULL, TRUE);
-
- while (true) {
- if (!StackWalk64(machineType, hProcess, hThread, &StackFrame,
- ep->ContextRecord, NULL, SymFunctionTableAccess64,
- SymGetModuleBase64, NULL)) {
- break;
- }
-
- if (StackFrame.AddrFrame.Offset == 0)
- break;
-
- // Print the PC in hexadecimal.
- DWORD64 PC = StackFrame.AddrPC.Offset;
-#if defined(_M_X64)
- fprintf(stderr, "0x%016llX", PC);
-#elif defined(_M_IX86)
- fprintf(stderr, "0x%08lX", static_cast<DWORD>(PC));
-#endif
-
- // Print the parameters. Assume there are four.
-#if defined(_M_X64)
- fprintf(stderr, " (0x%016llX 0x%016llX 0x%016llX 0x%016llX)",
- StackFrame.Params[0],
- StackFrame.Params[1],
- StackFrame.Params[2],
- StackFrame.Params[3]);
-#elif defined(_M_IX86)
- fprintf(stderr, " (0x%08lX 0x%08lX 0x%08lX 0x%08lX)",
- static_cast<DWORD>(StackFrame.Params[0]),
- static_cast<DWORD>(StackFrame.Params[1]),
- static_cast<DWORD>(StackFrame.Params[2]),
- static_cast<DWORD>(StackFrame.Params[3]));
-#endif
- // Verify the PC belongs to a module in this process.
- if (!SymGetModuleBase64(hProcess, PC)) {
- fputs(" <unknown module>\n", stderr);
- continue;
- }
-
- // Print the symbol name.
- char buffer[512];
- IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer);
- memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64));
- symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
- symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64);
-
- DWORD64 dwDisp;
- if (!SymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) {
- fputc('\n', stderr);
- continue;
- }
-
- buffer[511] = 0;
- if (dwDisp > 0)
- fprintf(stderr, ", %s() + 0x%llX bytes(s)", symbol->Name, dwDisp);
- else
- fprintf(stderr, ", %s", symbol->Name);
-
- // Print the source file and line number information.
- IMAGEHLP_LINE64 line;
- DWORD dwLineDisp;
- memset(&line, 0, sizeof(line));
- line.SizeOfStruct = sizeof(line);
- if (SymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) {
- fprintf(stderr, ", %s, line %lu", line.FileName, line.LineNumber);
- if (dwLineDisp > 0)
- fprintf(stderr, " + 0x%lX byte(s)", dwLineDisp);
- }
-
- fputc('\n', stderr);
- }
-
- if (ExitOnUnhandledExceptions)
- _exit(ep->ExceptionRecord->ExceptionCode);
-
- // Allow dialog box to pop up allowing choice to start debugger.
- if (OldFilter)
- return (*OldFilter)(ep);
- else
- return EXCEPTION_CONTINUE_SEARCH;
+ _exit(ep->ExceptionRecord->ExceptionCode);
}
static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) {
diff --git a/lib/Support/Windows/TimeValue.inc b/lib/Support/Windows/TimeValue.inc
index 0223ab424488..b90b4f1da008 100644
--- a/lib/Support/Windows/TimeValue.inc
+++ b/lib/Support/Windows/TimeValue.inc
@@ -47,6 +47,7 @@ std::string TimeValue::str() const {
__time64_t OurTime = this->toEpochTime();
int Error = ::_localtime64_s(&Storage, &OurTime);
assert(!Error);
+ (void)Error;
LT = &Storage;
#endif
diff --git a/lib/Support/Windows/WindowsSupport.h b/lib/Support/Windows/WindowsSupport.h
index 1d1cedcce299..5bb0b8d2d788 100644
--- a/lib/Support/Windows/WindowsSupport.h
+++ b/lib/Support/Windows/WindowsSupport.h
@@ -19,6 +19,9 @@
//=== is guaranteed to work on *all* Win32 variants.
//===----------------------------------------------------------------------===//
+#ifndef LLVM_SUPPORT_WINDOWSSUPPORT_H
+#define LLVM_SUPPORT_WINDOWSSUPPORT_H
+
// mingw-w64 tends to define it as 0x0502 in its headers.
#undef _WIN32_WINNT
#undef _WIN32_IE
@@ -89,7 +92,7 @@ public:
}
// True if Handle is valid.
- LLVM_EXPLICIT operator bool() const {
+ explicit operator bool() const {
return HandleTraits::IsValid(Handle) ? true : false;
}
@@ -178,3 +181,5 @@ std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len,
} // end namespace windows
} // end namespace sys
} // end namespace llvm.
+
+#endif
diff --git a/lib/Support/YAMLParser.cpp b/lib/Support/YAMLParser.cpp
index 4688ff173df7..d55da5ef1e4a 100644
--- a/lib/Support/YAMLParser.cpp
+++ b/lib/Support/YAMLParser.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/YAMLParser.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
@@ -100,6 +101,7 @@ namespace yaml {
void Node::anchor() {}
void NullNode::anchor() {}
void ScalarNode::anchor() {}
+void BlockScalarNode::anchor() {}
void KeyValueNode::anchor() {}
void MappingNode::anchor() {}
void SequenceNode::anchor() {}
@@ -127,6 +129,7 @@ struct Token : ilist_node<Token> {
TK_Key,
TK_Value,
TK_Scalar,
+ TK_BlockScalar,
TK_Alias,
TK_Anchor,
TK_Tag
@@ -136,6 +139,9 @@ struct Token : ilist_node<Token> {
/// of the token in the input.
StringRef Range;
+ /// The value of a block scalar node.
+ std::string Value;
+
Token() : Kind(TK_Error) {}
};
}
@@ -162,7 +168,7 @@ struct ilist_node_traits<Token> {
Token *createNode(const Token &V) {
return new (Alloc.Allocate<Token>()) Token(V);
}
- static void deleteNode(Token *V) {}
+ static void deleteNode(Token *V) { V->~Token(); }
void addNodeToList(Token *) {}
void removeNodeFromList(Token *) {}
@@ -259,8 +265,8 @@ namespace yaml {
/// @brief Scans YAML tokens from a MemoryBuffer.
class Scanner {
public:
- Scanner(StringRef Input, SourceMgr &SM);
- Scanner(MemoryBufferRef Buffer, SourceMgr &SM_);
+ Scanner(StringRef Input, SourceMgr &SM, bool ShowColors = true);
+ Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors = true);
/// @brief Parse the next token and return it without popping it.
Token &peekNext();
@@ -270,7 +276,7 @@ public:
void printError(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Message,
ArrayRef<SMRange> Ranges = None) {
- SM.PrintMessage(Loc, Kind, Message, Ranges);
+ SM.PrintMessage(Loc, Kind, Message, Ranges, /* FixIts= */ None, ShowColors);
}
void setError(const Twine &Message, StringRef::iterator Position) {
@@ -347,6 +353,14 @@ private:
/// b-break.
StringRef::iterator skip_b_break(StringRef::iterator Position);
+ /// Skip a single s-space[31] starting at Position.
+ ///
+ /// An s-space is 0x20
+ ///
+ /// @returns The code unit after the s-space, or Position if it's not a
+ /// s-space.
+ StringRef::iterator skip_s_space(StringRef::iterator Position);
+
/// @brief Skip a single s-white[33] starting at Position.
///
/// A s-white is 0x20 | 0x9
@@ -372,6 +386,10 @@ private:
StringRef::iterator skip_while( SkipWhileFunc Func
, StringRef::iterator Position);
+ /// Skip minimal well-formed code unit subsequences until Func returns its
+ /// input.
+ void advanceWhile(SkipWhileFunc Func);
+
/// @brief Scan ns-uri-char[39]s starting at Cur.
///
/// This updates Cur and Column while scanning.
@@ -392,6 +410,11 @@ private:
/// Pos is whitespace or a new line
bool isBlankOrBreak(StringRef::iterator Position);
+ /// Consume a single b-break[28] if it's present at the current position.
+ ///
+ /// Return false if the code unit at the current position isn't a line break.
+ bool consumeLineBreakIfPresent();
+
/// @brief If IsSimpleKeyAllowed, create and push_back a new SimpleKey.
void saveSimpleKeyCandidate( TokenQueueT::iterator Tok
, unsigned AtColumn
@@ -416,6 +439,10 @@ private:
, Token::TokenKind Kind
, TokenQueueT::iterator InsertPoint);
+ /// @brief Skip a single-line comment when the comment starts at the current
+ /// position of the scanner.
+ void skipComment();
+
/// @brief Skip whitespace and comments until the start of the next token.
void scanToNextToken();
@@ -461,6 +488,30 @@ private:
/// @brief Scan a block scalar starting with | or >.
bool scanBlockScalar(bool IsLiteral);
+ /// Scan a chomping indicator in a block scalar header.
+ char scanBlockChompingIndicator();
+
+ /// Scan an indentation indicator in a block scalar header.
+ unsigned scanBlockIndentationIndicator();
+
+ /// Scan a block scalar header.
+ ///
+ /// Return false if an error occurred.
+ bool scanBlockScalarHeader(char &ChompingIndicator, unsigned &IndentIndicator,
+ bool &IsDone);
+
+ /// Look for the indentation level of a block scalar.
+ ///
+ /// Return false if an error occurred.
+ bool findBlockScalarIndent(unsigned &BlockIndent, unsigned BlockExitIndent,
+ unsigned &LineBreaks, bool &IsDone);
+
+ /// Scan the indentation of a text line in a block scalar.
+ ///
+ /// Return false if an error occurred.
+ bool scanBlockScalarIndent(unsigned BlockIndent, unsigned BlockExitIndent,
+ bool &IsDone);
+
/// @brief Scan a tag of the form !stuff.
bool scanTag();
@@ -500,6 +551,9 @@ private:
/// @brief True if an error has occurred.
bool Failed;
+ /// @brief Should colors be used when printing out the diagnostic messages?
+ bool ShowColors;
+
/// @brief Queue of tokens. This is required to queue up tokens while looking
/// for the end of a simple key. And for cases where a single character
/// can produce multiple tokens (e.g. BlockEnd).
@@ -604,6 +658,9 @@ bool yaml::dumpTokens(StringRef Input, raw_ostream &OS) {
case Token::TK_Scalar:
OS << "Scalar: ";
break;
+ case Token::TK_BlockScalar:
+ OS << "Block Scalar: ";
+ break;
case Token::TK_Alias:
OS << "Alias: ";
break;
@@ -701,11 +758,13 @@ std::string yaml::escape(StringRef Input) {
return EscapedInput;
}
-Scanner::Scanner(StringRef Input, SourceMgr &sm) : SM(sm) {
+Scanner::Scanner(StringRef Input, SourceMgr &sm, bool ShowColors)
+ : SM(sm), ShowColors(ShowColors) {
init(MemoryBufferRef(Input, "YAML"));
}
-Scanner::Scanner(MemoryBufferRef Buffer, SourceMgr &SM_) : SM(SM_) {
+Scanner::Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors)
+ : SM(SM_), ShowColors(ShowColors) {
init(Buffer);
}
@@ -806,6 +865,13 @@ StringRef::iterator Scanner::skip_b_break(StringRef::iterator Position) {
return Position;
}
+StringRef::iterator Scanner::skip_s_space(StringRef::iterator Position) {
+ if (Position == End)
+ return Position;
+ if (*Position == ' ')
+ return Position + 1;
+ return Position;
+}
StringRef::iterator Scanner::skip_s_white(StringRef::iterator Position) {
if (Position == End)
@@ -834,6 +900,12 @@ StringRef::iterator Scanner::skip_while( SkipWhileFunc Func
return Position;
}
+void Scanner::advanceWhile(SkipWhileFunc Func) {
+ auto Final = skip_while(Func, Current);
+ Column += Final - Current;
+ Current = Final;
+}
+
static bool is_ns_hex_digit(const char C) {
return (C >= '0' && C <= '9')
|| (C >= 'a' && C <= 'z')
@@ -896,6 +968,16 @@ bool Scanner::isBlankOrBreak(StringRef::iterator Position) {
return false;
}
+bool Scanner::consumeLineBreakIfPresent() {
+ auto Next = skip_b_break(Current);
+ if (Next == Current)
+ return false;
+ Column = 0;
+ ++Line;
+ Current = Next;
+ return true;
+}
+
void Scanner::saveSimpleKeyCandidate( TokenQueueT::iterator Tok
, unsigned AtColumn
, bool IsRequired) {
@@ -961,24 +1043,27 @@ bool Scanner::rollIndent( int ToColumn
return true;
}
+void Scanner::skipComment() {
+ if (*Current != '#')
+ return;
+ while (true) {
+ // This may skip more than one byte, thus Column is only incremented
+ // for code points.
+ StringRef::iterator I = skip_nb_char(Current);
+ if (I == Current)
+ break;
+ Current = I;
+ ++Column;
+ }
+}
+
void Scanner::scanToNextToken() {
while (true) {
while (*Current == ' ' || *Current == '\t') {
skip(1);
}
- // Skip comment.
- if (*Current == '#') {
- while (true) {
- // This may skip more than one byte, thus Column is only incremented
- // for code points.
- StringRef::iterator i = skip_nb_char(Current);
- if (i == Current)
- break;
- Current = i;
- ++Column;
- }
- }
+ skipComment();
// Skip EOL.
StringRef::iterator i = skip_b_break(Current);
@@ -1361,38 +1446,204 @@ bool Scanner::scanAliasOrAnchor(bool IsAlias) {
return true;
}
-bool Scanner::scanBlockScalar(bool IsLiteral) {
- StringRef::iterator Start = Current;
- skip(1); // Eat | or >
- while(true) {
- StringRef::iterator i = skip_nb_char(Current);
- if (i == Current) {
- if (Column == 0)
- break;
- i = skip_b_break(Current);
- if (i != Current) {
- // We got a line break.
- Column = 0;
- ++Line;
- Current = i;
- continue;
- } else {
- // There was an error, which should already have been printed out.
+char Scanner::scanBlockChompingIndicator() {
+ char Indicator = ' ';
+ if (Current != End && (*Current == '+' || *Current == '-')) {
+ Indicator = *Current;
+ skip(1);
+ }
+ return Indicator;
+}
+
+/// Get the number of line breaks after chomping.
+///
+/// Return the number of trailing line breaks to emit, depending on
+/// \p ChompingIndicator.
+static unsigned getChompedLineBreaks(char ChompingIndicator,
+ unsigned LineBreaks, StringRef Str) {
+ if (ChompingIndicator == '-') // Strip all line breaks.
+ return 0;
+ if (ChompingIndicator == '+') // Keep all line breaks.
+ return LineBreaks;
+ // Clip trailing lines.
+ return Str.empty() ? 0 : 1;
+}
+
+unsigned Scanner::scanBlockIndentationIndicator() {
+ unsigned Indent = 0;
+ if (Current != End && (*Current >= '1' && *Current <= '9')) {
+ Indent = unsigned(*Current - '0');
+ skip(1);
+ }
+ return Indent;
+}
+
+bool Scanner::scanBlockScalarHeader(char &ChompingIndicator,
+ unsigned &IndentIndicator, bool &IsDone) {
+ auto Start = Current;
+
+ ChompingIndicator = scanBlockChompingIndicator();
+ IndentIndicator = scanBlockIndentationIndicator();
+ // Check for the chomping indicator once again.
+ if (ChompingIndicator == ' ')
+ ChompingIndicator = scanBlockChompingIndicator();
+ Current = skip_while(&Scanner::skip_s_white, Current);
+ skipComment();
+
+ if (Current == End) { // EOF, we have an empty scalar.
+ Token T;
+ T.Kind = Token::TK_BlockScalar;
+ T.Range = StringRef(Start, Current - Start);
+ TokenQueue.push_back(T);
+ IsDone = true;
+ return true;
+ }
+
+ if (!consumeLineBreakIfPresent()) {
+ setError("Expected a line break after block scalar header", Current);
+ return false;
+ }
+ return true;
+}
+
+bool Scanner::findBlockScalarIndent(unsigned &BlockIndent,
+ unsigned BlockExitIndent,
+ unsigned &LineBreaks, bool &IsDone) {
+ unsigned MaxAllSpaceLineCharacters = 0;
+ StringRef::iterator LongestAllSpaceLine;
+
+ while (true) {
+ advanceWhile(&Scanner::skip_s_space);
+ if (skip_nb_char(Current) != Current) {
+ // This line isn't empty, so try and find the indentation.
+ if (Column <= BlockExitIndent) { // End of the block literal.
+ IsDone = true;
+ return true;
+ }
+ // We found the block's indentation.
+ BlockIndent = Column;
+ if (MaxAllSpaceLineCharacters > BlockIndent) {
+ setError(
+ "Leading all-spaces line must be smaller than the block indent",
+ LongestAllSpaceLine);
return false;
}
+ return true;
}
- Current = i;
+ if (skip_b_break(Current) != Current &&
+ Column > MaxAllSpaceLineCharacters) {
+ // Record the longest all-space line in case it's longer than the
+ // discovered block indent.
+ MaxAllSpaceLineCharacters = Column;
+ LongestAllSpaceLine = Current;
+ }
+
+ // Check for EOF.
+ if (Current == End) {
+ IsDone = true;
+ return true;
+ }
+
+ if (!consumeLineBreakIfPresent()) {
+ IsDone = true;
+ return true;
+ }
+ ++LineBreaks;
+ }
+ return true;
+}
+
+bool Scanner::scanBlockScalarIndent(unsigned BlockIndent,
+ unsigned BlockExitIndent, bool &IsDone) {
+ // Skip the indentation.
+ while (Column < BlockIndent) {
+ auto I = skip_s_space(Current);
+ if (I == Current)
+ break;
+ Current = I;
++Column;
}
- if (Start == Current) {
- setError("Got empty block scalar", Start);
+ if (skip_nb_char(Current) == Current)
+ return true;
+
+ if (Column <= BlockExitIndent) { // End of the block literal.
+ IsDone = true;
+ return true;
+ }
+
+ if (Column < BlockIndent) {
+ if (Current != End && *Current == '#') { // Trailing comment.
+ IsDone = true;
+ return true;
+ }
+ setError("A text line is less indented than the block scalar", Current);
+ return false;
+ }
+ return true; // A normal text line.
+}
+
+bool Scanner::scanBlockScalar(bool IsLiteral) {
+ // Eat '|' or '>'
+ assert(*Current == '|' || *Current == '>');
+ skip(1);
+
+ char ChompingIndicator;
+ unsigned BlockIndent;
+ bool IsDone = false;
+ if (!scanBlockScalarHeader(ChompingIndicator, BlockIndent, IsDone))
return false;
+ if (IsDone)
+ return true;
+
+ auto Start = Current;
+ unsigned BlockExitIndent = Indent < 0 ? 0 : (unsigned)Indent;
+ unsigned LineBreaks = 0;
+ if (BlockIndent == 0) {
+ if (!findBlockScalarIndent(BlockIndent, BlockExitIndent, LineBreaks,
+ IsDone))
+ return false;
}
+ // Scan the block's scalars body.
+ SmallString<256> Str;
+ while (!IsDone) {
+ if (!scanBlockScalarIndent(BlockIndent, BlockExitIndent, IsDone))
+ return false;
+ if (IsDone)
+ break;
+
+ // Parse the current line.
+ auto LineStart = Current;
+ advanceWhile(&Scanner::skip_nb_char);
+ if (LineStart != Current) {
+ Str.append(LineBreaks, '\n');
+ Str.append(StringRef(LineStart, Current - LineStart));
+ LineBreaks = 0;
+ }
+
+ // Check for EOF.
+ if (Current == End)
+ break;
+
+ if (!consumeLineBreakIfPresent())
+ break;
+ ++LineBreaks;
+ }
+
+ if (Current == End && !LineBreaks)
+ // Ensure that there is at least one line break before the end of file.
+ LineBreaks = 1;
+ Str.append(getChompedLineBreaks(ChompingIndicator, LineBreaks, Str), '\n');
+
+ // New lines may start a simple key.
+ if (!FlowLevel)
+ IsSimpleKeyAllowed = true;
+
Token T;
- T.Kind = Token::TK_Scalar;
+ T.Kind = Token::TK_BlockScalar;
T.Range = StringRef(Start, Current - Start);
+ T.Value = Str.str().str();
TokenQueue.push_back(T);
return true;
}
@@ -1517,23 +1768,21 @@ bool Scanner::fetchMoreTokens() {
return false;
}
-Stream::Stream(StringRef Input, SourceMgr &SM)
- : scanner(new Scanner(Input, SM)), CurrentDoc() {}
+Stream::Stream(StringRef Input, SourceMgr &SM, bool ShowColors)
+ : scanner(new Scanner(Input, SM, ShowColors)), CurrentDoc() {}
-Stream::Stream(MemoryBufferRef InputBuffer, SourceMgr &SM)
- : scanner(new Scanner(InputBuffer, SM)), CurrentDoc() {}
+Stream::Stream(MemoryBufferRef InputBuffer, SourceMgr &SM, bool ShowColors)
+ : scanner(new Scanner(InputBuffer, SM, ShowColors)), CurrentDoc() {}
Stream::~Stream() {}
bool Stream::failed() { return scanner->failed(); }
void Stream::printError(Node *N, const Twine &Msg) {
- SmallVector<SMRange, 1> Ranges;
- Ranges.push_back(N->getSourceRange());
scanner->printError( N->getSourceRange().Start
, SourceMgr::DK_Error
, Msg
- , Ranges);
+ , N->getSourceRange());
}
document_iterator Stream::begin() {
@@ -1570,11 +1819,11 @@ std::string Node::getVerbatimTag() const {
if (Raw.find_last_of('!') == 0) {
Ret = Doc->getTagMap().find("!")->second;
Ret += Raw.substr(1);
- return std::move(Ret);
+ return Ret;
} else if (Raw.startswith("!!")) {
Ret = Doc->getTagMap().find("!!")->second;
Ret += Raw.substr(2);
- return std::move(Ret);
+ return Ret;
} else {
StringRef TagHandle = Raw.substr(0, Raw.find_last_of('!') + 1);
std::map<StringRef, StringRef>::const_iterator It =
@@ -1588,7 +1837,7 @@ std::string Node::getVerbatimTag() const {
setError(Twine("Unknown tag handle ") + TagHandle, T);
}
Ret += Raw.substr(Raw.find_last_of('!') + 1);
- return std::move(Ret);
+ return Ret;
}
}
@@ -1596,6 +1845,7 @@ std::string Node::getVerbatimTag() const {
case NK_Null:
return "tag:yaml.org,2002:null";
case NK_Scalar:
+ case NK_BlockScalar:
// TODO: Tag resolution.
return "tag:yaml.org,2002:str";
case NK_Mapping:
@@ -2127,6 +2377,14 @@ parse_property:
, AnchorInfo.Range.substr(1)
, TagInfo.Range
, T.Range);
+ case Token::TK_BlockScalar: {
+ getNext();
+ StringRef NullTerminatedStr(T.Value.c_str(), T.Value.length() + 1);
+ StringRef StrCopy = NullTerminatedStr.copy(NodeAllocator).drop_back();
+ return new (NodeAllocator)
+ BlockScalarNode(stream.CurrentDoc, AnchorInfo.Range.substr(1),
+ TagInfo.Range, StrCopy, T.Range);
+ }
case Token::TK_Key:
// Don't eat the TK_Key, KeyValueNode expects it.
return new (NodeAllocator)
diff --git a/lib/Support/YAMLTraits.cpp b/lib/Support/YAMLTraits.cpp
index c87790efb8c8..90f34f6e232d 100644
--- a/lib/Support/YAMLTraits.cpp
+++ b/lib/Support/YAMLTraits.cpp
@@ -7,13 +7,15 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Support/Errc.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/LineIterator.h"
#include "llvm/Support/YAMLParser.h"
-#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include <cctype>
#include <cstring>
@@ -167,10 +169,22 @@ void Input::endMapping() {
}
}
+void Input::beginFlowMapping() { beginMapping(); }
+
+void Input::endFlowMapping() { endMapping(); }
+
unsigned Input::beginSequence() {
- if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
+ if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode))
return SQ->Entries.size();
+ if (isa<EmptyHNode>(CurrentNode))
+ return 0;
+ // Treat case where there's a scalar "null" value as an empty sequence.
+ if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
+ if (isNull(SN->value()))
+ return 0;
}
+ // Any other type of HNode is an error.
+ setError(CurrentNode, "not a sequence");
return 0;
}
@@ -192,12 +206,7 @@ void Input::postflightElement(void *SaveInfo) {
CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
}
-unsigned Input::beginFlowSequence() {
- if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
- return SQ->Entries.size();
- }
- return 0;
-}
+unsigned Input::beginFlowSequence() { return beginSequence(); }
bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) {
if (EC)
@@ -233,6 +242,13 @@ bool Input::matchEnumScalar(const char *Str, bool) {
return false;
}
+bool Input::matchEnumFallback() {
+ if (ScalarMatchFound)
+ return false;
+ ScalarMatchFound = true;
+ return true;
+}
+
void Input::endEnumScalar() {
if (!ScalarMatchFound) {
setError(CurrentNode, "unknown enumerated scalar");
@@ -294,6 +310,8 @@ void Input::scalarString(StringRef &S, bool) {
}
}
+void Input::blockScalarString(StringRef &S) { scalarString(S, false); }
+
void Input::setError(HNode *hnode, const Twine &message) {
assert(hnode && "HNode must not be NULL");
this->setError(hnode->_node, message);
@@ -316,6 +334,11 @@ std::unique_ptr<Input::HNode> Input::createHNodes(Node *N) {
KeyStr = StringRef(Buf, Len);
}
return llvm::make_unique<ScalarHNode>(N, KeyStr);
+ } else if (BlockScalarNode *BSN = dyn_cast<BlockScalarNode>(N)) {
+ StringRef Value = BSN->getValue();
+ char *Buf = StringAllocator.Allocate<char>(Value.size());
+ memcpy(Buf, Value.data(), Value.size());
+ return llvm::make_unique<ScalarHNode>(N, StringRef(Buf, Value.size()));
} else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) {
auto SQHNode = llvm::make_unique<SequenceHNode>(N);
for (Node &SN : *SQ) {
@@ -382,6 +405,7 @@ Output::Output(raw_ostream &yout, void *context)
Out(yout),
Column(0),
ColumnAtFlowStart(0),
+ ColumnAtMapFlowStart(0),
NeedBitValueComma(false),
NeedFlowSequenceComma(false),
EnumerationMatchFound(false),
@@ -416,8 +440,13 @@ bool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault,
bool &UseDefault, void *&) {
UseDefault = false;
if (Required || !SameAsDefault) {
- this->newLineCheck();
- this->paddedKey(Key);
+ auto State = StateStack.back();
+ if (State == inFlowMapFirstKey || State == inFlowMapOtherKey) {
+ flowKey(Key);
+ } else {
+ this->newLineCheck();
+ this->paddedKey(Key);
+ }
return true;
}
return false;
@@ -427,9 +456,24 @@ void Output::postflightKey(void *) {
if (StateStack.back() == inMapFirstKey) {
StateStack.pop_back();
StateStack.push_back(inMapOtherKey);
+ } else if (StateStack.back() == inFlowMapFirstKey) {
+ StateStack.pop_back();
+ StateStack.push_back(inFlowMapOtherKey);
}
}
+void Output::beginFlowMapping() {
+ StateStack.push_back(inFlowMapFirstKey);
+ this->newLineCheck();
+ ColumnAtMapFlowStart = Column;
+ output("{ ");
+}
+
+void Output::endFlowMapping() {
+ StateStack.pop_back();
+ this->outputUpToEndOfLine(" }");
+}
+
void Output::beginDocuments() {
this->outputUpToEndOfLine("---");
}
@@ -508,6 +552,13 @@ bool Output::matchEnumScalar(const char *Str, bool Match) {
return false;
}
+bool Output::matchEnumFallback() {
+ if (EnumerationMatchFound)
+ return false;
+ EnumerationMatchFound = true;
+ return true;
+}
+
void Output::endEnumScalar() {
if (!EnumerationMatchFound)
llvm_unreachable("bad runtime enum value");
@@ -566,6 +617,24 @@ void Output::scalarString(StringRef &S, bool MustQuote) {
this->outputUpToEndOfLine("'"); // Ending single quote.
}
+void Output::blockScalarString(StringRef &S) {
+ if (!StateStack.empty())
+ newLineCheck();
+ output(" |");
+ outputNewLine();
+
+ unsigned Indent = StateStack.empty() ? 1 : StateStack.size();
+
+ auto Buffer = MemoryBuffer::getMemBuffer(S, "", false);
+ for (line_iterator Lines(*Buffer, false); !Lines.is_at_end(); ++Lines) {
+ for (unsigned I = 0; I < Indent; ++I) {
+ output(" ");
+ }
+ output(*Lines);
+ outputNewLine();
+ }
+}
+
void Output::setError(const Twine &message) {
}
@@ -589,7 +658,9 @@ void Output::output(StringRef s) {
void Output::outputUpToEndOfLine(StringRef s) {
this->output(s);
- if (StateStack.empty() || StateStack.back() != inFlowSeq)
+ if (StateStack.empty() || (StateStack.back() != inFlowSeq &&
+ StateStack.back() != inFlowMapFirstKey &&
+ StateStack.back() != inFlowMapOtherKey))
NeedsNewLine = true;
}
@@ -615,7 +686,9 @@ void Output::newLineCheck() {
if (StateStack.back() == inSeq) {
OutputDash = true;
- } else if ((StateStack.size() > 1) && (StateStack.back() == inMapFirstKey) &&
+ } else if ((StateStack.size() > 1) && ((StateStack.back() == inMapFirstKey) ||
+ (StateStack.back() == inFlowSeq) ||
+ (StateStack.back() == inFlowMapFirstKey)) &&
(StateStack[StateStack.size() - 2] == inSeq)) {
--Indent;
OutputDash = true;
@@ -640,6 +713,20 @@ void Output::paddedKey(StringRef key) {
output(" ");
}
+void Output::flowKey(StringRef Key) {
+ if (StateStack.back() == inFlowMapOtherKey)
+ output(", ");
+ if (Column > 70) {
+ output("\n");
+ for (int I = 0; I < ColumnAtMapFlowStart; ++I)
+ output(" ");
+ Column = ColumnAtMapFlowStart;
+ output(" ");
+ }
+ output(Key);
+ output(": ");
+}
+
//===----------------------------------------------------------------------===//
// traits for built-in types
//===----------------------------------------------------------------------===//
@@ -669,7 +756,7 @@ StringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *,
Val = Scalar;
return StringRef();
}
-
+
void ScalarTraits<std::string>::output(const std::string &Val, void *,
raw_ostream &Out) {
Out << Val;
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
index 1bcc31b40a4f..4c0b6c7b5634 100644
--- a/lib/Support/raw_ostream.cpp
+++ b/lib/Support/raw_ostream.cpp
@@ -242,7 +242,7 @@ raw_ostream &raw_ostream::operator<<(double N) {
char buf[16];
unsigned len;
- len = snprintf(buf, sizeof(buf), "%e", N);
+ len = format("%e", N).snprint(buf, sizeof(buf));
if (len <= sizeof(buf) - 2) {
if (len >= 5 && buf[len - 5] == 'e' && buf[len - 3] == '0') {
int cs = buf[len - 4];
@@ -410,9 +410,12 @@ raw_ostream &raw_ostream::operator<<(const FormattedString &FS) {
raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) {
if (FN.Hex) {
unsigned Nibbles = (64 - countLeadingZeros(FN.HexValue)+3)/4;
- unsigned Width = (FN.Width > Nibbles+2) ? FN.Width : Nibbles+2;
-
+ unsigned PrefixChars = FN.HexPrefix ? 2 : 0;
+ unsigned Width = std::max(FN.Width, Nibbles + PrefixChars);
+
char NumberBuffer[20] = "0x0000000000000000";
+ if (!FN.HexPrefix)
+ NumberBuffer[1] = '0';
char *EndPtr = NumberBuffer+Width;
char *CurPtr = EndPtr;
const char A = FN.Upper ? 'A' : 'a';
@@ -484,51 +487,53 @@ void format_object_base::home() {
// raw_fd_ostream
//===----------------------------------------------------------------------===//
-raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
- sys::fs::OpenFlags Flags)
- : Error(false), UseAtomicWrites(false), pos(0) {
- EC = std::error_code();
+static int getFD(StringRef Filename, std::error_code &EC,
+ sys::fs::OpenFlags Flags) {
// Handle "-" as stdout. Note that when we do this, we consider ourself
// the owner of stdout. This means that we can do things like close the
// file descriptor when we're done and set the "binary" flag globally.
if (Filename == "-") {
- FD = STDOUT_FILENO;
+ EC = std::error_code();
// If user requested binary then put stdout into binary mode if
// possible.
if (!(Flags & sys::fs::F_Text))
sys::ChangeStdoutToBinary();
- // Close stdout when we're done, to detect any output errors.
- ShouldClose = true;
- return;
+ return STDOUT_FILENO;
}
+ int FD;
EC = sys::fs::openFileForWrite(Filename, FD, Flags);
+ if (EC)
+ return -1;
- if (EC) {
- ShouldClose = false;
- return;
- }
-
- // Ok, we successfully opened the file, so it'll need to be closed.
- ShouldClose = true;
+ return FD;
}
-/// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If
-/// ShouldClose is true, this closes the file when the stream is destroyed.
+raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
+ sys::fs::OpenFlags Flags)
+ : raw_fd_ostream(getFD(Filename, EC, Flags), true) {}
+
+/// FD is the file descriptor that this writes to. If ShouldClose is true, this
+/// closes the file when the stream is destroyed.
raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered)
- : raw_ostream(unbuffered), FD(fd),
- ShouldClose(shouldClose), Error(false), UseAtomicWrites(false) {
-#ifdef O_BINARY
- // Setting STDOUT to binary mode is necessary in Win32
- // to avoid undesirable linefeed conversion.
- // Don't touch STDERR, or w*printf() (in assert()) would barf wide chars.
- if (fd == STDOUT_FILENO)
- setmode(fd, O_BINARY);
-#endif
+ : raw_pwrite_stream(unbuffered), FD(fd), ShouldClose(shouldClose),
+ Error(false), UseAtomicWrites(false) {
+ if (FD < 0 ) {
+ ShouldClose = false;
+ return;
+ }
// Get the starting position.
off_t loc = ::lseek(FD, 0, SEEK_CUR);
- if (loc == (off_t)-1)
+#ifdef LLVM_ON_WIN32
+ // MSVCRT's _lseek(SEEK_CUR) doesn't return -1 for pipes.
+ sys::fs::file_status Status;
+ std::error_code EC = status(FD, Status);
+ SupportsSeeking = !EC && Status.type() == sys::fs::file_type::regular_file;
+#else
+ SupportsSeeking = loc != (off_t)-1;
+#endif
+ if (!SupportsSeeking)
pos = 0;
else
pos = static_cast<uint64_t>(loc);
@@ -620,11 +625,19 @@ void raw_fd_ostream::close() {
uint64_t raw_fd_ostream::seek(uint64_t off) {
flush();
pos = ::lseek(FD, off, SEEK_SET);
- if (pos != off)
+ if (pos == (uint64_t)-1)
error_detected();
return pos;
}
+void raw_fd_ostream::pwrite_impl(const char *Ptr, size_t Size,
+ uint64_t Offset) {
+ uint64_t Pos = tell();
+ seek(Offset);
+ write(Ptr, Size);
+ seek(Pos);
+}
+
size_t raw_fd_ostream::preferred_buffer_size() const {
#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__minix)
// Windows and Minix have no st_blksize.
@@ -705,7 +718,9 @@ raw_ostream &llvm::outs() {
// Set buffer settings to model stdout behavior.
// Delete the file descriptor when the program exits, forcing error
// detection. If you don't want this behavior, don't use outs().
- static raw_fd_ostream S(STDOUT_FILENO, true);
+ std::error_code EC;
+ static raw_fd_ostream S("-", EC, sys::fs::F_None);
+ assert(!EC);
return S;
}
@@ -746,7 +761,14 @@ void raw_string_ostream::write_impl(const char *Ptr, size_t Size) {
// capacity. This allows raw_ostream to write directly into the correct place,
// and we only need to set the vector size when the data is flushed.
+raw_svector_ostream::raw_svector_ostream(SmallVectorImpl<char> &O, unsigned)
+ : OS(O) {}
+
raw_svector_ostream::raw_svector_ostream(SmallVectorImpl<char> &O) : OS(O) {
+ init();
+}
+
+void raw_svector_ostream::init() {
// Set up the initial external buffer. We make sure that the buffer has at
// least 128 bytes free; raw_ostream itself only requires 64, but we want to
// make sure that we don't grow the buffer unnecessarily on destruction (when
@@ -760,6 +782,12 @@ raw_svector_ostream::~raw_svector_ostream() {
flush();
}
+void raw_svector_ostream::pwrite_impl(const char *Ptr, size_t Size,
+ uint64_t Offset) {
+ flush();
+ memcpy(OS.begin() + Offset, Ptr, Size);
+}
+
/// resync - This is called when the SmallVector we're appending to is changed
/// outside of the raw_svector_ostream's control. It is only safe to do this
/// if the raw_svector_ostream has previously been flushed.
@@ -814,3 +842,6 @@ void raw_null_ostream::write_impl(const char *Ptr, size_t Size) {
uint64_t raw_null_ostream::current_pos() const {
return 0;
}
+
+void raw_null_ostream::pwrite_impl(const char *Ptr, size_t Size,
+ uint64_t Offset) {}
diff --git a/lib/Support/regcomp.c b/lib/Support/regcomp.c
index b79692966473..ebde64f9cf75 100644
--- a/lib/Support/regcomp.c
+++ b/lib/Support/regcomp.c
@@ -1422,7 +1422,7 @@ enlarge(struct parse *p, sopno size)
if (p->ssize >= size)
return;
- if ((unsigned long)size > SIZE_MAX / sizeof(sop)) {
+ if ((uintptr_t)size > SIZE_MAX / sizeof(sop)) {
SETERROR(REG_ESPACE);
return;
}
@@ -1443,7 +1443,7 @@ static void
stripsnug(struct parse *p, struct re_guts *g)
{
g->nstates = p->slen;
- if ((unsigned long)p->slen > SIZE_MAX / sizeof(sop)) {
+ if ((uintptr_t)p->slen > SIZE_MAX / sizeof(sop)) {
g->strip = p->strip;
SETERROR(REG_ESPACE);
return;