diff options
author | dim <dim@FreeBSD.org> | 2015-12-30 13:13:10 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2015-12-30 13:13:10 +0000 |
commit | 9b5bf5c4f53d65d6a48722d7410ed7cb15f5ba3a (patch) | |
tree | b466a4817f79516eb1df8eae92bccf62ecc84003 /contrib/llvm/lib/Support | |
parent | f09a28d1de99fda4f5517fb12670fc36552f4927 (diff) | |
parent | e194cd6d03d91631334d9d5e55b506036f423cc8 (diff) | |
download | FreeBSD-src-9b5bf5c4f53d65d6a48722d7410ed7cb15f5ba3a.zip FreeBSD-src-9b5bf5c4f53d65d6a48722d7410ed7cb15f5ba3a.tar.gz |
Update llvm to trunk r256633.
Diffstat (limited to 'contrib/llvm/lib/Support')
44 files changed, 1671 insertions, 937 deletions
diff --git a/contrib/llvm/lib/Support/APFloat.cpp b/contrib/llvm/lib/Support/APFloat.cpp index 5d31225..19b8221 100644 --- a/contrib/llvm/lib/Support/APFloat.cpp +++ b/contrib/llvm/lib/Support/APFloat.cpp @@ -768,6 +768,15 @@ APFloat::isLargest() const { } bool +APFloat::isInteger() const { + // This could be made more efficient; I'm going for obviously correct. + if (!isFinite()) return false; + APFloat truncated = *this; + truncated.roundToIntegral(rmTowardZero); + return compare(truncated) == cmpEqual; +} + +bool APFloat::bitwiseIsEqual(const APFloat &rhs) const { if (this == &rhs) return true; @@ -777,18 +786,12 @@ APFloat::bitwiseIsEqual(const APFloat &rhs) const { return false; if (category==fcZero || category==fcInfinity) return true; - else if (isFiniteNonZero() && exponent!=rhs.exponent) + + if (isFiniteNonZero() && exponent != rhs.exponent) return false; - else { - int i= partCount(); - const integerPart* p=significandParts(); - const integerPart* q=rhs.significandParts(); - for (; i>0; i--, p++, q++) { - if (*p != *q) - return false; - } - return true; - } + + return std::equal(significandParts(), significandParts() + partCount(), + rhs.significandParts()); } APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value) { @@ -847,6 +850,21 @@ APFloat::semanticsPrecision(const fltSemantics &semantics) { return semantics.precision; } +APFloat::ExponentType +APFloat::semanticsMaxExponent(const fltSemantics &semantics) +{ + return semantics.maxExponent; +} +APFloat::ExponentType +APFloat::semanticsMinExponent(const fltSemantics &semantics) +{ + return semantics.minExponent; +} +unsigned int +APFloat::semanticsSizeInBits(const fltSemantics &semantics) +{ + return semantics.sizeInBits; +} const integerPart * APFloat::significandParts() const @@ -1762,7 +1780,7 @@ APFloat::remainder(const APFloat &rhs) /* Normalized llvm frem (C fmod). This is not currently correct in all cases. */ APFloat::opStatus -APFloat::mod(const APFloat &rhs, roundingMode rounding_mode) +APFloat::mod(const APFloat &rhs) { opStatus fs; fs = modSpecials(rhs); @@ -1787,10 +1805,10 @@ APFloat::mod(const APFloat &rhs, roundingMode rounding_mode) rmNearestTiesToEven); assert(fs==opOK); // should always work - fs = V.multiply(rhs, rounding_mode); + fs = V.multiply(rhs, rmNearestTiesToEven); assert(fs==opOK || fs==opInexact); // should not overflow or underflow - fs = subtract(V, rounding_mode); + fs = subtract(V, rmNearestTiesToEven); assert(fs==opOK || fs==opInexact); // likewise if (isZero()) diff --git a/contrib/llvm/lib/Support/BlockFrequency.cpp b/contrib/llvm/lib/Support/BlockFrequency.cpp index 6f7e341..e7f3e17 100644 --- a/contrib/llvm/lib/Support/BlockFrequency.cpp +++ b/contrib/llvm/lib/Support/BlockFrequency.cpp @@ -11,37 +11,35 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/BranchProbability.h" #include "llvm/Support/BlockFrequency.h" #include "llvm/Support/raw_ostream.h" #include <cassert> using namespace llvm; -BlockFrequency &BlockFrequency::operator*=(const BranchProbability &Prob) { +BlockFrequency &BlockFrequency::operator*=(BranchProbability Prob) { Frequency = Prob.scale(Frequency); return *this; } -const BlockFrequency -BlockFrequency::operator*(const BranchProbability &Prob) const { +BlockFrequency BlockFrequency::operator*(BranchProbability Prob) const { BlockFrequency Freq(Frequency); Freq *= Prob; return Freq; } -BlockFrequency &BlockFrequency::operator/=(const BranchProbability &Prob) { +BlockFrequency &BlockFrequency::operator/=(BranchProbability Prob) { Frequency = Prob.scaleByInverse(Frequency); return *this; } -BlockFrequency BlockFrequency::operator/(const BranchProbability &Prob) const { +BlockFrequency BlockFrequency::operator/(BranchProbability Prob) const { BlockFrequency Freq(Frequency); Freq /= Prob; return Freq; } -BlockFrequency &BlockFrequency::operator+=(const BlockFrequency &Freq) { +BlockFrequency &BlockFrequency::operator+=(BlockFrequency Freq) { uint64_t Before = Freq.Frequency; Frequency += Freq.Frequency; @@ -52,11 +50,25 @@ BlockFrequency &BlockFrequency::operator+=(const BlockFrequency &Freq) { return *this; } -const BlockFrequency -BlockFrequency::operator+(const BlockFrequency &Prob) const { - BlockFrequency Freq(Frequency); - Freq += Prob; - return Freq; +BlockFrequency BlockFrequency::operator+(BlockFrequency Freq) const { + BlockFrequency NewFreq(Frequency); + NewFreq += Freq; + return NewFreq; +} + +BlockFrequency &BlockFrequency::operator-=(BlockFrequency Freq) { + // If underflow, set frequency to 0. + if (Frequency <= Freq.Frequency) + Frequency = 0; + else + Frequency -= Freq.Frequency; + return *this; +} + +BlockFrequency BlockFrequency::operator-(BlockFrequency Freq) const { + BlockFrequency NewFreq(Frequency); + NewFreq -= Freq; + return NewFreq; } BlockFrequency &BlockFrequency::operator>>=(const unsigned count) { diff --git a/contrib/llvm/lib/Support/BranchProbability.cpp b/contrib/llvm/lib/Support/BranchProbability.cpp index 65878d6..771d02c 100644 --- a/contrib/llvm/lib/Support/BranchProbability.cpp +++ b/contrib/llvm/lib/Support/BranchProbability.cpp @@ -15,17 +15,58 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> using namespace llvm; +const uint32_t BranchProbability::D; + raw_ostream &BranchProbability::print(raw_ostream &OS) const { - return OS << N << " / " << D << " = " - << format("%g%%", ((double)N / D) * 100.0); + if (isUnknown()) + return OS << "?%"; + + // Get a percentage rounded to two decimal digits. This avoids + // implementation-defined rounding inside printf. + double Percent = rint(((double)N / D) * 100.0 * 100.0) / 100.0; + return OS << format("0x%08" PRIx32 " / 0x%08" PRIx32 " = %.2f%%", N, D, + Percent); } void BranchProbability::dump() const { print(dbgs()) << '\n'; } +BranchProbability::BranchProbability(uint32_t Numerator, uint32_t Denominator) { + assert(Denominator > 0 && "Denominator cannot be 0!"); + assert(Numerator <= Denominator && "Probability cannot be bigger than 1!"); + if (Denominator == D) + N = Numerator; + else { + uint64_t Prob64 = + (Numerator * static_cast<uint64_t>(D) + Denominator / 2) / Denominator; + N = static_cast<uint32_t>(Prob64); + } +} + +BranchProbability +BranchProbability::getBranchProbability(uint64_t Numerator, + uint64_t Denominator) { + assert(Numerator <= Denominator && "Probability cannot be bigger than 1!"); + // Scale down Denominator to fit in a 32-bit integer. + int Scale = 0; + while (Denominator > UINT32_MAX) { + Denominator >>= 1; + Scale++; + } + return BranchProbability(Numerator >> Scale, Denominator); +} + +// If ConstD is not zero, then replace D by ConstD so that division and modulo +// operations by D can be optimized, in case this function is not inlined by the +// compiler. +template <uint32_t ConstD> static uint64_t scale(uint64_t Num, uint32_t N, uint32_t D) { + if (ConstD > 0) + D = ConstD; + assert(D && "divide by 0"); // Fast path for multiplying by 1.0. @@ -65,9 +106,9 @@ static uint64_t scale(uint64_t Num, uint32_t N, uint32_t D) { } uint64_t BranchProbability::scale(uint64_t Num) const { - return ::scale(Num, N, D); + return ::scale<D>(Num, N, D); } uint64_t BranchProbability::scaleByInverse(uint64_t Num) const { - return ::scale(Num, D, N); + return ::scale<0>(Num, D, N); } diff --git a/contrib/llvm/lib/Support/CommandLine.cpp b/contrib/llvm/lib/Support/CommandLine.cpp index 17fba95..fdcdb03 100644 --- a/contrib/llvm/lib/Support/CommandLine.cpp +++ b/contrib/llvm/lib/Support/CommandLine.cpp @@ -120,7 +120,7 @@ public: void addOption(Option *O) { bool HadErrors = false; - if (O->ArgStr[0]) { + if (O->hasArgStr()) { // Add argument to the argument map! if (!OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) { errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr @@ -151,12 +151,12 @@ public: } void removeOption(Option *O) { - SmallVector<const char *, 16> OptionNames; + SmallVector<StringRef, 16> OptionNames; O->getExtraOptionNames(OptionNames); - if (O->ArgStr[0]) + if (O->hasArgStr()) OptionNames.push_back(O->ArgStr); for (auto Name : OptionNames) - OptionsMap.erase(StringRef(Name)); + OptionsMap.erase(Name); if (O->getFormattingFlag() == cl::Positional) for (auto Opt = PositionalOpts.begin(); Opt != PositionalOpts.end(); @@ -182,13 +182,13 @@ public: nullptr != ConsumeAfterOpt); } - void updateArgStr(Option *O, const char *NewName) { + void updateArgStr(Option *O, StringRef 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)); + OptionsMap.erase(O->ArgStr); } void printOptionValues(); @@ -227,7 +227,7 @@ void Option::addArgument() { void Option::removeArgument() { GlobalParser->removeOption(this); } -void Option::setArgStr(const char *S) { +void Option::setArgStr(StringRef S) { if (FullyInitialized) GlobalParser->updateArgStr(this, S); ArgStr = S; @@ -296,24 +296,23 @@ static Option *LookupNearestOption(StringRef Arg, ie = OptionsMap.end(); it != ie; ++it) { Option *O = it->second; - SmallVector<const char *, 16> OptionNames; + SmallVector<StringRef, 16> OptionNames; O->getExtraOptionNames(OptionNames); - if (O->ArgStr[0]) + if (O->hasArgStr()) OptionNames.push_back(O->ArgStr); bool PermitValue = O->getValueExpectedFlag() != cl::ValueDisallowed; StringRef Flag = PermitValue ? LHS : Arg; - for (size_t i = 0, e = OptionNames.size(); i != e; ++i) { - StringRef Name = OptionNames[i]; + for (auto Name : OptionNames) { unsigned Distance = StringRef(Name).edit_distance( Flag, /*AllowReplacements=*/true, /*MaxEditDistance=*/BestDistance); if (!Best || Distance < BestDistance) { Best = O; BestDistance = Distance; if (RHS.empty() || !PermitValue) - NearestString = OptionNames[i]; + NearestString = Name; else - NearestString = (Twine(OptionNames[i]) + "=" + RHS).str(); + NearestString = (Twine(Name) + "=" + RHS).str(); } } } @@ -346,10 +345,7 @@ static bool CommaSeparateAndAddOccurrence(Option *Handler, unsigned pos, Value = Val; } - if (Handler->addOccurrence(pos, ArgName, Value, MultiArg)) - return true; - - return false; + return Handler->addOccurrence(pos, ArgName, Value, MultiArg); } /// ProvideOption - For Value, this differentiates between an empty value ("") @@ -799,7 +795,7 @@ void cl::ParseEnvironmentOptions(const char *progName, const char *envVar, // telling us. SmallVector<const char *, 20> newArgv; BumpPtrAllocator A; - BumpPtrStringSaver Saver(A); + StringSaver Saver(A); newArgv.push_back(Saver.save(progName)); // Parse the value of the environment variable into a "command line" @@ -822,7 +818,7 @@ void CommandLineParser::ParseCommandLineOptions(int argc, // Expand response files. SmallVector<const char *, 20> newArgv(argv, argv + argc); BumpPtrAllocator A; - BumpPtrStringSaver Saver(A); + StringSaver Saver(A); ExpandResponseFiles(Saver, TokenizeGNUCommandLine, newArgv); argv = &newArgv[0]; argc = static_cast<int>(newArgv.size()); @@ -859,7 +855,7 @@ void CommandLineParser::ParseCommandLineOptions(int argc, "error - this positional option will never be matched, " "because it does not Require a value, and a " "cl::ConsumeAfter option is active!"); - } else if (UnboundedFound && !Opt->ArgStr[0]) { + } else if (UnboundedFound && !Opt->hasArgStr()) { // This option does not "require" a value... Make sure this option is // not specified after an option that eats all extra arguments, or this // one will never get any! @@ -1144,8 +1140,8 @@ bool Option::addOccurrence(unsigned pos, StringRef ArgName, StringRef Value, // getValueStr - Get the value description string, using "DefaultMsg" if nothing // has been specified yet. // -static const char *getValueStr(const Option &O, const char *DefaultMsg) { - if (O.ValueStr[0] == 0) +static StringRef getValueStr(const Option &O, StringRef DefaultMsg) { + if (O.ValueStr.empty()) return DefaultMsg; return O.ValueStr; } @@ -1155,7 +1151,7 @@ static const char *getValueStr(const Option &O, const char *DefaultMsg) { // // Return the width of the option tag for printing... -size_t alias::getOptionWidth() const { return std::strlen(ArgStr) + 6; } +size_t alias::getOptionWidth() const { return ArgStr.size() + 6; } static void printHelpStr(StringRef HelpStr, size_t Indent, size_t FirstLineIndentedBy) { @@ -1170,7 +1166,7 @@ static void printHelpStr(StringRef HelpStr, size_t Indent, // Print out the option for the alias. void alias::printOptionInfo(size_t GlobalWidth) const { outs() << " -" << ArgStr; - printHelpStr(HelpStr, GlobalWidth, std::strlen(ArgStr) + 6); + printHelpStr(HelpStr, GlobalWidth, ArgStr.size() + 6); } //===----------------------------------------------------------------------===// @@ -1182,9 +1178,9 @@ void alias::printOptionInfo(size_t GlobalWidth) const { // Return the width of the option tag for printing... size_t basic_parser_impl::getOptionWidth(const Option &O) const { - size_t Len = std::strlen(O.ArgStr); + size_t Len = O.ArgStr.size(); if (const char *ValName = getValueName()) - Len += std::strlen(getValueStr(O, ValName)) + 3; + Len += getValueStr(O, ValName).size() + 3; return Len + 6; } @@ -1205,7 +1201,7 @@ void basic_parser_impl::printOptionInfo(const Option &O, void basic_parser_impl::printOptionName(const Option &O, size_t GlobalWidth) const { outs() << " -" << O.ArgStr; - outs().indent(GlobalWidth - std::strlen(O.ArgStr)); + outs().indent(GlobalWidth - O.ArgStr.size()); } // parser<bool> implementation @@ -1319,7 +1315,7 @@ unsigned generic_parser_base::findOption(const char *Name) { // Return the width of the option tag for printing... size_t generic_parser_base::getOptionWidth(const Option &O) const { if (O.hasArgStr()) { - size_t Size = std::strlen(O.ArgStr) + 6; + size_t Size = O.ArgStr.size() + 6; for (unsigned i = 0, e = getNumOptions(); i != e; ++i) Size = std::max(Size, std::strlen(getOption(i)) + 8); return Size; @@ -1338,7 +1334,7 @@ void generic_parser_base::printOptionInfo(const Option &O, size_t GlobalWidth) const { if (O.hasArgStr()) { outs() << " -" << O.ArgStr; - printHelpStr(O.HelpStr, GlobalWidth, std::strlen(O.ArgStr) + 6); + printHelpStr(O.HelpStr, GlobalWidth, O.ArgStr.size() + 6); for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { size_t NumSpaces = GlobalWidth - strlen(getOption(i)) - 8; @@ -1346,7 +1342,7 @@ void generic_parser_base::printOptionInfo(const Option &O, outs().indent(NumSpaces) << " - " << getDescription(i) << '\n'; } } else { - if (O.HelpStr[0]) + if (!O.HelpStr.empty()) outs() << " " << O.HelpStr << '\n'; for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { const char *Option = getOption(i); @@ -1365,7 +1361,7 @@ void generic_parser_base::printGenericOptionDiff( const Option &O, const GenericOptionValue &Value, const GenericOptionValue &Default, size_t GlobalWidth) const { outs() << " -" << O.ArgStr; - outs().indent(GlobalWidth - std::strlen(O.ArgStr)); + outs().indent(GlobalWidth - O.ArgStr.size()); unsigned NumOpts = getNumOptions(); for (unsigned i = 0; i != NumOpts; ++i) { @@ -1508,7 +1504,7 @@ public: outs() << "USAGE: " << GlobalParser->ProgramName << " [options]"; for (auto Opt : GlobalParser->PositionalOpts) { - if (Opt->ArgStr[0]) + if (Opt->hasArgStr()) outs() << " --" << Opt->ArgStr; outs() << " " << Opt->HelpStr; } diff --git a/contrib/llvm/lib/Support/CrashRecoveryContext.cpp b/contrib/llvm/lib/Support/CrashRecoveryContext.cpp index aba0f1d..3f4ef9d 100644 --- a/contrib/llvm/lib/Support/CrashRecoveryContext.cpp +++ b/contrib/llvm/lib/Support/CrashRecoveryContext.cpp @@ -24,6 +24,12 @@ static ManagedStatic< sys::ThreadLocal<const CrashRecoveryContextImpl> > CurrentContext; struct CrashRecoveryContextImpl { + // When threads are disabled, this links up all active + // CrashRecoveryContextImpls. When threads are enabled there's one thread + // per CrashRecoveryContext and CurrentContext is a thread-local, so only one + // CrashRecoveryContextImpl is active per thread and this is always null. + const CrashRecoveryContextImpl *Next; + CrashRecoveryContext *CRC; std::string Backtrace; ::jmp_buf JumpBuffer; @@ -34,21 +40,26 @@ public: CrashRecoveryContextImpl(CrashRecoveryContext *CRC) : CRC(CRC), Failed(false), SwitchedThread(false) { + Next = CurrentContext->get(); CurrentContext->set(this); } ~CrashRecoveryContextImpl() { if (!SwitchedThread) - CurrentContext->erase(); + CurrentContext->set(Next); } /// \brief Called when the separate crash-recovery thread was finished, to /// indicate that we don't need to clear the thread-local CurrentContext. - void setSwitchedThread() { SwitchedThread = true; } + void setSwitchedThread() { +#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0 + SwitchedThread = true; +#endif + } void HandleCrash() { // Eliminate the current context entry, to avoid re-entering in case the // cleanup code crashes. - CurrentContext->erase(); + CurrentContext->set(Next); assert(!Failed && "Crash recovery context already failed!"); Failed = true; @@ -65,7 +76,7 @@ public: static ManagedStatic<sys::Mutex> gCrashRecoveryContextMutex; static bool gCrashRecoveryEnabled = false; -static ManagedStatic<sys::ThreadLocal<const CrashRecoveryContextCleanup> > +static ManagedStatic<sys::ThreadLocal<const CrashRecoveryContext>> tlIsRecoveringFromCrash; CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup() {} @@ -73,7 +84,8 @@ CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup() {} CrashRecoveryContext::~CrashRecoveryContext() { // Reclaim registered resources. CrashRecoveryContextCleanup *i = head; - tlIsRecoveringFromCrash->set(head); + const CrashRecoveryContext *PC = tlIsRecoveringFromCrash->get(); + tlIsRecoveringFromCrash->set(this); while (i) { CrashRecoveryContextCleanup *tmp = i; i = tmp->next; @@ -81,7 +93,7 @@ CrashRecoveryContext::~CrashRecoveryContext() { tmp->recoverResources(); delete tmp; } - tlIsRecoveringFromCrash->erase(); + tlIsRecoveringFromCrash->set(PC); CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl; delete CRCI; @@ -232,7 +244,7 @@ void CrashRecoveryContext::Disable() { static const int Signals[] = { SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP }; -static const unsigned NumSignals = sizeof(Signals) / sizeof(Signals[0]); +static const unsigned NumSignals = array_lengthof(Signals); static struct sigaction PrevActions[NumSignals]; static void CrashRecoverySignalHandler(int Signal) { diff --git a/contrib/llvm/lib/Support/Dwarf.cpp b/contrib/llvm/lib/Support/Dwarf.cpp index 13a4155..7d72256 100644 --- a/contrib/llvm/lib/Support/Dwarf.cpp +++ b/contrib/llvm/lib/Support/Dwarf.cpp @@ -177,6 +177,23 @@ const char *llvm::dwarf::AttributeString(unsigned Attribute) { case DW_AT_MIPS_assumed_size: return "DW_AT_MIPS_assumed_size"; case DW_AT_lo_user: return "DW_AT_lo_user"; case DW_AT_hi_user: return "DW_AT_hi_user"; + case DW_AT_BORLAND_property_read: return "DW_AT_BORLAND_property_read"; + case DW_AT_BORLAND_property_write: return "DW_AT_BORLAND_property_write"; + case DW_AT_BORLAND_property_implements: return "DW_AT_BORLAND_property_implements"; + case DW_AT_BORLAND_property_index: return "DW_AT_BORLAND_property_index"; + case DW_AT_BORLAND_property_default: return "DW_AT_BORLAND_property_default"; + case DW_AT_BORLAND_Delphi_unit: return "DW_AT_BORLAND_Delphi_unit"; + case DW_AT_BORLAND_Delphi_class: return "DW_AT_BORLAND_Delphi_class"; + case DW_AT_BORLAND_Delphi_record: return "DW_AT_BORLAND_Delphi_record"; + case DW_AT_BORLAND_Delphi_metaclass: return "DW_AT_BORLAND_Delphi_metaclass"; + case DW_AT_BORLAND_Delphi_constructor: return "DW_AT_BORLAND_Delphi_constructor"; + case DW_AT_BORLAND_Delphi_destructor: return "DW_AT_BORLAND_Delphi_destructor"; + case DW_AT_BORLAND_Delphi_anonymous_method: return "DW_AT_BORLAND_Delphi_anonymous_method"; + case DW_AT_BORLAND_Delphi_interface: return "DW_AT_BORLAND_Delphi_interface"; + case DW_AT_BORLAND_Delphi_ABI: return "DW_AT_BORLAND_Delphi_ABI"; + case DW_AT_BORLAND_Delphi_return: return "DW_AT_BORLAND_Delphi_return"; + case DW_AT_BORLAND_Delphi_frameptr: return "DW_AT_BORLAND_Delphi_frameptr"; + case DW_AT_BORLAND_closure: return "DW_AT_BORLAND_closure"; case DW_AT_APPLE_optimized: return "DW_AT_APPLE_optimized"; case DW_AT_APPLE_flags: return "DW_AT_APPLE_flags"; case DW_AT_APPLE_isa: return "DW_AT_APPLE_isa"; @@ -201,6 +218,7 @@ const char *llvm::dwarf::AttributeString(unsigned Attribute) { case DW_AT_GNU_addr_base: return "DW_AT_GNU_addr_base"; case DW_AT_GNU_pubnames: return "DW_AT_GNU_pubnames"; case DW_AT_GNU_pubtypes: return "DW_AT_GNU_pubtypes"; + case DW_AT_GNU_discriminator: return "DW_AT_GNU_discriminator"; } return nullptr; } @@ -373,6 +391,14 @@ const char *llvm::dwarf::ConventionString(unsigned Convention) { case DW_CC_nocall: return "DW_CC_nocall"; case DW_CC_lo_user: return "DW_CC_lo_user"; case DW_CC_hi_user: return "DW_CC_hi_user"; + case DW_CC_GNU_borland_fastcall_i386: return "DW_CC_GNU_borland_fastcall_i386"; + case DW_CC_BORLAND_safecall: return "DW_CC_BORLAND_safecall"; + case DW_CC_BORLAND_stdcall: return "DW_CC_BORLAND_stdcall"; + case DW_CC_BORLAND_pascal: return "DW_CC_BORLAND_pascal"; + case DW_CC_BORLAND_msfastcall: return "DW_CC_BORLAND_msfastcall"; + case DW_CC_BORLAND_msreturn: return "DW_CC_BORLAND_msreturn"; + case DW_CC_BORLAND_thiscall: return "DW_CC_BORLAND_thiscall"; + case DW_CC_BORLAND_fastcall: return "DW_CC_BORLAND_fastcall"; } return nullptr; } @@ -442,10 +468,21 @@ const char *llvm::dwarf::MacinfoString(unsigned Encoding) { case DW_MACINFO_start_file: return "DW_MACINFO_start_file"; case DW_MACINFO_end_file: return "DW_MACINFO_end_file"; case DW_MACINFO_vendor_ext: return "DW_MACINFO_vendor_ext"; + case DW_MACINFO_invalid: return "DW_MACINFO_invalid"; } return nullptr; } +unsigned llvm::dwarf::getMacinfo(StringRef MacinfoString) { + return StringSwitch<unsigned>(MacinfoString) + .Case("DW_MACINFO_define", DW_MACINFO_define) + .Case("DW_MACINFO_undef", DW_MACINFO_undef) + .Case("DW_MACINFO_start_file", DW_MACINFO_start_file) + .Case("DW_MACINFO_end_file", DW_MACINFO_end_file) + .Case("DW_MACINFO_vendor_ext", DW_MACINFO_vendor_ext) + .Default(DW_MACINFO_invalid); +} + const char *llvm::dwarf::CallFrameString(unsigned Encoding) { switch (Encoding) { case DW_CFA_nop: return "DW_CFA_nop"; diff --git a/contrib/llvm/lib/Support/ErrorHandling.cpp b/contrib/llvm/lib/Support/ErrorHandling.cpp index a25e21a..2808bd3 100644 --- a/contrib/llvm/lib/Support/ErrorHandling.cpp +++ b/contrib/llvm/lib/Support/ErrorHandling.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/ErrorHandling.h" -#include "llvm-c/Core.h" +#include "llvm-c/ErrorHandling.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" #include "llvm/Config/config.h" diff --git a/contrib/llvm/lib/Support/FileOutputBuffer.cpp b/contrib/llvm/lib/Support/FileOutputBuffer.cpp index 307ff09..651e679 100644 --- a/contrib/llvm/lib/Support/FileOutputBuffer.cpp +++ b/contrib/llvm/lib/Support/FileOutputBuffer.cpp @@ -15,6 +15,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Errc.h" +#include "llvm/Support/Signals.h" #include <system_error> #if !defined(_MSC_VER) && !defined(__MINGW32__) @@ -34,10 +35,8 @@ FileOutputBuffer::~FileOutputBuffer() { sys::fs::remove(Twine(TempPath)); } -std::error_code -FileOutputBuffer::create(StringRef FilePath, size_t Size, - std::unique_ptr<FileOutputBuffer> &Result, - unsigned Flags) { +ErrorOr<std::unique_ptr<FileOutputBuffer>> +FileOutputBuffer::create(StringRef FilePath, size_t Size, unsigned Flags) { // If file already exists, it must be a regular file (to be mappable). sys::fs::file_status Stat; std::error_code EC = sys::fs::status(FilePath, Stat); @@ -76,6 +75,8 @@ FileOutputBuffer::create(StringRef FilePath, size_t Size, if (EC) return EC; + sys::RemoveFileOnSignal(TempFilePath); + #ifndef LLVM_ON_WIN32 // On Windows, CreateFileMapping (the mmap function on Windows) // automatically extends the underlying file. We don't need to @@ -95,10 +96,9 @@ FileOutputBuffer::create(StringRef FilePath, size_t Size, if (Ret) return std::error_code(errno, std::generic_category()); - Result.reset( + std::unique_ptr<FileOutputBuffer> Buf( new FileOutputBuffer(std::move(MappedFile), FilePath, TempFilePath)); - - return std::error_code(); + return std::move(Buf); } std::error_code FileOutputBuffer::commit() { @@ -107,6 +107,8 @@ std::error_code FileOutputBuffer::commit() { // Rename file to final name. - return sys::fs::rename(Twine(TempPath), Twine(FinalPath)); + std::error_code EC = sys::fs::rename(Twine(TempPath), Twine(FinalPath)); + sys::DontRemoveFileOnSignal(TempPath); + return EC; } } // namespace diff --git a/contrib/llvm/lib/Support/FoldingSet.cpp b/contrib/llvm/lib/Support/FoldingSet.cpp index b8538ff..bb0ec2d 100644 --- a/contrib/llvm/lib/Support/FoldingSet.cpp +++ b/contrib/llvm/lib/Support/FoldingSet.cpp @@ -232,9 +232,29 @@ FoldingSetImpl::FoldingSetImpl(unsigned Log2InitSize) { Buckets = AllocateBuckets(NumBuckets); NumNodes = 0; } + +FoldingSetImpl::FoldingSetImpl(FoldingSetImpl &&Arg) + : Buckets(Arg.Buckets), NumBuckets(Arg.NumBuckets), NumNodes(Arg.NumNodes) { + Arg.Buckets = nullptr; + Arg.NumBuckets = 0; + Arg.NumNodes = 0; +} + +FoldingSetImpl &FoldingSetImpl::operator=(FoldingSetImpl &&RHS) { + free(Buckets); // This may be null if the set is in a moved-from state. + Buckets = RHS.Buckets; + NumBuckets = RHS.NumBuckets; + NumNodes = RHS.NumNodes; + RHS.Buckets = nullptr; + RHS.NumBuckets = 0; + RHS.NumNodes = 0; + return *this; +} + FoldingSetImpl::~FoldingSetImpl() { free(Buckets); } + void FoldingSetImpl::clear() { // Set all but the last bucket to null pointers. memset(Buckets, 0, NumBuckets*sizeof(void*)); diff --git a/contrib/llvm/lib/Support/GraphWriter.cpp b/contrib/llvm/lib/Support/GraphWriter.cpp index a9b0220..d0e1d50 100644 --- a/contrib/llvm/lib/Support/GraphWriter.cpp +++ b/contrib/llvm/lib/Support/GraphWriter.cpp @@ -103,7 +103,7 @@ struct GraphSession { bool TryFindProgram(StringRef Names, std::string &ProgramPath) { raw_string_ostream Log(LogBuffer); SmallVector<StringRef, 8> parts; - Names.split(parts, "|"); + Names.split(parts, '|'); for (auto Name : parts) { if (ErrorOr<std::string> P = sys::findProgramByName(Name)) { ProgramPath = *P; @@ -189,61 +189,87 @@ bool llvm::DisplayGraph(StringRef FilenameRef, bool wait, return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg); } - enum PSViewerKind { PSV_None, PSV_OSXOpen, PSV_XDGOpen, PSV_Ghostview }; - PSViewerKind PSViewer = PSV_None; + enum ViewerKind { + VK_None, + VK_OSXOpen, + VK_XDGOpen, + VK_Ghostview, + VK_CmdStart + }; + ViewerKind Viewer = VK_None; #ifdef __APPLE__ - if (!PSViewer && S.TryFindProgram("open", ViewerPath)) - PSViewer = PSV_OSXOpen; + if (!Viewer && S.TryFindProgram("open", ViewerPath)) + Viewer = VK_OSXOpen; +#endif + if (!Viewer && S.TryFindProgram("gv", ViewerPath)) + Viewer = VK_Ghostview; + if (!Viewer && S.TryFindProgram("xdg-open", ViewerPath)) + Viewer = VK_XDGOpen; +#ifdef LLVM_ON_WIN32 + if (!Viewer && S.TryFindProgram("cmd", ViewerPath)) { + Viewer = VK_CmdStart; + } #endif - if (!PSViewer && S.TryFindProgram("gv", ViewerPath)) - PSViewer = PSV_Ghostview; - if (!PSViewer && S.TryFindProgram("xdg-open", ViewerPath)) - PSViewer = PSV_XDGOpen; - // PostScript graph generator + PostScript viewer + // PostScript or PDF graph generator + PostScript/PDF viewer std::string GeneratorPath; - if (PSViewer && + if (Viewer && (S.TryFindProgram(getProgramName(program), GeneratorPath) || S.TryFindProgram("dot|fdp|neato|twopi|circo", GeneratorPath))) { - std::string PSFilename = Filename + ".ps"; + std::string OutputFilename = + Filename + (Viewer == VK_CmdStart ? ".pdf" : ".ps"); std::vector<const char *> args; args.push_back(GeneratorPath.c_str()); - args.push_back("-Tps"); + if (Viewer == VK_CmdStart) + args.push_back("-Tpdf"); + else + args.push_back("-Tps"); args.push_back("-Nfontname=Courier"); args.push_back("-Gsize=7.5,10"); args.push_back(Filename.c_str()); args.push_back("-o"); - args.push_back(PSFilename.c_str()); + args.push_back(OutputFilename.c_str()); args.push_back(nullptr); errs() << "Running '" << GeneratorPath << "' program... "; - if (ExecGraphViewer(GeneratorPath, args, Filename, wait, ErrMsg)) + if (ExecGraphViewer(GeneratorPath, args, Filename, true, ErrMsg)) return true; + // The lifetime of StartArg must include the call of ExecGraphViewer + // because the args are passed as vector of char*. + std::string StartArg; + args.clear(); args.push_back(ViewerPath.c_str()); - switch (PSViewer) { - case PSV_OSXOpen: + switch (Viewer) { + case VK_OSXOpen: args.push_back("-W"); - args.push_back(PSFilename.c_str()); + args.push_back(OutputFilename.c_str()); break; - case PSV_XDGOpen: + case VK_XDGOpen: wait = false; - args.push_back(PSFilename.c_str()); + args.push_back(OutputFilename.c_str()); break; - case PSV_Ghostview: + case VK_Ghostview: args.push_back("--spartan"); - args.push_back(PSFilename.c_str()); + args.push_back(OutputFilename.c_str()); + break; + case VK_CmdStart: + args.push_back("/S"); + args.push_back("/C"); + StartArg = + (StringRef("start ") + (wait ? "/WAIT " : "") + OutputFilename).str(); + args.push_back(StartArg.c_str()); break; - case PSV_None: + case VK_None: llvm_unreachable("Invalid viewer"); } args.push_back(nullptr); ErrMsg.clear(); - return ExecGraphViewer(ViewerPath, args, PSFilename, wait, ErrMsg); + return ExecGraphViewer(ViewerPath, args, OutputFilename, wait, ErrMsg); } // dotty diff --git a/contrib/llvm/lib/Support/Host.cpp b/contrib/llvm/lib/Support/Host.cpp index 1bd1fe2..c0f9e07 100644 --- a/contrib/llvm/lib/Support/Host.cpp +++ b/contrib/llvm/lib/Support/Host.cpp @@ -368,8 +368,14 @@ StringRef sys::getHostCPUName() { // Broadwell: case 61: + case 71: return "broadwell"; + // Skylake: + case 78: + case 94: + return "skylake"; + case 28: // Most 45 nm Intel Atom processors case 38: // 45 nm Atom Lincroft case 39: // 32 nm Atom Medfield @@ -381,6 +387,8 @@ StringRef sys::getHostCPUName() { case 55: case 74: case 77: + case 90: + case 93: return "silvermont"; default: // Unknown family 6 CPU, try to guess. @@ -689,7 +697,7 @@ StringRef sys::getHostCPUName() { if (Lines[I].startswith("features")) { size_t Pos = Lines[I].find(":"); if (Pos != StringRef::npos) { - Lines[I].drop_front(Pos + 1).split(CPUFeatures, " "); + Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' '); break; } } @@ -766,14 +774,17 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) { // 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; + bool HasAVXSave = ((ECX >> 27) & 1) && ((ECX >> 28) & 1) && + !GetX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6); + Features["avx"] = HasAVXSave; + Features["fma"] = HasAVXSave && (ECX >> 12) & 1; + Features["f16c"] = HasAVXSave && (ECX >> 29) & 1; + + // Only enable XSAVE if OS has enabled support for saving YMM state. + Features["xsave"] = HasAVXSave && (ECX >> 26) & 1; // AVX512 requires additional context to be saved by the OS. - bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0); + bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0); unsigned MaxExtLevel; GetX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX); @@ -783,15 +794,15 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) { 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["xop"] = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave; + Features["fma4"] = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave; 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["avx2"] = HasAVXSave && HasLeaf7 && ((EBX >> 5) & 1); Features["fsgsbase"] = HasLeaf7 && ((EBX >> 0) & 1); Features["bmi"] = HasLeaf7 && ((EBX >> 3) & 1); @@ -801,6 +812,8 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) { Features["rdseed"] = HasLeaf7 && ((EBX >> 18) & 1); Features["adx"] = HasLeaf7 && ((EBX >> 19) & 1); Features["sha"] = HasLeaf7 && ((EBX >> 29) & 1); + // Enable protection keys + Features["pku"] = HasLeaf7 && ((ECX >> 4) & 1); // AVX512 is only supported if the OS supports the context save for it. Features["avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save; @@ -811,6 +824,14 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) { Features["avx512bw"] = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save; Features["avx512vl"] = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save; + bool HasLeafD = MaxLevel >= 0xd && + !GetX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX); + + // Only enable XSAVE if OS has enabled support for saving YMM state. + Features["xsaveopt"] = HasAVXSave && HasLeafD && ((EAX >> 0) & 1); + Features["xsavec"] = HasAVXSave && HasLeafD && ((EAX >> 1) & 1); + Features["xsaves"] = HasAVXSave && HasLeafD && ((EAX >> 3) & 1); + return true; } #elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__)) @@ -832,7 +853,7 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) { // Look for the CPU features. for (unsigned I = 0, E = Lines.size(); I != E; ++I) if (Lines[I].startswith("Features")) { - Lines[I].split(CPUFeatures, " "); + Lines[I].split(CPUFeatures, ' '); break; } diff --git a/contrib/llvm/lib/Support/JamCRC.cpp b/contrib/llvm/lib/Support/JamCRC.cpp new file mode 100644 index 0000000..bc21c91 --- /dev/null +++ b/contrib/llvm/lib/Support/JamCRC.cpp @@ -0,0 +1,96 @@ +//===-- JamCRC.cpp - Cyclic Redundancy Check --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains an implementation of JamCRC. +// +//===----------------------------------------------------------------------===// +// +// The implementation technique is the one mentioned in: +// D. V. Sarwate. 1988. Computation of cyclic redundancy checks via table +// look-up. Commun. ACM 31, 8 (August 1988) +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/JamCRC.h" + +using namespace llvm; + +static const uint32_t CRCTable[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +void JamCRC::update(ArrayRef<char> Data) { + for (char Byte : Data) { + int TableIdx = (CRC ^ Byte) & 0xff; + CRC = CRCTable[TableIdx] ^ (CRC >> 8); + } +} diff --git a/contrib/llvm/lib/Support/Locale.cpp b/contrib/llvm/lib/Support/Locale.cpp index d5cb72b..53bc0e3 100644 --- a/contrib/llvm/lib/Support/Locale.cpp +++ b/contrib/llvm/lib/Support/Locale.cpp @@ -1,3 +1,4 @@ +#include "llvm/Config/llvm-config.h" #include "llvm/Support/Locale.h" #include "llvm/Support/Unicode.h" diff --git a/contrib/llvm/lib/Support/ManagedStatic.cpp b/contrib/llvm/lib/Support/ManagedStatic.cpp index b8fb284..9868207 100644 --- a/contrib/llvm/lib/Support/ManagedStatic.cpp +++ b/contrib/llvm/lib/Support/ManagedStatic.cpp @@ -14,6 +14,7 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Config/config.h" #include "llvm/Support/Atomic.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/MutexGuard.h" #include <cassert> diff --git a/contrib/llvm/lib/Support/MemoryBuffer.cpp b/contrib/llvm/lib/Support/MemoryBuffer.cpp index d09ef3a..faee10b 100644 --- a/contrib/llvm/lib/Support/MemoryBuffer.cpp +++ b/contrib/llvm/lib/Support/MemoryBuffer.cpp @@ -162,13 +162,14 @@ MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) { } ErrorOr<std::unique_ptr<MemoryBuffer>> -MemoryBuffer::getFileOrSTDIN(const Twine &Filename, int64_t FileSize) { +MemoryBuffer::getFileOrSTDIN(const Twine &Filename, int64_t FileSize, + bool RequiresNullTerminator) { SmallString<256> NameBuf; StringRef NameRef = Filename.toStringRef(NameBuf); if (NameRef == "-") return getSTDIN(); - return getFile(Filename, FileSize); + return getFile(Filename, FileSize, RequiresNullTerminator); } ErrorOr<std::unique_ptr<MemoryBuffer>> diff --git a/contrib/llvm/lib/Support/Path.cpp b/contrib/llvm/lib/Support/Path.cpp index cf46738..4952f59 100644 --- a/contrib/llvm/lib/Support/Path.cpp +++ b/contrib/llvm/lib/Support/Path.cpp @@ -455,17 +455,15 @@ void append(SmallVectorImpl<char> &path, const Twine &a, if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage)); if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage)); - for (SmallVectorImpl<StringRef>::const_iterator i = components.begin(), - e = components.end(); - i != e; ++i) { + for (auto &component : components) { bool path_has_sep = !path.empty() && is_separator(path[path.size() - 1]); - bool component_has_sep = !i->empty() && is_separator((*i)[0]); - bool is_root_name = has_root_name(*i); + bool component_has_sep = !component.empty() && is_separator(component[0]); + bool is_root_name = has_root_name(component); if (path_has_sep) { // Strip separators from beginning of component. - size_t loc = i->find_first_not_of(separators); - StringRef c = i->substr(loc); + size_t loc = component.find_first_not_of(separators); + StringRef c = component.substr(loc); // Append it. path.append(c.begin(), c.end()); @@ -477,7 +475,7 @@ void append(SmallVectorImpl<char> &path, const Twine &a, path.push_back(preferred_separator); } - path.append(i->begin(), i->end()); + path.append(component.begin(), component.end()); } } @@ -661,8 +659,51 @@ bool is_absolute(const Twine &path) { return rootDir && rootName; } -bool is_relative(const Twine &path) { - return !is_absolute(path); +bool is_relative(const Twine &path) { return !is_absolute(path); } + +StringRef remove_leading_dotslash(StringRef Path) { + // Remove leading "./" (or ".//" or "././" etc.) + while (Path.size() > 2 && Path[0] == '.' && is_separator(Path[1])) { + Path = Path.substr(2); + while (Path.size() > 0 && is_separator(Path[0])) + Path = Path.substr(1); + } + return Path; +} + +static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot) { + SmallVector<StringRef, 16> components; + + // Skip the root path, then look for traversal in the components. + StringRef rel = path::relative_path(path); + for (StringRef C : llvm::make_range(path::begin(rel), path::end(rel))) { + if (C == ".") + continue; + if (remove_dot_dot) { + if (C == "..") { + if (!components.empty()) + components.pop_back(); + continue; + } + } + components.push_back(C); + } + + SmallString<256> buffer = path::root_path(path); + for (StringRef C : components) + path::append(buffer, C); + return buffer; +} + +bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot) { + StringRef p(path.data(), path.size()); + + SmallString<256> result = remove_dots(p, remove_dot_dot); + if (result == path) + return false; + + path.swap(result); + return true; } } // end namespace path @@ -732,7 +773,9 @@ std::error_code createUniqueDirectory(const Twine &Prefix, true, 0, FS_Dir); } -std::error_code make_absolute(SmallVectorImpl<char> &path) { +static std::error_code make_absolute(const Twine ¤t_directory, + SmallVectorImpl<char> &path, + bool use_current_directory) { StringRef p(path.data(), path.size()); bool rootDirectory = path::has_root_directory(p), @@ -748,7 +791,9 @@ std::error_code make_absolute(SmallVectorImpl<char> &path) { // All of the following conditions will need the current directory. SmallString<128> current_dir; - if (std::error_code ec = current_path(current_dir)) + if (use_current_directory) + current_directory.toVector(current_dir); + else if (std::error_code ec = current_path(current_dir)) return ec; // Relative path. Prepend the current directory. @@ -785,12 +830,22 @@ std::error_code make_absolute(SmallVectorImpl<char> &path) { "occurred above!"); } -std::error_code create_directories(const Twine &Path, bool IgnoreExisting) { +std::error_code make_absolute(const Twine ¤t_directory, + SmallVectorImpl<char> &path) { + return make_absolute(current_directory, path, true); +} + +std::error_code make_absolute(SmallVectorImpl<char> &path) { + return make_absolute(Twine(), path, false); +} + +std::error_code create_directories(const Twine &Path, bool IgnoreExisting, + perms Perms) { SmallString<128> PathStorage; StringRef P = Path.toStringRef(PathStorage); // Be optimistic and try to create the directory - std::error_code EC = create_directory(P, IgnoreExisting); + std::error_code EC = create_directory(P, IgnoreExisting, Perms); // If we succeeded, or had any error other than the parent not existing, just // return it. if (EC != errc::no_such_file_or_directory) @@ -802,10 +857,10 @@ std::error_code create_directories(const Twine &Path, bool IgnoreExisting) { if (Parent.empty()) return EC; - if ((EC = create_directories(Parent))) + if ((EC = create_directories(Parent, IgnoreExisting, Perms))) return EC; - return create_directory(P, IgnoreExisting); + return create_directory(P, IgnoreExisting, Perms); } std::error_code copy_file(const Twine &From, const Twine &To) { @@ -889,8 +944,7 @@ std::error_code is_other(const Twine &Path, bool &Result) { } void directory_entry::replace_filename(const Twine &filename, file_status st) { - SmallString<128> path(Path.begin(), Path.end()); - path::remove_filename(path); + SmallString<128> path = path::parent_path(Path); path::append(path, filename); Path = path.str(); Status = st; @@ -940,7 +994,8 @@ file_magic identify_magic(StringRef Magic) { break; case '!': if (Magic.size() >= 8) - if (memcmp(Magic.data(),"!<arch>\n",8) == 0) + if (memcmp(Magic.data(), "!<arch>\n", 8) == 0 || + memcmp(Magic.data(), "!<thin>\n", 8) == 0) return file_magic::archive; break; @@ -1074,3 +1129,20 @@ std::error_code directory_entry::status(file_status &result) const { #if defined(LLVM_ON_WIN32) #include "Windows/Path.inc" #endif + +namespace llvm { +namespace sys { +namespace path { + +bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1, + const Twine &Path2, const Twine &Path3) { + if (getUserCacheDir(Result)) { + append(Result, Path1, Path2, Path3); + return true; + } + return false; +} + +} // end namespace path +} // end namsspace sys +} // end namespace llvm diff --git a/contrib/llvm/lib/Support/PrettyStackTrace.cpp b/contrib/llvm/lib/Support/PrettyStackTrace.cpp index f9f8cab..05b3e31 100644 --- a/contrib/llvm/lib/Support/PrettyStackTrace.cpp +++ b/contrib/llvm/lib/Support/PrettyStackTrace.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/PrettyStackTrace.h" -#include "llvm-c/Core.h" +#include "llvm-c/ErrorHandling.h" #include "llvm/ADT/SmallString.h" #include "llvm/Config/config.h" // Get autoconf configuration settings #include "llvm/Support/Compiler.h" @@ -154,6 +154,20 @@ void llvm::EnablePrettyStackTrace() { #endif } +const void* llvm::SavePrettyStackState() { +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) + return PrettyStackTraceHead; +#else + return nullptr; +#endif +} + +void llvm::RestorePrettyStackState(const void* Top) { +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) + PrettyStackTraceHead = (const PrettyStackTraceEntry*)Top; +#endif +} + void LLVMEnablePrettyStackTrace() { EnablePrettyStackTrace(); } diff --git a/contrib/llvm/lib/Support/Signals.cpp b/contrib/llvm/lib/Support/Signals.cpp index a117893..3dc6b7c 100644 --- a/contrib/llvm/lib/Support/Signals.cpp +++ b/contrib/llvm/lib/Support/Signals.cpp @@ -12,8 +12,21 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/Signals.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Config/config.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/StringSaver.h" +#include "llvm/Support/raw_ostream.h" +#include <vector> namespace llvm { using namespace sys; @@ -23,6 +36,131 @@ using namespace sys; //=== independent code. //===----------------------------------------------------------------------===// +static ManagedStatic<std::vector<std::pair<void (*)(void *), void *>>> + CallBacksToRun; +void sys::RunSignalHandlers() { + if (!CallBacksToRun.isConstructed()) + return; + for (auto &I : *CallBacksToRun) + I.first(I.second); + CallBacksToRun->clear(); +} +} + +using namespace llvm; + +static bool findModulesAndOffsets(void **StackTrace, int Depth, + const char **Modules, intptr_t *Offsets, + const char *MainExecutableName, + StringSaver &StrPool); + +/// Format a pointer value as hexadecimal. Zero pad it out so its always the +/// same width. +static FormattedNumber format_ptr(void *PC) { + // Each byte is two hex digits plus 2 for the 0x prefix. + unsigned PtrWidth = 2 + 2 * sizeof(void *); + return format_hex((uint64_t)PC, PtrWidth); +} + +static bool printSymbolizedStackTrace(void **StackTrace, int Depth, + llvm::raw_ostream &OS) + LLVM_ATTRIBUTE_USED; + +/// Helper that launches llvm-symbolizer and symbolizes a backtrace. +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. + ErrorOr<std::string> LLVMSymbolizerPathOrErr = + sys::findProgramByName("llvm-symbolizer"); + if (!LLVMSymbolizerPathOrErr) + return false; + const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr; + // We don't know argv0 or the address of main() at this point, but try + // to guess it anyway (it's possible on some platforms). + std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr); + if (MainExecutableName.empty() || + MainExecutableName.find("llvm-symbolizer") != std::string::npos) + return false; + + BumpPtrAllocator Allocator; + StringSaver StrPool(Allocator); + std::vector<const char *> Modules(Depth, nullptr); + std::vector<intptr_t> Offsets(Depth, 0); + if (!findModulesAndOffsets(StackTrace, Depth, Modules.data(), Offsets.data(), + MainExecutableName.c_str(), StrPool)) + return false; + int InputFD; + SmallString<32> InputFile, OutputFile; + sys::fs::createTemporaryFile("symbolizer-input", "", InputFD, InputFile); + sys::fs::createTemporaryFile("symbolizer-output", "", OutputFile); + FileRemover InputRemover(InputFile.c_str()); + FileRemover OutputRemover(OutputFile.c_str()); + + { + raw_fd_ostream Input(InputFD, true); + for (int i = 0; i < Depth; i++) { + if (Modules[i]) + Input << Modules[i] << " " << (void*)Offsets[i] << "\n"; + } + } + + StringRef InputFileStr(InputFile); + StringRef OutputFileStr(OutputFile); + StringRef StderrFileStr; + const StringRef *Redirects[] = {&InputFileStr, &OutputFileStr, + &StderrFileStr}; + const char *Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining", +#ifdef LLVM_ON_WIN32 + // Pass --relative-address on Windows so that we don't + // have to add ImageBase from PE file. + // FIXME: Make this the default for llvm-symbolizer. + "--relative-address", +#endif + "--demangle", nullptr}; + int RunResult = + sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects); + if (RunResult != 0) + return false; + + // This report format is based on the sanitizer stack trace printer. See + // sanitizer_stacktrace_printer.cc in compiler-rt. + auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str()); + if (!OutputBuf) + return false; + StringRef Output = OutputBuf.get()->getBuffer(); + SmallVector<StringRef, 32> Lines; + Output.split(Lines, "\n"); + auto CurLine = Lines.begin(); + int frame_no = 0; + for (int i = 0; i < Depth; i++) { + if (!Modules[i]) { + OS << '#' << frame_no++ << ' ' << format_ptr(StackTrace[i]) << '\n'; + continue; + } + // Read pairs of lines (function name and file/line info) until we + // encounter empty line. + for (;;) { + if (CurLine == Lines.end()) + return false; + StringRef FunctionName = *CurLine++; + if (FunctionName.empty()) + break; + OS << '#' << frame_no++ << ' ' << format_ptr(StackTrace[i]) << ' '; + if (!FunctionName.startswith("??")) + OS << FunctionName << ' '; + if (CurLine == Lines.end()) + return false; + StringRef FileLineInfo = *CurLine++; + if (!FileLineInfo.startswith("??")) + OS << FileLineInfo; + else + OS << "(" << Modules[i] << '+' << format_hex(Offsets[i], 0) << ")"; + OS << "\n"; + } + } + return true; } // Include the platform-specific parts of this class. diff --git a/contrib/llvm/lib/Support/Statistic.cpp b/contrib/llvm/lib/Support/Statistic.cpp index 56c3b0f..e49d1cb 100644 --- a/contrib/llvm/lib/Support/Statistic.cpp +++ b/contrib/llvm/lib/Support/Statistic.cpp @@ -24,6 +24,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" #include "llvm/Support/ManagedStatic.h" @@ -33,9 +34,6 @@ #include <cstring> using namespace llvm; -// CreateInfoOutputFile - Return a file stream to print our output on. -namespace llvm { extern raw_ostream *CreateInfoOutputFile(); } - /// -stats - Command line option to cause transformations to emit stats about /// what they did. /// @@ -144,20 +142,18 @@ void llvm::PrintStatistics() { if (Stats.Stats.empty()) return; // Get the stream to write to. - raw_ostream &OutStream = *CreateInfoOutputFile(); - PrintStatistics(OutStream); - delete &OutStream; // Close the file. + std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile(); + PrintStatistics(*OutStream); + #else // Check if the -stats option is set instead of checking // !Stats.Stats.empty(). In release builds, Statistics operators // do nothing, so stats are never Registered. if (Enabled) { // Get the stream to write to. - raw_ostream &OutStream = *CreateInfoOutputFile(); - OutStream << "Statistics are disabled. " - << "Build with asserts or with -DLLVM_ENABLE_STATS\n"; - OutStream.flush(); - delete &OutStream; // Close the file. + std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile(); + (*OutStream) << "Statistics are disabled. " + << "Build with asserts or with -DLLVM_ENABLE_STATS\n"; } #endif } diff --git a/contrib/llvm/lib/Support/StringRef.cpp b/contrib/llvm/lib/Support/StringRef.cpp index ddece08..7ecff29 100644 --- a/contrib/llvm/lib/Support/StringRef.cpp +++ b/contrib/llvm/lib/Support/StringRef.cpp @@ -140,37 +140,44 @@ std::string StringRef::upper() const { /// \return - The index of the first occurrence of \arg Str, or npos if not /// found. size_t StringRef::find(StringRef Str, size_t From) const { + if (From > Length) + return npos; + + const char *Needle = Str.data(); size_t N = Str.size(); - if (N > Length) + if (N == 0) + return From; + + size_t Size = Length - From; + if (Size < N) return npos; + const char *Start = Data + From; + const char *Stop = Start + (Size - N + 1); + // For short haystacks or unsupported needles fall back to the naive algorithm - if (Length < 16 || N > 255 || N == 0) { - for (size_t e = Length - N + 1, i = std::min(From, e); i != e; ++i) - if (substr(i, N).equals(Str)) - return i; + if (Size < 16 || N > 255) { + do { + if (std::memcmp(Start, Needle, N) == 0) + return Start - Data; + ++Start; + } while (Start < Stop); return npos; } - if (From >= Length) - return npos; - // Build the bad char heuristic table, with uint8_t to reduce cache thrashing. uint8_t BadCharSkip[256]; std::memset(BadCharSkip, N, 256); for (unsigned i = 0; i != N-1; ++i) BadCharSkip[(uint8_t)Str[i]] = N-1-i; - unsigned Len = Length-From, Pos = From; - while (Len >= N) { - if (substr(Pos, N).equals(Str)) // See if this is the correct substring. - return Pos; + do { + if (std::memcmp(Start, Needle, N) == 0) + return Start - Data; // Otherwise skip the appropriate number of bytes. - uint8_t Skip = BadCharSkip[(uint8_t)(*this)[Pos+N-1]]; - Len -= Skip; - Pos += Skip; - } + Start += BadCharSkip[(uint8_t)Start[N-1]]; + } while (Start < Stop); return npos; } @@ -274,24 +281,56 @@ StringRef::size_type StringRef::find_last_not_of(StringRef Chars, } void StringRef::split(SmallVectorImpl<StringRef> &A, - StringRef Separators, int MaxSplit, + StringRef Separator, int MaxSplit, bool KeepEmpty) const { - StringRef rest = *this; - - // rest.data() is used to distinguish cases like "a," that splits into - // "a" + "" and "a" that splits into "a" + 0. - for (int splits = 0; - rest.data() != nullptr && (MaxSplit < 0 || splits < MaxSplit); - ++splits) { - std::pair<StringRef, StringRef> p = rest.split(Separators); - - if (KeepEmpty || p.first.size() != 0) - A.push_back(p.first); - rest = p.second; + StringRef S = *this; + + // Count down from MaxSplit. When MaxSplit is -1, this will just split + // "forever". This doesn't support splitting more than 2^31 times + // intentionally; if we ever want that we can make MaxSplit a 64-bit integer + // but that seems unlikely to be useful. + while (MaxSplit-- != 0) { + size_t Idx = S.find(Separator); + if (Idx == npos) + break; + + // Push this split. + if (KeepEmpty || Idx > 0) + A.push_back(S.slice(0, Idx)); + + // Jump forward. + S = S.slice(Idx + Separator.size(), npos); + } + + // Push the tail. + if (KeepEmpty || !S.empty()) + A.push_back(S); +} + +void StringRef::split(SmallVectorImpl<StringRef> &A, char Separator, + int MaxSplit, bool KeepEmpty) const { + StringRef S = *this; + + // Count down from MaxSplit. When MaxSplit is -1, this will just split + // "forever". This doesn't support splitting more than 2^31 times + // intentionally; if we ever want that we can make MaxSplit a 64-bit integer + // but that seems unlikely to be useful. + while (MaxSplit-- != 0) { + size_t Idx = S.find(Separator); + if (Idx == npos) + break; + + // Push this split. + if (KeepEmpty || Idx > 0) + A.push_back(S.slice(0, Idx)); + + // Jump forward. + S = S.slice(Idx + 1, npos); } - // If we have a tail left, add it. - if (rest.data() != nullptr && (rest.size() != 0 || KeepEmpty)) - A.push_back(rest); + + // Push the tail. + if (KeepEmpty || !S.empty()) + A.push_back(S); } //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/Support/StringSaver.cpp b/contrib/llvm/lib/Support/StringSaver.cpp index d6b84e5..bbc1fd2 100644 --- a/contrib/llvm/lib/Support/StringSaver.cpp +++ b/contrib/llvm/lib/Support/StringSaver.cpp @@ -11,7 +11,7 @@ using namespace llvm; -const char *StringSaver::saveImpl(StringRef S) { +const char *StringSaver::save(StringRef S) { char *P = Alloc.Allocate<char>(S.size() + 1); memcpy(P, S.data(), S.size()); P[S.size()] = '\0'; diff --git a/contrib/llvm/lib/Support/TargetParser.cpp b/contrib/llvm/lib/Support/TargetParser.cpp index 4d4c041..337532e 100644 --- a/contrib/llvm/lib/Support/TargetParser.cpp +++ b/contrib/llvm/lib/Support/TargetParser.cpp @@ -16,9 +16,11 @@ #include "llvm/Support/TargetParser.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" #include <cctype> using namespace llvm; +using namespace ARM; namespace { @@ -26,36 +28,19 @@ namespace { // features they correspond to (use getFPUFeatures). // FIXME: TableGen this. // The entries must appear in the order listed in ARM::FPUKind for correct indexing -struct { - const char * Name; +static const struct { + const char *NameCStr; + size_t NameLength; ARM::FPUKind ID; ARM::FPUVersion FPUVersion; ARM::NeonSupportLevel NeonSupport; ARM::FPURestriction Restriction; + + StringRef getName() const { return StringRef(NameCStr, NameLength); } } FPUNames[] = { - { "invalid", ARM::FK_INVALID, ARM::FV_NONE, ARM::NS_None, ARM::FR_None}, - { "none", ARM::FK_NONE, ARM::FV_NONE, ARM::NS_None, ARM::FR_None}, - { "vfp", ARM::FK_VFP, ARM::FV_VFPV2, ARM::NS_None, ARM::FR_None}, - { "vfpv2", ARM::FK_VFPV2, ARM::FV_VFPV2, ARM::NS_None, ARM::FR_None}, - { "vfpv3", ARM::FK_VFPV3, ARM::FV_VFPV3, ARM::NS_None, ARM::FR_None}, - { "vfpv3-fp16", ARM::FK_VFPV3_FP16, ARM::FV_VFPV3_FP16, ARM::NS_None, ARM::FR_None}, - { "vfpv3-d16", ARM::FK_VFPV3_D16, ARM::FV_VFPV3, ARM::NS_None, ARM::FR_D16}, - { "vfpv3-d16-fp16", ARM::FK_VFPV3_D16_FP16, ARM::FV_VFPV3_FP16, ARM::NS_None, ARM::FR_D16}, - { "vfpv3xd", ARM::FK_VFPV3XD, ARM::FV_VFPV3, ARM::NS_None, ARM::FR_SP_D16}, - { "vfpv3xd-fp16", ARM::FK_VFPV3XD_FP16, ARM::FV_VFPV3_FP16, ARM::NS_None, ARM::FR_SP_D16}, - { "vfpv4", ARM::FK_VFPV4, ARM::FV_VFPV4, ARM::NS_None, ARM::FR_None}, - { "vfpv4-d16", ARM::FK_VFPV4_D16, ARM::FV_VFPV4, ARM::NS_None, ARM::FR_D16}, - { "fpv4-sp-d16", ARM::FK_FPV4_SP_D16, ARM::FV_VFPV4, ARM::NS_None, ARM::FR_SP_D16}, - { "fpv5-d16", ARM::FK_FPV5_D16, ARM::FV_VFPV5, ARM::NS_None, ARM::FR_D16}, - { "fpv5-sp-d16", ARM::FK_FPV5_SP_D16, ARM::FV_VFPV5, ARM::NS_None, ARM::FR_SP_D16}, - { "fp-armv8", ARM::FK_FP_ARMV8, ARM::FV_VFPV5, ARM::NS_None, ARM::FR_None}, - { "neon", ARM::FK_NEON, ARM::FV_VFPV3, ARM::NS_Neon, ARM::FR_None}, - { "neon-fp16", ARM::FK_NEON_FP16, ARM::FV_VFPV3_FP16, ARM::NS_Neon, ARM::FR_None}, - { "neon-vfpv4", ARM::FK_NEON_VFPV4, ARM::FV_VFPV4, ARM::NS_Neon, ARM::FR_None}, - { "neon-fp-armv8", ARM::FK_NEON_FP_ARMV8, ARM::FV_VFPV5, ARM::NS_Neon, ARM::FR_None}, - { "crypto-neon-fp-armv8", - ARM::FK_CRYPTO_NEON_FP_ARMV8, ARM::FV_VFPV5, ARM::NS_Crypto, ARM::FR_None}, - { "softvfp", ARM::FK_SOFTVFP, ARM::FV_NONE, ARM::NS_None, ARM::FR_None}, +#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \ + { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION }, +#include "llvm/Support/ARMTargetParser.def" }; // List of canonical arch names (use getArchSynonym). @@ -66,165 +51,79 @@ struct { // of the triples and are not conforming with their official names. // Check to see if the expectation should be changed. // FIXME: TableGen this. -struct { - const char *Name; +static const struct { + const char *NameCStr; + size_t NameLength; + const char *CPUAttrCStr; + size_t CPUAttrLength; + const char *SubArchCStr; + size_t SubArchLength; + unsigned DefaultFPU; + unsigned ArchBaseExtensions; ARM::ArchKind ID; - const char *CPUAttr; // CPU class in build attributes. - const char *SubArch; // Sub-Arch name. ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes. + + StringRef getName() const { return StringRef(NameCStr, NameLength); } + + // CPU class in build attributes. + StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); } + + // Sub-Arch name. + StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); } } ARCHNames[] = { - { "invalid", ARM::AK_INVALID, nullptr, nullptr, ARMBuildAttrs::CPUArch::Pre_v4 }, - { "armv2", ARM::AK_ARMV2, "2", "v2", ARMBuildAttrs::CPUArch::Pre_v4 }, - { "armv2a", ARM::AK_ARMV2A, "2A", "v2a", ARMBuildAttrs::CPUArch::Pre_v4 }, - { "armv3", ARM::AK_ARMV3, "3", "v3", ARMBuildAttrs::CPUArch::Pre_v4 }, - { "armv3m", ARM::AK_ARMV3M, "3M", "v3m", ARMBuildAttrs::CPUArch::Pre_v4 }, - { "armv4", ARM::AK_ARMV4, "4", "v4", ARMBuildAttrs::CPUArch::v4 }, - { "armv4t", ARM::AK_ARMV4T, "4T", "v4t", ARMBuildAttrs::CPUArch::v4T }, - { "armv5t", ARM::AK_ARMV5T, "5T", "v5", ARMBuildAttrs::CPUArch::v5T }, - { "armv5te", ARM::AK_ARMV5TE, "5TE", "v5e", ARMBuildAttrs::CPUArch::v5TE }, - { "armv5tej", ARM::AK_ARMV5TEJ, "5TEJ", "v5e", ARMBuildAttrs::CPUArch::v5TEJ }, - { "armv6", ARM::AK_ARMV6, "6", "v6", ARMBuildAttrs::CPUArch::v6 }, - { "armv6k", ARM::AK_ARMV6K, "6K", "v6k", ARMBuildAttrs::CPUArch::v6K }, - { "armv6t2", ARM::AK_ARMV6T2, "6T2", "v6t2", ARMBuildAttrs::CPUArch::v6T2 }, - { "armv6z", ARM::AK_ARMV6Z, "6Z", "v6z", ARMBuildAttrs::CPUArch::v6KZ }, - { "armv6zk", ARM::AK_ARMV6ZK, "6ZK", "v6zk", ARMBuildAttrs::CPUArch::v6KZ }, - { "armv6-m", ARM::AK_ARMV6M, "6-M", "v6m", ARMBuildAttrs::CPUArch::v6_M }, - { "armv6s-m", ARM::AK_ARMV6SM, "6S-M", "v6sm", ARMBuildAttrs::CPUArch::v6S_M }, - { "armv7-a", ARM::AK_ARMV7A, "7-A", "v7", ARMBuildAttrs::CPUArch::v7 }, - { "armv7-r", ARM::AK_ARMV7R, "7-R", "v7r", ARMBuildAttrs::CPUArch::v7 }, - { "armv7-m", ARM::AK_ARMV7M, "7-M", "v7m", ARMBuildAttrs::CPUArch::v7 }, - { "armv7e-m", ARM::AK_ARMV7EM, "7E-M", "v7em", ARMBuildAttrs::CPUArch::v7E_M }, - { "armv8-a", ARM::AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8 }, - { "armv8.1-a", ARM::AK_ARMV8_1A, "8.1-A", "v8.1a", 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 }, - { "armv5", ARM::AK_ARMV5, "5T", "v5", ARMBuildAttrs::CPUArch::v5T }, - { "armv5e", ARM::AK_ARMV5E, "5TE", "v5e", ARMBuildAttrs::CPUArch::v5TE }, - { "armv6j", ARM::AK_ARMV6J, "6J", "v6", ARMBuildAttrs::CPUArch::v6 }, - { "armv6hl", ARM::AK_ARMV6HL, "6-M", "v6hl", ARMBuildAttrs::CPUArch::v6_M }, - { "armv7", ARM::AK_ARMV7, "7", "v7", ARMBuildAttrs::CPUArch::v7 }, - { "armv7l", ARM::AK_ARMV7L, "7-L", "v7l", ARMBuildAttrs::CPUArch::v7 }, - { "armv7hl", ARM::AK_ARMV7HL, "7-L", "v7hl", ARMBuildAttrs::CPUArch::v7 }, - { "armv7s", ARM::AK_ARMV7S, "7-S", "v7s", ARMBuildAttrs::CPUArch::v7 } +#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \ + {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \ + sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR}, +#include "llvm/Support/ARMTargetParser.def" }; + // List of Arch Extension names. // FIXME: TableGen this. -struct { - const char *Name; - ARM::ArchExtKind ID; +static const struct { + const char *NameCStr; + size_t NameLength; + unsigned ID; + const char *Feature; + const char *NegFeature; + + StringRef getName() const { return StringRef(NameCStr, NameLength); } } 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 }, - { "simd", ARM::AEK_SIMD }, - { "sec", ARM::AEK_SEC }, - { "virt", ARM::AEK_VIRT }, - { "os", ARM::AEK_OS }, - { "iwmmxt", ARM::AEK_IWMMXT }, - { "iwmmxt2", ARM::AEK_IWMMXT2 }, - { "maverick", ARM::AEK_MAVERICK }, - { "xscale", ARM::AEK_XSCALE } +#define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \ + { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE }, +#include "llvm/Support/ARMTargetParser.def" }; + +// List of HWDiv names (use getHWDivSynonym) and which architectural +// features they correspond to (use getHWDivFeatures). +// FIXME: TableGen this. +static const struct { + const char *NameCStr; + size_t NameLength; + unsigned ID; + + StringRef getName() const { return StringRef(NameCStr, NameLength); } +} HWDivNames[] = { +#define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID }, +#include "llvm/Support/ARMTargetParser.def" +}; + // 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. // When this becomes table-generated, we'd probably need two tables. // FIXME: TableGen this. -struct { - const char *Name; +static const struct { + const char *NameCStr; + size_t NameLength; ARM::ArchKind ArchID; - bool Default; + bool Default; // is $Name the default CPU for $ArchID ? + unsigned DefaultExtensions; + + StringRef getName() const { return StringRef(NameCStr, NameLength); } } CPUNames[] = { - { "arm2", ARM::AK_ARMV2, true }, - { "arm3", ARM::AK_ARMV2A, true }, - { "arm6", ARM::AK_ARMV3, true }, - { "arm7m", ARM::AK_ARMV3M, true }, - { "arm8", ARM::AK_ARMV4, false }, - { "arm810", ARM::AK_ARMV4, false }, - { "strongarm", ARM::AK_ARMV4, true }, - { "strongarm110", ARM::AK_ARMV4, false }, - { "strongarm1100", ARM::AK_ARMV4, false }, - { "strongarm1110", ARM::AK_ARMV4, false }, - { "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_ARMV5T, true }, - { "arm1020t", ARM::AK_ARMV5T, false }, - { "arm9e", ARM::AK_ARMV5TE, false }, - { "arm946e-s", ARM::AK_ARMV5TE, false }, - { "arm966e-s", ARM::AK_ARMV5TE, false }, - { "arm968e-s", ARM::AK_ARMV5TE, false }, - { "arm10e", ARM::AK_ARMV5TE, false }, - { "arm1020e", ARM::AK_ARMV5TE, false }, - { "arm1022e", ARM::AK_ARMV5TE, true }, - { "iwmmxt", ARM::AK_ARMV5TE, false }, - { "xscale", ARM::AK_ARMV5TE, false }, - { "arm926ej-s", ARM::AK_ARMV5TEJ, true }, - { "arm1136jf-s", ARM::AK_ARMV6, true }, - { "arm1176j-s", ARM::AK_ARMV6K, false }, - { "arm1176jz-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-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_ARMV7EM, true }, - { "cortex-m7", ARM::AK_ARMV7EM, 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. - { "iwmmxt", ARM::AK_IWMMXT, true }, - { "xscale", ARM::AK_XSCALE, true }, - { "arm10tdmi", ARM::AK_ARMV5, true }, - { "arm1022e", ARM::AK_ARMV5E, true }, - { "arm1136j-s", ARM::AK_ARMV6J, true }, - { "arm1136jz-s", ARM::AK_ARMV6J, false }, - { "cortex-m0", ARM::AK_ARMV6SM, true }, - { "arm1176jzf-s", ARM::AK_ARMV6HL, true }, - { "cortex-a8", ARM::AK_ARMV7, 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 } +#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ + { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT }, +#include "llvm/Support/ARMTargetParser.def" }; } // namespace @@ -233,33 +132,93 @@ struct { // Information by ID // ======================================================= // -const char *ARMTargetParser::getFPUName(unsigned FPUKind) { +StringRef llvm::ARM::getFPUName(unsigned FPUKind) { if (FPUKind >= ARM::FK_LAST) - return nullptr; - return FPUNames[FPUKind].Name; + return StringRef(); + return FPUNames[FPUKind].getName(); } -unsigned ARMTargetParser::getFPUVersion(unsigned FPUKind) { +unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) { if (FPUKind >= ARM::FK_LAST) return 0; return FPUNames[FPUKind].FPUVersion; } -unsigned ARMTargetParser::getFPUNeonSupportLevel(unsigned FPUKind) { +unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) { if (FPUKind >= ARM::FK_LAST) return 0; return FPUNames[FPUKind].NeonSupport; } -unsigned ARMTargetParser::getFPURestriction(unsigned FPUKind) { +unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) { if (FPUKind >= ARM::FK_LAST) return 0; return FPUNames[FPUKind].Restriction; } -bool ARMTargetParser::getFPUFeatures(unsigned FPUKind, +unsigned llvm::ARM::getDefaultFPU(StringRef CPU, unsigned ArchKind) { + if (CPU == "generic") + return ARCHNames[ArchKind].DefaultFPU; + + return StringSwitch<unsigned>(CPU) +#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ + .Case(NAME, DEFAULT_FPU) +#include "llvm/Support/ARMTargetParser.def" + .Default(ARM::FK_INVALID); +} + +unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, unsigned ArchKind) { + if (CPU == "generic") + return ARCHNames[ArchKind].ArchBaseExtensions; + + return StringSwitch<unsigned>(CPU) +#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ + .Case(NAME, ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT) +#include "llvm/Support/ARMTargetParser.def" + .Default(ARM::AEK_INVALID); +} + +bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind, + std::vector<const char *> &Features) { + + if (HWDivKind == ARM::AEK_INVALID) + return false; + + if (HWDivKind & ARM::AEK_HWDIVARM) + Features.push_back("+hwdiv-arm"); + else + Features.push_back("-hwdiv-arm"); + + if (HWDivKind & ARM::AEK_HWDIV) + Features.push_back("+hwdiv"); + else + Features.push_back("-hwdiv"); + + return true; +} + +bool llvm::ARM::getExtensionFeatures(unsigned Extensions, std::vector<const char *> &Features) { + if (Extensions == ARM::AEK_INVALID) + return false; + + if (Extensions & ARM::AEK_CRC) + Features.push_back("+crc"); + else + Features.push_back("-crc"); + + if (Extensions & ARM::AEK_DSP) + Features.push_back("+dsp"); + else + Features.push_back("-dsp"); + + return getHWDivFeatures(Extensions, Features); +} + +bool llvm::ARM::getFPUFeatures(unsigned FPUKind, + std::vector<const char *> &Features) { + if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID) return false; @@ -323,6 +282,7 @@ bool ARMTargetParser::getFPUFeatures(unsigned FPUKind, // crypto includes neon, so we handle this similarly to FPU version. switch (FPUNames[FPUKind].NeonSupport) { case ARM::NS_Crypto: + Features.push_back("+neon"); Features.push_back("+crypto"); break; case ARM::NS_Neon: @@ -338,88 +298,127 @@ bool ARMTargetParser::getFPUFeatures(unsigned FPUKind, return true; } -const char *ARMTargetParser::getArchName(unsigned ArchKind) { +StringRef llvm::ARM::getArchName(unsigned ArchKind) { if (ArchKind >= ARM::AK_LAST) - return nullptr; - return ARCHNames[ArchKind].Name; + return StringRef(); + return ARCHNames[ArchKind].getName(); } -const char *ARMTargetParser::getCPUAttr(unsigned ArchKind) { +StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) { if (ArchKind >= ARM::AK_LAST) - return nullptr; - return ARCHNames[ArchKind].CPUAttr; + return StringRef(); + return ARCHNames[ArchKind].getCPUAttr(); } -const char *ARMTargetParser::getSubArch(unsigned ArchKind) { +StringRef llvm::ARM::getSubArch(unsigned ArchKind) { if (ArchKind >= ARM::AK_LAST) - return nullptr; - return ARCHNames[ArchKind].SubArch; + return StringRef(); + return ARCHNames[ArchKind].getSubArch(); } -unsigned ARMTargetParser::getArchAttr(unsigned ArchKind) { +unsigned llvm::ARM::getArchAttr(unsigned ArchKind) { if (ArchKind >= ARM::AK_LAST) return ARMBuildAttrs::CPUArch::Pre_v4; return ARCHNames[ArchKind].ArchAttr; } -const char *ARMTargetParser::getArchExtName(unsigned ArchExtKind) { - if (ArchExtKind >= ARM::AEK_LAST) - return nullptr; - return ARCHExtNames[ArchExtKind].Name; +StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) { + for (const auto AE : ARCHExtNames) { + if (ArchExtKind == AE.ID) + return AE.getName(); + } + return StringRef(); } -const char *ARMTargetParser::getDefaultCPU(StringRef Arch) { +const char *llvm::ARM::getArchExtFeature(StringRef ArchExt) { + if (ArchExt.startswith("no")) { + StringRef ArchExtBase(ArchExt.substr(2)); + for (const auto AE : ARCHExtNames) { + if (AE.NegFeature && ArchExtBase == AE.getName()) + return AE.NegFeature; + } + } + for (const auto AE : ARCHExtNames) { + if (AE.Feature && ArchExt == AE.getName()) + return AE.Feature; + } + + return nullptr; +} + +StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) { + for (const auto D : HWDivNames) { + if (HWDivKind == D.ID) + return D.getName(); + } + return StringRef(); +} + +StringRef llvm::ARM::getDefaultCPU(StringRef Arch) { unsigned AK = parseArch(Arch); if (AK == ARM::AK_INVALID) - return nullptr; + return StringRef(); // 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 CPU.getName(); } - return nullptr; + + // If we can't find a default then target the architecture instead + return "generic"; } // ======================================================= // // Parsers // ======================================================= // -StringRef ARMTargetParser::getFPUSynonym(StringRef FPU) { +static StringRef getHWDivSynonym(StringRef HWDiv) { + return StringSwitch<StringRef>(HWDiv) + .Case("thumb,arm", "arm,thumb") + .Default(HWDiv); +} + +static StringRef 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") - .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16") - .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") - .Case("fp5-sp-d16", "fpv5-sp-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); + .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") + .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16") + .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") + .Case("fp5-sp-d16", "fpv5-sp-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) { +static StringRef getArchSynonym(StringRef Arch) { return StringSwitch<StringRef>(Arch) - .Case("v6sm", "v6s-m") - .Case("v6m", "v6-m") - .Case("v7a", "v7-a") - .Case("v7r", "v7-r") - .Case("v7m", "v7-m") - .Case("v7em", "v7e-m") - .Cases("v8", "v8a", "aarch64", "arm64", "v8-a") - .Case("v8.1a", "v8.1-a") - .Default(Arch); + .Case("v5", "v5t") + .Case("v5e", "v5te") + .Case("v6j", "v6") + .Case("v6hl", "v6k") + .Cases("v6m", "v6sm", "v6s-m", "v6-m") + .Cases("v6z", "v6zk", "v6kz") + .Cases("v7", "v7a", "v7hl", "v7l", "v7-a") + .Case("v7r", "v7-r") + .Case("v7m", "v7-m") + .Case("v7em", "v7e-m") + .Cases("v8", "v8a", "aarch64", "arm64", "v8-a") + .Case("v8.1a", "v8.1-a") + .Case("v8.2a", "v8.2-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) { +StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) { size_t offset = StringRef::npos; StringRef A = Arch; StringRef Error = ""; @@ -436,7 +435,7 @@ StringRef ARMTargetParser::getCanonicalArchName(StringRef Arch) { // AArch64 uses "_be", not "eb" suffix. if (A.find("eb") != StringRef::npos) return Error; - if (A.substr(offset,3) == "_be") + if (A.substr(offset, 3) == "_be") offset += 3; } @@ -456,7 +455,7 @@ StringRef ARMTargetParser::getCanonicalArchName(StringRef Arch) { // Only match non-marketing names if (offset != StringRef::npos) { - // Must start with 'vN'. + // Must start with 'vN'. if (A[0] != 'v' || !std::isdigit(A[1])) return Error; // Can't have an extra 'eb'. @@ -468,56 +467,64 @@ StringRef ARMTargetParser::getCanonicalArchName(StringRef Arch) { return A; } -unsigned ARMTargetParser::parseFPU(StringRef FPU) { +unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) { + StringRef Syn = getHWDivSynonym(HWDiv); + for (const auto D : HWDivNames) { + if (Syn == D.getName()) + return D.ID; + } + return ARM::AEK_INVALID; +} + +unsigned llvm::ARM::parseFPU(StringRef FPU) { StringRef Syn = getFPUSynonym(FPU); for (const auto F : FPUNames) { - if (Syn == F.Name) + if (Syn == F.getName()) return F.ID; } return ARM::FK_INVALID; } // Allows partial match, ex. "v7a" matches "armv7a". -unsigned ARMTargetParser::parseArch(StringRef Arch) { +unsigned llvm::ARM::parseArch(StringRef Arch) { Arch = getCanonicalArchName(Arch); StringRef Syn = getArchSynonym(Arch); for (const auto A : ARCHNames) { - if (StringRef(A.Name).endswith(Syn)) + if (A.getName().endswith(Syn)) return A.ID; } return ARM::AK_INVALID; } -unsigned ARMTargetParser::parseArchExt(StringRef ArchExt) { +unsigned llvm::ARM::parseArchExt(StringRef ArchExt) { for (const auto A : ARCHExtNames) { - if (ArchExt == A.Name) + if (ArchExt == A.getName()) return A.ID; } return ARM::AEK_INVALID; } -unsigned ARMTargetParser::parseCPUArch(StringRef CPU) { +unsigned llvm::ARM::parseCPUArch(StringRef CPU) { for (const auto C : CPUNames) { - if (CPU == C.Name) + if (CPU == C.getName()) return C.ArchID; } return ARM::AK_INVALID; } // ARM, Thumb, AArch64 -unsigned ARMTargetParser::parseArchISA(StringRef Arch) { +unsigned llvm::ARM::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) + .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") || +unsigned llvm::ARM::parseArchEndian(StringRef Arch) { + if (Arch.startswith("armeb") || Arch.startswith("thumbeb") || Arch.startswith("aarch64_be")) return ARM::EK_BIG; @@ -535,29 +542,29 @@ unsigned ARMTargetParser::parseArchEndian(StringRef Arch) { } // Profile A/R/M -unsigned ARMTargetParser::parseArchProfile(StringRef Arch) { +unsigned llvm::ARM::parseArchProfile(StringRef Arch) { Arch = getCanonicalArchName(Arch); - switch(parseArch(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_ARMV7K: case ARM::AK_ARMV8A: case ARM::AK_ARMV8_1A: + case ARM::AK_ARMV8_2A: return ARM::PK_A; } return ARM::PK_INVALID; } // Version number (ex. v7 = 7). -unsigned ARMTargetParser::parseArchVersion(StringRef Arch) { +unsigned llvm::ARM::parseArchVersion(StringRef Arch) { Arch = getCanonicalArchName(Arch); - switch(parseArch(Arch)) { + switch (parseArch(Arch)) { case ARM::AK_ARMV2: case ARM::AK_ARMV2A: return 2; @@ -567,36 +574,29 @@ unsigned ARMTargetParser::parseArchVersion(StringRef Arch) { 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_ARMV6KZ: 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: + case ARM::AK_ARMV7K: return 7; case ARM::AK_ARMV8A: case ARM::AK_ARMV8_1A: + case ARM::AK_ARMV8_2A: return 8; } return 0; diff --git a/contrib/llvm/lib/Support/ThreadPool.cpp b/contrib/llvm/lib/Support/ThreadPool.cpp new file mode 100644 index 0000000..d4dcb2e --- /dev/null +++ b/contrib/llvm/lib/Support/ThreadPool.cpp @@ -0,0 +1,155 @@ +//==-- llvm/Support/ThreadPool.cpp - A ThreadPool 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 a crude C++11 based thread pool. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ThreadPool.h" + +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +#if LLVM_ENABLE_THREADS + +// Default to std::thread::hardware_concurrency +ThreadPool::ThreadPool() : ThreadPool(std::thread::hardware_concurrency()) {} + +ThreadPool::ThreadPool(unsigned ThreadCount) + : ActiveThreads(0), EnableFlag(true) { + // Create ThreadCount threads that will loop forever, wait on QueueCondition + // for tasks to be queued or the Pool to be destroyed. + Threads.reserve(ThreadCount); + for (unsigned ThreadID = 0; ThreadID < ThreadCount; ++ThreadID) { + Threads.emplace_back([&] { + while (true) { + PackagedTaskTy Task; + { + std::unique_lock<std::mutex> LockGuard(QueueLock); + // Wait for tasks to be pushed in the queue + QueueCondition.wait(LockGuard, + [&] { return !EnableFlag || !Tasks.empty(); }); + // Exit condition + if (!EnableFlag && Tasks.empty()) + return; + // Yeah, we have a task, grab it and release the lock on the queue + + // We first need to signal that we are active before popping the queue + // in order for wait() to properly detect that even if the queue is + // empty, there is still a task in flight. + { + ++ActiveThreads; + std::unique_lock<std::mutex> LockGuard(CompletionLock); + } + Task = std::move(Tasks.front()); + Tasks.pop(); + } + // Run the task we just grabbed +#ifndef _MSC_VER + Task(); +#else + Task(/* unused */ false); +#endif + + { + // Adjust `ActiveThreads`, in case someone waits on ThreadPool::wait() + std::unique_lock<std::mutex> LockGuard(CompletionLock); + --ActiveThreads; + } + + // Notify task completion, in case someone waits on ThreadPool::wait() + CompletionCondition.notify_all(); + } + }); + } +} + +void ThreadPool::wait() { + // Wait for all threads to complete and the queue to be empty + std::unique_lock<std::mutex> LockGuard(CompletionLock); + CompletionCondition.wait(LockGuard, + [&] { return Tasks.empty() && !ActiveThreads; }); +} + +std::shared_future<ThreadPool::VoidTy> ThreadPool::asyncImpl(TaskTy Task) { + /// Wrap the Task in a packaged_task to return a future object. + PackagedTaskTy PackagedTask(std::move(Task)); + auto Future = PackagedTask.get_future(); + { + // Lock the queue and push the new task + std::unique_lock<std::mutex> LockGuard(QueueLock); + + // Don't allow enqueueing after disabling the pool + assert(EnableFlag && "Queuing a thread during ThreadPool destruction"); + + Tasks.push(std::move(PackagedTask)); + } + QueueCondition.notify_one(); + return Future.share(); +} + +// The destructor joins all threads, waiting for completion. +ThreadPool::~ThreadPool() { + { + std::unique_lock<std::mutex> LockGuard(QueueLock); + EnableFlag = false; + } + QueueCondition.notify_all(); + for (auto &Worker : Threads) + Worker.join(); +} + +#else // LLVM_ENABLE_THREADS Disabled + +ThreadPool::ThreadPool() : ThreadPool(0) {} + +// No threads are launched, issue a warning if ThreadCount is not 0 +ThreadPool::ThreadPool(unsigned ThreadCount) + : ActiveThreads(0) { + if (ThreadCount) { + errs() << "Warning: request a ThreadPool with " << ThreadCount + << " threads, but LLVM_ENABLE_THREADS has been turned off\n"; + } +} + +void ThreadPool::wait() { + // Sequential implementation running the tasks + while (!Tasks.empty()) { + auto Task = std::move(Tasks.front()); + Tasks.pop(); +#ifndef _MSC_VER + Task(); +#else + Task(/* unused */ false); +#endif + } +} + +std::shared_future<ThreadPool::VoidTy> ThreadPool::asyncImpl(TaskTy Task) { +#ifndef _MSC_VER + // Get a Future with launch::deferred execution using std::async + auto Future = std::async(std::launch::deferred, std::move(Task)).share(); + // Wrap the future so that both ThreadPool::wait() can operate and the + // returned future can be sync'ed on. + PackagedTaskTy PackagedTask([Future]() { Future.get(); }); +#else + auto Future = std::async(std::launch::deferred, std::move(Task), false).share(); + PackagedTaskTy PackagedTask([Future](bool) -> bool { Future.get(); return false; }); +#endif + Tasks.push(std::move(PackagedTask)); + return Future; +} + +ThreadPool::~ThreadPool() { + wait(); +} + +#endif diff --git a/contrib/llvm/lib/Support/TimeValue.cpp b/contrib/llvm/lib/Support/TimeValue.cpp index 136b93e..94a4c01 100644 --- a/contrib/llvm/lib/Support/TimeValue.cpp +++ b/contrib/llvm/lib/Support/TimeValue.cpp @@ -15,6 +15,7 @@ #include "llvm/Config/config.h" namespace llvm { + using namespace sys; const TimeValue::SecondsType @@ -22,8 +23,7 @@ const TimeValue::SecondsType const TimeValue::SecondsType TimeValue::Win32ZeroTimeSeconds = -12591158400ULL; -void -TimeValue::normalize( void ) { +void TimeValue::normalize() { if ( nanos_ >= NANOSECONDS_PER_SECOND ) { do { seconds_++; @@ -45,7 +45,7 @@ TimeValue::normalize( void ) { } } -} +} // namespace llvm /// Include the platform-specific portion of TimeValue class #ifdef LLVM_ON_UNIX diff --git a/contrib/llvm/lib/Support/Timer.cpp b/contrib/llvm/lib/Support/Timer.cpp index d7b6515..414f559 100644 --- a/contrib/llvm/lib/Support/Timer.cpp +++ b/contrib/llvm/lib/Support/Timer.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Timer.h" +#include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" @@ -22,9 +23,6 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; -// CreateInfoOutputFile - Return a file stream to print our output on. -namespace llvm { extern raw_ostream *CreateInfoOutputFile(); } - // getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy // of constructor/destructor ordering being unspecified by C++. Basically the // problem is that a Statistic object gets destroyed, which ends up calling @@ -52,28 +50,27 @@ namespace { cl::Hidden, cl::location(getLibSupportInfoOutputFilename())); } -// CreateInfoOutputFile - Return a file stream to print our output on. -raw_ostream *llvm::CreateInfoOutputFile() { +// Return a file stream to print our output on. +std::unique_ptr<raw_fd_ostream> llvm::CreateInfoOutputFile() { const std::string &OutputFilename = getLibSupportInfoOutputFilename(); if (OutputFilename.empty()) - return new raw_fd_ostream(2, false); // stderr. + return llvm::make_unique<raw_fd_ostream>(2, false); // stderr. if (OutputFilename == "-") - return new raw_fd_ostream(1, false); // stdout. - + return llvm::make_unique<raw_fd_ostream>(1, false); // stdout. + // Append mode is used because the info output file is opened and closed // each time -stats or -time-passes wants to print output to it. To // compensate for this, the test-suite Makefiles have code to delete the // info output file before running commands which write to it. std::error_code EC; - raw_ostream *Result = new raw_fd_ostream(OutputFilename, EC, - sys::fs::F_Append | sys::fs::F_Text); + auto Result = llvm::make_unique<raw_fd_ostream>( + OutputFilename, EC, sys::fs::F_Append | sys::fs::F_Text); if (!EC) return Result; - + errs() << "Error opening info-output-file '" << OutputFilename << " for appending!\n"; - delete Result; - return new raw_fd_ostream(2, false); // stderr. + return llvm::make_unique<raw_fd_ostream>(2, false); // stderr. } @@ -99,17 +96,13 @@ static TimerGroup *getDefaultTimerGroup() { //===----------------------------------------------------------------------===// void Timer::init(StringRef N) { - assert(!TG && "Timer already initialized"); - Name.assign(N.begin(), N.end()); - Started = false; - TG = getDefaultTimerGroup(); - TG->addTimer(*this); + init(N, *getDefaultTimerGroup()); } void Timer::init(StringRef N, TimerGroup &tg) { assert(!TG && "Timer already initialized"); Name.assign(N.begin(), N.end()); - Started = false; + Running = Triggered = false; TG = &tg; TG->addTimer(*this); } @@ -142,25 +135,22 @@ TimeRecord TimeRecord::getCurrentTime(bool Start) { return Result; } -static ManagedStatic<std::vector<Timer*> > ActiveTimers; - void Timer::startTimer() { - Started = true; - ActiveTimers->push_back(this); - Time -= TimeRecord::getCurrentTime(true); + assert(!Running && "Cannot start a running timer"); + Running = Triggered = true; + StartTime = TimeRecord::getCurrentTime(true); } void Timer::stopTimer() { + assert(Running && "Cannot stop a paused timer"); + Running = false; Time += TimeRecord::getCurrentTime(false); + Time -= StartTime; +} - if (ActiveTimers->back() == this) { - ActiveTimers->pop_back(); - } else { - std::vector<Timer*>::iterator I = - std::find(ActiveTimers->begin(), ActiveTimers->end(), this); - assert(I != ActiveTimers->end() && "stop but no startTimer?"); - ActiveTimers->erase(I); - } +void Timer::clear() { + Running = Triggered = false; + Time = StartTime = TimeRecord(); } static void printVal(double Val, double Total, raw_ostream &OS) { @@ -278,8 +268,8 @@ void TimerGroup::removeTimer(Timer &T) { sys::SmartScopedLock<true> L(*TimerLock); // If the timer was started, move its data to TimersToPrint. - if (T.Started) - TimersToPrint.push_back(std::make_pair(T.Time, T.Name)); + if (T.hasTriggered()) + TimersToPrint.emplace_back(T.Time, T.Name); T.TG = nullptr; @@ -292,10 +282,9 @@ void TimerGroup::removeTimer(Timer &T) { // them were started. if (FirstTimer || TimersToPrint.empty()) return; - - raw_ostream *OutStream = CreateInfoOutputFile(); + + std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile(); PrintQueuedTimers(*OutStream); - delete OutStream; // Close the file. } void TimerGroup::addTimer(Timer &T) { @@ -314,8 +303,8 @@ void TimerGroup::PrintQueuedTimers(raw_ostream &OS) { std::sort(TimersToPrint.begin(), TimersToPrint.end()); TimeRecord Total; - for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) - Total += TimersToPrint[i].first; + for (auto &RecordNamePair : TimersToPrint) + Total += RecordNamePair.first; // Print out timing header. OS << "===" << std::string(73, '-') << "===\n"; @@ -365,12 +354,11 @@ void TimerGroup::print(raw_ostream &OS) { // See if any of our timers were started, if so add them to TimersToPrint and // reset them. for (Timer *T = FirstTimer; T; T = T->Next) { - if (!T->Started) continue; - TimersToPrint.push_back(std::make_pair(T->Time, T->Name)); + if (!T->hasTriggered()) continue; + TimersToPrint.emplace_back(T->Time, T->Name); // Clear out the time. - T->Started = 0; - T->Time = TimeRecord(); + T->clear(); } // If any timers were started, print the group. diff --git a/contrib/llvm/lib/Support/Triple.cpp b/contrib/llvm/lib/Support/Triple.cpp index c6646fb..3bb1116 100644 --- a/contrib/llvm/lib/Support/Triple.cpp +++ b/contrib/llvm/lib/Support/Triple.cpp @@ -25,6 +25,7 @@ const char *Triple::getArchTypeName(ArchType Kind) { case aarch64_be: return "aarch64_be"; case arm: return "arm"; case armeb: return "armeb"; + case avr: return "avr"; case bpfel: return "bpfel"; case bpfeb: return "bpfeb"; case hexagon: return "hexagon"; @@ -80,6 +81,8 @@ const char *Triple::getArchTypePrefix(ArchType Kind) { case thumb: case thumbeb: return "arm"; + case avr: return "avr"; + case ppc64: case ppc64le: case ppc: return "ppc"; @@ -124,8 +127,8 @@ const char *Triple::getArchTypePrefix(ArchType Kind) { case spir64: return "spir"; case kalimba: return "kalimba"; case shave: return "shave"; - case wasm32: return "wasm32"; - case wasm64: return "wasm64"; + case wasm32: + case wasm64: return "wasm"; } } @@ -144,6 +147,7 @@ const char *Triple::getVendorTypeName(VendorType Kind) { case MipsTechnologies: return "mti"; case NVIDIA: return "nvidia"; case CSR: return "csr"; + case Myriad: return "myriad"; } llvm_unreachable("Invalid VendorType!"); @@ -177,6 +181,9 @@ const char *Triple::getOSTypeName(OSType Kind) { case NVCL: return "nvcl"; case AMDHSA: return "amdhsa"; case PS4: return "ps4"; + case ELFIAMCU: return "elfiamcu"; + case TvOS: return "tvos"; + case WatchOS: return "watchos"; } llvm_unreachable("Invalid OSType"); @@ -196,6 +203,8 @@ const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) { case MSVC: return "msvc"; case Itanium: return "itanium"; case Cygnus: return "cygnus"; + case AMDOpenCL: return "amdopencl"; + case CoreCLR: return "coreclr"; } llvm_unreachable("Invalid EnvironmentType!"); @@ -224,6 +233,7 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { .Case("arm64", aarch64) // "arm64" is an alias for "aarch64" .Case("arm", arm) .Case("armeb", armeb) + .Case("avr", avr) .StartsWith("bpf", BPFArch) .Case("mips", mips) .Case("mipsel", mipsel) @@ -265,8 +275,8 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { } static Triple::ArchType parseARMArch(StringRef ArchName) { - unsigned ISA = ARMTargetParser::parseArchISA(ArchName); - unsigned ENDIAN = ARMTargetParser::parseArchEndian(ArchName); + unsigned ISA = ARM::parseArchISA(ArchName); + unsigned ENDIAN = ARM::parseArchEndian(ArchName); Triple::ArchType arch = Triple::UnknownArch; switch (ENDIAN) { @@ -300,7 +310,7 @@ static Triple::ArchType parseARMArch(StringRef ArchName) { } } - ArchName = ARMTargetParser::getCanonicalArchName(ArchName); + ArchName = ARM::getCanonicalArchName(ArchName); if (ArchName.empty()) return Triple::UnknownArch; @@ -310,8 +320,8 @@ static Triple::ArchType parseARMArch(StringRef ArchName) { return Triple::UnknownArch; // Thumb only for v6m - unsigned Profile = ARMTargetParser::parseArchProfile(ArchName); - unsigned Version = ARMTargetParser::parseArchVersion(ArchName); + unsigned Profile = ARM::parseArchProfile(ArchName); + unsigned Version = ARM::parseArchVersion(ArchName); if (Profile == ARM::PK_M && Version == 6) { if (ENDIAN == ARM::EK_BIG) return Triple::thumbeb; @@ -323,10 +333,7 @@ static Triple::ArchType parseARMArch(StringRef ArchName) { } static Triple::ArchType parseArch(StringRef ArchName) { - Triple::ArchType ARMArch(parseARMArch(ArchName)); - Triple::ArchType BPFArch(parseBPFArch(ArchName)); - - return StringSwitch<Triple::ArchType>(ArchName) + auto AT = StringSwitch<Triple::ArchType>(ArchName) .Cases("i386", "i486", "i586", "i686", Triple::x86) // FIXME: Do we need to support these? .Cases("i786", "i886", "i986", Triple::x86) @@ -336,9 +343,14 @@ static Triple::ArchType parseArch(StringRef ArchName) { .Case("powerpc64le", Triple::ppc64le) .Case("xscale", Triple::arm) .Case("xscaleeb", Triple::armeb) - .StartsWith("arm", ARMArch) - .StartsWith("thumb", ARMArch) - .StartsWith("aarch64", ARMArch) + .Case("aarch64", Triple::aarch64) + .Case("aarch64_be", Triple::aarch64_be) + .Case("arm64", Triple::aarch64) + .Case("arm", Triple::arm) + .Case("armeb", Triple::armeb) + .Case("thumb", Triple::thumb) + .Case("thumbeb", Triple::thumbeb) + .Case("avr", Triple::avr) .Case("msp430", Triple::msp430) .Cases("mips", "mipseb", "mipsallegrex", Triple::mips) .Cases("mipsel", "mipsallegrexel", Triple::mipsel) @@ -346,7 +358,6 @@ static Triple::ArchType parseArch(StringRef ArchName) { .Case("mips64el", Triple::mips64el) .Case("r600", Triple::r600) .Case("amdgcn", Triple::amdgcn) - .StartsWith("bpf", BPFArch) .Case("hexagon", Triple::hexagon) .Case("s390x", Triple::systemz) .Case("sparc", Triple::sparc) @@ -369,6 +380,18 @@ static Triple::ArchType parseArch(StringRef ArchName) { .Case("wasm32", Triple::wasm32) .Case("wasm64", Triple::wasm64) .Default(Triple::UnknownArch); + + // Some architectures require special parsing logic just to compute the + // ArchType result. + if (AT == Triple::UnknownArch) { + if (ArchName.startswith("arm") || ArchName.startswith("thumb") || + ArchName.startswith("aarch64")) + return parseARMArch(ArchName); + if (ArchName.startswith("bpf")) + return parseBPFArch(ArchName); + } + + return AT; } static Triple::VendorType parseVendor(StringRef VendorName) { @@ -384,6 +407,7 @@ static Triple::VendorType parseVendor(StringRef VendorName) { .Case("mti", Triple::MipsTechnologies) .Case("nvidia", Triple::NVIDIA) .Case("csr", Triple::CSR) + .Case("myriad", Triple::Myriad) .Default(Triple::UnknownVendor); } @@ -414,6 +438,9 @@ static Triple::OSType parseOS(StringRef OSName) { .StartsWith("nvcl", Triple::NVCL) .StartsWith("amdhsa", Triple::AMDHSA) .StartsWith("ps4", Triple::PS4) + .StartsWith("elfiamcu", Triple::ELFIAMCU) + .StartsWith("tvos", Triple::TvOS) + .StartsWith("watchos", Triple::WatchOS) .Default(Triple::UnknownOS); } @@ -430,6 +457,8 @@ static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) { .StartsWith("msvc", Triple::MSVC) .StartsWith("itanium", Triple::Itanium) .StartsWith("cygnus", Triple::Cygnus) + .StartsWith("amdopencl", Triple::AMDOpenCL) + .StartsWith("coreclr", Triple::CoreCLR) .Default(Triple::UnknownEnvironment); } @@ -442,7 +471,7 @@ static Triple::ObjectFormatType parseFormat(StringRef EnvironmentName) { } static Triple::SubArchType parseSubArch(StringRef SubArchName) { - StringRef ARMSubArch = ARMTargetParser::getCanonicalArchName(SubArchName); + StringRef ARMSubArch = ARM::getCanonicalArchName(SubArchName); // For now, this is the small part. Early return. if (ARMSubArch.empty()) @@ -453,14 +482,12 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) { .Default(Triple::NoSubArch); // ARM sub arch. - switch(ARMTargetParser::parseArch(ARMSubArch)) { + switch(ARM::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: @@ -469,24 +496,19 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) { 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: + case ARM::AK_ARMV6KZ: 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_ARMV7K: + return Triple::ARMSubArch_v7k; case ARM::AK_ARMV7M: return Triple::ARMSubArch_v7m; case ARM::AK_ARMV7S: @@ -497,6 +519,8 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) { return Triple::ARMSubArch_v8; case ARM::AK_ARMV8_1A: return Triple::ARMSubArch_v8_1a; + case ARM::AK_ARMV8_2A: + return Triple::ARMSubArch_v8_2a; default: return Triple::NoSubArch; } @@ -514,20 +538,53 @@ static const char *getObjectFormatTypeName(Triple::ObjectFormatType Kind) { static Triple::ObjectFormatType getDefaultFormat(const Triple &T) { switch (T.getArch()) { - default: - break; + case Triple::UnknownArch: + case Triple::aarch64: + case Triple::arm: + case Triple::thumb: + case Triple::x86: + case Triple::x86_64: + if (T.isOSDarwin()) + return Triple::MachO; + else if (T.isOSWindows()) + return Triple::COFF; + return Triple::ELF; + + case Triple::aarch64_be: + case Triple::amdgcn: + case Triple::amdil: + case Triple::amdil64: + case Triple::armeb: + case Triple::avr: + case Triple::bpfeb: + case Triple::bpfel: case Triple::hexagon: + case Triple::hsail: + case Triple::hsail64: + case Triple::kalimba: + case Triple::le32: + case Triple::le64: case Triple::mips: - case Triple::mipsel: case Triple::mips64: case Triple::mips64el: + case Triple::mipsel: + case Triple::msp430: + case Triple::nvptx: + case Triple::nvptx64: + case Triple::ppc64le: case Triple::r600: - case Triple::amdgcn: + case Triple::shave: case Triple::sparc: + case Triple::sparcel: case Triple::sparcv9: + case Triple::spir: + case Triple::spir64: case Triple::systemz: + case Triple::tce: + case Triple::thumbeb: + case Triple::wasm32: + case Triple::wasm64: case Triple::xcore: - case Triple::ppc64le: return Triple::ELF; case Triple::ppc: @@ -536,12 +593,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) { return Triple::MachO; return Triple::ELF; } - - if (T.isOSDarwin()) - return Triple::MachO; - else if (T.isOSWindows()) - return Triple::COFF; - return Triple::ELF; + llvm_unreachable("unknown architecture"); } /// \brief Construct a triple from the string representation provided. @@ -549,14 +601,27 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) { /// This stores the string representation and parses the various pieces into /// enum members. Triple::Triple(const Twine &Str) - : Data(Str.str()), - Arch(parseArch(getArchName())), - SubArch(parseSubArch(getArchName())), - Vendor(parseVendor(getVendorName())), - OS(parseOS(getOSName())), - Environment(parseEnvironment(getEnvironmentName())), - ObjectFormat(parseFormat(getEnvironmentName())) { - if (ObjectFormat == Triple::UnknownObjectFormat) + : Data(Str.str()), Arch(UnknownArch), SubArch(NoSubArch), + Vendor(UnknownVendor), OS(UnknownOS), Environment(UnknownEnvironment), + ObjectFormat(UnknownObjectFormat) { + // Do minimal parsing by hand here. + SmallVector<StringRef, 4> Components; + StringRef(Data).split(Components, '-', /*MaxSplit*/ 3); + if (Components.size() > 0) { + Arch = parseArch(Components[0]); + SubArch = parseSubArch(Components[0]); + if (Components.size() > 1) { + Vendor = parseVendor(Components[1]); + if (Components.size() > 2) { + OS = parseOS(Components[2]); + if (Components.size() > 3) { + Environment = parseEnvironment(Components[3]); + ObjectFormat = parseFormat(Components[3]); + } + } + } + } + if (ObjectFormat == UnknownObjectFormat) ObjectFormat = getDefaultFormat(*this); } @@ -601,7 +666,7 @@ std::string Triple::normalize(StringRef Str) { // Parse into components. SmallVector<StringRef, 4> Components; - Str.split(Components, "-"); + Str.split(Components, '-'); // If the first component corresponds to a known architecture, preferentially // use it for the architecture. If the second component corresponds to a @@ -889,6 +954,8 @@ bool Triple::getMacOSXVersion(unsigned &Major, unsigned &Minor, return false; break; case IOS: + case TvOS: + case WatchOS: // Ignore the version from the triple. This is only handled because the // the clang driver combines OS X and IOS support into a common Darwin // toolchain that wants to know the OS X version number even when targeting @@ -916,11 +983,38 @@ void Triple::getiOSVersion(unsigned &Major, unsigned &Minor, Micro = 0; break; case IOS: + case TvOS: getOSVersion(Major, Minor, Micro); // Default to 5.0 (or 7.0 for arm64). if (Major == 0) Major = (getArch() == aarch64) ? 7 : 5; break; + case WatchOS: + llvm_unreachable("conflicting triple info"); + } +} + +void Triple::getWatchOSVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const { + switch (getOS()) { + default: llvm_unreachable("unexpected OS for Darwin triple"); + case Darwin: + case MacOSX: + // Ignore the version from the triple. This is only handled because the + // the clang driver combines OS X and IOS support into a common Darwin + // toolchain that wants to know the iOS version number even when targeting + // OS X. + Major = 2; + Minor = 0; + Micro = 0; + break; + case WatchOS: + getOSVersion(Major, Minor, Micro); + if (Major == 0) + Major = 2; + break; + case IOS: + llvm_unreachable("conflicting triple info"); } } @@ -993,6 +1087,7 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) { case llvm::Triple::UnknownArch: return 0; + case llvm::Triple::avr: case llvm::Triple::msp430: return 16; @@ -1062,6 +1157,7 @@ Triple Triple::get32BitArchVariant() const { case Triple::aarch64: case Triple::aarch64_be: case Triple::amdgcn: + case Triple::avr: case Triple::bpfel: case Triple::bpfeb: case Triple::msp430: @@ -1116,6 +1212,7 @@ Triple Triple::get64BitArchVariant() const { case Triple::UnknownArch: case Triple::arm: case Triple::armeb: + case Triple::avr: case Triple::hexagon: case Triple::kalimba: case Triple::msp430: @@ -1172,6 +1269,7 @@ Triple Triple::getBigEndianArchVariant() const { case Triple::amdgcn: case Triple::amdil64: case Triple::amdil: + case Triple::avr: case Triple::hexagon: case Triple::hsail64: case Triple::hsail: @@ -1244,6 +1342,7 @@ Triple Triple::getLittleEndianArchVariant() const { case Triple::amdil64: case Triple::amdil: case Triple::arm: + case Triple::avr: case Triple::bpfel: case Triple::hexagon: case Triple::hsail64: @@ -1281,10 +1380,10 @@ Triple Triple::getLittleEndianArchVariant() const { return T; } -const char *Triple::getARMCPUForArch(StringRef MArch) const { +StringRef Triple::getARMCPUForArch(StringRef MArch) const { if (MArch.empty()) MArch = getArchName(); - MArch = ARMTargetParser::getCanonicalArchName(MArch); + MArch = ARM::getCanonicalArchName(MArch); // Some defaults are forced. switch (getOS()) { @@ -1296,15 +1395,21 @@ const char *Triple::getARMCPUForArch(StringRef MArch) const { case llvm::Triple::Win32: // FIXME: this is invalid for WindowsCE return "cortex-a9"; + case llvm::Triple::MacOSX: + case llvm::Triple::IOS: + case llvm::Triple::WatchOS: + if (MArch == "v7k") + return "cortex-a7"; + break; default: break; } if (MArch.empty()) - return nullptr; + return StringRef(); - const char *CPU = ARMTargetParser::getDefaultCPU(MArch); - if (CPU) + StringRef CPU = ARM::getDefaultCPU(MArch); + if (!CPU.empty()) return CPU; // If no specific architecture version is requested, return the minimum CPU diff --git a/contrib/llvm/lib/Support/Unix/Memory.inc b/contrib/llvm/lib/Support/Unix/Memory.inc index c421ee8..d703191 100644 --- a/contrib/llvm/lib/Support/Unix/Memory.inc +++ b/contrib/llvm/lib/Support/Unix/Memory.inc @@ -50,9 +50,8 @@ int getPosixProtectionFlags(unsigned Flags) { return PROT_READ | PROT_WRITE; case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_EXEC: return PROT_READ | PROT_EXEC; - case llvm::sys::Memory::MF_READ | - llvm::sys::Memory::MF_WRITE | - llvm::sys::Memory::MF_EXEC: + case llvm::sys::Memory::MF_READ | llvm::sys::Memory::MF_WRITE | + llvm::sys::Memory::MF_EXEC: return PROT_READ | PROT_WRITE | PROT_EXEC; case llvm::sys::Memory::MF_EXEC: #if defined(__FreeBSD__) @@ -153,6 +152,7 @@ Memory::releaseMappedMemory(MemoryBlock &M) { std::error_code Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) { + static const size_t PageSize = Process::getPageSize(); if (M.Address == nullptr || M.Size == 0) return std::error_code(); @@ -161,7 +161,7 @@ Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) { int Protect = getPosixProtectionFlags(Flags); - int Result = ::mprotect(M.Address, M.Size, Protect); + int Result = ::mprotect((void*)((uintptr_t)M.Address & ~(PageSize-1)), PageSize*((M.Size+PageSize-1)/PageSize), Protect); if (Result != 0) return std::error_code(errno, std::generic_category()); @@ -181,7 +181,7 @@ Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, std::string *ErrMsg) { if (NumBytes == 0) return MemoryBlock(); - size_t PageSize = Process::getPageSize(); + static const size_t PageSize = Process::getPageSize(); size_t NumPages = (NumBytes+PageSize-1)/PageSize; int fd = -1; @@ -265,15 +265,12 @@ bool Memory::setWritable (MemoryBlock &M, std::string *ErrMsg) { } bool Memory::setExecutable (MemoryBlock &M, std::string *ErrMsg) { -#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)) if (M.Address == 0 || M.Size == 0) return false; Memory::InvalidateInstructionCache(M.Address, M.Size); +#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)) kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address, (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); return KERN_SUCCESS == kr; -#elif defined(__arm__) || defined(__aarch64__) - Memory::InvalidateInstructionCache(M.Address, M.Size); - return true; #else return true; #endif diff --git a/contrib/llvm/lib/Support/Unix/Path.inc b/contrib/llvm/lib/Support/Unix/Path.inc index 973d010..d85c37a 100644 --- a/contrib/llvm/lib/Support/Unix/Path.inc +++ b/contrib/llvm/lib/Support/Unix/Path.inc @@ -75,12 +75,12 @@ test_dir(char ret[PATH_MAX], const char *dir, const char *bin) char fullpath[PATH_MAX]; snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin); - if (realpath(fullpath, ret) == NULL) - return (1); + if (!realpath(fullpath, ret)) + return 1; if (stat(fullpath, &sb) != 0) - return (1); + return 1; - return (0); + return 0; } static char * @@ -91,34 +91,34 @@ getprogpath(char ret[PATH_MAX], const char *bin) /* First approach: absolute path. */ if (bin[0] == '/') { if (test_dir(ret, "/", bin) == 0) - return (ret); - return (NULL); + return ret; + return nullptr; } /* Second approach: relative path. */ - if (strchr(bin, '/') != NULL) { + if (strchr(bin, '/')) { char cwd[PATH_MAX]; - if (getcwd(cwd, PATH_MAX) == NULL) - return (NULL); + if (!getcwd(cwd, PATH_MAX)) + return nullptr; if (test_dir(ret, cwd, bin) == 0) - return (ret); - return (NULL); + return ret; + return nullptr; } /* Third approach: $PATH */ - if ((pv = getenv("PATH")) == NULL) - return (NULL); + if ((pv = getenv("PATH")) == nullptr) + return nullptr; s = pv = strdup(pv); - if (pv == NULL) - return (NULL); - while ((t = strsep(&s, ":")) != NULL) { + if (!pv) + return nullptr; + while ((t = strsep(&s, ":")) != nullptr) { if (test_dir(ret, t, bin) == 0) { free(pv); - return (ret); + return ret; } } free(pv); - return (NULL); + return nullptr; } #endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__ @@ -153,8 +153,8 @@ std::string getMainExecutable(const char *argv0, void *MainAddr) { return std::string(exe_path, len); } else { // Fall back to the classical detection. - if (getprogpath(exe_path, argv0) != NULL) - return exe_path; + if (getprogpath(exe_path, argv0)) + return exe_path; } #elif defined(HAVE_DLFCN_H) // Use dladdr to get executable path if available. @@ -219,11 +219,12 @@ std::error_code current_path(SmallVectorImpl<char> &result) { return std::error_code(); } -std::error_code create_directory(const Twine &path, bool IgnoreExisting) { +std::error_code create_directory(const Twine &path, bool IgnoreExisting, + perms Perms) { SmallString<128> path_storage; StringRef p = path.toNullTerminatedStringRef(path_storage); - if (::mkdir(p.begin(), S_IRWXU | S_IRWXG) == -1) { + if (::mkdir(p.begin(), Perms) == -1) { if (errno != EEXIST || !IgnoreExisting) return std::error_code(errno, std::generic_category()); } @@ -324,6 +325,10 @@ std::error_code access(const Twine &Path, AccessMode Mode) { return std::error_code(); } +bool can_execute(const Twine &Path) { + return !access(Path, AccessMode::Execute); +} + bool equivalent(file_status A, file_status B) { assert(status_known(A) && status_known(B)); return A.fs_st_dev == B.fs_st_dev && @@ -555,6 +560,54 @@ bool home_directory(SmallVectorImpl<char> &result) { return false; } +static bool getDarwinConfDir(bool TempDir, SmallVectorImpl<char> &Result) { + #if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR) + // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR. + // macros defined in <unistd.h> on darwin >= 9 + int ConfName = TempDir ? _CS_DARWIN_USER_TEMP_DIR + : _CS_DARWIN_USER_CACHE_DIR; + size_t ConfLen = confstr(ConfName, nullptr, 0); + if (ConfLen > 0) { + do { + Result.resize(ConfLen); + ConfLen = confstr(ConfName, Result.data(), Result.size()); + } while (ConfLen > 0 && ConfLen != Result.size()); + + if (ConfLen > 0) { + assert(Result.back() == 0); + Result.pop_back(); + return true; + } + + Result.clear(); + } + #endif + return false; +} + +static bool getUserCacheDir(SmallVectorImpl<char> &Result) { + // First try using XDS_CACHE_HOME env variable, + // as specified in XDG Base Directory Specification at + // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html + if (const char *XdsCacheDir = std::getenv("XDS_CACHE_HOME")) { + Result.clear(); + Result.append(XdsCacheDir, XdsCacheDir + strlen(XdsCacheDir)); + return true; + } + + // Try Darwin configuration query + if (getDarwinConfDir(false, Result)) + return true; + + // Use "$HOME/.cache" if $HOME is available + if (home_directory(Result)) { + append(Result, ".cache"); + return true; + } + + return false; +} + static const char *getEnvTempDir() { // Check whether the temporary directory is specified by an environment // variable. @@ -589,27 +642,8 @@ void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) { } } -#if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR) - // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR. - // macros defined in <unistd.h> on darwin >= 9 - int ConfName = ErasedOnReboot? _CS_DARWIN_USER_TEMP_DIR - : _CS_DARWIN_USER_CACHE_DIR; - size_t ConfLen = confstr(ConfName, nullptr, 0); - if (ConfLen > 0) { - do { - Result.resize(ConfLen); - ConfLen = confstr(ConfName, Result.data(), Result.size()); - } while (ConfLen > 0 && ConfLen != Result.size()); - - if (ConfLen > 0) { - assert(Result.back() == 0); - Result.pop_back(); - return; - } - - Result.clear(); - } -#endif + if (getDarwinConfDir(ErasedOnReboot, Result)) + return; const char *RequestedDir = getDefaultTempDir(ErasedOnReboot); Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); diff --git a/contrib/llvm/lib/Support/Unix/Process.inc b/contrib/llvm/lib/Support/Unix/Process.inc index df13bd2..27083ee 100644 --- a/contrib/llvm/lib/Support/Unix/Process.inc +++ b/contrib/llvm/lib/Support/Unix/Process.inc @@ -430,13 +430,18 @@ const char *Process::ResetColor() { #if !defined(HAVE_DECL_ARC4RANDOM) || !HAVE_DECL_ARC4RANDOM static unsigned GetRandomNumberSeed() { // Attempt to get the initial seed from /dev/urandom, if possible. - if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) { + int urandomFD = open("/dev/urandom", O_RDONLY); + + if (urandomFD != -1) { unsigned seed; - int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource); - ::fclose(RandomSource); + // Don't use a buffered read to avoid reading more data + // from /dev/urandom than we need. + int count = read(urandomFD, (void *)&seed, sizeof(seed)); + + close(urandomFD); // Return the seed if the read was successful. - if (count == 1) + if (count == sizeof(seed)) return seed; } diff --git a/contrib/llvm/lib/Support/Unix/Program.inc b/contrib/llvm/lib/Support/Unix/Program.inc index 8947b62..a8d1fe3 100644 --- a/contrib/llvm/lib/Support/Unix/Program.inc +++ b/contrib/llvm/lib/Support/Unix/Program.inc @@ -323,7 +323,6 @@ namespace llvm { ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, bool WaitUntilTerminates, std::string *ErrMsg) { -#ifdef HAVE_SYS_WAIT_H struct sigaction Act, Old; assert(PI.Pid && "invalid pid to wait on, process not started?"); @@ -417,12 +416,6 @@ ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, // signal during execution as opposed to failing to execute. WaitResult.ReturnCode = -2; } -#else - if (ErrMsg) - *ErrMsg = "Program::Wait is not implemented on this platform yet!"; - ProcessInfo WaitResult; - WaitResult.ReturnCode = -2; -#endif return WaitResult; } diff --git a/contrib/llvm/lib/Support/Unix/Signals.inc b/contrib/llvm/lib/Support/Unix/Signals.inc index bfe2a3a..061cdb3 100644 --- a/contrib/llvm/lib/Support/Unix/Signals.inc +++ b/contrib/llvm/lib/Support/Unix/Signals.inc @@ -17,7 +17,6 @@ #include "llvm/Support/Format.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FileUtilities.h" -#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/Program.h" @@ -25,7 +24,6 @@ #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <string> -#include <vector> #if HAVE_EXECINFO_H # include <execinfo.h> // For backtrace(). #endif @@ -58,8 +56,6 @@ static ManagedStatic<SmartMutex<true> > SignalsMutex; static void (*InterruptFunction)() = nullptr; static ManagedStatic<std::vector<std::string>> FilesToRemove; -static ManagedStatic<std::vector<std::pair<void (*)(void *), void *>>> - CallBacksToRun; // IntSigs - Signals that represent requested termination. There's no bug // or failure, or if there is, it's not our direct responsibility. For whatever @@ -90,12 +86,11 @@ static unsigned NumRegisteredSignals = 0; static struct { struct sigaction SA; int SigNo; -} RegisteredSignalInfo[(sizeof(IntSigs)+sizeof(KillSigs))/sizeof(KillSigs[0])]; +} RegisteredSignalInfo[array_lengthof(IntSigs) + array_lengthof(KillSigs)]; static void RegisterHandler(int Signal) { - assert(NumRegisteredSignals < - sizeof(RegisteredSignalInfo)/sizeof(RegisteredSignalInfo[0]) && + assert(NumRegisteredSignals < array_lengthof(RegisteredSignalInfo) && "Out of space for signal handlers!"); struct sigaction NewHandler; @@ -117,7 +112,7 @@ static void RegisterHandlers() { // 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; @@ -148,9 +143,6 @@ static void RemoveFilesToRemove() { // memory. std::vector<std::string>& FilesToRemoveRef = *FilesToRemove; for (unsigned i = 0, e = FilesToRemoveRef.size(); i != e; ++i) { - // We rely on a std::string implementation for which repeated calls to - // 'c_str()' don't allocate memory. We pre-call 'c_str()' on all of these - // strings to try to ensure this is safe. const char *path = FilesToRemoveRef[i].c_str(); // Get the status so we can determine if it's a file or directory. If we @@ -164,7 +156,7 @@ static void RemoveFilesToRemove() { // super-user permissions. if (!S_ISREG(buf.st_mode)) continue; - + // Otherwise, remove the file. We ignore any errors here as there is nothing // else we can do. unlink(path); @@ -205,11 +197,7 @@ static RETSIGTYPE SignalHandler(int Sig) { } // Otherwise if it is a fault (like SEGV) run any handler. - if (CallBacksToRun.isConstructed()) { - auto &CallBacksToRunRef = *CallBacksToRun; - for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i) - CallBacksToRunRef[i].first(CallBacksToRunRef[i].second); - } + llvm::sys::RunSignalHandlers(); #ifdef __s390__ // On S/390, certain signals are delivered with PSW Address pointing to @@ -239,21 +227,7 @@ bool llvm::sys::RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg) { { sys::SmartScopedLock<true> Guard(*SignalsMutex); - std::vector<std::string>& FilesToRemoveRef = *FilesToRemove; - std::string *OldPtr = - FilesToRemoveRef.empty() ? nullptr : &FilesToRemoveRef[0]; - FilesToRemoveRef.push_back(Filename); - - // We want to call 'c_str()' on every std::string in this vector so that if - // the underlying implementation requires a re-allocation, it happens here - // rather than inside of the signal handler. If we see the vector grow, we - // have to call it on every entry. If it remains in place, we only need to - // call it on the latest one. - if (OldPtr == &FilesToRemoveRef[0]) - FilesToRemoveRef.back().c_str(); - else - for (unsigned i = 0, e = FilesToRemoveRef.size(); i != e; ++i) - FilesToRemoveRef[i].c_str(); + FilesToRemove->push_back(Filename); } RegisterHandlers(); @@ -268,13 +242,6 @@ void llvm::sys::DontRemoveFileOnSignal(StringRef Filename) { std::vector<std::string>::iterator I = FilesToRemove->end(); if (RI != FilesToRemove->rend()) I = FilesToRemove->erase(RI.base()-1); - - // We need to call c_str() on every element which would have been moved by - // the erase. These elements, in a C++98 implementation where c_str() - // requires a reallocation on the first call may have had the call to c_str() - // made on insertion become invalid by being copied down an element. - for (std::vector<std::string>::iterator E = FilesToRemove->end(); I != E; ++I) - I->c_str(); } /// AddSignalHandler - Add a function to be called when a signal is delivered @@ -285,10 +252,9 @@ void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { RegisterHandlers(); } -#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) - -#if HAVE_LINK_H && (defined(__linux__) || defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || defined(__NetBSD__)) +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) && HAVE_LINK_H && \ + (defined(__linux__) || defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || defined(__NetBSD__)) struct DlIteratePhdrData { void **StackTrace; int depth; @@ -321,108 +287,27 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { return 0; } +/// If this is an ELF platform, we can find all loaded modules and their virtual +/// addresses with dl_iterate_phdr. static bool findModulesAndOffsets(void **StackTrace, int Depth, const char **Modules, intptr_t *Offsets, - const char *MainExecutableName) { + const char *MainExecutableName, + StringSaver &StrPool) { DlIteratePhdrData data = {StackTrace, Depth, true, Modules, Offsets, MainExecutableName}; dl_iterate_phdr(dl_iterate_phdr_cb, &data); return true; } #else +/// This platform does not have dl_iterate_phdr, so we do not yet know how to +/// find all loaded DSOs. static bool findModulesAndOffsets(void **StackTrace, int Depth, const char **Modules, intptr_t *Offsets, - const char *MainExecutableName) { + const char *MainExecutableName, + StringSaver &StrPool) { return false; } -#endif - -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. - ErrorOr<std::string> LLVMSymbolizerPathOrErr = - sys::findProgramByName("llvm-symbolizer"); - if (!LLVMSymbolizerPathOrErr) - return false; - const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr; - // We don't know argv0 or the address of main() at this point, but try - // to guess it anyway (it's possible on some platforms). - std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr); - if (MainExecutableName.empty() || - MainExecutableName.find("llvm-symbolizer") != std::string::npos) - return false; - - std::vector<const char *> Modules(Depth, nullptr); - std::vector<intptr_t> Offsets(Depth, 0); - if (!findModulesAndOffsets(StackTrace, Depth, Modules.data(), Offsets.data(), - MainExecutableName.c_str())) - return false; - int InputFD; - SmallString<32> InputFile, OutputFile; - sys::fs::createTemporaryFile("symbolizer-input", "", InputFD, InputFile); - sys::fs::createTemporaryFile("symbolizer-output", "", OutputFile); - FileRemover InputRemover(InputFile.c_str()); - FileRemover OutputRemover(OutputFile.c_str()); - - { - raw_fd_ostream Input(InputFD, true); - for (int i = 0; i < Depth; i++) { - if (Modules[i]) - Input << Modules[i] << " " << (void*)Offsets[i] << "\n"; - } - } - - StringRef InputFileStr(InputFile); - StringRef OutputFileStr(OutputFile); - StringRef StderrFileStr; - const StringRef *Redirects[] = {&InputFileStr, &OutputFileStr, - &StderrFileStr}; - const char *Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining", - "--demangle", nullptr}; - int RunResult = - sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects); - if (RunResult != 0) - return false; - - auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str()); - if (!OutputBuf) - return false; - StringRef Output = OutputBuf.get()->getBuffer(); - SmallVector<StringRef, 32> Lines; - Output.split(Lines, "\n"); - auto CurLine = Lines.begin(); - int frame_no = 0; - for (int i = 0; i < Depth; i++) { - if (!Modules[i]) { - OS << format("#%d %p\n", frame_no++, StackTrace[i]); - continue; - } - // Read pairs of lines (function name and file/line info) until we - // encounter empty line. - for (;;) { - if (CurLine == Lines.end()) - return false; - StringRef FunctionName = *CurLine++; - if (FunctionName.empty()) - break; - OS << format("#%d %p ", frame_no++, StackTrace[i]); - if (!FunctionName.startswith("??")) - OS << format("%s ", FunctionName.str().c_str()); - if (CurLine == Lines.end()) - return false; - StringRef FileLineInfo = *CurLine++; - if (!FileLineInfo.startswith("??")) - OS << format("%s", FileLineInfo.str().c_str()); - else - OS << format("(%s+%p)", Modules[i], (void *)Offsets[i]); - OS << "\n"; - } - } - return true; -} -#endif // defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) +#endif // defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) && ... // PrintStackTrace - In the case of a program crash or fault, print out a stack // trace so that the user has an indication of why and where we died. diff --git a/contrib/llvm/lib/Support/Unix/Unix.h b/contrib/llvm/lib/Support/Unix/Unix.h index e16a226..871e612 100644 --- a/contrib/llvm/lib/Support/Unix/Unix.h +++ b/contrib/llvm/lib/Support/Unix/Unix.h @@ -29,6 +29,7 @@ #include <cstring> #include <string> #include <sys/types.h> +#include <sys/wait.h> #ifdef HAVE_UNISTD_H #include <unistd.h> @@ -43,22 +44,10 @@ #endif #include <time.h> -#ifdef HAVE_SYS_WAIT_H -# include <sys/wait.h> -#endif - #ifdef HAVE_DLFCN_H # include <dlfcn.h> #endif -#ifndef WEXITSTATUS -# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) -#endif - -#ifndef WIFEXITED -# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) -#endif - /// This function builds an error message into \p ErrMsg using the \p prefix /// string and the Unix error number given by \p errnum. If errnum is -1, the /// default then the value of errno is used. diff --git a/contrib/llvm/lib/Support/Valgrind.cpp b/contrib/llvm/lib/Support/Valgrind.cpp index facf8d9..8d852a6 100644 --- a/contrib/llvm/lib/Support/Valgrind.cpp +++ b/contrib/llvm/lib/Support/Valgrind.cpp @@ -15,6 +15,7 @@ #include "llvm/Support/Valgrind.h" #include "llvm/Config/config.h" +#include <cstddef> #if HAVE_VALGRIND_VALGRIND_H #include <valgrind/valgrind.h> @@ -52,23 +53,3 @@ void llvm::sys::ValgrindDiscardTranslations(const void *Addr, size_t Len) { } #endif // !HAVE_VALGRIND_VALGRIND_H - -// 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 -// same reason we are. -extern "C" { -LLVM_ATTRIBUTE_WEAK void AnnotateHappensAfter(const char *file, int line, - const volatile void *cv); -void AnnotateHappensAfter(const char *file, int line, const volatile void *cv) { -} -LLVM_ATTRIBUTE_WEAK void AnnotateHappensBefore(const char *file, int line, - const volatile void *cv); -void AnnotateHappensBefore(const char *file, int line, - const volatile void *cv) {} -LLVM_ATTRIBUTE_WEAK void AnnotateIgnoreWritesBegin(const char *file, int line); -void AnnotateIgnoreWritesBegin(const char *file, int line) {} -LLVM_ATTRIBUTE_WEAK void AnnotateIgnoreWritesEnd(const char *file, int line); -void AnnotateIgnoreWritesEnd(const char *file, int line) {} -} - diff --git a/contrib/llvm/lib/Support/Windows/COM.inc b/contrib/llvm/lib/Support/Windows/COM.inc index 0c50d6f..54f3ecf 100644 --- a/contrib/llvm/lib/Support/Windows/COM.inc +++ b/contrib/llvm/lib/Support/Windows/COM.inc @@ -1,4 +1,4 @@ -//===- llvm/Support/Windows/COM.inc - Windows COM Implementation *- C++ -*-===// +//==- llvm/Support/Windows/COM.inc - Windows COM Implementation -*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc b/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc index d38f197..17418b0 100644 --- a/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc +++ b/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc @@ -76,14 +76,14 @@ DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, SmallVector<wchar_t, MAX_PATH> filenameUnicode; if (std::error_code ec = windows::UTF8ToUTF16(filename, filenameUnicode)) { SetLastError(ec.value()); - MakeErrMsg(errMsg, std::string(filename) + ": Can't convert to UTF-16: "); + MakeErrMsg(errMsg, std::string(filename) + ": Can't convert to UTF-16"); return DynamicLibrary(); } HMODULE a_handle = LoadLibraryW(filenameUnicode.data()); if (a_handle == 0) { - MakeErrMsg(errMsg, std::string(filename) + ": Can't open : "); + MakeErrMsg(errMsg, std::string(filename) + ": Can't open"); return DynamicLibrary(); } diff --git a/contrib/llvm/lib/Support/Windows/Memory.inc b/contrib/llvm/lib/Support/Windows/Memory.inc index 4b2ff2e..7eab9ff 100644 --- a/contrib/llvm/lib/Support/Windows/Memory.inc +++ b/contrib/llvm/lib/Support/Windows/Memory.inc @@ -192,14 +192,14 @@ static DWORD getProtection(const void *addr) { bool Memory::setWritable(MemoryBlock &M, std::string *ErrMsg) { if (!setRangeWritable(M.Address, M.Size)) { - return MakeErrMsg(ErrMsg, "Cannot set memory to writeable: "); + return MakeErrMsg(ErrMsg, "Cannot set memory to writeable"); } return true; } bool Memory::setExecutable(MemoryBlock &M, std::string *ErrMsg) { if (!setRangeExecutable(M.Address, M.Size)) { - return MakeErrMsg(ErrMsg, "Cannot set memory to executable: "); + return MakeErrMsg(ErrMsg, "Cannot set memory to executable"); } return true; } diff --git a/contrib/llvm/lib/Support/Windows/Path.inc b/contrib/llvm/lib/Support/Windows/Path.inc index 72da7c5..4e48412 100644 --- a/contrib/llvm/lib/Support/Windows/Path.inc +++ b/contrib/llvm/lib/Support/Windows/Path.inc @@ -182,7 +182,8 @@ std::error_code current_path(SmallVectorImpl<char> &result) { return UTF16ToUTF8(cur_path.begin(), cur_path.size(), result); } -std::error_code create_directory(const Twine &path, bool IgnoreExisting) { +std::error_code create_directory(const Twine &path, bool IgnoreExisting, + perms Perms) { SmallVector<wchar_t, 128> path_utf16; if (std::error_code ec = widenPath(path, path_utf16)) @@ -252,17 +253,34 @@ std::error_code rename(const Twine &from, const Twine &to) { return ec; std::error_code ec = std::error_code(); + + // Retry while we see ERROR_ACCESS_DENIED. + // System scanners (eg. indexer) might open the source file when it is written + // and closed. + for (int i = 0; i < 2000; i++) { + // Try ReplaceFile first, as it is able to associate a new data stream with + // the destination even if the destination file is currently open. + if (::ReplaceFileW(wide_to.begin(), wide_from.begin(), NULL, 0, NULL, NULL)) + return std::error_code(); + + // We get ERROR_FILE_NOT_FOUND if the destination file is missing. + // MoveFileEx can handle this case. + DWORD ReplaceError = ::GetLastError(); + ec = mapWindowsError(ReplaceError); + if (ReplaceError != ERROR_ACCESS_DENIED && + ReplaceError != ERROR_FILE_NOT_FOUND && + ReplaceError != ERROR_SHARING_VIOLATION) + break; + if (::MoveFileExW(wide_from.begin(), wide_to.begin(), 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. - // System scanners (eg. indexer) might open the source file when - // It is written and closed. + + DWORD MoveError = ::GetLastError(); + ec = mapWindowsError(MoveError); + if (MoveError != ERROR_ACCESS_DENIED) break; + ::Sleep(1); } @@ -301,6 +319,11 @@ std::error_code access(const Twine &Path, AccessMode Mode) { return std::error_code(); } +bool can_execute(const Twine &Path) { + return !access(Path, AccessMode::Execute) || + !access(Path + ".exe", AccessMode::Execute); +} + bool equivalent(file_status A, file_status B) { assert(status_known(A) && status_known(B)); return A.FileIndexHigh == B.FileIndexHigh && @@ -325,10 +348,12 @@ std::error_code equivalent(const Twine &A, const Twine &B, bool &result) { static bool isReservedName(StringRef path) { // This list of reserved names comes from MSDN, at: // http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx - static const char *sReservedNames[] = { "nul", "con", "prn", "aux", - "com1", "com2", "com3", "com4", "com5", "com6", - "com7", "com8", "com9", "lpt1", "lpt2", "lpt3", - "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9" }; + static const char *const sReservedNames[] = { "nul", "con", "prn", "aux", + "com1", "com2", "com3", "com4", + "com5", "com6", "com7", "com8", + "com9", "lpt1", "lpt2", "lpt3", + "lpt4", "lpt5", "lpt6", "lpt7", + "lpt8", "lpt9" }; // First, check to see if this is a device namespace, which always // starts with \\.\, since device namespaces are not legal file paths. @@ -643,9 +668,10 @@ std::error_code openFileForRead(const Twine &Name, int &ResultFD) { if (std::error_code EC = widenPath(Name, PathUTF16)) return EC; - HANDLE H = ::CreateFileW(PathUTF16.begin(), GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + HANDLE H = + ::CreateFileW(PathUTF16.begin(), GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (H == INVALID_HANDLE_VALUE) { DWORD LastError = ::GetLastError(); std::error_code EC = mapWindowsError(LastError); @@ -728,30 +754,31 @@ std::error_code openFileForWrite(const Twine &Name, int &ResultFD, } // end namespace fs namespace path { - -bool home_directory(SmallVectorImpl<char> &result) { - wchar_t Path[MAX_PATH]; - if (::SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, - /*SHGFP_TYPE_CURRENT*/0, Path) != S_OK) +static bool getKnownFolderPath(KNOWNFOLDERID folderId, + SmallVectorImpl<char> &result) { + wchar_t *path = nullptr; + if (::SHGetKnownFolderPath(folderId, KF_FLAG_CREATE, nullptr, &path) != S_OK) return false; - if (UTF16ToUTF8(Path, ::wcslen(Path), result)) - return false; + bool ok = !UTF16ToUTF8(path, ::wcslen(path), result); + ::CoTaskMemFree(path); + return ok; +} - return true; +bool getUserCacheDir(SmallVectorImpl<char> &Result) { + return getKnownFolderPath(FOLDERID_LocalAppData, Result); } -static bool getTempDirEnvVar(const char *Var, SmallVectorImpl<char> &Res) { - SmallVector<wchar_t, 128> NameUTF16; - if (windows::UTF8ToUTF16(Var, NameUTF16)) - return false; +bool home_directory(SmallVectorImpl<char> &result) { + return getKnownFolderPath(FOLDERID_Profile, result); +} +static bool getTempDirEnvVar(const wchar_t *Var, SmallVectorImpl<char> &Res) { SmallVector<wchar_t, 1024> Buf; size_t Size = 1024; do { Buf.reserve(Size); - Size = - GetEnvironmentVariableW(NameUTF16.data(), Buf.data(), Buf.capacity()); + Size = GetEnvironmentVariableW(Var, Buf.data(), Buf.capacity()); if (Size == 0) return false; @@ -759,14 +786,12 @@ static bool getTempDirEnvVar(const char *Var, SmallVectorImpl<char> &Res) { } while (Size > Buf.capacity()); Buf.set_size(Size); - if (windows::UTF16ToUTF8(Buf.data(), Size, Res)) - return false; - return true; + return !windows::UTF16ToUTF8(Buf.data(), Size, Res); } static bool getTempDirEnvVar(SmallVectorImpl<char> &Res) { - const char *EnvironmentVariables[] = {"TMP", "TEMP", "USERPROFILE"}; - for (const char *Env : EnvironmentVariables) { + const wchar_t *EnvironmentVariables[] = {L"TMP", L"TEMP", L"USERPROFILE"}; + for (auto *Env : EnvironmentVariables) { if (getTempDirEnvVar(Env, Res)) return true; } @@ -777,13 +802,19 @@ void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) { (void)ErasedOnReboot; Result.clear(); - // Check whether the temporary directory is specified by an environment - // variable. - if (getTempDirEnvVar(Result)) + // Check whether the temporary directory is specified by an environment var. + // This matches GetTempPath logic to some degree. GetTempPath is not used + // directly as it cannot handle evn var longer than 130 chars on Windows 7 + // (fixed on Windows 8). + if (getTempDirEnvVar(Result)) { + assert(!Result.empty() && "Unexpected empty path"); + native(Result); // Some Unix-like shells use Unix path separator in $TMP. + fs::make_absolute(Result); // Make it absolute if not already. return; + } // Fall back to a system default. - const char *DefaultResult = "C:\\TEMP"; + const char *DefaultResult = "C:\\Temp"; Result.append(DefaultResult, DefaultResult + strlen(DefaultResult)); } } // end namespace path diff --git a/contrib/llvm/lib/Support/Windows/Process.inc b/contrib/llvm/lib/Support/Windows/Process.inc index 8164956..dae35a8 100644 --- a/contrib/llvm/lib/Support/Windows/Process.inc +++ b/contrib/llvm/lib/Support/Windows/Process.inc @@ -417,16 +417,23 @@ const char *Process::ResetColor() { return 0; } +// Include GetLastError() in a fatal error message. +static void ReportLastErrorFatal(const char *Msg) { + std::string ErrMsg; + MakeErrMsg(&ErrMsg, Msg); + report_fatal_error(ErrMsg); +} + unsigned Process::GetRandomNumber() { HCRYPTPROV HCPC; if (!::CryptAcquireContextW(&HCPC, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) - report_fatal_error("Could not acquire a cryptographic context"); + ReportLastErrorFatal("Could not acquire a cryptographic context"); ScopedCryptContext CryptoProvider(HCPC); unsigned Ret; if (!::CryptGenRandom(CryptoProvider, sizeof(Ret), reinterpret_cast<BYTE *>(&Ret))) - report_fatal_error("Could not generate a random number"); + ReportLastErrorFatal("Could not generate a random number"); return Ret; } diff --git a/contrib/llvm/lib/Support/Windows/Program.inc b/contrib/llvm/lib/Support/Windows/Program.inc index c29d872..d4e14dd 100644 --- a/contrib/llvm/lib/Support/Windows/Program.inc +++ b/contrib/llvm/lib/Support/Windows/Program.inc @@ -75,8 +75,15 @@ ErrorOr<std::string> sys::findProgramByName(StringRef Name, do { U16Result.reserve(Len); - Len = ::SearchPathW(Path, c_str(U16Name), - U16Ext.empty() ? nullptr : c_str(U16Ext), + // Lets attach the extension manually. That is needed for files + // with a point in name like aaa.bbb. SearchPathW will not add extension + // from its argument to such files because it thinks they already had one. + SmallVector<wchar_t, MAX_PATH> U16NameExt; + if (std::error_code EC = + windows::UTF8ToUTF16(Twine(Name + Ext).str(), U16NameExt)) + return EC; + + Len = ::SearchPathW(Path, c_str(U16NameExt), nullptr, U16Result.capacity(), U16Result.data(), nullptr); } while (Len > U16Result.capacity()); @@ -132,7 +139,7 @@ static HANDLE RedirectIO(const StringRef *path, int fd, std::string* ErrMsg) { FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) { MakeErrMsg(ErrMsg, fname + ": Can't open file for " + - (fd ? "input: " : "output: ")); + (fd ? "input" : "output")); } return h; @@ -251,6 +258,14 @@ static bool Execute(ProcessInfo &PI, StringRef Program, const char **args, return false; } + // can_execute may succeed by looking at Program + ".exe". CreateProcessW + // will implicitly add the .exe if we provide a command line without an + // executable path, but since we use an explicit executable, we have to add + // ".exe" ourselves. + SmallString<64> ProgramStorage; + if (!sys::fs::exists(Program)) + Program = Twine(Program + ".exe").toStringRef(ProgramStorage); + // Windows wants a command line, not an array of args, to pass to the new // process. We have to concatenate them all, while quoting the args that // have embedded spaces (or are empty). @@ -416,7 +431,7 @@ ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, if (SecondsToWait) { if (!TerminateProcess(PI.ProcessHandle, 1)) { if (ErrMsg) - MakeErrMsg(ErrMsg, "Failed to terminate timed-out program."); + MakeErrMsg(ErrMsg, "Failed to terminate timed-out program"); // -2 indicates a crash or timeout as opposed to failure to execute. WaitResult.ReturnCode = -2; @@ -441,7 +456,7 @@ ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, if (!rc) { SetLastError(err); if (ErrMsg) - MakeErrMsg(ErrMsg, "Failed getting status for program."); + MakeErrMsg(ErrMsg, "Failed getting status for program"); // -2 indicates a crash or timeout as opposed to failure to execute. WaitResult.ReturnCode = -2; diff --git a/contrib/llvm/lib/Support/Windows/Signals.inc b/contrib/llvm/lib/Support/Windows/Signals.inc index 5c8c239..d109a66 100644 --- a/contrib/llvm/lib/Support/Windows/Signals.inc +++ b/contrib/llvm/lib/Support/Windows/Signals.inc @@ -14,7 +14,6 @@ #include <algorithm> #include <signal.h> #include <stdio.h> -#include <vector> #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -136,6 +135,10 @@ typedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64, PDWORD, PIMAGEHLP_LINE64); static fpSymGetLineFromAddr64 fSymGetLineFromAddr64; +typedef BOOL(WINAPI *fpSymGetModuleInfo64)(HANDLE hProcess, DWORD64 dwAddr, + PIMAGEHLP_MODULE64 ModuleInfo); +static fpSymGetModuleInfo64 fSymGetModuleInfo64; + typedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64); static fpSymFunctionTableAccess64 fSymFunctionTableAccess64; @@ -145,6 +148,9 @@ static fpSymSetOptions fSymSetOptions; typedef BOOL (WINAPI *fpSymInitialize)(HANDLE, PCSTR, BOOL); static fpSymInitialize fSymInitialize; +typedef BOOL (WINAPI *fpEnumerateLoadedModules)(HANDLE,PENUMLOADED_MODULES_CALLBACK64,PVOID); +static fpEnumerateLoadedModules fEnumerateLoadedModules; + static bool load64BitDebugHelp(void) { HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll"); if (hLib) { @@ -156,14 +162,20 @@ static bool load64BitDebugHelp(void) { ::GetProcAddress(hLib, "SymGetSymFromAddr64"); fSymGetLineFromAddr64 = (fpSymGetLineFromAddr64) ::GetProcAddress(hLib, "SymGetLineFromAddr64"); + fSymGetModuleInfo64 = (fpSymGetModuleInfo64) + ::GetProcAddress(hLib, "SymGetModuleInfo64"); fSymFunctionTableAccess64 = (fpSymFunctionTableAccess64) ::GetProcAddress(hLib, "SymFunctionTableAccess64"); fSymSetOptions = (fpSymSetOptions)::GetProcAddress(hLib, "SymSetOptions"); fSymInitialize = (fpSymInitialize)::GetProcAddress(hLib, "SymInitialize"); + fEnumerateLoadedModules = (fpEnumerateLoadedModules) + ::GetProcAddress(hLib, "EnumerateLoadedModules64"); } return fStackWalk64 && fSymInitialize && fSymSetOptions; } +using namespace llvm; + // Forward declare. static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep); static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType); @@ -172,7 +184,6 @@ static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType); static void (*InterruptFunction)() = 0; 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 PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL; @@ -183,23 +194,106 @@ static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL; 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; +enum { #if defined(_M_X64) - machineType = IMAGE_FILE_MACHINE_AMD64; + NativeMachineType = IMAGE_FILE_MACHINE_AMD64 #else - machineType = IMAGE_FILE_MACHINE_I386; + NativeMachineType = IMAGE_FILE_MACHINE_I386 #endif +}; + +static bool printStackTraceWithLLVMSymbolizer(llvm::raw_ostream &OS, + HANDLE hProcess, HANDLE hThread, + STACKFRAME64 &StackFrameOrig, + CONTEXT *ContextOrig) { + // StackWalk64 modifies the incoming stack frame and context, so copy them. + STACKFRAME64 StackFrame = StackFrameOrig; + + // Copy the register context so that we don't modify it while we unwind. We + // could use InitializeContext + CopyContext, but that's only required to get + // at AVX registers, which typically aren't needed by StackWalk64. Reduce the + // flag set to indicate that there's less data. + CONTEXT Context = *ContextOrig; + Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; + + static void *StackTrace[256]; + size_t Depth = 0; + while (fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame, + &Context, 0, fSymFunctionTableAccess64, + fSymGetModuleBase64, 0)) { + if (StackFrame.AddrFrame.Offset == 0) + break; + StackTrace[Depth++] = (void *)(uintptr_t)StackFrame.AddrPC.Offset; + if (Depth >= array_lengthof(StackTrace)) + break; + } + + return printSymbolizedStackTrace(&StackTrace[0], Depth, OS); +} + +namespace { +struct FindModuleData { + void **StackTrace; + int Depth; + const char **Modules; + intptr_t *Offsets; + StringSaver *StrPool; +}; +} + +static BOOL CALLBACK findModuleCallback(WIN32_ELMCB_PCSTR ModuleName, + DWORD64 ModuleBase, ULONG ModuleSize, + void *VoidData) { + FindModuleData *Data = (FindModuleData*)VoidData; + intptr_t Beg = ModuleBase; + intptr_t End = Beg + ModuleSize; + for (int I = 0; I < Data->Depth; I++) { + if (Data->Modules[I]) + continue; + intptr_t Addr = (intptr_t)Data->StackTrace[I]; + if (Beg <= Addr && Addr < End) { + Data->Modules[I] = Data->StrPool->save(ModuleName); + Data->Offsets[I] = Addr - Beg; + } + } + return TRUE; +} + +static bool findModulesAndOffsets(void **StackTrace, int Depth, + const char **Modules, intptr_t *Offsets, + const char *MainExecutableName, + StringSaver &StrPool) { + if (!fEnumerateLoadedModules) + return false; + FindModuleData Data; + Data.StackTrace = StackTrace; + Data.Depth = Depth; + Data.Modules = Modules; + Data.Offsets = Offsets; + Data.StrPool = &StrPool; + fEnumerateLoadedModules(GetCurrentProcess(), findModuleCallback, &Data); + return true; +} +static void PrintStackTraceForThread(llvm::raw_ostream &OS, HANDLE hProcess, + HANDLE hThread, STACKFRAME64 &StackFrame, + CONTEXT *Context) { // Initialize the symbol handler. fSymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES); fSymInitialize(hProcess, NULL, TRUE); + // Try llvm-symbolizer first. llvm-symbolizer knows how to deal with both PDBs + // and DWARF, so it should do a good job regardless of what debug info or + // linker is in use. + if (printStackTraceWithLLVMSymbolizer(OS, hProcess, hThread, StackFrame, + Context)) { + return; + } + while (true) { - if (!fStackWalk64(machineType, hProcess, hThread, &StackFrame, Context, 0, - fSymFunctionTableAccess64, fSymGetModuleBase64, 0)) { + if (!fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame, + Context, 0, fSymFunctionTableAccess64, + fSymGetModuleBase64, 0)) { break; } @@ -311,10 +405,7 @@ static void RegisterHandler() { // If we cannot load up the APIs (which would be unexpected as they should // exist on every version of Windows we support), we will bail out since // there would be nothing to report. - if (!load64BitDebugHelp()) { - assert(false && "These APIs should always be available"); - return; - } + assert(load64BitDebugHelp() && "These APIs should always be available"); if (RegisteredUnhandledExceptionFilter) { EnterCriticalSection(&CriticalSection); @@ -404,7 +495,6 @@ extern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord); #endif void llvm::sys::PrintStackTrace(raw_ostream &OS) { - STACKFRAME64 StackFrame = {}; CONTEXT Context = {}; ::RtlCaptureContext(&Context); @@ -436,8 +526,6 @@ void llvm::sys::SetInterruptFunction(void (*IF)()) { /// to the process. The handler can have a cookie passed to it to identify /// what instance of the handler it is. 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); @@ -454,17 +542,12 @@ static void Cleanup() { CleanupExecuted = true; // FIXME: open files cannot be deleted. - if (FilesToRemove != NULL) while (!FilesToRemove->empty()) { llvm::sys::fs::remove(FilesToRemove->back()); FilesToRemove->pop_back(); } - - if (CallBacksToRun) - for (auto &I : *CallBacksToRun) - I.first(I.second); - + llvm::sys::RunSignalHandlers(); LeaveCriticalSection(&CriticalSection); } diff --git a/contrib/llvm/lib/Support/Windows/WindowsSupport.h b/contrib/llvm/lib/Support/Windows/WindowsSupport.h index 5bb0b8d..34d961b 100644 --- a/contrib/llvm/lib/Support/Windows/WindowsSupport.h +++ b/contrib/llvm/lib/Support/Windows/WindowsSupport.h @@ -26,12 +26,13 @@ #undef _WIN32_WINNT #undef _WIN32_IE -// Require at least Windows XP(5.1) API. -#define _WIN32_WINNT 0x0501 -#define _WIN32_IE 0x0600 // MinGW at it again. +// Require at least Windows 7 API. +#define _WIN32_WINNT 0x0601 +#define _WIN32_IE 0x0800 // MinGW at it again. FIXME: verify if still needed. #define WIN32_LEAN_AND_MEAN #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Config/config.h" // Get build system configuration settings @@ -47,13 +48,16 @@ inline bool MakeErrMsg(std::string* ErrMsg, const std::string& prefix) { if (!ErrMsg) return true; char *buffer = NULL; + DWORD LastError = GetLastError(); DWORD R = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, GetLastError(), 0, (LPSTR)&buffer, 1, NULL); + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_MAX_WIDTH_MASK, + NULL, LastError, 0, (LPSTR)&buffer, 1, NULL); if (R) - *ErrMsg = prefix + buffer; + *ErrMsg = prefix + ": " + buffer; else - *ErrMsg = prefix + "Unknown error"; + *ErrMsg = prefix + ": Unknown error"; + *ErrMsg += " (0x" + llvm::utohexstr(LastError) + ")"; LocalFree(buffer); return R != 0; diff --git a/contrib/llvm/lib/Support/YAMLParser.cpp b/contrib/llvm/lib/Support/YAMLParser.cpp index d55da5e..c4384ca 100644 --- a/contrib/llvm/lib/Support/YAMLParser.cpp +++ b/contrib/llvm/lib/Support/YAMLParser.cpp @@ -801,7 +801,7 @@ Token &Scanner::peekNext() { removeStaleSimpleKeyCandidates(); SimpleKey SK; - SK.Tok = TokenQueue.front(); + SK.Tok = TokenQueue.begin(); if (std::find(SimpleKeys.begin(), SimpleKeys.end(), SK) == SimpleKeys.end()) break; @@ -962,10 +962,8 @@ void Scanner::skip(uint32_t Distance) { bool Scanner::isBlankOrBreak(StringRef::iterator Position) { if (Position == End) return false; - if ( *Position == ' ' || *Position == '\t' - || *Position == '\r' || *Position == '\n') - return true; - return false; + return *Position == ' ' || *Position == '\t' || *Position == '\r' || + *Position == '\n'; } bool Scanner::consumeLineBreakIfPresent() { @@ -1163,7 +1161,7 @@ bool Scanner::scanFlowCollectionStart(bool IsSequence) { TokenQueue.push_back(T); // [ and { may begin a simple key. - saveSimpleKeyCandidate(TokenQueue.back(), Column - 1, false); + saveSimpleKeyCandidate(--TokenQueue.end(), Column - 1, false); // And may also be followed by a simple key. IsSimpleKeyAllowed = true; @@ -1326,7 +1324,7 @@ bool Scanner::scanFlowScalar(bool IsDoubleQuoted) { T.Range = StringRef(Start, Current - Start); TokenQueue.push_back(T); - saveSimpleKeyCandidate(TokenQueue.back(), ColStart, false); + saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false); IsSimpleKeyAllowed = false; @@ -1404,7 +1402,7 @@ bool Scanner::scanPlainScalar() { TokenQueue.push_back(T); // Plain scalars can be simple keys. - saveSimpleKeyCandidate(TokenQueue.back(), ColStart, false); + saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false); IsSimpleKeyAllowed = false; @@ -1439,7 +1437,7 @@ bool Scanner::scanAliasOrAnchor(bool IsAlias) { TokenQueue.push_back(T); // Alias and anchors can be simple keys. - saveSimpleKeyCandidate(TokenQueue.back(), ColStart, false); + saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false); IsSimpleKeyAllowed = false; @@ -1669,7 +1667,7 @@ bool Scanner::scanTag() { TokenQueue.push_back(T); // Tags can be simple keys. - saveSimpleKeyCandidate(TokenQueue.back(), ColStart, false); + saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false); IsSimpleKeyAllowed = false; diff --git a/contrib/llvm/lib/Support/YAMLTraits.cpp b/contrib/llvm/lib/Support/YAMLTraits.cpp index 6b59a16..2aa6e9b 100644 --- a/contrib/llvm/lib/Support/YAMLTraits.cpp +++ b/contrib/llvm/lib/Support/YAMLTraits.cpp @@ -332,17 +332,12 @@ std::unique_ptr<Input::HNode> Input::createHNodes(Node *N) { StringRef KeyStr = SN->getValue(StringStorage); if (!StringStorage.empty()) { // Copy string to permanent storage - unsigned Len = StringStorage.size(); - char *Buf = StringAllocator.Allocate<char>(Len); - memcpy(Buf, &StringStorage[0], Len); - KeyStr = StringRef(Buf, Len); + KeyStr = StringStorage.str().copy(StringAllocator); } 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())); + StringRef ValueCopy = BSN->getValue().copy(StringAllocator); + return llvm::make_unique<ScalarHNode>(N, ValueCopy); } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) { auto SQHNode = llvm::make_unique<SequenceHNode>(N); for (Node &SN : *SQ) { @@ -365,10 +360,7 @@ std::unique_ptr<Input::HNode> Input::createHNodes(Node *N) { StringRef KeyStr = KeyScalar->getValue(StringStorage); if (!StringStorage.empty()) { // Copy string to permanent storage - unsigned Len = StringStorage.size(); - char *Buf = StringAllocator.Allocate<char>(Len); - memcpy(Buf, &StringStorage[0], Len); - KeyStr = StringRef(Buf, Len); + KeyStr = StringStorage.str().copy(StringAllocator); } auto ValueHNode = this->createHNodes(KVN.getValue()); if (EC) diff --git a/contrib/llvm/lib/Support/raw_ostream.cpp b/contrib/llvm/lib/Support/raw_ostream.cpp index 42f830b..57c7ac3 100644 --- a/contrib/llvm/lib/Support/raw_ostream.cpp +++ b/contrib/llvm/lib/Support/raw_ostream.cpp @@ -517,7 +517,7 @@ raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC, /// closes the file when the stream is destroyed. raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered) : raw_pwrite_stream(unbuffered), FD(fd), ShouldClose(shouldClose), - Error(false), UseAtomicWrites(false) { + Error(false) { if (FD < 0 ) { ShouldClose = false; return; @@ -568,21 +568,7 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { pos += Size; do { - ssize_t ret; - - // Check whether we should attempt to use atomic writes. - if (LLVM_LIKELY(!UseAtomicWrites)) { - ret = ::write(FD, Ptr, Size); - } else { - // Use ::writev() where available. -#if defined(HAVE_WRITEV) - const void *Addr = static_cast<const void *>(Ptr); - struct iovec IOV = {const_cast<void *>(Addr), Size }; - ret = ::writev(FD, &IOV, 1); -#else - ret = ::write(FD, Ptr, Size); -#endif - } + ssize_t ret = ::write(FD, Ptr, Size); if (ret < 0) { // If it's a recoverable error, swallow it and retry the write. @@ -755,72 +741,15 @@ void raw_string_ostream::write_impl(const char *Ptr, size_t Size) { // raw_svector_ostream //===----------------------------------------------------------------------===// -// The raw_svector_ostream implementation uses the SmallVector itself as the -// buffer for the raw_ostream. We guarantee that the raw_ostream buffer is -// always pointing past the end of the vector, but within the vector -// 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) {} +uint64_t raw_svector_ostream::current_pos() const { return OS.size(); } -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 - // the data is flushed). See the FIXME below. - OS.reserve(OS.size() + 128); - SetBuffer(OS.end(), OS.capacity() - OS.size()); -} - -raw_svector_ostream::~raw_svector_ostream() { - // FIXME: Prevent resizing during this flush(). - flush(); +void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) { + OS.append(Ptr, Ptr + Size); } 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. -void raw_svector_ostream::resync() { - assert(GetNumBytesInBuffer() == 0 && "Didn't flush before mutating vector"); - - if (OS.capacity() - OS.size() < 64) - OS.reserve(OS.capacity() * 2); - SetBuffer(OS.end(), OS.capacity() - OS.size()); -} - -void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) { - if (Ptr == OS.end()) { - // Grow the buffer to include the scratch area without copying. - size_t NewSize = OS.size() + Size; - assert(NewSize <= OS.capacity() && "Invalid write_impl() call!"); - OS.set_size(NewSize); - } else { - assert(!GetNumBytesInBuffer()); - OS.append(Ptr, Ptr + Size); - } - - OS.reserve(OS.size() + 64); - SetBuffer(OS.end(), OS.capacity() - OS.size()); -} - -uint64_t raw_svector_ostream::current_pos() const { - return OS.size(); -} - -StringRef raw_svector_ostream::str() { - flush(); - return StringRef(OS.begin(), OS.size()); + memcpy(OS.data() + Offset, Ptr, Size); } //===----------------------------------------------------------------------===// |