diff options
Diffstat (limited to 'contrib/llvm/lib/Support')
58 files changed, 2146 insertions, 1764 deletions
diff --git a/contrib/llvm/lib/Support/APFloat.cpp b/contrib/llvm/lib/Support/APFloat.cpp index 7989e30..393ecf4 100644 --- a/contrib/llvm/lib/Support/APFloat.cpp +++ b/contrib/llvm/lib/Support/APFloat.cpp @@ -35,8 +35,7 @@ using namespace llvm; /* Assumed in hexadecimal significand parsing, and conversion to hexadecimal strings. */ -#define COMPILE_TIME_ASSERT(cond) extern int CTAssert[(cond) ? 1 : -1] -COMPILE_TIME_ASSERT(integerPartWidth % 4 == 0); +static_assert(integerPartWidth % 4 == 0, "Part width must be divisible by 4!"); namespace llvm { @@ -212,15 +211,15 @@ skipLeadingZeroesAndAnyDot(StringRef::iterator begin, StringRef::iterator end, { StringRef::iterator p = begin; *dot = end; - while (*p == '0' && p != end) + while (p != end && *p == '0') p++; - if (*p == '.') { + if (p != end && *p == '.') { *dot = p++; assert(end - begin != 1 && "Significand has no digits"); - while (*p == '0' && p != end) + while (p != end && *p == '0') p++; } @@ -927,7 +926,10 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) assert(semantics == rhs.semantics); precision = semantics->precision; - newPartsCount = partCountForBits(precision * 2); + + // Allocate space for twice as many bits as the original significand, plus one + // extra bit for the addition to overflow into. + newPartsCount = partCountForBits(precision * 2 + 1); if (newPartsCount > 4) fullSignificand = new integerPart[newPartsCount]; @@ -949,13 +951,14 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) // *this = a23 . a22 ... a0 * 2^e1 // rhs = b23 . b22 ... b0 * 2^e2 // the result of multiplication is: - // *this = c47 c46 . c45 ... c0 * 2^(e1+e2) - // Note that there are two significant bits at the left-hand side of the - // radix point. Move the radix point toward left by one bit, and adjust - // exponent accordingly. - exponent += 1; - - if (addend) { + // *this = c48 c47 c46 . c45 ... c0 * 2^(e1+e2) + // Note that there are three significant bits at the left-hand side of the + // radix point: two for the multiplication, and an overflow bit for the + // addition (that will always be zero at this point). Move the radix point + // toward left by two bits, and adjust exponent accordingly. + exponent += 2; + + if (addend && addend->isNonZero()) { // The intermediate result of the multiplication has "2 * precision" // signicant bit; adjust the addend to be consistent with mul result. // @@ -965,13 +968,13 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) opStatus status; unsigned int extendedPrecision; - /* Normalize our MSB. */ - extendedPrecision = 2 * precision; - if (omsb != extendedPrecision) { + // Normalize our MSB to one below the top bit to allow for overflow. + extendedPrecision = 2 * precision + 1; + if (omsb != extendedPrecision - 1) { assert(extendedPrecision > omsb); APInt::tcShiftLeft(fullSignificand, newPartsCount, - extendedPrecision - omsb); - exponent -= extendedPrecision - omsb; + (extendedPrecision - 1) - omsb); + exponent -= (extendedPrecision - 1) - omsb; } /* Create new semantics. */ @@ -988,6 +991,14 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) status = extendedAddend.convert(extendedSemantics, rmTowardZero, &ignored); assert(status == opOK); (void)status; + + // Shift the significand of the addend right by one bit. This guarantees + // that the high bit of the significand is zero (same as fullSignificand), + // so the addition will overflow (if it does overflow at all) into the top bit. + lost_fraction = extendedAddend.shiftSignificandRight(1); + assert(lost_fraction == lfExactlyZero && + "Lost precision while shifting addend for fused-multiply-add."); + lost_fraction = addOrSubtractSignificand(extendedAddend, false); /* Restore our state. */ @@ -1003,7 +1014,7 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) // having "precision" significant-bits. First, move the radix point from // poision "2*precision - 1" to "precision - 1". The exponent need to be // adjusted by "2*precision - 1" - "precision - 1" = "precision". - exponent -= precision; + exponent -= precision + 1; // In case MSB resides at the left-hand side of radix point, shift the // mantissa right by some amount to make sure the MSB reside right before @@ -1801,7 +1812,7 @@ APFloat::fusedMultiplyAdd(const APFloat &multiplicand, extended-precision calculation. */ if (isFiniteNonZero() && multiplicand.isFiniteNonZero() && - addend.isFiniteNonZero()) { + addend.isFinite()) { lostFraction lost_fraction; lost_fraction = multiplySignificand(multiplicand, &addend); @@ -1812,7 +1823,7 @@ APFloat::fusedMultiplyAdd(const APFloat &multiplicand, /* If two numbers add (exactly) to zero, IEEE 754 decrees it is a positive zero unless rounding to minus infinity, except that adding two like-signed zeroes gives that zero. */ - if (category == fcZero && sign != addend.sign) + if (category == fcZero && !(fs & opUnderflow) && sign != addend.sign) sign = (rounding_mode == rmTowardNegative); } else { fs = multiplySpecials(multiplicand); @@ -3377,7 +3388,9 @@ void APFloat::makeLargest(bool Negative) { // internal consistency. const unsigned NumUnusedHighBits = PartCount*integerPartWidth - semantics->precision; - significand[PartCount - 1] = ~integerPart(0) >> NumUnusedHighBits; + significand[PartCount - 1] = (NumUnusedHighBits < integerPartWidth) + ? (~integerPart(0) >> NumUnusedHighBits) + : 0; } /// Make this number the smallest magnitude denormal number in the given @@ -3904,3 +3917,20 @@ APFloat::makeZero(bool Negative) { exponent = semantics->minExponent-1; APInt::tcSet(significandParts(), 0, partCount()); } + +APFloat llvm::scalbn(APFloat X, int Exp) { + if (X.isInfinity() || X.isZero() || X.isNaN()) + return std::move(X); + + auto MaxExp = X.getSemantics().maxExponent; + auto MinExp = X.getSemantics().minExponent; + if (Exp > (MaxExp - X.exponent)) + // Overflow saturates to infinity. + return APFloat::getInf(X.getSemantics(), X.isNegative()); + if (Exp < (MinExp - X.exponent)) + // Underflow saturates to zero. + return APFloat::getZero(X.getSemantics(), X.isNegative()); + + X.exponent += Exp; + return std::move(X); +} diff --git a/contrib/llvm/lib/Support/APInt.cpp b/contrib/llvm/lib/Support/APInt.cpp index fa929eb..0ddc2ab 100644 --- a/contrib/llvm/lib/Support/APInt.cpp +++ b/contrib/llvm/lib/Support/APInt.cpp @@ -454,8 +454,10 @@ APInt APInt::XorSlowCase(const APInt& RHS) const { for (unsigned i = 0; i < numWords; ++i) val[i] = pVal[i] ^ RHS.pVal[i]; + APInt Result(val, getBitWidth()); // 0^0==1 so clear the high bits in case they got set. - return APInt(val, getBitWidth()).clearUnusedBits(); + Result.clearUnusedBits(); + return Result; } APInt APInt::operator*(const APInt& RHS) const { @@ -473,7 +475,8 @@ APInt APInt::operator+(const APInt& RHS) const { return APInt(BitWidth, VAL + RHS.VAL); APInt Result(BitWidth, 0); add(Result.pVal, this->pVal, RHS.pVal, getNumWords()); - return Result.clearUnusedBits(); + Result.clearUnusedBits(); + return Result; } APInt APInt::operator-(const APInt& RHS) const { @@ -482,7 +485,8 @@ APInt APInt::operator-(const APInt& RHS) const { return APInt(BitWidth, VAL - RHS.VAL); APInt Result(BitWidth, 0); sub(Result.pVal, this->pVal, RHS.pVal, getNumWords()); - return Result.clearUnusedBits(); + Result.clearUnusedBits(); + return Result; } bool APInt::EqualSlowCase(const APInt& RHS) const { @@ -1114,7 +1118,9 @@ APInt APInt::ashr(unsigned shiftAmt) const { uint64_t fillValue = (isNegative() ? -1ULL : 0); for (unsigned i = breakWord+1; i < getNumWords(); ++i) val[i] = fillValue; - return APInt(val, BitWidth).clearUnusedBits(); + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; } /// Logical right-shift this APInt by shiftAmt. @@ -1151,7 +1157,9 @@ APInt APInt::lshr(unsigned shiftAmt) const { // If we are shifting less than a word, compute the shift with a simple carry if (shiftAmt < APINT_BITS_PER_WORD) { lshrNear(val, pVal, getNumWords(), shiftAmt); - return APInt(val, BitWidth).clearUnusedBits(); + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; } // Compute some values needed by the remaining shift algorithms @@ -1164,7 +1172,9 @@ APInt APInt::lshr(unsigned shiftAmt) const { val[i] = pVal[i+offset]; for (unsigned i = getNumWords()-offset; i < getNumWords(); i++) val[i] = 0; - return APInt(val,BitWidth).clearUnusedBits(); + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; } // Shift the low order words @@ -1178,7 +1188,9 @@ APInt APInt::lshr(unsigned shiftAmt) const { // Remaining words are 0 for (unsigned i = breakWord+1; i < getNumWords(); ++i) val[i] = 0; - return APInt(val, BitWidth).clearUnusedBits(); + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; } /// Left-shift this APInt by shiftAmt. @@ -1211,7 +1223,9 @@ APInt APInt::shlSlowCase(unsigned shiftAmt) const { val[i] = pVal[i] << shiftAmt | carry; carry = pVal[i] >> (APINT_BITS_PER_WORD - shiftAmt); } - return APInt(val, BitWidth).clearUnusedBits(); + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; } // Compute some values needed by the remaining shift algorithms @@ -1224,7 +1238,9 @@ APInt APInt::shlSlowCase(unsigned shiftAmt) const { val[i] = 0; for (unsigned i = offset; i < getNumWords(); i++) val[i] = pVal[i-offset]; - return APInt(val,BitWidth).clearUnusedBits(); + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; } // Copy whole words from this to Result. @@ -1235,7 +1251,9 @@ APInt APInt::shlSlowCase(unsigned shiftAmt) const { val[offset] = pVal[0] << wordShift; for (i = 0; i < offset; ++i) val[i] = 0; - return APInt(val, BitWidth).clearUnusedBits(); + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; } APInt APInt::rotl(const APInt &rotateAmt) const { @@ -1303,7 +1321,7 @@ APInt APInt::sqrt() const { // Okay, all the short cuts are exhausted. We must compute it. The following // is a classical Babylonian method for computing the square root. This code - // was adapted to APINt from a wikipedia article on such computations. + // was adapted to APInt from a wikipedia article on such computations. // See http://www.wikipedia.org/ and go to the page named // Calculate_an_integer_square_root. unsigned nbits = BitWidth, i = 4; @@ -1938,6 +1956,18 @@ APInt APInt::srem(const APInt &RHS) const { void APInt::udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder) { + assert(LHS.BitWidth == RHS.BitWidth && "Bit widths must be the same"); + + // First, deal with the easy case + if (LHS.isSingleWord()) { + assert(RHS.VAL != 0 && "Divide by zero?"); + uint64_t QuotVal = LHS.VAL / RHS.VAL; + uint64_t RemVal = LHS.VAL % RHS.VAL; + Quotient = APInt(LHS.BitWidth, QuotVal); + Remainder = APInt(LHS.BitWidth, RemVal); + return; + } + // Get some size facts about the dividend and divisor unsigned lhsBits = LHS.getActiveBits(); unsigned lhsWords = !lhsBits ? 0 : (APInt::whichWord(lhsBits - 1) + 1); @@ -2046,19 +2076,29 @@ APInt APInt::umul_ov(const APInt &RHS, bool &Overflow) const { return Res; } -APInt APInt::sshl_ov(unsigned ShAmt, bool &Overflow) const { - Overflow = ShAmt >= getBitWidth(); +APInt APInt::sshl_ov(const APInt &ShAmt, bool &Overflow) const { + Overflow = ShAmt.uge(getBitWidth()); if (Overflow) - ShAmt = getBitWidth()-1; + return APInt(BitWidth, 0); if (isNonNegative()) // Don't allow sign change. - Overflow = ShAmt >= countLeadingZeros(); + Overflow = ShAmt.uge(countLeadingZeros()); else - Overflow = ShAmt >= countLeadingOnes(); + Overflow = ShAmt.uge(countLeadingOnes()); return *this << ShAmt; } +APInt APInt::ushl_ov(const APInt &ShAmt, bool &Overflow) const { + Overflow = ShAmt.uge(getBitWidth()); + if (Overflow) + return APInt(BitWidth, 0); + + Overflow = ShAmt.ugt(countLeadingZeros()); + + return *this << ShAmt; +} + @@ -2270,8 +2310,7 @@ void APInt::print(raw_ostream &OS, bool isSigned) const { // Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe // and unrestricting assumption. -#define COMPILE_TIME_ASSERT(cond) extern int CTAssert[(cond) ? 1 : -1] -COMPILE_TIME_ASSERT(integerPartWidth % 2 == 0); +static_assert(integerPartWidth % 2 == 0, "Part width must be divisible by 2!"); /* Some handy functions local to this file. */ namespace { diff --git a/contrib/llvm/lib/Support/CommandLine.cpp b/contrib/llvm/lib/Support/CommandLine.cpp index 586ecea..40570ca 100644 --- a/contrib/llvm/lib/Support/CommandLine.cpp +++ b/contrib/llvm/lib/Support/CommandLine.cpp @@ -17,6 +17,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/CommandLine.h" +#include "llvm-c/Support.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" @@ -43,7 +44,8 @@ using namespace cl; //===----------------------------------------------------------------------===// // Template instantiations and anchors. // -namespace llvm { namespace cl { +namespace llvm { +namespace cl { TEMPLATE_INSTANTIATION(class basic_parser<bool>); TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>); TEMPLATE_INSTANTIATION(class basic_parser<int>); @@ -59,7 +61,8 @@ TEMPLATE_INSTANTIATION(class opt<int>); TEMPLATE_INSTANTIATION(class opt<std::string>); TEMPLATE_INSTANTIATION(class opt<char>); TEMPLATE_INSTANTIATION(class opt<bool>); -} } // end namespace llvm::cl +} +} // end namespace llvm::cl // Pin the vtables to this file. void GenericOptionValue::anchor() {} @@ -86,19 +89,16 @@ static char ProgramName[80] = "<premain>"; static const char *ProgramOverview = nullptr; // This collects additional help to be printed. -static ManagedStatic<std::vector<const char*> > MoreHelp; +static ManagedStatic<std::vector<const char *>> MoreHelp; -extrahelp::extrahelp(const char *Help) - : morehelp(Help) { +extrahelp::extrahelp(const char *Help) : morehelp(Help) { MoreHelp->push_back(Help); } static bool OptionListChanged = false; // MarkOptionsChanged - Internal helper function. -void cl::MarkOptionsChanged() { - OptionListChanged = true; -} +void cl::MarkOptionsChanged() { OptionListChanged = true; } /// RegisteredOptionList - This is the list of the command line options that /// have statically constructed themselves. @@ -113,14 +113,20 @@ void Option::addArgument() { } void Option::removeArgument() { - assert(NextRegistered && "argument never registered"); - assert(RegisteredOptionList == this && "argument is not the last registered"); - RegisteredOptionList = NextRegistered; + if (RegisteredOptionList == this) { + RegisteredOptionList = NextRegistered; + MarkOptionsChanged(); + return; + } + Option *O = RegisteredOptionList; + for (; O->NextRegistered != this; O = O->NextRegistered) + ; + O->NextRegistered = NextRegistered; MarkOptionsChanged(); } // This collects the different option categories that have been registered. -typedef SmallPtrSet<OptionCategory*,16> OptionCatSet; +typedef SmallPtrSet<OptionCategory *, 16> OptionCatSet; static ManagedStatic<OptionCatSet> RegisteredOptionCategories; // Initialise the general option category. @@ -131,7 +137,8 @@ void OptionCategory::registerCategory() { RegisteredOptionCategories->end(), [this](const OptionCategory *Category) { return getName() == Category->getName(); - }) == 0 && "Duplicate option categories"); + }) == 0 && + "Duplicate option categories"); RegisteredOptionCategories->insert(this); } @@ -142,12 +149,12 @@ void OptionCategory::registerCategory() { /// GetOptionInfo - Scan the list of registered options, turning them into data /// structures that are easier to handle. -static void GetOptionInfo(SmallVectorImpl<Option*> &PositionalOpts, - SmallVectorImpl<Option*> &SinkOpts, - StringMap<Option*> &OptionsMap) { +static void GetOptionInfo(SmallVectorImpl<Option *> &PositionalOpts, + SmallVectorImpl<Option *> &SinkOpts, + StringMap<Option *> &OptionsMap) { bool HadErrors = false; - SmallVector<const char*, 16> OptionNames; - Option *CAOpt = nullptr; // The ConsumeAfter option if it exists. + SmallVector<const char *, 16> OptionNames; + Option *CAOpt = nullptr; // The ConsumeAfter option if it exists. for (Option *O = RegisteredOptionList; O; O = O->getNextRegisteredOption()) { // If this option wants to handle multiple option names, get the full set. // This handles enum options like "-O1 -O2" etc. @@ -158,7 +165,7 @@ static void GetOptionInfo(SmallVectorImpl<Option*> &PositionalOpts, // Handle named options. for (size_t i = 0, e = OptionNames.size(); i != e; ++i) { // Add argument to the argument map! - if (OptionsMap.GetOrCreateValue(OptionNames[i], O).second != O) { + if (!OptionsMap.insert(std::make_pair(OptionNames[i], O)).second) { errs() << ProgramName << ": CommandLine Error: Option '" << OptionNames[i] << "' registered more than once!\n"; HadErrors = true; @@ -194,31 +201,32 @@ static void GetOptionInfo(SmallVectorImpl<Option*> &PositionalOpts, report_fatal_error("inconsistency in registered CommandLine options"); } - /// LookupOption - Lookup the option specified by the specified option on the /// command line. If there is a value specified (after an equal sign) return /// that as well. This assumes that leading dashes have already been stripped. static Option *LookupOption(StringRef &Arg, StringRef &Value, - const StringMap<Option*> &OptionsMap) { + const StringMap<Option *> &OptionsMap) { // Reject all dashes. - if (Arg.empty()) return nullptr; + if (Arg.empty()) + return nullptr; size_t EqualPos = Arg.find('='); // If we have an equals sign, remember the value. if (EqualPos == StringRef::npos) { // Look up the option. - StringMap<Option*>::const_iterator I = OptionsMap.find(Arg); + StringMap<Option *>::const_iterator I = OptionsMap.find(Arg); return I != OptionsMap.end() ? I->second : nullptr; } // If the argument before the = is a valid option name, we match. If not, // return Arg unmolested. - StringMap<Option*>::const_iterator I = - OptionsMap.find(Arg.substr(0, EqualPos)); - if (I == OptionsMap.end()) return nullptr; + StringMap<Option *>::const_iterator I = + OptionsMap.find(Arg.substr(0, EqualPos)); + if (I == OptionsMap.end()) + return nullptr; - Value = Arg.substr(EqualPos+1); + Value = Arg.substr(EqualPos + 1); Arg = Arg.substr(0, EqualPos); return I->second; } @@ -228,23 +236,25 @@ static Option *LookupOption(StringRef &Arg, StringRef &Value, /// (after an equal sign) return that as well. This assumes that leading dashes /// have already been stripped. static Option *LookupNearestOption(StringRef Arg, - const StringMap<Option*> &OptionsMap, + const StringMap<Option *> &OptionsMap, std::string &NearestString) { // Reject all dashes. - if (Arg.empty()) return nullptr; + if (Arg.empty()) + return nullptr; // Split on any equal sign. std::pair<StringRef, StringRef> SplitArg = Arg.split('='); - StringRef &LHS = SplitArg.first; // LHS == Arg when no '=' is present. + StringRef &LHS = SplitArg.first; // LHS == Arg when no '=' is present. StringRef &RHS = SplitArg.second; // Find the closest match. Option *Best = nullptr; unsigned BestDistance = 0; - for (StringMap<Option*>::const_iterator it = OptionsMap.begin(), - ie = OptionsMap.end(); it != ie; ++it) { + for (StringMap<Option *>::const_iterator it = OptionsMap.begin(), + ie = OptionsMap.end(); + it != ie; ++it) { Option *O = it->second; - SmallVector<const char*, 16> OptionNames; + SmallVector<const char *, 16> OptionNames; O->getExtraOptionNames(OptionNames); if (O->ArgStr[0]) OptionNames.push_back(O->ArgStr); @@ -254,7 +264,7 @@ static Option *LookupNearestOption(StringRef Arg, for (size_t i = 0, e = OptionNames.size(); i != e; ++i) { StringRef Name = OptionNames[i]; unsigned Distance = StringRef(Name).edit_distance( - Flag, /*AllowReplacements=*/true, /*MaxEditDistance=*/BestDistance); + Flag, /*AllowReplacements=*/true, /*MaxEditDistance=*/BestDistance); if (!Best || Distance < BestDistance) { Best = O; BestDistance = Distance; @@ -285,8 +295,8 @@ static bool CommaSeparateAndAddOccurrence(Option *Handler, unsigned pos, if (Handler->addOccurrence(pos, ArgName, Val.substr(0, Pos), MultiArg)) return true; // Erase the portion before the comma, AND the comma. - Val = Val.substr(Pos+1); - Value.substr(Pos+1); // Increment the original value pointer as well. + Val = Val.substr(Pos + 1); + Value.substr(Pos + 1); // Increment the original value pointer as well. // Check for another comma. Pos = Val.find(','); } @@ -313,9 +323,10 @@ static inline bool ProvideOption(Option *Handler, StringRef ArgName, switch (Handler->getValueExpectedFlag()) { case ValueRequired: if (!Value.data()) { // No value specified? - if (i+1 >= argc) + if (i + 1 >= argc) return Handler->error("requires a value!"); // Steal the next argument, like for '-o filename' + assert(argv && "null check"); Value = argv[++i]; } break; @@ -325,8 +336,8 @@ static inline bool ProvideOption(Option *Handler, StringRef ArgName, " with ValueDisallowed modifier!"); if (Value.data()) - return Handler->error("does not allow a value! '" + - Twine(Value) + "' specified."); + return Handler->error("does not allow a value! '" + Twine(Value) + + "' specified."); break; case ValueOptional: break; @@ -347,8 +358,9 @@ static inline bool ProvideOption(Option *Handler, StringRef ArgName, } while (NumAdditionalVals > 0) { - if (i+1 >= argc) + if (i + 1 >= argc) return Handler->error("not enough values!"); + assert(argv && "null check"); Value = argv[++i]; if (CommaSeparateAndAddOccurrence(Handler, i, ArgName, Value, MultiArg)) @@ -364,7 +376,6 @@ static bool ProvidePositionalOption(Option *Handler, StringRef Arg, int i) { return ProvideOption(Handler, Handler->ArgStr, Arg, 0, nullptr, Dummy); } - // Option predicates... static inline bool isGrouping(const Option *O) { return O->getFormattingFlag() == cl::Grouping; @@ -380,39 +391,42 @@ static inline bool isPrefixedOrGrouping(const Option *O) { // otherwise return null. // static Option *getOptionPred(StringRef Name, size_t &Length, - bool (*Pred)(const Option*), - const StringMap<Option*> &OptionsMap) { + bool (*Pred)(const Option *), + const StringMap<Option *> &OptionsMap) { - StringMap<Option*>::const_iterator OMI = OptionsMap.find(Name); + StringMap<Option *>::const_iterator OMI = OptionsMap.find(Name); // Loop while we haven't found an option and Name still has at least two // characters in it (so that the next iteration will not be the empty // string. while (OMI == OptionsMap.end() && Name.size() > 1) { - Name = Name.substr(0, Name.size()-1); // Chop off the last character. + Name = Name.substr(0, Name.size() - 1); // Chop off the last character. OMI = OptionsMap.find(Name); } if (OMI != OptionsMap.end() && Pred(OMI->second)) { Length = Name.size(); - return OMI->second; // Found one! + return OMI->second; // Found one! } - return nullptr; // No option found! + return nullptr; // No option found! } /// HandlePrefixedOrGroupedOption - The specified argument string (which started /// with at least one '-') does not fully match an available option. Check to /// see if this is a prefix or grouped option. If so, split arg into output an /// Arg/Value pair and return the Option to parse it with. -static Option *HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value, - bool &ErrorParsing, - const StringMap<Option*> &OptionsMap) { - if (Arg.size() == 1) return nullptr; +static Option * +HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value, + bool &ErrorParsing, + const StringMap<Option *> &OptionsMap) { + if (Arg.size() == 1) + return nullptr; // Do the lookup! size_t Length = 0; Option *PGOpt = getOptionPred(Arg, Length, isPrefixedOrGrouping, OptionsMap); - if (!PGOpt) return nullptr; + if (!PGOpt) + return nullptr; // If the option is a prefixed option, then the value is simply the // rest of the name... so fall through to later processing, by @@ -438,8 +452,8 @@ static Option *HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value, assert(PGOpt->getValueExpectedFlag() != cl::ValueRequired && "Option can not be cl::Grouping AND cl::ValueRequired!"); int Dummy = 0; - ErrorParsing |= ProvideOption(PGOpt, OneArgName, - StringRef(), 0, nullptr, Dummy); + ErrorParsing |= + ProvideOption(PGOpt, OneArgName, StringRef(), 0, nullptr, Dummy); // Get the next grouping option. PGOpt = getOptionPred(Arg, Length, isGrouping, OptionsMap); @@ -449,8 +463,6 @@ static Option *HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value, return PGOpt; } - - static bool RequiresValue(const Option *O) { return O->getNumOccurrencesFlag() == cl::Required || O->getNumOccurrencesFlag() == cl::OneOrMore; @@ -461,33 +473,33 @@ static bool EatsUnboundedNumberOfValues(const Option *O) { O->getNumOccurrencesFlag() == cl::OneOrMore; } -static bool isWhitespace(char C) { - return strchr(" \t\n\r\f\v", C); -} +static bool isWhitespace(char C) { return strchr(" \t\n\r\f\v", C); } -static bool isQuote(char C) { - return C == '\"' || C == '\''; -} +static bool isQuote(char C) { return C == '\"' || C == '\''; } -static bool isGNUSpecial(char C) { - return strchr("\\\"\' ", C); -} +static bool isGNUSpecial(char C) { return strchr("\\\"\' ", C); } void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, - SmallVectorImpl<const char *> &NewArgv) { + SmallVectorImpl<const char *> &NewArgv, + bool MarkEOLs) { SmallString<128> Token; for (size_t I = 0, E = Src.size(); I != E; ++I) { // Consume runs of whitespace. if (Token.empty()) { - while (I != E && isWhitespace(Src[I])) + while (I != E && isWhitespace(Src[I])) { + // Mark the end of lines in response files + if (MarkEOLs && Src[I] == '\n') + NewArgv.push_back(nullptr); ++I; - if (I == E) break; + } + if (I == E) + break; } // Backslashes can escape backslashes, spaces, and other quotes. Otherwise // they are literal. This makes it much easier to read Windows file paths. if (I + 1 < E && Src[I] == '\\' && isGNUSpecial(Src[I + 1])) { - ++I; // Skip the escape. + ++I; // Skip the escape. Token.push_back(Src[I]); continue; } @@ -502,7 +514,8 @@ void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, Token.push_back(Src[I]); ++I; } - if (I == E) break; + if (I == E) + break; continue; } @@ -521,6 +534,9 @@ void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, // Append the last token after hitting EOF with no whitespace. if (!Token.empty()) NewArgv.push_back(Saver.SaveString(Token.c_str())); + // Mark the end of response files + if (MarkEOLs) + NewArgv.push_back(nullptr); } /// Backslashes are interpreted in a rather complicated way in the Windows-style @@ -562,7 +578,8 @@ static size_t parseBackslash(StringRef Src, size_t I, SmallString<128> &Token) { } void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver, - SmallVectorImpl<const char *> &NewArgv) { + SmallVectorImpl<const char *> &NewArgv, + bool MarkEOLs) { SmallString<128> Token; // This is a small state machine to consume characters until it reaches the @@ -572,8 +589,12 @@ void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver, // INIT state indicates that the current input index is at the start of // the string or between tokens. if (State == INIT) { - if (isWhitespace(Src[I])) + if (isWhitespace(Src[I])) { + // Mark the end of lines in response files + if (MarkEOLs && Src[I] == '\n') + NewArgv.push_back(nullptr); continue; + } if (Src[I] == '"') { State = QUOTED; continue; @@ -596,6 +617,9 @@ void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver, NewArgv.push_back(Saver.SaveString(Token.c_str())); Token.clear(); State = INIT; + // Mark the end of lines in response files + if (MarkEOLs && Src[I] == '\n') + NewArgv.push_back(nullptr); continue; } if (Src[I] == '"') { @@ -626,20 +650,24 @@ void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver, // Append the last token after hitting EOF with no whitespace. if (!Token.empty()) NewArgv.push_back(Saver.SaveString(Token.c_str())); + // Mark the end of response files + if (MarkEOLs) + NewArgv.push_back(nullptr); } static bool ExpandResponseFile(const char *FName, StringSaver &Saver, TokenizerCallback Tokenizer, - SmallVectorImpl<const char *> &NewArgv) { + SmallVectorImpl<const char *> &NewArgv, + bool MarkEOLs = false) { ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr = MemoryBuffer::getFile(FName); if (!MemBufOrErr) return false; - std::unique_ptr<MemoryBuffer> MemBuf = std::move(MemBufOrErr.get()); - StringRef Str(MemBuf->getBufferStart(), MemBuf->getBufferSize()); + MemoryBuffer &MemBuf = *MemBufOrErr.get(); + StringRef Str(MemBuf.getBufferStart(), MemBuf.getBufferSize()); // If we have a UTF-16 byte order mark, convert to UTF-8 for parsing. - ArrayRef<char> BufRef(MemBuf->getBufferStart(), MemBuf->getBufferEnd()); + ArrayRef<char> BufRef(MemBuf.getBufferStart(), MemBuf.getBufferEnd()); std::string UTF8Buf; if (hasUTF16ByteOrderMark(BufRef)) { if (!convertUTF16ToUTF8String(BufRef, UTF8Buf)) @@ -648,7 +676,7 @@ static bool ExpandResponseFile(const char *FName, StringSaver &Saver, } // Tokenize the contents into NewArgv. - Tokenizer(Str, Saver, NewArgv); + Tokenizer(Str, Saver, NewArgv, MarkEOLs); return true; } @@ -656,13 +684,19 @@ static bool ExpandResponseFile(const char *FName, StringSaver &Saver, /// \brief Expand response files on a command line recursively using the given /// StringSaver and tokenization strategy. bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, - SmallVectorImpl<const char *> &Argv) { + SmallVectorImpl<const char *> &Argv, + bool MarkEOLs) { unsigned RspFiles = 0; bool AllExpanded = true; // Don't cache Argv.size() because it can change. - for (unsigned I = 0; I != Argv.size(); ) { + for (unsigned I = 0; I != Argv.size();) { const char *Arg = Argv[I]; + // Check if it is an EOL marker + if (Arg == nullptr) { + ++I; + continue; + } if (Arg[0] != '@') { ++I; continue; @@ -678,7 +712,8 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, // FIXME: If a nested response file uses a relative path, is it relative to // the cwd of the process or the response file? SmallVector<const char *, 0> ExpandedArgv; - if (!ExpandResponseFile(Arg + 1, Saver, Tokenizer, ExpandedArgv)) { + if (!ExpandResponseFile(Arg + 1, Saver, Tokenizer, ExpandedArgv, + MarkEOLs)) { // We couldn't read this file, so we leave it in the argument stream and // move on. AllExpanded = false; @@ -692,22 +727,23 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, } namespace { - class StrDupSaver : public StringSaver { - std::vector<char*> Dups; - public: - ~StrDupSaver() { - for (std::vector<char *>::iterator I = Dups.begin(), E = Dups.end(); - I != E; ++I) { - char *Dup = *I; - free(Dup); - } - } - const char *SaveString(const char *Str) override { - char *Dup = strdup(Str); - Dups.push_back(Dup); - return Dup; +class StrDupSaver : public StringSaver { + std::vector<char *> Dups; + +public: + ~StrDupSaver() { + for (std::vector<char *>::iterator I = Dups.begin(), E = Dups.end(); I != E; + ++I) { + char *Dup = *I; + free(Dup); } - }; + } + const char *SaveString(const char *Str) override { + char *Dup = strdup(Str); + Dups.push_back(Dup); + return Dup; + } +}; } /// ParseEnvironmentOptions - An alternative entry point to the @@ -739,16 +775,15 @@ void cl::ParseEnvironmentOptions(const char *progName, const char *envVar, ParseCommandLineOptions(newArgc, &newArgv[0], Overview); } -void cl::ParseCommandLineOptions(int argc, const char * const *argv, +void cl::ParseCommandLineOptions(int argc, const char *const *argv, const char *Overview) { // Process all registered options. - SmallVector<Option*, 4> PositionalOpts; - SmallVector<Option*, 4> SinkOpts; - StringMap<Option*> Opts; + SmallVector<Option *, 4> PositionalOpts; + SmallVector<Option *, 4> SinkOpts; + StringMap<Option *> Opts; GetOptionInfo(PositionalOpts, SinkOpts, Opts); - assert((!Opts.empty() || !PositionalOpts.empty()) && - "No options specified!"); + assert((!Opts.empty() || !PositionalOpts.empty()) && "No options specified!"); // Expand response files. SmallVector<const char *, 20> newArgv; @@ -784,8 +819,8 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, // Calculate how many positional values are _required_. bool UnboundedFound = false; - for (size_t i = ConsumeAfterOpt ? 1 : 0, e = PositionalOpts.size(); - i != e; ++i) { + for (size_t i = ConsumeAfterOpt ? 1 : 0, e = PositionalOpts.size(); i != e; + ++i) { Option *Opt = PositionalOpts[i]; if (RequiresValue(Opt)) ++NumPositionalRequired; @@ -793,10 +828,10 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, // ConsumeAfter cannot be combined with "optional" positional options // unless there is only one positional argument... if (PositionalOpts.size() > 2) - ErrorParsing |= - Opt->error("error - this positional option will never be matched, " - "because it does not Require a value, and a " - "cl::ConsumeAfter option is active!"); + ErrorParsing |= Opt->error( + "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]) { // This option does not "require" a value... Make sure this option is // not specified after an option that eats all extra arguments, or this @@ -815,7 +850,7 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, // PositionalVals - A vector of "positional" arguments we accumulate into // the process at the end. // - SmallVector<std::pair<StringRef,unsigned>, 4> PositionalVals; + SmallVector<std::pair<StringRef, unsigned>, 4> PositionalVals; // If the program has named positional arguments, and the name has been run // across, keep track of which positional argument was named. Otherwise put @@ -823,7 +858,7 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, Option *ActivePositionalArg = nullptr; // Loop over all of the arguments... processing them. - bool DashDashFound = false; // Have we read '--'? + bool DashDashFound = false; // Have we read '--'? for (int i = 1; i < argc; ++i) { Option *Handler = nullptr; Option *NearestHandler = nullptr; @@ -850,19 +885,19 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, // Positional argument! if (ActivePositionalArg) { ProvidePositionalOption(ActivePositionalArg, argv[i], i); - continue; // We are done! + continue; // We are done! } if (!PositionalOpts.empty()) { - PositionalVals.push_back(std::make_pair(argv[i],i)); + PositionalVals.push_back(std::make_pair(argv[i], i)); // All of the positional arguments have been fulfulled, give the rest to // the consume after option... if it's specified... // if (PositionalVals.size() >= NumPositionalRequired && ConsumeAfterOpt) { for (++i; i < argc; ++i) - PositionalVals.push_back(std::make_pair(argv[i],i)); - break; // Handle outside of the argument processing loop... + PositionalVals.push_back(std::make_pair(argv[i], i)); + break; // Handle outside of the argument processing loop... } // Delay processing positional arguments until the end... @@ -870,14 +905,14 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, } } else if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] == 0 && !DashDashFound) { - DashDashFound = true; // This is the mythical "--"? - continue; // Don't try to process it as an argument itself. + DashDashFound = true; // This is the mythical "--"? + continue; // Don't try to process it as an argument itself. } else if (ActivePositionalArg && (ActivePositionalArg->getMiscFlags() & PositionalEatsArgs)) { // If there is a positional argument eating options, check to see if this // option is another positional argument. If so, treat it as an argument, // otherwise feed it to the eating positional. - ArgName = argv[i]+1; + ArgName = argv[i] + 1; // Eat leading dashes. while (!ArgName.empty() && ArgName[0] == '-') ArgName = ArgName.substr(1); @@ -885,11 +920,11 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, Handler = LookupOption(ArgName, Value, Opts); if (!Handler || Handler->getFormattingFlag() != cl::Positional) { ProvidePositionalOption(ActivePositionalArg, argv[i], i); - continue; // We are done! + continue; // We are done! } - } else { // We start with a '-', must be an argument. - ArgName = argv[i]+1; + } else { // We start with a '-', must be an argument. + ArgName = argv[i] + 1; // Eat leading dashes. while (!ArgName.empty() && ArgName[0] == '-') ArgName = ArgName.substr(1); @@ -898,31 +933,32 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, // Check to see if this "option" is really a prefixed or grouped argument. if (!Handler) - Handler = HandlePrefixedOrGroupedOption(ArgName, Value, - ErrorParsing, Opts); + Handler = + HandlePrefixedOrGroupedOption(ArgName, Value, ErrorParsing, Opts); // Otherwise, look for the closest available option to report to the user // in the upcoming error. if (!Handler && SinkOpts.empty()) - NearestHandler = LookupNearestOption(ArgName, Opts, - NearestHandlerString); + NearestHandler = + LookupNearestOption(ArgName, Opts, NearestHandlerString); } if (!Handler) { if (SinkOpts.empty()) { - errs() << ProgramName << ": Unknown command line argument '" - << argv[i] << "'. Try: '" << argv[0] << " -help'\n"; + errs() << ProgramName << ": Unknown command line argument '" << argv[i] + << "'. Try: '" << argv[0] << " -help'\n"; if (NearestHandler) { // If we know a near match, report it as well. - errs() << ProgramName << ": Did you mean '-" - << NearestHandlerString << "'?\n"; + errs() << ProgramName << ": Did you mean '-" << NearestHandlerString + << "'?\n"; } ErrorParsing = true; } else { - for (SmallVectorImpl<Option*>::iterator I = SinkOpts.begin(), - E = SinkOpts.end(); I != E ; ++I) + for (SmallVectorImpl<Option *>::iterator I = SinkOpts.begin(), + E = SinkOpts.end(); + I != E; ++I) (*I)->addOccurrence(i, "", argv[i]); } continue; @@ -939,17 +975,16 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, // Check and handle positional arguments now... if (NumPositionalRequired > PositionalVals.size()) { errs() << ProgramName - << ": Not enough positional command line arguments specified!\n" - << "Must specify at least " << NumPositionalRequired - << " positional arguments: See: " << argv[0] << " -help\n"; + << ": Not enough positional command line arguments specified!\n" + << "Must specify at least " << NumPositionalRequired + << " positional arguments: See: " << argv[0] << " -help\n"; ErrorParsing = true; } else if (!HasUnlimitedPositionals && PositionalVals.size() > PositionalOpts.size()) { - errs() << ProgramName - << ": Too many positional arguments specified!\n" - << "Can specify at most " << PositionalOpts.size() - << " positional arguments: See: " << argv[0] << " -help\n"; + errs() << ProgramName << ": Too many positional arguments specified!\n" + << "Can specify at most " << PositionalOpts.size() + << " positional arguments: See: " << argv[0] << " -help\n"; ErrorParsing = true; } else if (!ConsumeAfterOpt) { @@ -960,7 +995,7 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, ProvidePositionalOption(PositionalOpts[i], PositionalVals[ValNo].first, PositionalVals[ValNo].second); ValNo++; - --NumPositionalRequired; // We fulfilled our duty... + --NumPositionalRequired; // We fulfilled our duty... } // If we _can_ give this option more arguments, do so now, as long as we @@ -968,13 +1003,13 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, // option even _WANTS_ any more. // bool Done = PositionalOpts[i]->getNumOccurrencesFlag() == cl::Required; - while (NumVals-ValNo > NumPositionalRequired && !Done) { + while (NumVals - ValNo > NumPositionalRequired && !Done) { switch (PositionalOpts[i]->getNumOccurrencesFlag()) { case cl::Optional: - Done = true; // Optional arguments want _at most_ one value - // FALL THROUGH - case cl::ZeroOrMore: // Zero or more will take all they can get... - case cl::OneOrMore: // One or more will take all they can get... + Done = true; // Optional arguments want _at most_ one value + // FALL THROUGH + case cl::ZeroOrMore: // Zero or more will take all they can get... + case cl::OneOrMore: // One or more will take all they can get... ProvidePositionalOption(PositionalOpts[i], PositionalVals[ValNo].first, PositionalVals[ValNo].second); @@ -982,7 +1017,7 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, break; default: llvm_unreachable("Internal error, unexpected NumOccurrences flag in " - "positional argument processing!"); + "positional argument processing!"); } } } @@ -1012,9 +1047,9 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, // Handle over all of the rest of the arguments to the // cl::ConsumeAfter command line option... for (; ValNo != PositionalVals.size(); ++ValNo) - ErrorParsing |= ProvidePositionalOption(ConsumeAfterOpt, - PositionalVals[ValNo].first, - PositionalVals[ValNo].second); + ErrorParsing |= + ProvidePositionalOption(ConsumeAfterOpt, PositionalVals[ValNo].first, + PositionalVals[ValNo].second); } // Loop over args and make sure all required args are specified! @@ -1026,7 +1061,7 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, Opt.second->error("must be specified at least once!"); ErrorParsing = true; } - // Fall through + // Fall through default: break; } @@ -1036,10 +1071,8 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, // Note that if ReadResponseFiles == true, this must be done before the // memory allocated for the expanded command line is free()d below. DEBUG(dbgs() << "Args: "; - for (int i = 0; i < argc; ++i) - dbgs() << argv[i] << ' '; - dbgs() << '\n'; - ); + for (int i = 0; i < argc; ++i) dbgs() << argv[i] << ' '; + dbgs() << '\n';); // Free all of the memory allocated to the map. Command line options may only // be processed once! @@ -1048,7 +1081,8 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, MoreHelp->clear(); // If we had an error processing our arguments, don't let the program execute - if (ErrorParsing) exit(1); + if (ErrorParsing) + exit(1); } //===----------------------------------------------------------------------===// @@ -1056,9 +1090,10 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, // bool Option::error(const Twine &Message, StringRef ArgName) { - if (!ArgName.data()) ArgName = ArgStr; + if (!ArgName.data()) + ArgName = ArgStr; if (ArgName.empty()) - errs() << HelpStr; // Be nice for positional arguments + errs() << HelpStr; // Be nice for positional arguments else errs() << ProgramName << ": for the -" << ArgName; @@ -1066,10 +1101,10 @@ bool Option::error(const Twine &Message, StringRef ArgName) { return true; } -bool Option::addOccurrence(unsigned pos, StringRef ArgName, - StringRef Value, bool MultiArg) { +bool Option::addOccurrence(unsigned pos, StringRef ArgName, StringRef Value, + bool MultiArg) { if (!MultiArg) - NumOccurrences++; // Increment the number of times we have been seen + NumOccurrences++; // Increment the number of times we have been seen switch (getNumOccurrencesFlag()) { case Optional: @@ -1079,21 +1114,22 @@ bool Option::addOccurrence(unsigned pos, StringRef ArgName, case Required: if (NumOccurrences > 1) return error("must occur exactly one time!", ArgName); - // Fall through + // Fall through case OneOrMore: case ZeroOrMore: - case ConsumeAfter: break; + case ConsumeAfter: + break; } return handleOccurrence(pos, ArgName, 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) return DefaultMsg; + if (O.ValueStr[0] == 0) + return DefaultMsg; return O.ValueStr; } @@ -1102,9 +1138,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 std::strlen(ArgStr) + 6; } static void printHelpStr(StringRef HelpStr, size_t Indent, size_t FirstLineIndentedBy) { @@ -1133,7 +1167,7 @@ void alias::printOptionInfo(size_t GlobalWidth) const { size_t basic_parser_impl::getOptionWidth(const Option &O) const { size_t Len = std::strlen(O.ArgStr); if (const char *ValName = getValueName()) - Len += std::strlen(getValueStr(O, ValName))+3; + Len += std::strlen(getValueStr(O, ValName)) + 3; return Len + 6; } @@ -1154,14 +1188,13 @@ 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 - std::strlen(O.ArgStr)); } - // parser<bool> implementation // -bool parser<bool>::parse(Option &O, StringRef ArgName, - StringRef Arg, bool &Value) { +bool parser<bool>::parse(Option &O, StringRef ArgName, StringRef Arg, + bool &Value) { if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" || Arg == "1") { Value = true; @@ -1178,8 +1211,8 @@ bool parser<bool>::parse(Option &O, StringRef ArgName, // parser<boolOrDefault> implementation // -bool parser<boolOrDefault>::parse(Option &O, StringRef ArgName, - StringRef Arg, boolOrDefault &Value) { +bool parser<boolOrDefault>::parse(Option &O, StringRef ArgName, StringRef Arg, + boolOrDefault &Value) { if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" || Arg == "1") { Value = BOU_TRUE; @@ -1196,8 +1229,8 @@ bool parser<boolOrDefault>::parse(Option &O, StringRef ArgName, // parser<int> implementation // -bool parser<int>::parse(Option &O, StringRef ArgName, - StringRef Arg, int &Value) { +bool parser<int>::parse(Option &O, StringRef ArgName, StringRef Arg, + int &Value) { if (Arg.getAsInteger(0, Value)) return O.error("'" + Arg + "' value invalid for integer argument!"); return false; @@ -1205,8 +1238,8 @@ bool parser<int>::parse(Option &O, StringRef ArgName, // parser<unsigned> implementation // -bool parser<unsigned>::parse(Option &O, StringRef ArgName, - StringRef Arg, unsigned &Value) { +bool parser<unsigned>::parse(Option &O, StringRef ArgName, StringRef Arg, + unsigned &Value) { if (Arg.getAsInteger(0, Value)) return O.error("'" + Arg + "' value invalid for uint argument!"); @@ -1216,7 +1249,8 @@ bool parser<unsigned>::parse(Option &O, StringRef ArgName, // parser<unsigned long long> implementation // bool parser<unsigned long long>::parse(Option &O, StringRef ArgName, - StringRef Arg, unsigned long long &Value){ + StringRef Arg, + unsigned long long &Value) { if (Arg.getAsInteger(0, Value)) return O.error("'" + Arg + "' value invalid for uint argument!"); @@ -1235,13 +1269,13 @@ static bool parseDouble(Option &O, StringRef Arg, double &Value) { return false; } -bool parser<double>::parse(Option &O, StringRef ArgName, - StringRef Arg, double &Val) { +bool parser<double>::parse(Option &O, StringRef ArgName, StringRef Arg, + double &Val) { return parseDouble(O, Arg, Val); } -bool parser<float>::parse(Option &O, StringRef ArgName, - StringRef Arg, float &Val) { +bool parser<float>::parse(Option &O, StringRef ArgName, StringRef Arg, + float &Val) { double dVal; if (parseDouble(O, Arg, dVal)) return true; @@ -1249,8 +1283,6 @@ bool parser<float>::parse(Option &O, StringRef ArgName, return false; } - - // generic_parser_base implementation // @@ -1267,18 +1299,17 @@ unsigned generic_parser_base::findOption(const char *Name) { return e; } - // 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 = std::strlen(O.ArgStr) + 6; for (unsigned i = 0, e = getNumOptions(); i != e; ++i) - Size = std::max(Size, std::strlen(getOption(i))+8); + Size = std::max(Size, std::strlen(getOption(i)) + 8); return Size; } else { size_t BaseSize = 0; for (unsigned i = 0, e = getNumOptions(); i != e; ++i) - BaseSize = std::max(BaseSize, std::strlen(getOption(i))+8); + BaseSize = std::max(BaseSize, std::strlen(getOption(i)) + 8); return BaseSize; } } @@ -1293,7 +1324,7 @@ void generic_parser_base::printOptionInfo(const Option &O, printHelpStr(O.HelpStr, GlobalWidth, std::strlen(O.ArgStr) + 6); for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { - size_t NumSpaces = GlobalWidth-strlen(getOption(i))-8; + size_t NumSpaces = GlobalWidth - strlen(getOption(i)) - 8; outs() << " =" << getOption(i); outs().indent(NumSpaces) << " - " << getDescription(i) << '\n'; } @@ -1313,12 +1344,11 @@ static const size_t MaxOptWidth = 8; // arbitrary spacing for printOptionDiff // printGenericOptionDiff - Print the value of this option and it's default. // // "Generic" options have each value mapped to a name. -void generic_parser_base:: -printGenericOptionDiff(const Option &O, const GenericOptionValue &Value, - const GenericOptionValue &Default, - size_t GlobalWidth) const { +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 - std::strlen(O.ArgStr)); unsigned NumOpts = getNumOptions(); for (unsigned i = 0; i != NumOpts; ++i) { @@ -1343,25 +1373,25 @@ printGenericOptionDiff(const Option &O, const GenericOptionValue &Value, // printOptionDiff - Specializations for printing basic value types. // -#define PRINT_OPT_DIFF(T) \ - void parser<T>:: \ - printOptionDiff(const Option &O, T V, OptionValue<T> D, \ - size_t GlobalWidth) const { \ - printOptionName(O, GlobalWidth); \ - std::string Str; \ - { \ - raw_string_ostream SS(Str); \ - SS << V; \ - } \ - outs() << "= " << Str; \ - size_t NumSpaces = MaxOptWidth > Str.size() ? MaxOptWidth - Str.size() : 0;\ - outs().indent(NumSpaces) << " (default: "; \ - if (D.hasValue()) \ - outs() << D.getValue(); \ - else \ - outs() << "*no default*"; \ - outs() << ")\n"; \ - } \ +#define PRINT_OPT_DIFF(T) \ + void parser<T>::printOptionDiff(const Option &O, T V, OptionValue<T> D, \ + size_t GlobalWidth) const { \ + printOptionName(O, GlobalWidth); \ + std::string Str; \ + { \ + raw_string_ostream SS(Str); \ + SS << V; \ + } \ + outs() << "= " << Str; \ + size_t NumSpaces = \ + MaxOptWidth > Str.size() ? MaxOptWidth - Str.size() : 0; \ + outs().indent(NumSpaces) << " (default: "; \ + if (D.hasValue()) \ + outs() << D.getValue(); \ + else \ + outs() << "*no default*"; \ + outs() << ")\n"; \ + } PRINT_OPT_DIFF(bool) PRINT_OPT_DIFF(boolOrDefault) @@ -1372,9 +1402,9 @@ PRINT_OPT_DIFF(double) PRINT_OPT_DIFF(float) PRINT_OPT_DIFF(char) -void parser<std::string>:: -printOptionDiff(const Option &O, StringRef V, OptionValue<std::string> D, - size_t GlobalWidth) const { +void parser<std::string>::printOptionDiff(const Option &O, StringRef V, + OptionValue<std::string> D, + size_t GlobalWidth) const { printOptionName(O, GlobalWidth); outs() << "= " << V; size_t NumSpaces = MaxOptWidth > V.size() ? MaxOptWidth - V.size() : 0; @@ -1387,8 +1417,8 @@ printOptionDiff(const Option &O, StringRef V, OptionValue<std::string> D, } // Print a placeholder for options that don't yet support printOptionDiff(). -void basic_parser_impl:: -printOptionNoValue(const Option &O, size_t GlobalWidth) const { +void basic_parser_impl::printOptionNoValue(const Option &O, + size_t GlobalWidth) const { printOptionName(O, GlobalWidth); outs() << "= *cannot print option value*\n"; } @@ -1398,19 +1428,18 @@ printOptionNoValue(const Option &O, size_t GlobalWidth) const { // static int OptNameCompare(const void *LHS, const void *RHS) { - typedef std::pair<const char *, Option*> pair_ty; + typedef std::pair<const char *, Option *> pair_ty; - return strcmp(((const pair_ty*)LHS)->first, ((const pair_ty*)RHS)->first); + return strcmp(((const pair_ty *)LHS)->first, ((const pair_ty *)RHS)->first); } // Copy Options into a vector so we can sort them as we like. -static void -sortOpts(StringMap<Option*> &OptMap, - SmallVectorImpl< std::pair<const char *, Option*> > &Opts, - bool ShowHidden) { - SmallPtrSet<Option*, 128> OptionSet; // Duplicate option detection. +static void sortOpts(StringMap<Option *> &OptMap, + SmallVectorImpl<std::pair<const char *, Option *>> &Opts, + bool ShowHidden) { + SmallPtrSet<Option *, 128> OptionSet; // Duplicate option detection. - for (StringMap<Option*>::iterator I = OptMap.begin(), E = OptMap.end(); + for (StringMap<Option *>::iterator I = OptMap.begin(), E = OptMap.end(); I != E; ++I) { // Ignore really-hidden options. if (I->second->getOptionHiddenFlag() == ReallyHidden) @@ -1421,11 +1450,11 @@ sortOpts(StringMap<Option*> &OptMap, continue; // If we've already seen this option, don't add it to the list again. - if (!OptionSet.insert(I->second)) + if (!OptionSet.insert(I->second).second) continue; - Opts.push_back(std::pair<const char *, Option*>(I->getKey().data(), - I->second)); + Opts.push_back( + std::pair<const char *, Option *>(I->getKey().data(), I->second)); } // Sort the options list alphabetically. @@ -1437,7 +1466,8 @@ namespace { class HelpPrinter { protected: const bool ShowHidden; - typedef SmallVector<std::pair<const char *, Option*>,128> StrOptionPairVector; + typedef SmallVector<std::pair<const char *, Option *>, 128> + StrOptionPairVector; // Print the options. Opts is assumed to be alphabetically sorted. virtual void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) { for (size_t i = 0, e = Opts.size(); i != e; ++i) @@ -1450,12 +1480,13 @@ public: // Invoke the printer. void operator=(bool Value) { - if (Value == false) return; + if (Value == false) + return; // Get all the options. - SmallVector<Option*, 4> PositionalOpts; - SmallVector<Option*, 4> SinkOpts; - StringMap<Option*> OptMap; + SmallVector<Option *, 4> PositionalOpts; + SmallVector<Option *, 4> SinkOpts; + StringMap<Option *> OptMap; GetOptionInfo(PositionalOpts, SinkOpts, OptMap); StrOptionPairVector Opts; @@ -1467,7 +1498,7 @@ public: outs() << "USAGE: " << ProgramName << " [options]"; // Print out the positional options. - Option *CAOpt = nullptr; // The cl::ConsumeAfter option, if it exists... + Option *CAOpt = nullptr; // The cl::ConsumeAfter option, if it exists... if (!PositionalOpts.empty() && PositionalOpts[0]->getNumOccurrencesFlag() == ConsumeAfter) CAOpt = PositionalOpts[0]; @@ -1479,7 +1510,8 @@ public: } // Print the consume after option info if it exists... - if (CAOpt) outs() << " " << CAOpt->HelpStr; + if (CAOpt) + outs() << " " << CAOpt->HelpStr; outs() << "\n\n"; @@ -1515,12 +1547,12 @@ public: } // Make sure we inherit our base class's operator=() - using HelpPrinter::operator= ; + using HelpPrinter::operator=; protected: void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) override { std::vector<OptionCategory *> SortedCategories; - std::map<OptionCategory *, std::vector<Option *> > CategorizedOptions; + std::map<OptionCategory *, std::vector<Option *>> CategorizedOptions; // Collect registered option categories into vector in preparation for // sorting. @@ -1597,9 +1629,9 @@ private: public: explicit HelpPrinterWrapper(HelpPrinter &UncategorizedPrinter, - CategorizedHelpPrinter &CategorizedPrinter) : - UncategorizedPrinter(UncategorizedPrinter), - CategorizedPrinter(CategorizedPrinter) { } + CategorizedHelpPrinter &CategorizedPrinter) + : UncategorizedPrinter(UncategorizedPrinter), + CategorizedPrinter(CategorizedPrinter) {} // Invoke the printer. void operator=(bool Value); @@ -1614,7 +1646,6 @@ static HelpPrinter UncategorizedHiddenPrinter(true); static CategorizedHelpPrinter CategorizedNormalPrinter(false); static CategorizedHelpPrinter CategorizedHiddenPrinter(true); - // Declare HelpPrinter wrappers that will decide whether or not to invoke // a categorizing help printer static HelpPrinterWrapper WrappedNormalPrinter(UncategorizedNormalPrinter, @@ -1625,38 +1656,36 @@ static HelpPrinterWrapper WrappedHiddenPrinter(UncategorizedHiddenPrinter, // Define uncategorized help printers. // -help-list is hidden by default because if Option categories are being used // then -help behaves the same as -help-list. -static cl::opt<HelpPrinter, true, parser<bool> > -HLOp("help-list", - cl::desc("Display list of available options (-help-list-hidden for more)"), - cl::location(UncategorizedNormalPrinter), cl::Hidden, cl::ValueDisallowed); +static cl::opt<HelpPrinter, true, parser<bool>> HLOp( + "help-list", + cl::desc("Display list of available options (-help-list-hidden for more)"), + cl::location(UncategorizedNormalPrinter), cl::Hidden, cl::ValueDisallowed); -static cl::opt<HelpPrinter, true, parser<bool> > -HLHOp("help-list-hidden", - cl::desc("Display list of all available options"), - cl::location(UncategorizedHiddenPrinter), cl::Hidden, cl::ValueDisallowed); +static cl::opt<HelpPrinter, true, parser<bool>> + HLHOp("help-list-hidden", cl::desc("Display list of all available options"), + cl::location(UncategorizedHiddenPrinter), cl::Hidden, + cl::ValueDisallowed); // Define uncategorized/categorized help printers. These printers change their // behaviour at runtime depending on whether one or more Option categories have // been declared. -static cl::opt<HelpPrinterWrapper, true, parser<bool> > -HOp("help", cl::desc("Display available options (-help-hidden for more)"), - cl::location(WrappedNormalPrinter), cl::ValueDisallowed); - -static cl::opt<HelpPrinterWrapper, true, parser<bool> > -HHOp("help-hidden", cl::desc("Display all available options"), - cl::location(WrappedHiddenPrinter), cl::Hidden, cl::ValueDisallowed); - +static cl::opt<HelpPrinterWrapper, true, parser<bool>> + HOp("help", cl::desc("Display available options (-help-hidden for more)"), + cl::location(WrappedNormalPrinter), cl::ValueDisallowed); +static cl::opt<HelpPrinterWrapper, true, parser<bool>> + HHOp("help-hidden", cl::desc("Display all available options"), + cl::location(WrappedHiddenPrinter), cl::Hidden, cl::ValueDisallowed); -static cl::opt<bool> -PrintOptions("print-options", - cl::desc("Print non-default options after command line parsing"), - cl::Hidden, cl::init(false)); +static cl::opt<bool> PrintOptions( + "print-options", + cl::desc("Print non-default options after command line parsing"), + cl::Hidden, cl::init(false)); -static cl::opt<bool> -PrintAllOptions("print-all-options", - cl::desc("Print all option values after command line parsing"), - cl::Hidden, cl::init(false)); +static cl::opt<bool> PrintAllOptions( + "print-all-options", + cl::desc("Print all option values after command line parsing"), cl::Hidden, + cl::init(false)); void HelpPrinterWrapper::operator=(bool Value) { if (Value == false) @@ -1671,23 +1700,23 @@ void HelpPrinterWrapper::operator=(bool Value) { HLOp.setHiddenFlag(NotHidden); CategorizedPrinter = true; // Invoke categorized printer - } - else + } else UncategorizedPrinter = true; // Invoke uncategorized printer } // Print the value of each option. void cl::PrintOptionValues() { - if (!PrintOptions && !PrintAllOptions) return; + if (!PrintOptions && !PrintAllOptions) + return; // Get all the options. - SmallVector<Option*, 4> PositionalOpts; - SmallVector<Option*, 4> SinkOpts; - StringMap<Option*> OptMap; + SmallVector<Option *, 4> PositionalOpts; + SmallVector<Option *, 4> SinkOpts; + StringMap<Option *> OptMap; GetOptionInfo(PositionalOpts, SinkOpts, OptMap); - SmallVector<std::pair<const char *, Option*>, 128> Opts; - sortOpts(OptMap, Opts, /*ShowHidden*/true); + SmallVector<std::pair<const char *, Option *>, 128> Opts; + sortOpts(OptMap, Opts, /*ShowHidden*/ true); // Compute the maximum argument length... size_t MaxArgLen = 0; @@ -1700,7 +1729,7 @@ void cl::PrintOptionValues() { static void (*OverrideVersionPrinter)() = nullptr; -static std::vector<void (*)()>* ExtraVersionPrinters = nullptr; +static std::vector<void (*)()> *ExtraVersionPrinters = nullptr; namespace { class VersionPrinter { @@ -1722,7 +1751,8 @@ public: OS << " with assertions"; #endif std::string CPU = sys::getHostCPUName(); - if (CPU == "generic") CPU = "(unknown)"; + if (CPU == "generic") + CPU = "(unknown)"; OS << ".\n" #if (ENABLE_TIMESTAMPS == 1) << " Built " << __DATE__ << " (" << __TIME__ << ").\n" @@ -1731,7 +1761,8 @@ public: << " Host CPU: " << CPU << '\n'; } void operator=(bool OptionWasSpecified) { - if (!OptionWasSpecified) return; + if (!OptionWasSpecified) + return; if (OverrideVersionPrinter != nullptr) { (*OverrideVersionPrinter)(); @@ -1754,13 +1785,12 @@ public: }; } // End anonymous namespace - // Define the --version option that prints out the LLVM version for the tool static VersionPrinter VersionPrinterInstance; -static cl::opt<VersionPrinter, true, parser<bool> > -VersOp("version", cl::desc("Display the version of this program"), - cl::location(VersionPrinterInstance), cl::ValueDisallowed); +static cl::opt<VersionPrinter, true, parser<bool>> + VersOp("version", cl::desc("Display the version of this program"), + cl::location(VersionPrinterInstance), cl::ValueDisallowed); // Utility function for printing the help message. void cl::PrintHelpMessage(bool Hidden, bool Categorized) { @@ -1782,13 +1812,9 @@ void cl::PrintHelpMessage(bool Hidden, bool Categorized) { } /// Utility function for printing version number. -void cl::PrintVersionMessage() { - VersionPrinterInstance.print(); -} +void cl::PrintVersionMessage() { VersionPrinterInstance.print(); } -void cl::SetVersionPrinter(void (*func)()) { - OverrideVersionPrinter = func; -} +void cl::SetVersionPrinter(void (*func)()) { OverrideVersionPrinter = func; } void cl::AddExtraVersionPrinter(void (*func)()) { if (!ExtraVersionPrinters) @@ -1797,12 +1823,16 @@ void cl::AddExtraVersionPrinter(void (*func)()) { ExtraVersionPrinters->push_back(func); } -void cl::getRegisteredOptions(StringMap<Option*> &Map) -{ +void cl::getRegisteredOptions(StringMap<Option *> &Map) { // Get all the options. - SmallVector<Option*, 4> PositionalOpts; //NOT USED - SmallVector<Option*, 4> SinkOpts; //NOT USED + SmallVector<Option *, 4> PositionalOpts; // NOT USED + SmallVector<Option *, 4> SinkOpts; // NOT USED assert(Map.size() == 0 && "StringMap must be empty"); GetOptionInfo(PositionalOpts, SinkOpts, Map); return; } + +void LLVMParseCommandLineOptions(int argc, const char *const *argv, + const char *Overview) { + llvm::cl::ParseCommandLineOptions(argc, argv, Overview); +} diff --git a/contrib/llvm/lib/Support/Compression.cpp b/contrib/llvm/lib/Support/Compression.cpp index c32eb21..17ae295 100644 --- a/contrib/llvm/lib/Support/Compression.cpp +++ b/contrib/llvm/lib/Support/Compression.cpp @@ -54,6 +54,9 @@ zlib::Status zlib::compress(StringRef InputBuffer, Status Res = encodeZlibReturnValue(::compress2( (Bytef *)CompressedBuffer.data(), &CompressedSize, (const Bytef *)InputBuffer.data(), InputBuffer.size(), CLevel)); + // Tell MemorySanitizer that zlib output buffer is fully initialized. + // This avoids a false report when running LLVM with uninstrumented ZLib. + __msan_unpoison(CompressedBuffer.data(), CompressedSize); CompressedBuffer.resize(CompressedSize); return Res; } @@ -65,6 +68,9 @@ zlib::Status zlib::uncompress(StringRef InputBuffer, Status Res = encodeZlibReturnValue(::uncompress( (Bytef *)UncompressedBuffer.data(), (uLongf *)&UncompressedSize, (const Bytef *)InputBuffer.data(), InputBuffer.size())); + // Tell MemorySanitizer that zlib output buffer is fully initialized. + // This avoids a false report when running LLVM with uninstrumented ZLib. + __msan_unpoison(UncompressedBuffer.data(), UncompressedSize); UncompressedBuffer.resize(UncompressedSize); return Res; } diff --git a/contrib/llvm/lib/Support/DataStream.cpp b/contrib/llvm/lib/Support/DataStream.cpp index 32653de..dbf6465 100644 --- a/contrib/llvm/lib/Support/DataStream.cpp +++ b/contrib/llvm/lib/Support/DataStream.cpp @@ -32,12 +32,12 @@ using namespace llvm; #define DEBUG_TYPE "Data-stream" // Interface goals: -// * StreamableMemoryObject doesn't care about complexities like using +// * StreamingMemoryObject doesn't care about complexities like using // threads/async callbacks to actually overlap download+compile // * Don't want to duplicate Data in memory // * Don't need to know total Data len in advance // Non-goals: -// StreamableMemoryObject already has random access so this interface only does +// StreamingMemoryObject already has random access so this interface only does // in-order streaming (no arbitrary seeking, else we'd have to buffer all the // Data here in addition to MemoryObject). This also means that if we want // to be able to to free Data, BitstreamBytes/BitcodeReader will implement it diff --git a/contrib/llvm/lib/Support/Debug.cpp b/contrib/llvm/lib/Support/Debug.cpp index ad4d4ef..cb86ea6 100644 --- a/contrib/llvm/lib/Support/Debug.cpp +++ b/contrib/llvm/lib/Support/Debug.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Signals.h" #include "llvm/Support/circular_raw_ostream.h" @@ -50,14 +51,16 @@ DebugBufferSize("debug-buffer-size", cl::Hidden, cl::init(0)); -static std::string CurrentDebugType; +static ManagedStatic<std::vector<std::string> > CurrentDebugType; namespace { struct DebugOnlyOpt { void operator=(const std::string &Val) const { - DebugFlag |= !Val.empty(); - CurrentDebugType = Val; + if (Val.empty()) + return; + DebugFlag = true; + CurrentDebugType->push_back(Val); } }; @@ -67,7 +70,7 @@ static DebugOnlyOpt DebugOnlyOptLoc; static cl::opt<DebugOnlyOpt, true, cl::parser<std::string> > DebugOnly("debug-only", cl::desc("Enable a specific type of debug output"), - cl::Hidden, cl::value_desc("debug string"), + cl::Hidden, cl::ZeroOrMore, cl::value_desc("debug string"), cl::location(DebugOnlyOptLoc), cl::ValueRequired); // Signal handlers - dump debug output on termination. @@ -86,7 +89,15 @@ static void debug_user_sig_handler(void *Cookie) { // with the -debug-only=X option. // bool llvm::isCurrentDebugType(const char *DebugType) { - return CurrentDebugType.empty() || DebugType == CurrentDebugType; + if (CurrentDebugType->empty()) + return true; + // see if DebugType is in list. Note: do not use find() as that forces us to + // unnecessarily create an std::string instance. + for (auto d : *CurrentDebugType) { + if (d == DebugType) + return true; + } + return false; } /// setCurrentDebugType - Set the current debug type, as if the -debug-only=X @@ -94,7 +105,8 @@ bool llvm::isCurrentDebugType(const char *DebugType) { /// debug output to be produced. /// void llvm::setCurrentDebugType(const char *Type) { - CurrentDebugType = Type; + CurrentDebugType->clear(); + CurrentDebugType->push_back(Type); } /// dbgs - Return a circular-buffered debug stream. diff --git a/contrib/llvm/lib/Support/Dwarf.cpp b/contrib/llvm/lib/Support/Dwarf.cpp index c9efa61..4b6337e 100644 --- a/contrib/llvm/lib/Support/Dwarf.cpp +++ b/contrib/llvm/lib/Support/Dwarf.cpp @@ -17,8 +17,6 @@ using namespace llvm; using namespace dwarf; -/// TagString - Return the string for the specified tag. -/// const char *llvm::dwarf::TagString(unsigned Tag) { switch (Tag) { case DW_TAG_array_type: return "DW_TAG_array_type"; @@ -82,6 +80,7 @@ const char *llvm::dwarf::TagString(unsigned Tag) { case DW_TAG_hi_user: return "DW_TAG_hi_user"; case DW_TAG_auto_variable: return "DW_TAG_auto_variable"; case DW_TAG_arg_variable: return "DW_TAG_arg_variable"; + case DW_TAG_expression: return "DW_TAG_expression"; case DW_TAG_rvalue_reference_type: return "DW_TAG_rvalue_reference_type"; case DW_TAG_template_alias: return "DW_TAG_template_alias"; case DW_TAG_coarray_type: return "DW_TAG_coarray_type"; @@ -103,8 +102,6 @@ const char *llvm::dwarf::TagString(unsigned Tag) { return nullptr; } -/// ChildrenString - Return the string for the specified children flag. -/// const char *llvm::dwarf::ChildrenString(unsigned Children) { switch (Children) { case DW_CHILDREN_no: return "DW_CHILDREN_no"; @@ -113,8 +110,6 @@ const char *llvm::dwarf::ChildrenString(unsigned Children) { return nullptr; } -/// AttributeString - Return the string for the specified attribute. -/// const char *llvm::dwarf::AttributeString(unsigned Attribute) { switch (Attribute) { case DW_AT_sibling: return "DW_AT_sibling"; @@ -274,8 +269,6 @@ const char *llvm::dwarf::AttributeString(unsigned Attribute) { return nullptr; } -/// FormEncodingString - Return the string for the specified form encoding. -/// const char *llvm::dwarf::FormEncodingString(unsigned Encoding) { switch (Encoding) { case DW_FORM_addr: return "DW_FORM_addr"; @@ -311,8 +304,6 @@ const char *llvm::dwarf::FormEncodingString(unsigned Encoding) { return nullptr; } -/// OperationEncodingString - Return the string for the specified operation -/// encoding. const char *llvm::dwarf::OperationEncodingString(unsigned Encoding) { switch (Encoding) { case DW_OP_addr: return "DW_OP_addr"; @@ -480,8 +471,6 @@ const char *llvm::dwarf::OperationEncodingString(unsigned Encoding) { return nullptr; } -/// AttributeEncodingString - Return the string for the specified attribute -/// encoding. const char *llvm::dwarf::AttributeEncodingString(unsigned Encoding) { switch (Encoding) { case DW_ATE_address: return "DW_ATE_address"; @@ -506,8 +495,6 @@ const char *llvm::dwarf::AttributeEncodingString(unsigned Encoding) { return nullptr; } -/// DecimalSignString - Return the string for the specified decimal sign -/// attribute. const char *llvm::dwarf::DecimalSignString(unsigned Sign) { switch (Sign) { case DW_DS_unsigned: return "DW_DS_unsigned"; @@ -519,8 +506,6 @@ const char *llvm::dwarf::DecimalSignString(unsigned Sign) { return nullptr; } -/// EndianityString - Return the string for the specified endianity. -/// const char *llvm::dwarf::EndianityString(unsigned Endian) { switch (Endian) { case DW_END_default: return "DW_END_default"; @@ -532,8 +517,6 @@ const char *llvm::dwarf::EndianityString(unsigned Endian) { return nullptr; } -/// AccessibilityString - Return the string for the specified accessibility. -/// const char *llvm::dwarf::AccessibilityString(unsigned Access) { switch (Access) { // Accessibility codes @@ -544,8 +527,6 @@ const char *llvm::dwarf::AccessibilityString(unsigned Access) { return nullptr; } -/// VisibilityString - Return the string for the specified visibility. -/// const char *llvm::dwarf::VisibilityString(unsigned Visibility) { switch (Visibility) { case DW_VIS_local: return "DW_VIS_local"; @@ -555,8 +536,6 @@ const char *llvm::dwarf::VisibilityString(unsigned Visibility) { return nullptr; } -/// VirtualityString - Return the string for the specified virtuality. -/// const char *llvm::dwarf::VirtualityString(unsigned Virtuality) { switch (Virtuality) { case DW_VIRTUALITY_none: return "DW_VIRTUALITY_none"; @@ -566,8 +545,6 @@ const char *llvm::dwarf::VirtualityString(unsigned Virtuality) { return nullptr; } -/// LanguageString - Return the string for the specified language. -/// const char *llvm::dwarf::LanguageString(unsigned Language) { switch (Language) { case DW_LANG_C89: return "DW_LANG_C89"; @@ -598,13 +575,12 @@ const char *llvm::dwarf::LanguageString(unsigned Language) { case DW_LANG_C_plus_plus_11: return "DW_LANG_C_plus_plus_11"; case DW_LANG_OCaml: return "DW_LANG_OCaml"; case DW_LANG_lo_user: return "DW_LANG_lo_user"; + case DW_LANG_Mips_Assembler: return "DW_LANG_Mips_Assembler"; case DW_LANG_hi_user: return "DW_LANG_hi_user"; } return nullptr; } -/// CaseString - Return the string for the specified identifier case. -/// const char *llvm::dwarf::CaseString(unsigned Case) { switch (Case) { case DW_ID_case_sensitive: return "DW_ID_case_sensitive"; @@ -615,8 +591,6 @@ const char *llvm::dwarf::CaseString(unsigned Case) { return nullptr; } -/// ConventionString - Return the string for the specified calling convention. -/// const char *llvm::dwarf::ConventionString(unsigned Convention) { switch (Convention) { case DW_CC_normal: return "DW_CC_normal"; @@ -628,8 +602,6 @@ const char *llvm::dwarf::ConventionString(unsigned Convention) { return nullptr; } -/// InlineCodeString - Return the string for the specified inline code. -/// const char *llvm::dwarf::InlineCodeString(unsigned Code) { switch (Code) { case DW_INL_not_inlined: return "DW_INL_not_inlined"; @@ -640,8 +612,6 @@ const char *llvm::dwarf::InlineCodeString(unsigned Code) { return nullptr; } -/// ArrayOrderString - Return the string for the specified array order. -/// const char *llvm::dwarf::ArrayOrderString(unsigned Order) { switch (Order) { case DW_ORD_row_major: return "DW_ORD_row_major"; @@ -650,8 +620,6 @@ const char *llvm::dwarf::ArrayOrderString(unsigned Order) { return nullptr; } -/// DiscriminantString - Return the string for the specified discriminant -/// descriptor. const char *llvm::dwarf::DiscriminantString(unsigned Discriminant) { switch (Discriminant) { case DW_DSC_label: return "DW_DSC_label"; @@ -660,8 +628,6 @@ const char *llvm::dwarf::DiscriminantString(unsigned Discriminant) { return nullptr; } -/// LNStandardString - Return the string for the specified line number standard. -/// const char *llvm::dwarf::LNStandardString(unsigned Standard) { switch (Standard) { case DW_LNS_copy: return "DW_LNS_copy"; @@ -680,8 +646,6 @@ const char *llvm::dwarf::LNStandardString(unsigned Standard) { return nullptr; } -/// LNExtendedString - Return the string for the specified line number extended -/// opcode encodings. const char *llvm::dwarf::LNExtendedString(unsigned Encoding) { switch (Encoding) { // Line Number Extended Opcode Encodings @@ -695,8 +659,6 @@ const char *llvm::dwarf::LNExtendedString(unsigned Encoding) { return nullptr; } -/// MacinfoString - Return the string for the specified macinfo type encodings. -/// const char *llvm::dwarf::MacinfoString(unsigned Encoding) { switch (Encoding) { // Macinfo Type Encodings @@ -709,8 +671,6 @@ const char *llvm::dwarf::MacinfoString(unsigned Encoding) { return nullptr; } -/// CallFrameString - Return the string for the specified call frame instruction -/// encodings. const char *llvm::dwarf::CallFrameString(unsigned Encoding) { switch (Encoding) { case DW_CFA_nop: return "DW_CFA_nop"; @@ -748,6 +708,36 @@ const char *llvm::dwarf::CallFrameString(unsigned Encoding) { return nullptr; } +const char *llvm::dwarf::ApplePropertyString(unsigned Prop) { + switch (Prop) { + case DW_APPLE_PROPERTY_readonly: + return "DW_APPLE_PROPERTY_readonly"; + case DW_APPLE_PROPERTY_getter: + return "DW_APPLE_PROPERTY_getter"; + case DW_APPLE_PROPERTY_assign: + return "DW_APPLE_PROPERTY_assign"; + case DW_APPLE_PROPERTY_readwrite: + return "DW_APPLE_PROPERTY_readwrite"; + case DW_APPLE_PROPERTY_retain: + return "DW_APPLE_PROPERTY_retain"; + case DW_APPLE_PROPERTY_copy: + return "DW_APPLE_PROPERTY_copy"; + case DW_APPLE_PROPERTY_nonatomic: + return "DW_APPLE_PROPERTY_nonatomic"; + case DW_APPLE_PROPERTY_setter: + return "DW_APPLE_PROPERTY_setter"; + case DW_APPLE_PROPERTY_atomic: + return "DW_APPLE_PROPERTY_atomic"; + case DW_APPLE_PROPERTY_weak: + return "DW_APPLE_PROPERTY_weak"; + case DW_APPLE_PROPERTY_strong: + return "DW_APPLE_PROPERTY_strong"; + case DW_APPLE_PROPERTY_unsafe_unretained: + return "DW_APPLE_PROPERTY_unsafe_unretained"; + } + return nullptr; +} + const char *llvm::dwarf::AtomTypeString(unsigned AT) { switch (AT) { case dwarf::DW_ATOM_null: @@ -795,3 +785,34 @@ const char *llvm::dwarf::GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage } llvm_unreachable("Unknown GDBIndexEntryLinkage value"); } + +const char *llvm::dwarf::AttributeValueString(uint16_t Attr, unsigned Val) { + switch (Attr) { + case DW_AT_accessibility: + return AccessibilityString(Val); + case DW_AT_virtuality: + return VirtualityString(Val); + case DW_AT_language: + return LanguageString(Val); + case DW_AT_encoding: + return AttributeEncodingString(Val); + case DW_AT_decimal_sign: + return DecimalSignString(Val); + case DW_AT_endianity: + return EndianityString(Val); + case DW_AT_visibility: + return VisibilityString(Val); + case DW_AT_identifier_case: + return CaseString(Val); + case DW_AT_calling_convention: + return ConventionString(Val); + case DW_AT_inline: + return InlineCodeString(Val); + case DW_AT_ordering: + return ArrayOrderString(Val); + case DW_AT_discr_value: + return DiscriminantString(Val); + } + + return nullptr; +} diff --git a/contrib/llvm/lib/Support/Errno.cpp b/contrib/llvm/lib/Support/Errno.cpp index 1eefa3e..3ba2a12 100644 --- a/contrib/llvm/lib/Support/Errno.cpp +++ b/contrib/llvm/lib/Support/Errno.cpp @@ -35,12 +35,14 @@ std::string StrError() { #endif // HAVE_ERRNO_H std::string StrError(int errnum) { - const int MaxErrStrLen = 2000; - char buffer[MaxErrStrLen]; - buffer[0] = '\0'; std::string str; if (errnum == 0) return str; +#if defined(HAVE_STRERROR_R) || HAVE_DECL_STRERROR_S + const int MaxErrStrLen = 2000; + char buffer[MaxErrStrLen]; + buffer[0] = '\0'; +#endif #ifdef HAVE_STRERROR_R // strerror_r is thread-safe. diff --git a/contrib/llvm/lib/Support/ErrorHandling.cpp b/contrib/llvm/lib/Support/ErrorHandling.cpp index c36007f..a25e21a 100644 --- a/contrib/llvm/lib/Support/ErrorHandling.cpp +++ b/contrib/llvm/lib/Support/ErrorHandling.cpp @@ -19,9 +19,10 @@ #include "llvm/Config/config.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Errc.h" -#include "llvm/Support/Signals.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/MutexGuard.h" +#include "llvm/Support/Signals.h" #include "llvm/Support/Threading.h" #include "llvm/Support/WindowsError.h" #include "llvm/Support/raw_ostream.h" @@ -41,18 +42,18 @@ using namespace llvm; static fatal_error_handler_t ErrorHandler = nullptr; static void *ErrorHandlerUserData = nullptr; -static sys::Mutex ErrorHandlerMutex; +static ManagedStatic<sys::Mutex> ErrorHandlerMutex; void llvm::install_fatal_error_handler(fatal_error_handler_t handler, void *user_data) { - llvm::MutexGuard Lock(ErrorHandlerMutex); + llvm::MutexGuard Lock(*ErrorHandlerMutex); assert(!ErrorHandler && "Error handler already registered!\n"); ErrorHandler = handler; ErrorHandlerUserData = user_data; } void llvm::remove_fatal_error_handler() { - llvm::MutexGuard Lock(ErrorHandlerMutex); + llvm::MutexGuard Lock(*ErrorHandlerMutex); ErrorHandler = nullptr; ErrorHandlerUserData = nullptr; } @@ -75,7 +76,7 @@ void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) { { // Only acquire the mutex while reading the handler, so as not to invoke a // user-supplied callback under a lock. - llvm::MutexGuard Lock(ErrorHandlerMutex); + llvm::MutexGuard Lock(*ErrorHandlerMutex); handler = ErrorHandler; handlerData = ErrorHandlerUserData; } diff --git a/contrib/llvm/lib/Support/FileOutputBuffer.cpp b/contrib/llvm/lib/Support/FileOutputBuffer.cpp index 94bcdc5..b176a8b 100644 --- a/contrib/llvm/lib/Support/FileOutputBuffer.cpp +++ b/contrib/llvm/lib/Support/FileOutputBuffer.cpp @@ -12,20 +12,24 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Errc.h" -#include "llvm/Support/FileOutputBuffer.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/raw_ostream.h" #include <system_error> +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#include <unistd.h> +#else +#include <io.h> +#endif + using llvm::sys::fs::mapped_file_region; namespace llvm { -FileOutputBuffer::FileOutputBuffer(mapped_file_region * R, +FileOutputBuffer::FileOutputBuffer(std::unique_ptr<mapped_file_region> R, StringRef Path, StringRef TmpPath) - : Region(R) - , FinalPath(Path) - , TempPath(TmpPath) { -} + : Region(std::move(R)), FinalPath(Path), TempPath(TmpPath) {} FileOutputBuffer::~FileOutputBuffer() { sys::fs::remove(Twine(TempPath)); @@ -73,28 +77,28 @@ FileOutputBuffer::create(StringRef FilePath, size_t Size, if (EC) return EC; - std::unique_ptr<mapped_file_region> MappedFile(new mapped_file_region( - FD, true, mapped_file_region::readwrite, Size, 0, EC)); + EC = sys::fs::resize_file(FD, Size); if (EC) return EC; - Result.reset(new FileOutputBuffer(MappedFile.get(), FilePath, TempFilePath)); - if (Result) - MappedFile.release(); + auto MappedFile = llvm::make_unique<mapped_file_region>( + FD, mapped_file_region::readwrite, Size, 0, EC); + int Ret = close(FD); + if (EC) + return EC; + if (Ret) + return std::error_code(errno, std::generic_category()); + + Result.reset( + new FileOutputBuffer(std::move(MappedFile), FilePath, TempFilePath)); return std::error_code(); } -std::error_code FileOutputBuffer::commit(int64_t NewSmallerSize) { +std::error_code FileOutputBuffer::commit() { // Unmap buffer, letting OS flush dirty pages to file on disk. Region.reset(); - // If requested, resize file as part of commit. - if ( NewSmallerSize != -1 ) { - std::error_code EC = sys::fs::resize_file(Twine(TempPath), NewSmallerSize); - if (EC) - return EC; - } // Rename file to final name. return sys::fs::rename(Twine(TempPath), Twine(FinalPath)); diff --git a/contrib/llvm/lib/Support/FileUtilities.cpp b/contrib/llvm/lib/Support/FileUtilities.cpp index 8a23491..5316f04 100644 --- a/contrib/llvm/lib/Support/FileUtilities.cpp +++ b/contrib/llvm/lib/Support/FileUtilities.cpp @@ -182,7 +182,7 @@ int llvm::DiffFilesWithTolerance(StringRef NameA, *Error = EC.message(); return 2; } - std::unique_ptr<MemoryBuffer> F1 = std::move(F1OrErr.get()); + MemoryBuffer &F1 = *F1OrErr.get(); ErrorOr<std::unique_ptr<MemoryBuffer>> F2OrErr = MemoryBuffer::getFile(NameB); if (std::error_code EC = F2OrErr.getError()) { @@ -190,17 +190,17 @@ int llvm::DiffFilesWithTolerance(StringRef NameA, *Error = EC.message(); return 2; } - std::unique_ptr<MemoryBuffer> F2 = std::move(F2OrErr.get()); + MemoryBuffer &F2 = *F2OrErr.get(); // Okay, now that we opened the files, scan them for the first difference. - const char *File1Start = F1->getBufferStart(); - const char *File2Start = F2->getBufferStart(); - const char *File1End = F1->getBufferEnd(); - const char *File2End = F2->getBufferEnd(); + const char *File1Start = F1.getBufferStart(); + const char *File2Start = F2.getBufferStart(); + const char *File1End = F1.getBufferEnd(); + const char *File2End = F2.getBufferEnd(); const char *F1P = File1Start; const char *F2P = File2Start; - uint64_t A_size = F1->getBufferSize(); - uint64_t B_size = F2->getBufferSize(); + uint64_t A_size = F1.getBufferSize(); + uint64_t B_size = F2.getBufferSize(); // Are the buffers identical? Common case: Handle this efficiently. if (A_size == B_size && diff --git a/contrib/llvm/lib/Support/GraphWriter.cpp b/contrib/llvm/lib/Support/GraphWriter.cpp index e68ee43..054df52 100644 --- a/contrib/llvm/lib/Support/GraphWriter.cpp +++ b/contrib/llvm/lib/Support/GraphWriter.cpp @@ -105,9 +105,10 @@ struct GraphSession { SmallVector<StringRef, 8> parts; Names.split(parts, "|"); for (auto Name : parts) { - ProgramPath = sys::FindProgramByName(Name); - if (!ProgramPath.empty()) + if (ErrorOr<std::string> P = sys::findProgramByName(Name)) { + ProgramPath = *P; return true; + } Log << " Tried '" << Name << "'\n"; } return false; diff --git a/contrib/llvm/lib/Support/Host.cpp b/contrib/llvm/lib/Support/Host.cpp index e2dd6d5..2abbc14 100644 --- a/contrib/llvm/lib/Support/Host.cpp +++ b/contrib/llvm/lib/Support/Host.cpp @@ -17,8 +17,8 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/Config/config.h" -#include "llvm/Support/DataStream.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/raw_ostream.h" #include <string.h> @@ -49,6 +49,26 @@ using namespace llvm; +#if defined(__linux__) +static ssize_t LLVM_ATTRIBUTE_UNUSED readCpuInfo(void *Buf, size_t Size) { + // Note: We cannot mmap /proc/cpuinfo here and then process the resulting + // memory buffer because the 'file' has 0 size (it can be read from only + // as a stream). + + int FD; + std::error_code EC = sys::fs::openFileForRead("/proc/cpuinfo", FD); + if (EC) { + DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << EC.message() << "\n"); + return -1; + } + int Ret = read(FD, Buf, Size); + int CloseStatus = close(FD); + if (CloseStatus) + return -1; + return Ret; +} +#endif + #if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)\ || defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) @@ -489,22 +509,12 @@ StringRef sys::getHostCPUName() { // processor type. On Linux, this is exposed through the /proc/cpuinfo file. const char *generic = "generic"; - // Note: We cannot mmap /proc/cpuinfo here and then process the resulting - // memory buffer because the 'file' has 0 size (it can be read from only - // as a stream). - - std::string Err; - DataStreamer *DS = getDataFileStreamer("/proc/cpuinfo", &Err); - if (!DS) { - DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << Err << "\n"); - return generic; - } - // The cpu line is second (after the 'processor: 0' line), so if this // buffer is too small then something has changed (or is wrong). char buffer[1024]; - size_t CPUInfoSize = DS->GetBytes((unsigned char*) buffer, sizeof(buffer)); - delete DS; + ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer)); + if (CPUInfoSize == -1) + return generic; const char *CPUInfoStart = buffer; const char *CPUInfoEnd = buffer + CPUInfoSize; @@ -578,22 +588,13 @@ StringRef sys::getHostCPUName() { StringRef sys::getHostCPUName() { // The cpuid register on arm is not accessible from user space. On Linux, // it is exposed through the /proc/cpuinfo file. - // Note: We cannot mmap /proc/cpuinfo here and then process the resulting - // memory buffer because the 'file' has 0 size (it can be read from only - // as a stream). - - std::string Err; - DataStreamer *DS = getDataFileStreamer("/proc/cpuinfo", &Err); - if (!DS) { - DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << Err << "\n"); - return "generic"; - } // Read 1024 bytes from /proc/cpuinfo, which should contain the CPU part line // in all cases. char buffer[1024]; - size_t CPUInfoSize = DS->GetBytes((unsigned char*) buffer, sizeof(buffer)); - delete DS; + ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer)); + if (CPUInfoSize == -1) + return "generic"; StringRef Str(buffer, CPUInfoSize); @@ -643,22 +644,13 @@ StringRef sys::getHostCPUName() { #elif defined(__linux__) && defined(__s390x__) StringRef sys::getHostCPUName() { // STIDP is a privileged operation, so use /proc/cpuinfo instead. - // Note: We cannot mmap /proc/cpuinfo here and then process the resulting - // memory buffer because the 'file' has 0 size (it can be read from only - // as a stream). - - std::string Err; - DataStreamer *DS = getDataFileStreamer("/proc/cpuinfo", &Err); - if (!DS) { - DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << Err << "\n"); - return "generic"; - } // The "processor 0:" line comes after a fair amount of other information, // including a cache breakdown, but this should be plenty. char buffer[2048]; - size_t CPUInfoSize = DS->GetBytes((unsigned char*) buffer, sizeof(buffer)); - delete DS; + ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer)); + if (CPUInfoSize == -1) + return "generic"; StringRef Str(buffer, CPUInfoSize); SmallVector<StringRef, 32> Lines; @@ -690,18 +682,12 @@ StringRef sys::getHostCPUName() { #if defined(__linux__) && (defined(__arm__) || defined(__aarch64__)) bool sys::getHostCPUFeatures(StringMap<bool> &Features) { - std::string Err; - DataStreamer *DS = getDataFileStreamer("/proc/cpuinfo", &Err); - if (!DS) { - DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << Err << "\n"); - return false; - } - // Read 1024 bytes from /proc/cpuinfo, which should contain the Features line // in all cases. char buffer[1024]; - size_t CPUInfoSize = DS->GetBytes((unsigned char*) buffer, sizeof(buffer)); - delete DS; + ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer)); + if (CPUInfoSize == -1) + return false; StringRef Str(buffer, CPUInfoSize); @@ -759,13 +745,13 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) { #endif if (LLVMFeatureStr != "") - Features.GetOrCreateValue(LLVMFeatureStr).setValue(true); + Features[LLVMFeatureStr] = true; } #if defined(__aarch64__) // If we have all crypto bits we can add the feature if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2)) - Features.GetOrCreateValue("crypto").setValue(true); + Features["crypto"] = true; #endif return true; diff --git a/contrib/llvm/lib/Support/IncludeFile.cpp b/contrib/llvm/lib/Support/IncludeFile.cpp deleted file mode 100644 index e67acb3..0000000 --- a/contrib/llvm/lib/Support/IncludeFile.cpp +++ /dev/null @@ -1,20 +0,0 @@ -//===- lib/Support/IncludeFile.cpp - Ensure Linking Of Implementation -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the IncludeFile constructor. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/IncludeFile.h" - -using namespace llvm; - -// This constructor is used to ensure linking of other modules. See the -// llvm/Support/IncludeFile.h header for details. -IncludeFile::IncludeFile(const void*) {} diff --git a/contrib/llvm/lib/Support/LineIterator.cpp b/contrib/llvm/lib/Support/LineIterator.cpp index 947a8fb..5baa1a3 100644 --- a/contrib/llvm/lib/Support/LineIterator.cpp +++ b/contrib/llvm/lib/Support/LineIterator.cpp @@ -12,16 +12,39 @@ using namespace llvm; -line_iterator::line_iterator(const MemoryBuffer &Buffer, char CommentMarker) +static bool isAtLineEnd(const char *P) { + if (*P == '\n') + return true; + if (*P == '\r' && *(P + 1) == '\n') + return true; + return false; +} + +static bool skipIfAtLineEnd(const char *&P) { + if (*P == '\n') { + ++P; + return true; + } + if (*P == '\r' && *(P + 1) == '\n') { + P += 2; + return true; + } + return false; +} + +line_iterator::line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks, + char CommentMarker) : Buffer(Buffer.getBufferSize() ? &Buffer : nullptr), - CommentMarker(CommentMarker), LineNumber(1), + CommentMarker(CommentMarker), SkipBlanks(SkipBlanks), LineNumber(1), CurrentLine(Buffer.getBufferSize() ? Buffer.getBufferStart() : nullptr, 0) { // Ensure that if we are constructed on a non-empty memory buffer that it is // a null terminated buffer. if (Buffer.getBufferSize()) { assert(Buffer.getBufferEnd()[0] == '\0'); - advance(); + // Make sure we don't skip a leading newline if we're keeping blanks + if (SkipBlanks || !isAtLineEnd(Buffer.getBufferStart())) + advance(); } } @@ -29,25 +52,27 @@ void line_iterator::advance() { assert(Buffer && "Cannot advance past the end!"); const char *Pos = CurrentLine.end(); - assert(Pos == Buffer->getBufferStart() || *Pos == '\n' || *Pos == '\0'); + assert(Pos == Buffer->getBufferStart() || isAtLineEnd(Pos) || *Pos == '\0'); - if (CommentMarker == '\0') { + if (skipIfAtLineEnd(Pos)) + ++LineNumber; + if (!SkipBlanks && isAtLineEnd(Pos)) { + // Nothing to do for a blank line. + } else if (CommentMarker == '\0') { // If we're not stripping comments, this is simpler. - size_t Blanks = 0; - while (Pos[Blanks] == '\n') - ++Blanks; - Pos += Blanks; - LineNumber += Blanks; + while (skipIfAtLineEnd(Pos)) + ++LineNumber; } else { // Skip comments and count line numbers, which is a bit more complex. for (;;) { + if (isAtLineEnd(Pos) && !SkipBlanks) + break; if (*Pos == CommentMarker) do { ++Pos; - } while (*Pos != '\0' && *Pos != '\n'); - if (*Pos != '\n') + } while (*Pos != '\0' && !isAtLineEnd(Pos)); + if (!skipIfAtLineEnd(Pos)) break; - ++Pos; ++LineNumber; } } @@ -61,9 +86,9 @@ void line_iterator::advance() { // Measure the line. size_t Length = 0; - do { + while (Pos[Length] != '\0' && !isAtLineEnd(&Pos[Length])) { ++Length; - } while (Pos[Length] != '\0' && Pos[Length] != '\n'); + } CurrentLine = StringRef(Pos, Length); } diff --git a/contrib/llvm/lib/Support/LockFileManager.cpp b/contrib/llvm/lib/Support/LockFileManager.cpp index 3f224e0..5b82c36 100644 --- a/contrib/llvm/lib/Support/LockFileManager.cpp +++ b/contrib/llvm/lib/Support/LockFileManager.cpp @@ -39,11 +39,11 @@ LockFileManager::readLockFile(StringRef LockFileName) { sys::fs::remove(LockFileName); return None; } - std::unique_ptr<MemoryBuffer> MB = std::move(MBOrErr.get()); + MemoryBuffer &MB = *MBOrErr.get(); StringRef Hostname; StringRef PIDStr; - std::tie(Hostname, PIDStr) = getToken(MB->getBuffer(), " "); + std::tie(Hostname, PIDStr) = getToken(MB.getBuffer(), " "); PIDStr = PIDStr.substr(PIDStr.find_first_not_of(" ")); int PID; if (!PIDStr.getAsInteger(10, PID)) { @@ -204,8 +204,8 @@ LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock() { // If the lock file is still expected to be there, check whether it still // is. if (!LockFileGone) { - bool Exists; - if (!sys::fs::exists(LockFileName.str(), Exists) && !Exists) { + if (sys::fs::access(LockFileName.c_str(), sys::fs::AccessMode::Exist) == + errc::no_such_file_or_directory) { LockFileGone = true; LockFileJustDisappeared = true; } diff --git a/contrib/llvm/lib/Support/MD5.cpp b/contrib/llvm/lib/Support/MD5.cpp index 514466c..ceab580 100644 --- a/contrib/llvm/lib/Support/MD5.cpp +++ b/contrib/llvm/lib/Support/MD5.cpp @@ -208,11 +208,11 @@ void MD5::update(ArrayRef<uint8_t> Data) { memcpy(&buffer[used], Ptr, free); Ptr = Ptr + free; Size -= free; - body(ArrayRef<uint8_t>(buffer, 64)); + body(makeArrayRef(buffer, 64)); } if (Size >= 64) { - Ptr = body(ArrayRef<uint8_t>(Ptr, Size & ~(unsigned long) 0x3f)); + Ptr = body(makeArrayRef(Ptr, Size & ~(unsigned long) 0x3f)); Size &= 0x3f; } @@ -229,7 +229,7 @@ void MD5::update(StringRef Str) { /// \brief Finish the hash and place the resulting hash into \p result. /// \param result is assumed to be a minimum of 16-bytes in size. -void MD5::final(MD5Result &result) { +void MD5::final(MD5Result &Result) { unsigned long used, free; used = lo & 0x3f; @@ -240,7 +240,7 @@ void MD5::final(MD5Result &result) { if (free < 8) { memset(&buffer[used], 0, free); - body(ArrayRef<uint8_t>(buffer, 64)); + body(makeArrayRef(buffer, 64)); used = 0; free = 64; } @@ -257,30 +257,30 @@ void MD5::final(MD5Result &result) { buffer[62] = hi >> 16; buffer[63] = hi >> 24; - body(ArrayRef<uint8_t>(buffer, 64)); - - result[0] = a; - result[1] = a >> 8; - result[2] = a >> 16; - result[3] = a >> 24; - result[4] = b; - result[5] = b >> 8; - result[6] = b >> 16; - result[7] = b >> 24; - result[8] = c; - result[9] = c >> 8; - result[10] = c >> 16; - result[11] = c >> 24; - result[12] = d; - result[13] = d >> 8; - result[14] = d >> 16; - result[15] = d >> 24; + body(makeArrayRef(buffer, 64)); + + Result[0] = a; + Result[1] = a >> 8; + Result[2] = a >> 16; + Result[3] = a >> 24; + Result[4] = b; + Result[5] = b >> 8; + Result[6] = b >> 16; + Result[7] = b >> 24; + Result[8] = c; + Result[9] = c >> 8; + Result[10] = c >> 16; + Result[11] = c >> 24; + Result[12] = d; + Result[13] = d >> 8; + Result[14] = d >> 16; + Result[15] = d >> 24; } -void MD5::stringifyResult(MD5Result &result, SmallString<32> &Str) { +void MD5::stringifyResult(MD5Result &Result, SmallString<32> &Str) { raw_svector_ostream Res(Str); for (int i = 0; i < 16; ++i) - Res << format("%.2x", result[i]); + Res << format("%.2x", Result[i]); } } diff --git a/contrib/llvm/lib/Support/MathExtras.cpp b/contrib/llvm/lib/Support/MathExtras.cpp new file mode 100644 index 0000000..ba09245 --- /dev/null +++ b/contrib/llvm/lib/Support/MathExtras.cpp @@ -0,0 +1,32 @@ +//===-- MathExtras.cpp - Implement the MathExtras header --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the MathExtras.h header +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/MathExtras.h" + +#ifdef _MSC_VER +#include <limits> +#else +#include <math.h> +#endif + +namespace llvm { + +#if defined(_MSC_VER) + // Visual Studio defines the HUGE_VAL class of macros using purposeful + // constant arithmetic overflow, which it then warns on when encountered. + const float huge_valf = std::numeric_limits<float>::infinity(); +#else + const float huge_valf = HUGE_VALF; +#endif + +} diff --git a/contrib/llvm/lib/Support/MemoryBuffer.cpp b/contrib/llvm/lib/Support/MemoryBuffer.cpp index 5f4b7da..379db88 100644 --- a/contrib/llvm/lib/Support/MemoryBuffer.cpp +++ b/contrib/llvm/lib/Support/MemoryBuffer.cpp @@ -64,14 +64,17 @@ static void CopyStringRef(char *Memory, StringRef Data) { namespace { struct NamedBufferAlloc { - StringRef Name; - NamedBufferAlloc(StringRef Name) : Name(Name) {} + const Twine &Name; + NamedBufferAlloc(const Twine &Name) : Name(Name) {} }; } void *operator new(size_t N, const NamedBufferAlloc &Alloc) { - char *Mem = static_cast<char *>(operator new(N + Alloc.Name.size() + 1)); - CopyStringRef(Mem + N, Alloc.Name); + SmallString<256> NameBuf; + StringRef NameRef = Alloc.Name.toStringRef(NameBuf); + + char *Mem = static_cast<char *>(operator new(N + NameRef.size() + 1)); + CopyStringRef(Mem + N, NameRef); return Mem; } @@ -94,71 +97,86 @@ public: }; } -/// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note -/// that InputData must be a null terminated if RequiresNullTerminator is true! -MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData, - StringRef BufferName, - bool RequiresNullTerminator) { - return new (NamedBufferAlloc(BufferName)) +static ErrorOr<std::unique_ptr<MemoryBuffer>> +getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize, + uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize); + +std::unique_ptr<MemoryBuffer> +MemoryBuffer::getMemBuffer(StringRef InputData, StringRef BufferName, + bool RequiresNullTerminator) { + auto *Ret = new (NamedBufferAlloc(BufferName)) MemoryBufferMem(InputData, RequiresNullTerminator); + return std::unique_ptr<MemoryBuffer>(Ret); +} + +std::unique_ptr<MemoryBuffer> +MemoryBuffer::getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator) { + return std::unique_ptr<MemoryBuffer>(getMemBuffer( + Ref.getBuffer(), Ref.getBufferIdentifier(), RequiresNullTerminator)); } -/// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, -/// copying the contents and taking ownership of it. This has no requirements -/// on EndPtr[0]. -MemoryBuffer *MemoryBuffer::getMemBufferCopy(StringRef InputData, - StringRef BufferName) { - MemoryBuffer *Buf = getNewUninitMemBuffer(InputData.size(), BufferName); - if (!Buf) return nullptr; +std::unique_ptr<MemoryBuffer> +MemoryBuffer::getMemBufferCopy(StringRef InputData, const Twine &BufferName) { + std::unique_ptr<MemoryBuffer> Buf = + getNewUninitMemBuffer(InputData.size(), BufferName); + if (!Buf) + return nullptr; memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.data(), InputData.size()); return Buf; } -/// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size -/// that is not initialized. Note that the caller should initialize the -/// memory allocated by this method. The memory is owned by the MemoryBuffer -/// object. -MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size, - StringRef BufferName) { +std::unique_ptr<MemoryBuffer> +MemoryBuffer::getNewUninitMemBuffer(size_t Size, const Twine &BufferName) { // Allocate space for the MemoryBuffer, the data and the name. It is important // that MemoryBuffer and data are aligned so PointerIntPair works with them. // TODO: Is 16-byte alignment enough? We copy small object files with large // alignment expectations into this buffer. + SmallString<256> NameBuf; + StringRef NameRef = BufferName.toStringRef(NameBuf); size_t AlignedStringLen = - RoundUpToAlignment(sizeof(MemoryBufferMem) + BufferName.size() + 1, 16); + RoundUpToAlignment(sizeof(MemoryBufferMem) + NameRef.size() + 1, 16); size_t RealLen = AlignedStringLen + Size + 1; char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow)); - if (!Mem) return nullptr; + if (!Mem) + return nullptr; // The name is stored after the class itself. - CopyStringRef(Mem + sizeof(MemoryBufferMem), BufferName); + CopyStringRef(Mem + sizeof(MemoryBufferMem), NameRef); // The buffer begins after the name and must be aligned. char *Buf = Mem + AlignedStringLen; Buf[Size] = 0; // Null terminate buffer. - return new (Mem) MemoryBufferMem(StringRef(Buf, Size), true); + auto *Ret = new (Mem) MemoryBufferMem(StringRef(Buf, Size), true); + return std::unique_ptr<MemoryBuffer>(Ret); } -/// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that -/// is completely initialized to zeros. Note that the caller should -/// initialize the memory allocated by this method. The memory is owned by -/// the MemoryBuffer object. -MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) { - MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName); - if (!SB) return nullptr; +std::unique_ptr<MemoryBuffer> +MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) { + std::unique_ptr<MemoryBuffer> SB = getNewUninitMemBuffer(Size, BufferName); + if (!SB) + return nullptr; memset(const_cast<char*>(SB->getBufferStart()), 0, Size); return SB; } ErrorOr<std::unique_ptr<MemoryBuffer>> -MemoryBuffer::getFileOrSTDIN(StringRef Filename, int64_t FileSize) { - if (Filename == "-") +MemoryBuffer::getFileOrSTDIN(const Twine &Filename, int64_t FileSize) { + SmallString<256> NameBuf; + StringRef NameRef = Filename.toStringRef(NameBuf); + + if (NameRef == "-") return getSTDIN(); return getFile(Filename, FileSize); } +ErrorOr<std::unique_ptr<MemoryBuffer>> +MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize, + uint64_t Offset) { + return getFileAux(FilePath, -1, MapSize, Offset, false, false); +} + //===----------------------------------------------------------------------===// // MemoryBuffer::getFile implementation. @@ -185,8 +203,8 @@ class MemoryBufferMMapFile : public MemoryBuffer { public: MemoryBufferMMapFile(bool RequiresNullTerminator, int FD, uint64_t Len, - uint64_t Offset, std::error_code EC) - : MFR(FD, false, sys::fs::mapped_file_region::readonly, + uint64_t Offset, std::error_code &EC) + : MFR(FD, sys::fs::mapped_file_region::readonly, getLegalMapSize(Len, Offset), getLegalMapOffset(Offset), EC) { if (!EC) { const char *Start = getStart(Len, Offset); @@ -206,7 +224,7 @@ public: } static ErrorOr<std::unique_ptr<MemoryBuffer>> -getMemoryBufferForStream(int FD, StringRef BufferName) { +getMemoryBufferForStream(int FD, const Twine &BufferName) { const ssize_t ChunkSize = 4096*4; SmallString<ChunkSize> Buffer; ssize_t ReadBytes; @@ -221,40 +239,32 @@ getMemoryBufferForStream(int FD, StringRef BufferName) { Buffer.set_size(Buffer.size() + ReadBytes); } while (ReadBytes != 0); - std::unique_ptr<MemoryBuffer> Ret( - MemoryBuffer::getMemBufferCopy(Buffer, BufferName)); - return std::move(Ret); + return MemoryBuffer::getMemBufferCopy(Buffer, BufferName); } -static ErrorOr<std::unique_ptr<MemoryBuffer>> -getFileAux(const char *Filename, int64_t FileSize, bool RequiresNullTerminator, - bool IsVolatileSize); ErrorOr<std::unique_ptr<MemoryBuffer>> -MemoryBuffer::getFile(Twine Filename, int64_t FileSize, +MemoryBuffer::getFile(const Twine &Filename, int64_t FileSize, bool RequiresNullTerminator, bool IsVolatileSize) { - // Ensure the path is null terminated. - SmallString<256> PathBuf; - StringRef NullTerminatedName = Filename.toNullTerminatedStringRef(PathBuf); - return getFileAux(NullTerminatedName.data(), FileSize, RequiresNullTerminator, - IsVolatileSize); + return getFileAux(Filename, FileSize, FileSize, 0, + RequiresNullTerminator, IsVolatileSize); } static ErrorOr<std::unique_ptr<MemoryBuffer>> -getOpenFileImpl(int FD, const char *Filename, uint64_t FileSize, +getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize, uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize); static ErrorOr<std::unique_ptr<MemoryBuffer>> -getFileAux(const char *Filename, int64_t FileSize, bool RequiresNullTerminator, - bool IsVolatileSize) { +getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize, + uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize) { int FD; std::error_code EC = sys::fs::openFileForRead(Filename, FD); if (EC) return EC; ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = - getOpenFileImpl(FD, Filename, FileSize, FileSize, 0, + getOpenFileImpl(FD, Filename, FileSize, MapSize, Offset, RequiresNullTerminator, IsVolatileSize); close(FD); return Ret; @@ -305,14 +315,22 @@ static bool shouldUseMmap(int FD, if ((FileSize & (PageSize -1)) == 0) return false; +#if defined(__CYGWIN__) + // Don't try to map files that are exactly a multiple of the physical page size + // if we need a null terminator. + // FIXME: We should reorganize again getPageSize() on Win32. + if ((FileSize & (4096 - 1)) == 0) + return false; +#endif + return true; } static ErrorOr<std::unique_ptr<MemoryBuffer>> -getOpenFileImpl(int FD, const char *Filename, uint64_t FileSize, +getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize, uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize) { - static int PageSize = sys::process::get_self()->page_size(); + static int PageSize = sys::Process::getPageSize(); // Default is to map the full file. if (MapSize == uint64_t(-1)) { @@ -347,15 +365,15 @@ getOpenFileImpl(int FD, const char *Filename, uint64_t FileSize, return std::move(Result); } - MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename); + std::unique_ptr<MemoryBuffer> Buf = + MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename); if (!Buf) { // Failed to create a buffer. The only way it can fail is if // new(std::nothrow) returns 0. return make_error_code(errc::not_enough_memory); } - std::unique_ptr<MemoryBuffer> SB(Buf); - char *BufPtr = const_cast<char*>(SB->getBufferStart()); + char *BufPtr = const_cast<char *>(Buf->getBufferStart()); size_t BytesLeft = MapSize; #ifndef HAVE_PREAD @@ -383,21 +401,22 @@ getOpenFileImpl(int FD, const char *Filename, uint64_t FileSize, BufPtr += NumRead; } - return std::move(SB); + return std::move(Buf); } ErrorOr<std::unique_ptr<MemoryBuffer>> -MemoryBuffer::getOpenFile(int FD, const char *Filename, uint64_t FileSize, +MemoryBuffer::getOpenFile(int FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator, bool IsVolatileSize) { return getOpenFileImpl(FD, Filename, FileSize, FileSize, 0, RequiresNullTerminator, IsVolatileSize); } ErrorOr<std::unique_ptr<MemoryBuffer>> -MemoryBuffer::getOpenFileSlice(int FD, const char *Filename, uint64_t MapSize, - int64_t Offset, bool IsVolatileSize) { +MemoryBuffer::getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize, + int64_t Offset) { + assert(MapSize != uint64_t(-1)); return getOpenFileImpl(FD, Filename, -1, MapSize, Offset, false, - IsVolatileSize); + /*IsVolatileSize*/ false); } ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() { @@ -409,3 +428,9 @@ ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() { return getMemoryBufferForStream(0, "<stdin>"); } + +MemoryBufferRef MemoryBuffer::getMemBufferRef() const { + StringRef Data = getBuffer(); + StringRef Identifier = getBufferIdentifier(); + return MemoryBufferRef(Data, Identifier); +} diff --git a/contrib/llvm/lib/Support/MemoryObject.cpp b/contrib/llvm/lib/Support/MemoryObject.cpp index 02b5b50..d796acf 100644 --- a/contrib/llvm/lib/Support/MemoryObject.cpp +++ b/contrib/llvm/lib/Support/MemoryObject.cpp @@ -12,22 +12,3 @@ using namespace llvm; MemoryObject::~MemoryObject() { } - -int MemoryObject::readBytes(uint64_t address, - uint64_t size, - uint8_t* buf) const { - uint64_t current = address; - uint64_t limit = getBase() + getExtent(); - - if (current + size > limit) - return -1; - - while (current - address < size) { - if (readByte(current, &buf[(current - address)])) - return -1; - - current++; - } - - return 0; -} diff --git a/contrib/llvm/lib/Support/Options.cpp b/contrib/llvm/lib/Support/Options.cpp new file mode 100644 index 0000000..7125845 --- /dev/null +++ b/contrib/llvm/lib/Support/Options.cpp @@ -0,0 +1,33 @@ +//===- llvm/Support/Options.cpp - Debug options support ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the helper objects for defining debug options using the +// new API built on cl::opt, but not requiring the use of static globals. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Options.h" +#include "llvm/Support/ManagedStatic.h" + +using namespace llvm; + +OptionRegistry::~OptionRegistry() { + for (auto IT = Options.begin(); IT != Options.end(); ++IT) + delete IT->second; +} + +void OptionRegistry::addOption(void *Key, cl::Option *O) { + assert(Options.find(Key) == Options.end() && + "Argument with this key already registerd"); + Options.insert(std::make_pair(Key, O)); +} + +static ManagedStatic<OptionRegistry> OR; + +OptionRegistry &OptionRegistry::instance() { return *OR; } diff --git a/contrib/llvm/lib/Support/Path.cpp b/contrib/llvm/lib/Support/Path.cpp index d5a0ec5..fdb27e6 100644 --- a/contrib/llvm/lib/Support/Path.cpp +++ b/contrib/llvm/lib/Support/Path.cpp @@ -11,11 +11,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/Errc.h" -#include "llvm/Support/Path.h" +#include "llvm/Support/COFF.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include <cctype> #include <cstdio> @@ -164,9 +165,6 @@ enum FSEntity { FS_Name }; -// Implemented in Unix/Path.inc and Windows/Path.inc. -static std::error_code TempDir(SmallVectorImpl<char> &result); - static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD, SmallVectorImpl<char> &ResultPath, bool MakeAbsolute, unsigned Mode, @@ -178,8 +176,7 @@ static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD, // Make model absolute by prepending a temp directory if it's not already. if (!sys::path::is_absolute(Twine(ModelStorage))) { SmallString<128> TDir; - if (std::error_code EC = TempDir(TDir)) - return EC; + sys::path::system_temp_directory(true, TDir); sys::path::append(TDir, Twine(ModelStorage)); ModelStorage.swap(TDir); } @@ -214,13 +211,13 @@ retry_random_path: } case FS_Name: { - bool Exists; - std::error_code EC = sys::fs::exists(ResultPath.begin(), Exists); + std::error_code EC = + sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist); + if (EC == errc::no_such_file_or_directory) + return std::error_code(); if (EC) return EC; - if (Exists) - goto retry_random_path; - return std::error_code(); + goto retry_random_path; } case FS_Dir: { @@ -308,7 +305,30 @@ const_iterator &const_iterator::operator++() { return *this; } -const_iterator &const_iterator::operator--() { +bool const_iterator::operator==(const const_iterator &RHS) const { + return Path.begin() == RHS.Path.begin() && Position == RHS.Position; +} + +ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const { + return Position - RHS.Position; +} + +reverse_iterator rbegin(StringRef Path) { + reverse_iterator I; + I.Path = Path; + I.Position = Path.size(); + return ++I; +} + +reverse_iterator rend(StringRef Path) { + reverse_iterator I; + I.Path = Path; + I.Component = Path.substr(0, 0); + I.Position = 0; + return I; +} + +reverse_iterator &reverse_iterator::operator++() { // If we're at the end and the previous char was a '/', return '.' unless // we are the root path. size_t root_dir_pos = root_dir_start(Path); @@ -335,20 +355,12 @@ const_iterator &const_iterator::operator--() { return *this; } -bool const_iterator::operator==(const const_iterator &RHS) const { - return Path.begin() == RHS.Path.begin() && +bool reverse_iterator::operator==(const reverse_iterator &RHS) const { + return Path.begin() == RHS.Path.begin() && Component == RHS.Component && Position == RHS.Position; } -bool const_iterator::operator!=(const const_iterator &RHS) const { - return !(*this == RHS); -} - -ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const { - return Position - RHS.Position; -} - -const StringRef root_path(StringRef path) { +StringRef root_path(StringRef path) { const_iterator b = begin(path), pos = b, e = end(path); @@ -380,7 +392,7 @@ const StringRef root_path(StringRef path) { return StringRef(); } -const StringRef root_name(StringRef path) { +StringRef root_name(StringRef path) { const_iterator b = begin(path), e = end(path); if (b != e) { @@ -402,7 +414,7 @@ const StringRef root_name(StringRef path) { return StringRef(); } -const StringRef root_directory(StringRef path) { +StringRef root_directory(StringRef path) { const_iterator b = begin(path), pos = b, e = end(path); @@ -431,7 +443,7 @@ const StringRef root_directory(StringRef path) { return StringRef(); } -const StringRef relative_path(StringRef path) { +StringRef relative_path(StringRef path) { StringRef root = root_path(path); return path.substr(root.size()); } @@ -483,7 +495,7 @@ void append(SmallVectorImpl<char> &path, path::append(path, *begin); } -const StringRef parent_path(StringRef path) { +StringRef parent_path(StringRef path) { size_t end_pos = parent_path_end(path); if (end_pos == StringRef::npos) return StringRef(); @@ -525,17 +537,27 @@ void native(const Twine &path, SmallVectorImpl<char> &result) { native(result); } -void native(SmallVectorImpl<char> &path) { +void native(SmallVectorImpl<char> &Path) { #ifdef LLVM_ON_WIN32 - std::replace(path.begin(), path.end(), '/', '\\'); + std::replace(Path.begin(), Path.end(), '/', '\\'); +#else + for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) { + if (*PI == '\\') { + auto PN = PI + 1; + if (PN < PE && *PN == '\\') + ++PI; // increment once, the for loop will move over the escaped slash + else + *PI = '/'; + } + } #endif } -const StringRef filename(StringRef path) { - return *(--end(path)); +StringRef filename(StringRef path) { + return *rbegin(path); } -const StringRef stem(StringRef path) { +StringRef stem(StringRef path) { StringRef fname = filename(path); size_t pos = fname.find_last_of('.'); if (pos == StringRef::npos) @@ -548,7 +570,7 @@ const StringRef stem(StringRef path) { return fname.substr(0, pos); } -const StringRef extension(StringRef path) { +StringRef extension(StringRef path) { StringRef fname = filename(path); size_t pos = fname.find_last_of('.'); if (pos == StringRef::npos) @@ -573,62 +595,10 @@ bool is_separator(char value) { static const char preferred_separator_string[] = { preferred_separator, '\0' }; -const StringRef get_separator() { +StringRef get_separator() { return preferred_separator_string; } -void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result) { - result.clear(); - -#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 - - // Check whether the temporary directory is specified by an environment - // variable. - const char *EnvironmentVariable; -#ifdef LLVM_ON_WIN32 - EnvironmentVariable = "TEMP"; -#else - EnvironmentVariable = "TMPDIR"; -#endif - if (char *RequestedDir = getenv(EnvironmentVariable)) { - result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); - return; - } - - // Fall back to a system default. - const char *DefaultResult; -#ifdef LLVM_ON_WIN32 - (void)erasedOnReboot; - DefaultResult = "C:\\TEMP"; -#else - if (erasedOnReboot) - DefaultResult = "/tmp"; - else - DefaultResult = "/var/tmp"; -#endif - result.append(DefaultResult, DefaultResult + strlen(DefaultResult)); -} - bool has_root_name(const Twine &path) { SmallString<128> path_storage; StringRef p = path.toStringRef(path_storage); @@ -918,6 +888,14 @@ bool is_other(file_status status) { !is_directory(status); } +std::error_code is_other(const Twine &Path, bool &Result) { + file_status FileStatus; + if (std::error_code EC = status(Path, FileStatus)) + return EC; + Result = is_other(FileStatus); + return std::error_code(); +} + void directory_entry::replace_filename(const Twine &filename, file_status st) { SmallString<128> path(Path.begin(), Path.end()); path::remove_filename(path); @@ -932,10 +910,23 @@ file_magic identify_magic(StringRef Magic) { return file_magic::unknown; switch ((unsigned char)Magic[0]) { case 0x00: { - // COFF short import library file + // COFF bigobj or short import library file if (Magic[1] == (char)0x00 && Magic[2] == (char)0xff && - Magic[3] == (char)0xff) - return file_magic::coff_import_library; + Magic[3] == (char)0xff) { + size_t MinSize = offsetof(COFF::BigObjHeader, UUID) + sizeof(COFF::BigObjMagic); + if (Magic.size() < MinSize) + return file_magic::coff_import_library; + + int BigObjVersion = *reinterpret_cast<const support::ulittle16_t*>( + Magic.data() + offsetof(COFF::BigObjHeader, Version)); + if (BigObjVersion < COFF::BigObjHeader::MinBigObjectVersion) + return file_magic::coff_import_library; + + const char *Start = Magic.data() + offsetof(COFF::BigObjHeader, UUID); + if (memcmp(Start, COFF::BigObjMagic, sizeof(COFF::BigObjMagic)) != 0) + return file_magic::coff_import_library; + return file_magic::coff_object; + } // Windows resource file const char Expected[] = { 0, 0, 0, 0, '\x20', 0, 0, 0, '\xff' }; if (Magic.size() >= sizeof(Expected) && @@ -975,6 +966,9 @@ file_magic identify_magic(StringRef Magic) { case 3: return file_magic::elf_shared_object; case 4: return file_magic::elf_core; } + else + // It's still some type of ELF file. + return file_magic::elf; } break; @@ -1016,7 +1010,7 @@ file_magic identify_magic(StringRef Magic) { case 6: return file_magic::macho_dynamically_linked_shared_lib; case 7: return file_magic::macho_dynamic_linker; case 8: return file_magic::macho_bundle; - case 9: return file_magic::macho_dynamic_linker; + case 9: return file_magic::macho_dynamically_linked_shared_lib_stub; case 10: return file_magic::macho_dsym_companion; } break; @@ -1037,12 +1031,13 @@ file_magic identify_magic(StringRef Magic) { return file_magic::coff_object; break; - case 0x4d: // Possible MS-DOS stub on Windows PE file - if (Magic[1] == 0x5a) { + case 'M': // Possible MS-DOS stub on Windows PE file + if (Magic[1] == 'Z') { uint32_t off = *reinterpret_cast<const support::ulittle32_t*>(Magic.data() + 0x3c); // PE/COFF file, either EXE or DLL. - if (off < Magic.size() && memcmp(Magic.data() + off, "PE\0\0",4) == 0) + if (off < Magic.size() && + memcmp(Magic.data()+off, COFF::PEMagic, sizeof(COFF::PEMagic)) == 0) return file_magic::pecoff_executable; } break; diff --git a/contrib/llvm/lib/Support/Process.cpp b/contrib/llvm/lib/Support/Process.cpp index 0d42e0e..ad67e1b 100644 --- a/contrib/llvm/lib/Support/Process.cpp +++ b/contrib/llvm/lib/Support/Process.cpp @@ -26,25 +26,6 @@ using namespace sys; //=== independent code. //===----------------------------------------------------------------------===// -// Empty virtual destructor to anchor the vtable for the process class. -process::~process() {} - -self_process *process::get_self() { - // Use a function local static for thread safe initialization and allocate it - // as a raw pointer to ensure it is never destroyed. - static self_process *SP = new self_process(); - - return SP; -} - -// The destructor for the self_process subclass must never actually be -// executed. There should be at most one instance of this class, and that -// instance should live until the process terminates to avoid the potential for -// racy accesses during shutdown. -self_process::~self_process() { - llvm_unreachable("This destructor must never be executed!"); -} - /// \brief A helper function to compute the elapsed wall-time since the program /// started. /// @@ -63,12 +44,6 @@ static TimeValue getElapsedWallTime() { /// create race conditions during program startup or shutdown. static volatile TimeValue DummyTimeValue = getElapsedWallTime(); -// Implement this routine by using the static helpers above. They're already -// portable. -TimeValue self_process::get_wall_time() const { - return getElapsedWallTime(); -} - Optional<std::string> Process::FindInEnvPath(const std::string& EnvName, const std::string& FileName) { diff --git a/contrib/llvm/lib/Support/RandomNumberGenerator.cpp b/contrib/llvm/lib/Support/RandomNumberGenerator.cpp index c50e7cb..2943137 100644 --- a/contrib/llvm/lib/Support/RandomNumberGenerator.cpp +++ b/contrib/llvm/lib/Support/RandomNumberGenerator.cpp @@ -7,16 +7,16 @@ // //===----------------------------------------------------------------------===// // -// This file implements random number generation (RNG). +// This file implements deterministic random number generation (RNG). // The current implementation is NOT cryptographically secure as it uses // the C++11 <random> facilities. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "rng" -#include "llvm/Support/RandomNumberGenerator.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/RandomNumberGenerator.h" using namespace llvm; @@ -31,31 +31,25 @@ Seed("rng-seed", cl::value_desc("seed"), RandomNumberGenerator::RandomNumberGenerator(StringRef Salt) { DEBUG( if (Seed == 0) - errs() << "Warning! Using unseeded random number generator.\n" + dbgs() << "Warning! Using unseeded random number generator.\n" ); - // Combine seed and salt using std::seed_seq. - // Entropy: Seed-low, Seed-high, Salt... + // Combine seed and salts using std::seed_seq. + // Data: Seed-low, Seed-high, Salt + // Note: std::seed_seq can only store 32-bit values, even though we + // are using a 64-bit RNG. This isn't a problem since the Mersenne + // twister constructor copies these correctly into its initial state. std::vector<uint32_t> Data; - Data.reserve(2 + Salt.size()/4 + 1); + Data.reserve(2 + Salt.size()); Data.push_back(Seed); Data.push_back(Seed >> 32); - uint32_t Pack = 0; - for (size_t I = 0; I < Salt.size(); ++I) { - Pack <<= 8; - Pack += Salt[I]; - - if (I%4 == 3) - Data.push_back(Pack); - } - Data.push_back(Pack); + std::copy(Salt.begin(), Salt.end(), Data.end()); std::seed_seq SeedSeq(Data.begin(), Data.end()); Generator.seed(SeedSeq); } -uint64_t RandomNumberGenerator::next(uint64_t Max) { - std::uniform_int_distribution<uint64_t> distribution(0, Max - 1); - return distribution(Generator); +uint_fast64_t RandomNumberGenerator::operator()() { + return Generator(); } diff --git a/contrib/llvm/lib/Support/ScaledNumber.cpp b/contrib/llvm/lib/Support/ScaledNumber.cpp index 3fe027b..6f6699c 100644 --- a/contrib/llvm/lib/Support/ScaledNumber.cpp +++ b/contrib/llvm/lib/Support/ScaledNumber.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/ScaledNumber.h" - #include "llvm/ADT/APFloat.h" #include "llvm/Support/Debug.h" @@ -169,6 +168,7 @@ static std::string toStringAPFloat(uint64_t D, int E, unsigned Precision) { int Shift = 63 - (NewE - E); assert(Shift <= LeadingZeros); assert(Shift == LeadingZeros || NewE == ScaledNumbers::MaxScale); + assert(Shift >= 0 && Shift < 64 && "undefined behavior"); D <<= Shift; E = NewE; @@ -220,6 +220,9 @@ std::string ScaledNumberBase::toString(uint64_t D, int16_t E, int Width, } else if (E > -64) { Above0 = D >> -E; Below0 = D << (64 + E); + } else if (E == -64) { + // Special case: shift by 64 bits is undefined behavior. + Below0 = D; } else if (E > -120) { Below0 = D >> (-E - 64); Extra = D << (128 + E); diff --git a/contrib/llvm/lib/Support/SmallPtrSet.cpp b/contrib/llvm/lib/Support/SmallPtrSet.cpp index a80e095..c87ee7d 100644 --- a/contrib/llvm/lib/Support/SmallPtrSet.cpp +++ b/contrib/llvm/lib/Support/SmallPtrSet.cpp @@ -34,18 +34,19 @@ void SmallPtrSetImplBase::shrink_and_clear() { memset(CurArray, -1, CurArraySize*sizeof(void*)); } -bool SmallPtrSetImplBase::insert_imp(const void * Ptr) { +std::pair<const void *const *, bool> +SmallPtrSetImplBase::insert_imp(const void *Ptr) { if (isSmall()) { // Check to see if it is already in the set. for (const void **APtr = SmallArray, **E = SmallArray+NumElements; APtr != E; ++APtr) if (*APtr == Ptr) - return false; - + return std::make_pair(APtr, false); + // Nope, there isn't. If we stay small, just 'pushback' now. - if (NumElements < CurArraySize-1) { + if (NumElements < CurArraySize) { SmallArray[NumElements++] = Ptr; - return true; + return std::make_pair(SmallArray + (NumElements - 1), true); } // Otherwise, hit the big set case, which will call grow. } @@ -61,14 +62,15 @@ bool SmallPtrSetImplBase::insert_imp(const void * Ptr) { // Okay, we know we have space. Find a hash bucket. const void **Bucket = const_cast<const void**>(FindBucketFor(Ptr)); - if (*Bucket == Ptr) return false; // Already inserted, good. - + if (*Bucket == Ptr) + return std::make_pair(Bucket, false); // Already inserted, good. + // Otherwise, insert it! if (*Bucket == getTombstoneMarker()) --NumTombstones; *Bucket = Ptr; ++NumElements; // Track density. - return true; + return std::make_pair(Bucket, true); } bool SmallPtrSetImplBase::erase_imp(const void * Ptr) { @@ -200,13 +202,12 @@ SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage, if (that.isSmall()) { CurArray = SmallArray; memcpy(CurArray, that.CurArray, sizeof(void *) * CurArraySize); - return; + } else { + // Otherwise, we steal the large memory allocation and no copy is needed. + CurArray = that.CurArray; + that.CurArray = that.SmallArray; } - // Otherwise, we steal the large memory allocation and no copy is needed. - CurArray = that.CurArray; - that.CurArray = that.SmallArray; - // Make the "that" object small and empty. that.CurArraySize = SmallSize; assert(that.CurArray == that.SmallArray); diff --git a/contrib/llvm/lib/Support/SourceMgr.cpp b/contrib/llvm/lib/Support/SourceMgr.cpp index 003cb56..b50a66b 100644 --- a/contrib/llvm/lib/Support/SourceMgr.cpp +++ b/contrib/llvm/lib/Support/SourceMgr.cpp @@ -42,11 +42,6 @@ SourceMgr::~SourceMgr() { // Delete the line # cache if allocated. if (LineNoCacheTy *Cache = getCache(LineNoCache)) delete Cache; - - while (!Buffers.empty()) { - delete Buffers.back().Buffer; - Buffers.pop_back(); - } } unsigned SourceMgr::AddIncludeFile(const std::string &Filename, @@ -54,20 +49,20 @@ unsigned SourceMgr::AddIncludeFile(const std::string &Filename, std::string &IncludedFile) { IncludedFile = Filename; ErrorOr<std::unique_ptr<MemoryBuffer>> NewBufOrErr = - MemoryBuffer::getFile(IncludedFile.c_str()); + MemoryBuffer::getFile(IncludedFile); // If the file didn't exist directly, see if it's in an include path. for (unsigned i = 0, e = IncludeDirectories.size(); i != e && !NewBufOrErr; ++i) { IncludedFile = IncludeDirectories[i] + sys::path::get_separator().data() + Filename; - NewBufOrErr = MemoryBuffer::getFile(IncludedFile.c_str()); + NewBufOrErr = MemoryBuffer::getFile(IncludedFile); } if (!NewBufOrErr) return 0; - return AddNewSourceBuffer(NewBufOrErr.get().release(), IncludeLoc); + return AddNewSourceBuffer(std::move(*NewBufOrErr), IncludeLoc); } unsigned SourceMgr::FindBufferContainingLoc(SMLoc Loc) const { diff --git a/contrib/llvm/lib/Support/SpecialCaseList.cpp b/contrib/llvm/lib/Support/SpecialCaseList.cpp index 21e43c5..785cc60 100644 --- a/contrib/llvm/lib/Support/SpecialCaseList.cpp +++ b/contrib/llvm/lib/Support/SpecialCaseList.cpp @@ -48,10 +48,10 @@ struct SpecialCaseList::Entry { SpecialCaseList::SpecialCaseList() : Entries() {} -SpecialCaseList *SpecialCaseList::create( - const StringRef Path, std::string &Error) { +std::unique_ptr<SpecialCaseList> SpecialCaseList::create(StringRef Path, + std::string &Error) { if (Path.empty()) - return new SpecialCaseList(); + return std::unique_ptr<SpecialCaseList>(new SpecialCaseList()); ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = MemoryBuffer::getFile(Path); if (std::error_code EC = FileOrErr.getError()) { @@ -61,17 +61,17 @@ SpecialCaseList *SpecialCaseList::create( return create(FileOrErr.get().get(), Error); } -SpecialCaseList *SpecialCaseList::create( - const MemoryBuffer *MB, std::string &Error) { +std::unique_ptr<SpecialCaseList> SpecialCaseList::create(const MemoryBuffer *MB, + std::string &Error) { std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList()); if (!SCL->parse(MB, Error)) return nullptr; - return SCL.release(); + return SCL; } -SpecialCaseList *SpecialCaseList::createOrDie(const StringRef Path) { +std::unique_ptr<SpecialCaseList> SpecialCaseList::createOrDie(StringRef Path) { std::string Error; - if (SpecialCaseList *SCL = create(Path, Error)) + if (auto SCL = create(Path, Error)) return SCL; report_fatal_error(Error); } @@ -103,18 +103,6 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) { std::string Regexp = SplitRegexp.first; StringRef Category = SplitRegexp.second; - // Backwards compatibility. - if (Prefix == "global-init") { - Prefix = "global"; - Category = "init"; - } else if (Prefix == "global-init-type") { - Prefix = "type"; - Category = "init"; - } else if (Prefix == "global-init-src") { - Prefix = "src"; - Category = "init"; - } - // See if we can store Regexp in Strings. if (Regex::isLiteralERE(Regexp)) { Entries[Prefix][Category].Strings.insert(Regexp); @@ -157,8 +145,8 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) { SpecialCaseList::~SpecialCaseList() {} -bool SpecialCaseList::inSection(const StringRef Section, const StringRef Query, - const StringRef Category) const { +bool SpecialCaseList::inSection(StringRef Section, StringRef Query, + StringRef Category) const { StringMap<StringMap<Entry> >::const_iterator I = Entries.find(Section); if (I == Entries.end()) return false; StringMap<Entry>::const_iterator II = I->second.find(Category); diff --git a/contrib/llvm/lib/Support/StreamableMemoryObject.cpp b/contrib/llvm/lib/Support/StreamingMemoryObject.cpp index 5cb0680..68beeef 100644 --- a/contrib/llvm/lib/Support/StreamableMemoryObject.cpp +++ b/contrib/llvm/lib/Support/StreamingMemoryObject.cpp @@ -1,4 +1,4 @@ -//===- StreamableMemoryObject.cpp - Streamable data interface -------------===// +//===- StreamingMemoryObject.cpp - Streamable data interface -------------===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/StreamableMemoryObject.h" +#include "llvm/Support/StreamingMemoryObject.h" #include "llvm/Support/Compiler.h" #include <cassert> #include <cstddef> @@ -18,27 +18,22 @@ using namespace llvm; namespace { -class RawMemoryObject : public StreamableMemoryObject { +class RawMemoryObject : public MemoryObject { public: RawMemoryObject(const unsigned char *Start, const unsigned char *End) : FirstChar(Start), LastChar(End) { assert(LastChar >= FirstChar && "Invalid start/end range"); } - uint64_t getBase() const override { return 0; } uint64_t getExtent() const override { return LastChar - FirstChar; } - int readByte(uint64_t address, uint8_t* ptr) const override; - int readBytes(uint64_t address, uint64_t size, - uint8_t *buf) const override; + uint64_t readBytes(uint8_t *Buf, uint64_t Size, + uint64_t Address) const override; const uint8_t *getPointer(uint64_t address, uint64_t size) const override; bool isValidAddress(uint64_t address) const override { return validAddress(address); } - bool isObjectEnd(uint64_t address) const override { - return objectEnd(address); - } private: const uint8_t* const FirstChar; @@ -49,26 +44,25 @@ private: bool validAddress(uint64_t address) const { return static_cast<std::ptrdiff_t>(address) < LastChar - FirstChar; } - bool objectEnd(uint64_t address) const { - return static_cast<std::ptrdiff_t>(address) == LastChar - FirstChar; - } RawMemoryObject(const RawMemoryObject&) LLVM_DELETED_FUNCTION; void operator=(const RawMemoryObject&) LLVM_DELETED_FUNCTION; }; -int RawMemoryObject::readByte(uint64_t address, uint8_t* ptr) const { - if (!validAddress(address)) return -1; - *ptr = *((uint8_t *)(uintptr_t)(address + FirstChar)); - return 0; -} +uint64_t RawMemoryObject::readBytes(uint8_t *Buf, uint64_t Size, + uint64_t Address) const { + uint64_t BufferSize = LastChar - FirstChar; + if (Address >= BufferSize) + return 0; -int RawMemoryObject::readBytes(uint64_t address, - uint64_t size, - uint8_t *buf) const { - if (!validAddress(address) || !validAddress(address + size - 1)) return -1; - memcpy(buf, (uint8_t *)(uintptr_t)(address + FirstChar), size); - return size; + uint64_t End = Address + Size; + if (End > BufferSize) + End = BufferSize; + + assert(static_cast<int64_t>(End - Address) >= 0); + Size = End - Address; + memcpy(Buf, Address + FirstChar, Size); + return Size; } const uint8_t *RawMemoryObject::getPointer(uint64_t address, @@ -85,12 +79,6 @@ bool StreamingMemoryObject::isValidAddress(uint64_t address) const { return fetchToPos(address); } -bool StreamingMemoryObject::isObjectEnd(uint64_t address) const { - if (ObjectSize) return address == ObjectSize; - fetchToPos(address); - return address == ObjectSize && address != 0; -} - uint64_t StreamingMemoryObject::getExtent() const { if (ObjectSize) return ObjectSize; size_t pos = BytesRead + kChunkSize; @@ -99,18 +87,19 @@ uint64_t StreamingMemoryObject::getExtent() const { return ObjectSize; } -int StreamingMemoryObject::readByte(uint64_t address, uint8_t* ptr) const { - if (!fetchToPos(address)) return -1; - *ptr = Bytes[address + BytesSkipped]; - return 0; -} - -int StreamingMemoryObject::readBytes(uint64_t address, - uint64_t size, - uint8_t *buf) const { - if (!fetchToPos(address + size - 1)) return -1; - memcpy(buf, &Bytes[address + BytesSkipped], size); - return 0; +uint64_t StreamingMemoryObject::readBytes(uint8_t *Buf, uint64_t Size, + uint64_t Address) const { + fetchToPos(Address + Size - 1); + if (Address >= BytesRead) + return 0; + + uint64_t End = Address + Size; + if (End > BytesRead) + End = BytesRead; + assert(static_cast<int64_t>(End - Address) >= 0); + Size = End - Address; + memcpy(Buf, &Bytes[Address + BytesSkipped], Size); + return Size; } bool StreamingMemoryObject::dropLeadingBytes(size_t s) { @@ -125,13 +114,11 @@ void StreamingMemoryObject::setKnownObjectSize(size_t size) { Bytes.reserve(size); } -StreamableMemoryObject *getNonStreamedMemoryObject( - const unsigned char *Start, const unsigned char *End) { +MemoryObject *getNonStreamedMemoryObject(const unsigned char *Start, + const unsigned char *End) { return new RawMemoryObject(Start, End); } -StreamableMemoryObject::~StreamableMemoryObject() { } - StreamingMemoryObject::StreamingMemoryObject(DataStreamer *streamer) : Bytes(kChunkSize), Streamer(streamer), BytesRead(0), BytesSkipped(0), ObjectSize(0), EOFReached(false) { diff --git a/contrib/llvm/lib/Support/StringRef.cpp b/contrib/llvm/lib/Support/StringRef.cpp index cde8258..ddece08 100644 --- a/contrib/llvm/lib/Support/StringRef.cpp +++ b/contrib/llvm/lib/Support/StringRef.cpp @@ -50,7 +50,7 @@ static int ascii_strncasecmp(const char *LHS, const char *RHS, size_t Length) { /// compare_lower - Compare strings, ignoring case. int StringRef::compare_lower(StringRef RHS) const { - if (int Res = ascii_strncasecmp(Data, RHS.Data, min(Length, RHS.Length))) + if (int Res = ascii_strncasecmp(Data, RHS.Data, std::min(Length, RHS.Length))) return Res; if (Length == RHS.Length) return 0; @@ -71,7 +71,7 @@ bool StringRef::endswith_lower(StringRef Suffix) const { /// compare_numeric - Compare strings, handle embedded numbers. int StringRef::compare_numeric(StringRef RHS) const { - for (size_t I = 0, E = min(Length, RHS.Length); I != E; ++I) { + for (size_t I = 0, E = std::min(Length, RHS.Length); I != E; ++I) { // Check for sequences of digits. if (ascii_isdigit(Data[I]) && ascii_isdigit(RHS.Data[I])) { // The longer sequence of numbers is considered larger. @@ -105,8 +105,8 @@ unsigned StringRef::edit_distance(llvm::StringRef Other, bool AllowReplacements, unsigned MaxEditDistance) const { return llvm::ComputeEditDistance( - llvm::ArrayRef<char>(data(), size()), - llvm::ArrayRef<char>(Other.data(), Other.size()), + makeArrayRef(data(), size()), + makeArrayRef(Other.data(), Other.size()), AllowReplacements, MaxEditDistance); } @@ -146,7 +146,7 @@ size_t StringRef::find(StringRef Str, size_t From) const { // 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 = min(From, e); i != e; ++i) + for (size_t e = Length - N + 1, i = std::min(From, e); i != e; ++i) if (substr(i, N).equals(Str)) return i; return npos; @@ -201,7 +201,7 @@ StringRef::size_type StringRef::find_first_of(StringRef Chars, for (size_type i = 0; i != Chars.size(); ++i) CharBits.set((unsigned char)Chars[i]); - for (size_type i = min(From, Length), e = Length; i != e; ++i) + for (size_type i = std::min(From, Length), e = Length; i != e; ++i) if (CharBits.test((unsigned char)Data[i])) return i; return npos; @@ -210,7 +210,7 @@ StringRef::size_type StringRef::find_first_of(StringRef Chars, /// find_first_not_of - Find the first character in the string that is not /// \arg C or npos if not found. StringRef::size_type StringRef::find_first_not_of(char C, size_t From) const { - for (size_type i = min(From, Length), e = Length; i != e; ++i) + for (size_type i = std::min(From, Length), e = Length; i != e; ++i) if (Data[i] != C) return i; return npos; @@ -226,7 +226,7 @@ StringRef::size_type StringRef::find_first_not_of(StringRef Chars, for (size_type i = 0; i != Chars.size(); ++i) CharBits.set((unsigned char)Chars[i]); - for (size_type i = min(From, Length), e = Length; i != e; ++i) + for (size_type i = std::min(From, Length), e = Length; i != e; ++i) if (!CharBits.test((unsigned char)Data[i])) return i; return npos; @@ -242,7 +242,7 @@ StringRef::size_type StringRef::find_last_of(StringRef Chars, for (size_type i = 0; i != Chars.size(); ++i) CharBits.set((unsigned char)Chars[i]); - for (size_type i = min(From, Length) - 1, e = -1; i != e; --i) + for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i) if (CharBits.test((unsigned char)Data[i])) return i; return npos; @@ -251,7 +251,7 @@ StringRef::size_type StringRef::find_last_of(StringRef Chars, /// find_last_not_of - Find the last character in the string that is not /// \arg C, or npos if not found. StringRef::size_type StringRef::find_last_not_of(char C, size_t From) const { - for (size_type i = min(From, Length) - 1, e = -1; i != e; --i) + for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i) if (Data[i] != C) return i; return npos; @@ -267,7 +267,7 @@ StringRef::size_type StringRef::find_last_not_of(StringRef Chars, for (size_type i = 0, e = Chars.size(); i != e; ++i) CharBits.set((unsigned char)Chars[i]); - for (size_type i = min(From, Length) - 1, e = -1; i != e; --i) + for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i) if (!CharBits.test((unsigned char)Data[i])) return i; return npos; diff --git a/contrib/llvm/lib/Support/StringRefMemoryObject.cpp b/contrib/llvm/lib/Support/StringRefMemoryObject.cpp deleted file mode 100644 index e035ed1..0000000 --- a/contrib/llvm/lib/Support/StringRefMemoryObject.cpp +++ /dev/null @@ -1,29 +0,0 @@ -//===- lib/Support/StringRefMemoryObject.cpp --------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/StringRefMemoryObject.h" - -using namespace llvm; - -int StringRefMemoryObject::readByte(uint64_t Addr, uint8_t *Byte) const { - if (Addr >= Base + getExtent() || Addr < Base) - return -1; - *Byte = Bytes[Addr - Base]; - return 0; -} - -int StringRefMemoryObject::readBytes(uint64_t Addr, - uint64_t Size, - uint8_t *Buf) const { - uint64_t Offset = Addr - Base; - if (Addr >= Base + getExtent() || Offset + Size > getExtent() || Addr < Base) - return -1; - memcpy(Buf, Bytes.data() + Offset, Size); - return 0; -} diff --git a/contrib/llvm/lib/Support/ThreadLocal.cpp b/contrib/llvm/lib/Support/ThreadLocal.cpp index 2dec9eb..9da1603 100644 --- a/contrib/llvm/lib/Support/ThreadLocal.cpp +++ b/contrib/llvm/lib/Support/ThreadLocal.cpp @@ -31,58 +31,14 @@ void ThreadLocalImpl::setInstance(const void* d) { void **pd = reinterpret_cast<void**>(&data); *pd = const_cast<void*>(d); } -const void* ThreadLocalImpl::getInstance() { +void *ThreadLocalImpl::getInstance() { void **pd = reinterpret_cast<void**>(&data); return *pd; } void ThreadLocalImpl::removeInstance() { - setInstance(0); -} -} -#else - -#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_GETSPECIFIC) - -#include <cassert> -#include <pthread.h> -#include <stdlib.h> - -namespace llvm { -using namespace sys; - -ThreadLocalImpl::ThreadLocalImpl() : data() { - static_assert(sizeof(pthread_key_t) <= sizeof(data), "size too big"); - pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data); - int errorcode = pthread_key_create(key, nullptr); - assert(errorcode == 0); - (void) errorcode; -} - -ThreadLocalImpl::~ThreadLocalImpl() { - pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data); - int errorcode = pthread_key_delete(*key); - assert(errorcode == 0); - (void) errorcode; -} - -void ThreadLocalImpl::setInstance(const void* d) { - pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data); - int errorcode = pthread_setspecific(*key, d); - assert(errorcode == 0); - (void) errorcode; -} - -const void* ThreadLocalImpl::getInstance() { - pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data); - return pthread_getspecific(*key); -} - -void ThreadLocalImpl::removeInstance() { setInstance(nullptr); } - } - #elif defined(LLVM_ON_UNIX) #include "Unix/ThreadLocal.inc" #elif defined( LLVM_ON_WIN32) @@ -90,4 +46,3 @@ void ThreadLocalImpl::removeInstance() { #else #warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 set in Support/ThreadLocal.cpp #endif -#endif diff --git a/contrib/llvm/lib/Support/TimeValue.cpp b/contrib/llvm/lib/Support/TimeValue.cpp index 4a70797..136b93e 100644 --- a/contrib/llvm/lib/Support/TimeValue.cpp +++ b/contrib/llvm/lib/Support/TimeValue.cpp @@ -22,12 +22,6 @@ const TimeValue::SecondsType const TimeValue::SecondsType TimeValue::Win32ZeroTimeSeconds = -12591158400ULL; -const TimeValue TimeValue::MinTime = TimeValue ( INT64_MIN,0 ); -const TimeValue TimeValue::MaxTime = TimeValue ( INT64_MAX,0 ); -const TimeValue TimeValue::ZeroTime = TimeValue ( 0,0 ); -const TimeValue TimeValue::PosixZeroTime = TimeValue ( PosixZeroTimeSeconds,0 ); -const TimeValue TimeValue::Win32ZeroTime = TimeValue ( Win32ZeroTimeSeconds,0 ); - void TimeValue::normalize( void ) { if ( nanos_ >= NANOSECONDS_PER_SECOND ) { diff --git a/contrib/llvm/lib/Support/Timer.cpp b/contrib/llvm/lib/Support/Timer.cpp index 210bda7..e1a531a 100644 --- a/contrib/llvm/lib/Support/Timer.cpp +++ b/contrib/llvm/lib/Support/Timer.cpp @@ -66,10 +66,10 @@ raw_ostream *llvm::CreateInfoOutputFile() { // 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::string Error; - raw_ostream *Result = new raw_fd_ostream( - OutputFilename.c_str(), Error, sys::fs::F_Append | sys::fs::F_Text); - if (Error.empty()) + std::error_code EC; + raw_ostream *Result = new raw_fd_ostream(OutputFilename, EC, + sys::fs::F_Append | sys::fs::F_Text); + if (!EC) return Result; errs() << "Error opening info-output-file '" diff --git a/contrib/llvm/lib/Support/ToolOutputFile.cpp b/contrib/llvm/lib/Support/ToolOutputFile.cpp index b5fb20f..8ae977d 100644 --- a/contrib/llvm/lib/Support/ToolOutputFile.cpp +++ b/contrib/llvm/lib/Support/ToolOutputFile.cpp @@ -16,8 +16,8 @@ #include "llvm/Support/Signals.h" using namespace llvm; -tool_output_file::CleanupInstaller::CleanupInstaller(const char *filename) - : Filename(filename), Keep(false) { +tool_output_file::CleanupInstaller::CleanupInstaller(StringRef Filename) + : Filename(Filename), Keep(false) { // Arrange for the file to be deleted if the process is killed. if (Filename != "-") sys::RemoveFileOnSignal(Filename); @@ -34,14 +34,13 @@ tool_output_file::CleanupInstaller::~CleanupInstaller() { sys::DontRemoveFileOnSignal(Filename); } -tool_output_file::tool_output_file(const char *filename, std::string &ErrorInfo, +tool_output_file::tool_output_file(StringRef Filename, std::error_code &EC, sys::fs::OpenFlags Flags) - : Installer(filename), OS(filename, ErrorInfo, Flags) { + : Installer(Filename), OS(Filename, EC, Flags) { // If open fails, no cleanup is needed. - if (!ErrorInfo.empty()) + if (EC) Installer.Keep = true; } -tool_output_file::tool_output_file(const char *Filename, int FD) - : Installer(Filename), OS(FD, true) { -} +tool_output_file::tool_output_file(StringRef Filename, int FD) + : Installer(Filename), OS(FD, true) {} diff --git a/contrib/llvm/lib/Support/Triple.cpp b/contrib/llvm/lib/Support/Triple.cpp index ca68775..f923a9a 100644 --- a/contrib/llvm/lib/Support/Triple.cpp +++ b/contrib/llvm/lib/Support/Triple.cpp @@ -23,8 +23,6 @@ const char *Triple::getArchTypeName(ArchType Kind) { case aarch64_be: return "aarch64_be"; case arm: return "arm"; case armeb: return "armeb"; - case arm64: return "arm64"; - case arm64_be: return "arm64_be"; case hexagon: return "hexagon"; case mips: return "mips"; case mipsel: return "mipsel"; @@ -35,6 +33,7 @@ const char *Triple::getArchTypeName(ArchType Kind) { case ppc64le: return "powerpc64le"; case ppc: return "powerpc"; case r600: return "r600"; + case amdgcn: return "amdgcn"; case sparc: return "sparc"; case sparcv9: return "sparcv9"; case systemz: return "s390x"; @@ -47,7 +46,11 @@ const char *Triple::getArchTypeName(ArchType Kind) { case nvptx: return "nvptx"; case nvptx64: return "nvptx64"; case le32: return "le32"; + case le64: return "le64"; case amdil: return "amdil"; + case amdil64: return "amdil64"; + case hsail: return "hsail"; + case hsail64: return "hsail64"; case spir: return "spir"; case spir64: return "spir64"; case kalimba: return "kalimba"; @@ -61,8 +64,6 @@ const char *Triple::getArchTypePrefix(ArchType Kind) { default: return nullptr; - case arm64: - case arm64_be: case aarch64: case aarch64_be: return "aarch64"; @@ -82,7 +83,8 @@ const char *Triple::getArchTypePrefix(ArchType Kind) { case hexagon: return "hexagon"; - case r600: return "r600"; + case amdgcn: + case r600: return "amdgpu"; case sparcv9: case sparc: return "sparc"; @@ -98,8 +100,15 @@ const char *Triple::getArchTypePrefix(ArchType Kind) { case nvptx64: return "nvptx"; case le32: return "le32"; - case amdil: return "amdil"; - case spir: return "spir"; + case le64: return "le64"; + + case amdil: + case amdil64: return "amdil"; + + case hsail: + case hsail64: return "hsail"; + + case spir: case spir64: return "spir"; case kalimba: return "kalimba"; } @@ -129,8 +138,6 @@ const char *Triple::getOSTypeName(OSType Kind) { switch (Kind) { case UnknownOS: return "unknown"; - case AuroraUX: return "auroraux"; - case Cygwin: return "cygwin"; case Darwin: return "darwin"; case DragonFly: return "dragonfly"; case FreeBSD: return "freebsd"; @@ -139,7 +146,6 @@ const char *Triple::getOSTypeName(OSType Kind) { case Linux: return "linux"; case Lv2: return "lv2"; case MacOSX: return "macosx"; - case MinGW32: return "mingw32"; case NetBSD: return "netbsd"; case OpenBSD: return "openbsd"; case Solaris: return "solaris"; @@ -153,6 +159,7 @@ const char *Triple::getOSTypeName(OSType Kind) { case AIX: return "aix"; case CUDA: return "cuda"; case NVCL: return "nvcl"; + case AMDHSA: return "amdhsa"; } llvm_unreachable("Invalid OSType"); @@ -181,10 +188,9 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { return StringSwitch<Triple::ArchType>(Name) .Case("aarch64", aarch64) .Case("aarch64_be", aarch64_be) + .Case("arm64", aarch64) // "arm64" is an alias for "aarch64" .Case("arm", arm) .Case("armeb", armeb) - .Case("arm64", arm64) - .Case("arm64_be", arm64_be) .Case("mips", mips) .Case("mipsel", mipsel) .Case("mips64", mips64) @@ -195,6 +201,7 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { .Case("ppc", ppc) .Case("ppc64le", ppc64le) .Case("r600", r600) + .Case("amdgcn", amdgcn) .Case("hexagon", hexagon) .Case("sparc", sparc) .Case("sparcv9", sparcv9) @@ -208,40 +215,59 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { .Case("nvptx", nvptx) .Case("nvptx64", nvptx64) .Case("le32", le32) + .Case("le64", le64) .Case("amdil", amdil) + .Case("amdil64", amdil64) + .Case("hsail", hsail) + .Case("hsail64", hsail64) .Case("spir", spir) .Case("spir64", spir64) .Case("kalimba", kalimba) .Default(UnknownArch); } -// Returns architecture name that is understood by the target assembler. -const char *Triple::getArchNameForAssembler() { - if (!isOSDarwin() && getVendor() != Triple::Apple) - return nullptr; - - return StringSwitch<const char*>(getArchName()) - .Case("i386", "i386") - .Case("x86_64", "x86_64") - .Case("powerpc", "ppc") - .Case("powerpc64", "ppc64") - .Case("powerpc64le", "ppc64le") - .Case("arm", "arm") - .Cases("armv4t", "thumbv4t", "armv4t") - .Cases("armv5", "armv5e", "thumbv5", "thumbv5e", "armv5") - .Cases("armv6", "thumbv6", "armv6") - .Cases("armv7", "thumbv7", "armv7") - .Case("armeb", "armeb") - .Case("arm64", "arm64") - .Case("arm64_be", "arm64") - .Case("r600", "r600") - .Case("nvptx", "nvptx") - .Case("nvptx64", "nvptx64") - .Case("le32", "le32") - .Case("amdil", "amdil") - .Case("spir", "spir") - .Case("spir64", "spir64") - .Default(nullptr); +static Triple::ArchType parseARMArch(StringRef ArchName) { + size_t offset = StringRef::npos; + Triple::ArchType arch = Triple::UnknownArch; + bool isThumb = ArchName.startswith("thumb"); + + if (ArchName.equals("arm")) + return Triple::arm; + if (ArchName.equals("armeb")) + return Triple::armeb; + if (ArchName.equals("thumb")) + return Triple::thumb; + if (ArchName.equals("thumbeb")) + return Triple::thumbeb; + if (ArchName.equals("arm64") || ArchName.equals("aarch64")) + return Triple::aarch64; + if (ArchName.equals("aarch64_be")) + return Triple::aarch64_be; + + if (ArchName.startswith("armv")) { + offset = 3; + arch = Triple::arm; + } else if (ArchName.startswith("armebv")) { + offset = 5; + arch = Triple::armeb; + } else if (ArchName.startswith("thumbv")) { + offset = 5; + arch = Triple::thumb; + } else if (ArchName.startswith("thumbebv")) { + offset = 7; + arch = Triple::thumbeb; + } + return StringSwitch<Triple::ArchType>(ArchName.substr(offset)) + .Cases("v2", "v2a", isThumb ? Triple::UnknownArch : arch) + .Cases("v3", "v3m", isThumb ? Triple::UnknownArch : arch) + .Cases("v4", "v4t", arch) + .Cases("v5", "v5e", "v5t", "v5te", "v5tej", arch) + .Cases("v6", "v6j", "v6k", "v6m", arch) + .Cases("v6t2", "v6z", "v6zk", arch) + .Cases("v7", "v7a", "v7em", "v7l", arch) + .Cases("v7m", "v7r", "v7s", arch) + .Cases("v8", "v8a", arch) + .Default(Triple::UnknownArch); } static Triple::ArchType parseArch(StringRef ArchName) { @@ -253,26 +279,17 @@ static Triple::ArchType parseArch(StringRef ArchName) { .Case("powerpc", Triple::ppc) .Cases("powerpc64", "ppu", Triple::ppc64) .Case("powerpc64le", Triple::ppc64le) - .Case("aarch64", Triple::aarch64) - .Case("aarch64_be", Triple::aarch64_be) - .Cases("arm", "xscale", Triple::arm) - // FIXME: It would be good to replace these with explicit names for all the - // various suffixes supported. - .StartsWith("armv", Triple::arm) - .Case("armeb", Triple::armeb) - .StartsWith("armebv", Triple::armeb) - .Case("thumb", Triple::thumb) - .StartsWith("thumbv", Triple::thumb) - .Case("thumbeb", Triple::thumbeb) - .StartsWith("thumbebv", Triple::thumbeb) - .Case("arm64", Triple::arm64) - .Case("arm64_be", Triple::arm64_be) + .Case("xscale", Triple::arm) + .StartsWith("arm", parseARMArch(ArchName)) + .StartsWith("thumb", parseARMArch(ArchName)) + .StartsWith("aarch64", parseARMArch(ArchName)) .Case("msp430", Triple::msp430) .Cases("mips", "mipseb", "mipsallegrex", Triple::mips) .Cases("mipsel", "mipsallegrexel", Triple::mipsel) .Cases("mips64", "mips64eb", Triple::mips64) .Case("mips64el", Triple::mips64el) .Case("r600", Triple::r600) + .Case("amdgcn", Triple::amdgcn) .Case("hexagon", Triple::hexagon) .Case("s390x", Triple::systemz) .Case("sparc", Triple::sparc) @@ -282,10 +299,14 @@ static Triple::ArchType parseArch(StringRef ArchName) { .Case("nvptx", Triple::nvptx) .Case("nvptx64", Triple::nvptx64) .Case("le32", Triple::le32) + .Case("le64", Triple::le64) .Case("amdil", Triple::amdil) + .Case("amdil64", Triple::amdil64) + .Case("hsail", Triple::hsail) + .Case("hsail64", Triple::hsail64) .Case("spir", Triple::spir) .Case("spir64", Triple::spir64) - .Case("kalimba", Triple::kalimba) + .StartsWith("kalimba", Triple::kalimba) .Default(Triple::UnknownArch); } @@ -307,8 +328,6 @@ static Triple::VendorType parseVendor(StringRef VendorName) { static Triple::OSType parseOS(StringRef OSName) { return StringSwitch<Triple::OSType>(OSName) - .StartsWith("auroraux", Triple::AuroraUX) - .StartsWith("cygwin", Triple::Cygwin) .StartsWith("darwin", Triple::Darwin) .StartsWith("dragonfly", Triple::DragonFly) .StartsWith("freebsd", Triple::FreeBSD) @@ -317,7 +336,6 @@ static Triple::OSType parseOS(StringRef OSName) { .StartsWith("linux", Triple::Linux) .StartsWith("lv2", Triple::Lv2) .StartsWith("macosx", Triple::MacOSX) - .StartsWith("mingw32", Triple::MinGW32) .StartsWith("netbsd", Triple::NetBSD) .StartsWith("openbsd", Triple::OpenBSD) .StartsWith("solaris", Triple::Solaris) @@ -332,6 +350,7 @@ static Triple::OSType parseOS(StringRef OSName) { .StartsWith("aix", Triple::AIX) .StartsWith("cuda", Triple::CUDA) .StartsWith("nvcl", Triple::NVCL) + .StartsWith("amdhsa", Triple::AMDHSA) .Default(Triple::UnknownOS); } @@ -378,6 +397,9 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) { .EndsWith("v5t", Triple::ARMSubArch_v5) .EndsWith("v5te", Triple::ARMSubArch_v5te) .EndsWith("v4t", Triple::ARMSubArch_v4t) + .EndsWith("kalimba3", Triple::KalimbaSubArch_v3) + .EndsWith("kalimba4", Triple::KalimbaSubArch_v4) + .EndsWith("kalimba5", Triple::KalimbaSubArch_v5) .Default(Triple::NoSubArch); } @@ -451,6 +473,9 @@ Triple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr, } std::string Triple::normalize(StringRef Str) { + bool IsMinGW32 = false; + bool IsCygwin = false; + // Parse into components. SmallVector<StringRef, 4> Components; Str.split(Components, "-"); @@ -467,8 +492,11 @@ std::string Triple::normalize(StringRef Str) { if (Components.size() > 1) Vendor = parseVendor(Components[1]); OSType OS = UnknownOS; - if (Components.size() > 2) + if (Components.size() > 2) { OS = parseOS(Components[2]); + IsCygwin = Components[2].startswith("cygwin"); + IsMinGW32 = Components[2].startswith("mingw"); + } EnvironmentType Environment = UnknownEnvironment; if (Components.size() > 3) Environment = parseEnvironment(Components[3]); @@ -511,7 +539,9 @@ std::string Triple::normalize(StringRef Str) { break; case 2: OS = parseOS(Comp); - Valid = OS != UnknownOS; + IsCygwin = Comp.startswith("cygwin"); + IsMinGW32 = Comp.startswith("mingw"); + Valid = OS != UnknownOS || IsCygwin || IsMinGW32; break; case 3: Environment = parseEnvironment(Comp); @@ -591,16 +621,16 @@ std::string Triple::normalize(StringRef Str) { else Components[3] = getObjectFormatTypeName(ObjectFormat); } - } else if (OS == Triple::MinGW32) { + } else if (IsMinGW32) { Components.resize(4); Components[2] = "windows"; Components[3] = "gnu"; - } else if (OS == Triple::Cygwin) { + } else if (IsCygwin) { Components.resize(4); Components[2] = "windows"; Components[3] = "cygnus"; } - if (OS == Triple::MinGW32 || OS == Triple::Cygwin || + if (IsMinGW32 || IsCygwin || (OS == Triple::Win32 && Environment != UnknownEnvironment)) { if (ObjectFormat != UnknownObjectFormat && ObjectFormat != Triple::COFF) { Components.resize(5); @@ -742,7 +772,7 @@ void Triple::getiOSVersion(unsigned &Major, unsigned &Minor, getOSVersion(Major, Minor, Micro); // Default to 5.0 (or 7.0 for arm64). if (Major == 0) - Major = (getArch() == arm64) ? 7 : 5; + Major = (getArch() == aarch64) ? 7 : 5; break; } } @@ -815,7 +845,6 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) { case llvm::Triple::msp430: return 16; - case llvm::Triple::amdil: case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::hexagon: @@ -831,14 +860,16 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) { case llvm::Triple::thumbeb: case llvm::Triple::x86: case llvm::Triple::xcore: + case llvm::Triple::amdil: + case llvm::Triple::hsail: case llvm::Triple::spir: case llvm::Triple::kalimba: return 32; - case llvm::Triple::arm64: - case llvm::Triple::arm64_be: case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: + case llvm::Triple::amdgcn: + case llvm::Triple::le64: case llvm::Triple::mips64: case llvm::Triple::mips64el: case llvm::Triple::nvptx64: @@ -847,6 +878,8 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) { case llvm::Triple::sparcv9: case llvm::Triple::systemz: case llvm::Triple::x86_64: + case llvm::Triple::amdil64: + case llvm::Triple::hsail64: case llvm::Triple::spir64: return 64; } @@ -871,8 +904,7 @@ Triple Triple::get32BitArchVariant() const { case Triple::UnknownArch: case Triple::aarch64: case Triple::aarch64_be: - case Triple::arm64: - case Triple::arm64_be: + case Triple::amdgcn: case Triple::msp430: case Triple::systemz: case Triple::ppc64le: @@ -880,6 +912,7 @@ Triple Triple::get32BitArchVariant() const { break; case Triple::amdil: + case Triple::hsail: case Triple::spir: case Triple::arm: case Triple::armeb: @@ -900,12 +933,15 @@ Triple Triple::get32BitArchVariant() const { // Already 32-bit. break; + case Triple::le64: T.setArch(Triple::le32); break; case Triple::mips64: T.setArch(Triple::mips); break; case Triple::mips64el: T.setArch(Triple::mipsel); break; case Triple::nvptx64: T.setArch(Triple::nvptx); break; case Triple::ppc64: T.setArch(Triple::ppc); break; case Triple::sparcv9: T.setArch(Triple::sparc); break; case Triple::x86_64: T.setArch(Triple::x86); break; + case Triple::amdil64: T.setArch(Triple::amdil); break; + case Triple::hsail64: T.setArch(Triple::hsail); break; case Triple::spir64: T.setArch(Triple::spir); break; } return T; @@ -915,12 +951,10 @@ Triple Triple::get64BitArchVariant() const { Triple T(*this); switch (getArch()) { case Triple::UnknownArch: - case Triple::amdil: case Triple::arm: case Triple::armeb: case Triple::hexagon: case Triple::kalimba: - case Triple::le32: case Triple::msp430: case Triple::r600: case Triple::tce: @@ -932,6 +966,10 @@ Triple Triple::get64BitArchVariant() const { case Triple::aarch64: case Triple::aarch64_be: + case Triple::le64: + case Triple::amdil64: + case Triple::amdgcn: + case Triple::hsail64: case Triple::spir64: case Triple::mips64: case Triple::mips64el: @@ -941,17 +979,18 @@ Triple Triple::get64BitArchVariant() const { case Triple::sparcv9: case Triple::systemz: case Triple::x86_64: - case Triple::arm64: - case Triple::arm64_be: // Already 64-bit. break; + case Triple::le32: T.setArch(Triple::le64); break; case Triple::mips: T.setArch(Triple::mips64); break; case Triple::mipsel: T.setArch(Triple::mips64el); break; case Triple::nvptx: T.setArch(Triple::nvptx64); break; case Triple::ppc: T.setArch(Triple::ppc64); break; case Triple::sparc: T.setArch(Triple::sparcv9); break; case Triple::x86: T.setArch(Triple::x86_64); break; + case Triple::amdil: T.setArch(Triple::amdil64); break; + case Triple::hsail: T.setArch(Triple::hsail64); break; case Triple::spir: T.setArch(Triple::spir64); break; } return T; diff --git a/contrib/llvm/lib/Support/Unix/Host.inc b/contrib/llvm/lib/Support/Unix/Host.inc index 7941166..519f2a1 100644 --- a/contrib/llvm/lib/Support/Unix/Host.inc +++ b/contrib/llvm/lib/Support/Unix/Host.inc @@ -1,4 +1,4 @@ - //===- llvm/Support/Unix/Host.inc -------------------------------*- C++ -*-===// +//===- llvm/Support/Unix/Host.inc -------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,21 +16,15 @@ //=== is guaranteed to work on *all* UNIX variants. //===----------------------------------------------------------------------===// -#include "llvm/Config/config.h" -#include "llvm/ADT/StringRef.h" #include "Unix.h" -#include <sys/utsname.h> +#include "llvm/ADT/StringRef.h" +#include "llvm/Config/config.h" #include <cctype> #include <string> -#include <cstdlib> // ::getenv +#include <sys/utsname.h> using namespace llvm; -#ifdef __FreeBSD__ -std::string sys::getDefaultTargetTriple() { - return LLVM_DEFAULT_TARGET_TRIPLE; -} -#else // __FreeBSD__ static std::string getOSVersion() { struct utsname info; @@ -44,7 +38,8 @@ std::string sys::getDefaultTargetTriple() { StringRef TargetTripleString(LLVM_DEFAULT_TARGET_TRIPLE); std::pair<StringRef, StringRef> ArchSplit = TargetTripleString.split('-'); - // Normalize the arch, since the target triple may not actually match the target. + // Normalize the arch, since the target triple may not actually match the + // target. std::string Arch = ArchSplit.first; std::string Triple(Arch); @@ -66,4 +61,3 @@ std::string sys::getDefaultTargetTriple() { return Triple::normalize(Triple); } -#endif // __FreeBSD__ diff --git a/contrib/llvm/lib/Support/Unix/Memory.inc b/contrib/llvm/lib/Support/Unix/Memory.inc index c9d89a8..7ccde46 100644 --- a/contrib/llvm/lib/Support/Unix/Memory.inc +++ b/contrib/llvm/lib/Support/Unix/Memory.inc @@ -88,7 +88,7 @@ Memory::allocateMappedMemory(size_t NumBytes, if (NumBytes == 0) return MemoryBlock(); - static const size_t PageSize = process::get_self()->page_size(); + static const size_t PageSize = Process::getPageSize(); const size_t NumPages = (NumBytes+PageSize-1)/PageSize; int fd = -1; @@ -181,7 +181,7 @@ Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, std::string *ErrMsg) { if (NumBytes == 0) return MemoryBlock(); - size_t PageSize = process::get_self()->page_size(); + size_t PageSize = Process::getPageSize(); size_t NumPages = (NumBytes+PageSize-1)/PageSize; int fd = -1; diff --git a/contrib/llvm/lib/Support/Unix/Path.inc b/contrib/llvm/lib/Support/Unix/Path.inc index 623547a..973d010 100644 --- a/contrib/llvm/lib/Support/Unix/Path.inc +++ b/contrib/llvm/lib/Support/Unix/Path.inc @@ -62,47 +62,6 @@ using namespace llvm; -namespace { - /// This class automatically closes the given file descriptor when it goes out - /// of scope. You can take back explicit ownership of the file descriptor by - /// calling take(). The destructor does not verify that close was successful. - /// Therefore, never allow this class to call close on a file descriptor that - /// has been read from or written to. - struct AutoFD { - int FileDescriptor; - - AutoFD(int fd) : FileDescriptor(fd) {} - ~AutoFD() { - if (FileDescriptor >= 0) - ::close(FileDescriptor); - } - - int take() { - int ret = FileDescriptor; - FileDescriptor = -1; - return ret; - } - - operator int() const {return FileDescriptor;} - }; -} - -static std::error_code TempDir(SmallVectorImpl<char> &result) { - // FIXME: Don't use TMPDIR if program is SUID or SGID enabled. - const char *dir = nullptr; - (dir = std::getenv("TMPDIR")) || (dir = std::getenv("TMP")) || - (dir = std::getenv("TEMP")) || (dir = std::getenv("TEMPDIR")) || -#ifdef P_tmpdir - (dir = P_tmpdir) || -#endif - (dir = "/tmp"); - - result.clear(); - StringRef d(dir); - result.append(d.begin(), d.end()); - return std::error_code(); -} - namespace llvm { namespace sys { namespace fs { @@ -191,7 +150,7 @@ std::string getMainExecutable(const char *argv0, void *MainAddr) { // /proc is not always mounted under Linux (chroot for example). ssize_t len = readlink(aPath.str().c_str(), exe_path, sizeof(exe_path)); if (len >= 0) - return StringRef(exe_path, len); + return std::string(exe_path, len); } else { // Fall back to the classical detection. if (getprogpath(exe_path, argv0) != NULL) @@ -272,19 +231,6 @@ std::error_code create_directory(const Twine &path, bool IgnoreExisting) { return std::error_code(); } -std::error_code normalize_separators(SmallVectorImpl<char> &Path) { - for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) { - if (*PI == '\\') { - auto PN = PI + 1; - if (PN < PE && *PN == '\\') - ++PI; // increment once, the for loop will move over the escaped slash - else - *PI = '/'; - } - } - return std::error_code(); -} - // Note that we are using symbolic link because hard links are not supported by // all filesystems (SMB doesn't). std::error_code create_link(const Twine &to, const Twine &from) { @@ -340,48 +286,42 @@ std::error_code rename(const Twine &from, const Twine &to) { return std::error_code(); } -std::error_code resize_file(const Twine &path, uint64_t size) { - SmallString<128> path_storage; - StringRef p = path.toNullTerminatedStringRef(path_storage); - - if (::truncate(p.begin(), size) == -1) +std::error_code resize_file(int FD, uint64_t Size) { + if (::ftruncate(FD, Size) == -1) return std::error_code(errno, std::generic_category()); return std::error_code(); } -std::error_code exists(const Twine &path, bool &result) { - SmallString<128> path_storage; - StringRef p = path.toNullTerminatedStringRef(path_storage); - - if (::access(p.begin(), F_OK) == -1) { - if (errno != ENOENT) - return std::error_code(errno, std::generic_category()); - result = false; - } else - result = true; - - return std::error_code(); +static int convertAccessMode(AccessMode Mode) { + switch (Mode) { + case AccessMode::Exist: + return F_OK; + case AccessMode::Write: + return W_OK; + case AccessMode::Execute: + return R_OK | X_OK; // scripts also need R_OK. + } + llvm_unreachable("invalid enum"); } -bool can_write(const Twine &Path) { +std::error_code access(const Twine &Path, AccessMode Mode) { SmallString<128> PathStorage; StringRef P = Path.toNullTerminatedStringRef(PathStorage); - return 0 == access(P.begin(), W_OK); -} -bool can_execute(const Twine &Path) { - SmallString<128> PathStorage; - StringRef P = Path.toNullTerminatedStringRef(PathStorage); + if (::access(P.begin(), convertAccessMode(Mode)) == -1) + return std::error_code(errno, std::generic_category()); - if (0 != access(P.begin(), R_OK | X_OK)) - return false; - struct stat buf; - if (0 != stat(P.begin(), &buf)) - return false; - if (!S_ISREG(buf.st_mode)) - return false; - return true; + if (Mode == AccessMode::Execute) { + // Don't say that directories are executable. + struct stat buf; + if (0 != stat(P.begin(), &buf)) + return errc::permission_denied; + if (!S_ISREG(buf.st_mode)) + return errc::permission_denied; + } + + return std::error_code(); } bool equivalent(file_status A, file_status B) { @@ -472,80 +412,28 @@ std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time) { #endif } -std::error_code mapped_file_region::init(int FD, bool CloseFD, uint64_t Offset) { - AutoFD ScopedFD(FD); - if (!CloseFD) - ScopedFD.take(); - - // Figure out how large the file is. - struct stat FileInfo; - if (fstat(FD, &FileInfo) == -1) - return std::error_code(errno, std::generic_category()); - uint64_t FileSize = FileInfo.st_size; - - if (Size == 0) - Size = FileSize; - else if (FileSize < Size) { - // We need to grow the file. - if (ftruncate(FD, Size) == -1) - return std::error_code(errno, std::generic_category()); - } +std::error_code mapped_file_region::init(int FD, uint64_t Offset, + mapmode Mode) { + assert(Size != 0); int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE; int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE); -#ifdef MAP_FILE - flags |= MAP_FILE; -#endif Mapping = ::mmap(nullptr, Size, prot, flags, FD, Offset); if (Mapping == MAP_FAILED) return std::error_code(errno, std::generic_category()); return std::error_code(); } -mapped_file_region::mapped_file_region(const Twine &path, - mapmode mode, - uint64_t length, - uint64_t offset, - std::error_code &ec) - : Mode(mode) - , Size(length) - , Mapping() { +mapped_file_region::mapped_file_region(int fd, mapmode mode, uint64_t length, + uint64_t offset, std::error_code &ec) + : Size(length), Mapping() { // Make sure that the requested size fits within SIZE_T. if (length > std::numeric_limits<size_t>::max()) { ec = make_error_code(errc::invalid_argument); return; } - SmallString<128> path_storage; - StringRef name = path.toNullTerminatedStringRef(path_storage); - int oflags = (mode == readonly) ? O_RDONLY : O_RDWR; - int ofd = ::open(name.begin(), oflags); - if (ofd == -1) { - ec = std::error_code(errno, std::generic_category()); - return; - } - - ec = init(ofd, true, offset); - if (ec) - Mapping = nullptr; -} - -mapped_file_region::mapped_file_region(int fd, - bool closefd, - mapmode mode, - uint64_t length, - uint64_t offset, - std::error_code &ec) - : Mode(mode) - , Size(length) - , Mapping() { - // Make sure that the requested size fits within SIZE_T. - if (length > std::numeric_limits<size_t>::max()) { - ec = make_error_code(errc::invalid_argument); - return; - } - - ec = init(fd, closefd, offset); + ec = init(fd, offset, mode); if (ec) Mapping = nullptr; } @@ -555,16 +443,6 @@ mapped_file_region::~mapped_file_region() { ::munmap(Mapping, Size); } -mapped_file_region::mapped_file_region(mapped_file_region &&other) - : Mode(other.Mode), Size(other.Size), Mapping(other.Mapping) { - other.Mapping = nullptr; -} - -mapped_file_region::mapmode mapped_file_region::flags() const { - assert(Mapping && "Mapping failed but used anyway!"); - return Mode; -} - uint64_t mapped_file_region::size() const { assert(Mapping && "Mapping failed but used anyway!"); return Size; @@ -572,7 +450,6 @@ uint64_t mapped_file_region::size() const { char *mapped_file_region::data() const { assert(Mapping && "Mapping failed but used anyway!"); - assert(Mode != readonly && "Cannot get non-const data for readonly mapping!"); return reinterpret_cast<char*>(Mapping); } @@ -582,7 +459,7 @@ const char *mapped_file_region::const_data() const { } int mapped_file_region::alignment() { - return process::get_self()->page_size(); + return Process::getPageSize(); } std::error_code detail::directory_iterator_construct(detail::DirIterState &it, @@ -678,6 +555,66 @@ bool home_directory(SmallVectorImpl<char> &result) { return false; } +static const char *getEnvTempDir() { + // Check whether the temporary directory is specified by an environment + // variable. + const char *EnvironmentVariables[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; + for (const char *Env : EnvironmentVariables) { + if (const char *Dir = std::getenv(Env)) + return Dir; + } + + return nullptr; +} + +static const char *getDefaultTempDir(bool ErasedOnReboot) { +#ifdef P_tmpdir + if ((bool)P_tmpdir) + return P_tmpdir; +#endif + + if (ErasedOnReboot) + return "/tmp"; + return "/var/tmp"; +} + +void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) { + Result.clear(); + + if (ErasedOnReboot) { + // There is no env variable for the cache directory. + if (const char *RequestedDir = getEnvTempDir()) { + Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); + return; + } + } + +#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 + + const char *RequestedDir = getDefaultTempDir(ErasedOnReboot); + Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); +} + } // end namespace path } // end namespace sys diff --git a/contrib/llvm/lib/Support/Unix/Process.inc b/contrib/llvm/lib/Support/Unix/Process.inc index d2c5dbc..530f86c 100644 --- a/contrib/llvm/lib/Support/Unix/Process.inc +++ b/contrib/llvm/lib/Support/Unix/Process.inc @@ -14,15 +14,25 @@ #include "Unix.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/MutexGuard.h" #include "llvm/Support/TimeValue.h" +#if HAVE_FCNTL_H +#include <fcntl.h> +#endif #ifdef HAVE_SYS_TIME_H #include <sys/time.h> #endif #ifdef HAVE_SYS_RESOURCE_H #include <sys/resource.h> #endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#if HAVE_SIGNAL_H +#include <signal.h> +#endif // DragonFlyBSD, OpenBSD, and Bitrig have deprecated <malloc.h> for // <stdlib.h> instead. Unix.h includes this for us already. #if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \ @@ -47,10 +57,6 @@ using namespace llvm; using namespace sys; -process::id_type self_process::get_id() { - return getpid(); -} - static std::pair<TimeValue, TimeValue> getRUsageTimes() { #if defined(HAVE_GETRUSAGE) struct rusage RU; @@ -70,43 +76,19 @@ static std::pair<TimeValue, TimeValue> getRUsageTimes() { #endif } -TimeValue self_process::get_user_time() const { -#if _POSIX_TIMERS > 0 && _POSIX_CPUTIME > 0 - // Try to get a high resolution CPU timer. - struct timespec TS; - if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0) - return TimeValue(static_cast<TimeValue::SecondsType>(TS.tv_sec), - static_cast<TimeValue::NanoSecondsType>(TS.tv_nsec)); -#endif - - // Otherwise fall back to rusage based timing. - return getRUsageTimes().first; -} - -TimeValue self_process::get_system_time() const { - // We can only collect system time by inspecting the results of getrusage. - return getRUsageTimes().second; -} - // On Cygwin, getpagesize() returns 64k(AllocationGranularity) and // offset in mmap(3) should be aligned to the AllocationGranularity. -static unsigned getPageSize() { +unsigned Process::getPageSize() { #if defined(HAVE_GETPAGESIZE) - const int page_size = ::getpagesize(); + static const int page_size = ::getpagesize(); #elif defined(HAVE_SYSCONF) - long page_size = ::sysconf(_SC_PAGE_SIZE); + static long page_size = ::sysconf(_SC_PAGE_SIZE); #else #warning Cannot get the page size on this machine #endif return static_cast<unsigned>(page_size); } -// This constructor guaranteed to be run exactly once on a single thread, and -// sets up various process invariants that can be queried cheaply from then on. -self_process::self_process() : PageSize(getPageSize()) { -} - - size_t Process::GetMallocUsage() { #if defined(HAVE_MALLINFO) struct mallinfo mi; @@ -198,6 +180,97 @@ Process::GetArgumentVector(SmallVectorImpl<const char *> &ArgsOut, return std::error_code(); } +namespace { +class FDCloser { +public: + FDCloser(int &FD) : FD(FD), KeepOpen(false) {} + void keepOpen() { KeepOpen = true; } + ~FDCloser() { + if (!KeepOpen && FD >= 0) + ::close(FD); + } + +private: + FDCloser(const FDCloser &) LLVM_DELETED_FUNCTION; + void operator=(const FDCloser &) LLVM_DELETED_FUNCTION; + + int &FD; + bool KeepOpen; +}; +} + +std::error_code Process::FixupStandardFileDescriptors() { + int NullFD = -1; + FDCloser FDC(NullFD); + const int StandardFDs[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}; + for (int StandardFD : StandardFDs) { + struct stat st; + errno = 0; + while (fstat(StandardFD, &st) < 0) { + assert(errno && "expected errno to be set if fstat failed!"); + // fstat should return EBADF if the file descriptor is closed. + if (errno == EBADF) + break; + // retry fstat if we got EINTR, otherwise bubble up the failure. + if (errno != EINTR) + return std::error_code(errno, std::generic_category()); + } + // if fstat succeeds, move on to the next FD. + if (!errno) + continue; + assert(errno == EBADF && "expected errno to have EBADF at this point!"); + + if (NullFD < 0) { + while ((NullFD = open("/dev/null", O_RDWR)) < 0) { + if (errno == EINTR) + continue; + return std::error_code(errno, std::generic_category()); + } + } + + if (NullFD == StandardFD) + FDC.keepOpen(); + else if (dup2(NullFD, StandardFD) < 0) + return std::error_code(errno, std::generic_category()); + } + return std::error_code(); +} + +std::error_code Process::SafelyCloseFileDescriptor(int FD) { + // Create a signal set filled with *all* signals. + sigset_t FullSet; + if (sigfillset(&FullSet) < 0) + return std::error_code(errno, std::generic_category()); + // Atomically swap our current signal mask with a full mask. + sigset_t SavedSet; +#if LLVM_ENABLE_THREADS + if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet)) + return std::error_code(EC, std::generic_category()); +#else + if (sigprocmask(SIG_SETMASK, &FullSet, &SavedSet) < 0) + return std::error_code(errno, std::generic_category()); +#endif + // Attempt to close the file descriptor. + // We need to save the error, if one occurs, because our subsequent call to + // pthread_sigmask might tamper with errno. + int ErrnoFromClose = 0; + if (::close(FD) < 0) + ErrnoFromClose = errno; + // Restore the signal mask back to what we saved earlier. + int EC = 0; +#if LLVM_ENABLE_THREADS + EC = pthread_sigmask(SIG_SETMASK, &SavedSet, nullptr); +#else + if (sigprocmask(SIG_SETMASK, &SavedSet, nullptr) < 0) + EC = errno; +#endif + // The error code from close takes precedence over the one from + // pthread_sigmask. + if (ErrnoFromClose) + return std::error_code(ErrnoFromClose, std::generic_category()); + return std::error_code(EC, std::generic_category()); +} + bool Process::StandardInIsUserInput() { return FileDescriptorIsDisplayed(STDIN_FILENO); } @@ -263,11 +336,14 @@ extern "C" int del_curterm(struct term *termp); extern "C" int tigetnum(char *capname); #endif +#ifdef HAVE_TERMINFO +static ManagedStatic<sys::Mutex> TermColorMutex; +#endif + static bool terminalHasColors(int fd) { #ifdef HAVE_TERMINFO // First, acquire a global lock because these C routines are thread hostile. - static sys::Mutex M; - MutexGuard G(M); + MutexGuard G(*TermColorMutex); int errret = 0; if (setupterm((char *)nullptr, fd, &errret) != 0) diff --git a/contrib/llvm/lib/Support/Unix/Program.inc b/contrib/llvm/lib/Support/Unix/Program.inc index 06a33cd..0f45df1 100644 --- a/contrib/llvm/lib/Support/Unix/Program.inc +++ b/contrib/llvm/lib/Support/Unix/Program.inc @@ -17,8 +17,10 @@ //===----------------------------------------------------------------------===// #include "Unix.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" #include <llvm/Config/config.h> #if HAVE_SYS_STAT_H #include <sys/stat.h> @@ -53,50 +55,32 @@ using namespace sys; ProcessInfo::ProcessInfo() : Pid(0), ReturnCode(0) {} -// This function just uses the PATH environment variable to find the program. -std::string -sys::FindProgramByName(const std::string& progName) { - - // Check some degenerate cases - if (progName.length() == 0) // no program - return ""; - std::string temp = progName; +ErrorOr<std::string> sys::findProgramByName(StringRef Name, + ArrayRef<StringRef> Paths) { + assert(!Name.empty() && "Must have a name!"); // Use the given path verbatim if it contains any slashes; this matches // the behavior of sh(1) and friends. - if (progName.find('/') != std::string::npos) - return temp; - - // At this point, the file name is valid and does not contain slashes. Search - // for it through the directories specified in the PATH environment variable. - - // Get the path. If its empty, we can't do anything to find it. - const char *PathStr = getenv("PATH"); - if (!PathStr) - return ""; + if (Name.find('/') != StringRef::npos) + return std::string(Name); + + SmallVector<StringRef, 16> EnvironmentPaths; + if (Paths.empty()) + if (const char *PathEnv = std::getenv("PATH")) { + SplitString(PathEnv, EnvironmentPaths, ":"); + Paths = EnvironmentPaths; + } - // Now we have a colon separated list of directories to search; try them. - size_t PathLen = strlen(PathStr); - while (PathLen) { - // Find the first colon... - const char *Colon = std::find(PathStr, PathStr+PathLen, ':'); + for (auto Path : Paths) { + if (Path.empty()) + continue; // Check to see if this first directory contains the executable... - SmallString<128> FilePath(PathStr,Colon); - sys::path::append(FilePath, progName); - if (sys::fs::can_execute(Twine(FilePath))) - return FilePath.str(); // Found the executable! - - // Nope it wasn't in this directory, check the next path in the list! - PathLen -= Colon-PathStr; - PathStr = Colon; - - // Advance past duplicate colons - while (*PathStr == ':') { - PathStr++; - PathLen--; - } + SmallString<128> FilePath(Path); + sys::path::append(FilePath, Name); + if (sys::fs::can_execute(FilePath.c_str())) + return std::string(FilePath.str()); // Found the executable! } - return ""; + return std::errc::no_such_file_or_directory; } static bool RedirectIO(const StringRef *Path, int FD, std::string* ErrMsg) { @@ -334,7 +318,6 @@ ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, pid_t ChildPid = PI.Pid; if (WaitUntilTerminates) { SecondsToWait = 0; - ChildPid = -1; // mimic a wait() using waitpid() } else if (SecondsToWait) { // Install a timeout handler. The handler itself does nothing, but the // simple fact of having a handler at all causes the wait below to return @@ -440,6 +423,23 @@ ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, return std::error_code(); } +std::error_code +llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents, + WindowsEncodingMethod Encoding /*unused*/) { + std::error_code EC; + llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text); + + if (EC) + return EC; + + OS << Contents; + + if (OS.has_error()) + return std::make_error_code(std::errc::io_error); + + return EC; +} + bool llvm::sys::argumentsFitWithinSystemLimits(ArrayRef<const char*> Args) { static long ArgMax = sysconf(_SC_ARG_MAX); @@ -448,13 +448,13 @@ bool llvm::sys::argumentsFitWithinSystemLimits(ArrayRef<const char*> Args) { return true; // Conservatively account for space required by environment variables. - ArgMax /= 2; + long HalfArgMax = ArgMax / 2; size_t ArgLength = 0; for (ArrayRef<const char*>::iterator I = Args.begin(), E = Args.end(); I != E; ++I) { ArgLength += strlen(*I) + 1; - if (ArgLength > size_t(ArgMax)) { + if (ArgLength > size_t(HalfArgMax)) { return false; } } diff --git a/contrib/llvm/lib/Support/Unix/RWMutex.inc b/contrib/llvm/lib/Support/Unix/RWMutex.inc index edcbd52..85a1043 100644 --- a/contrib/llvm/lib/Support/Unix/RWMutex.inc +++ b/contrib/llvm/lib/Support/Unix/RWMutex.inc @@ -26,26 +26,26 @@ using namespace sys; // will therefore deadlock if a thread tries to acquire a read lock // multiple times. -RWMutexImpl::RWMutexImpl() : data_(new Mutex(false)) { } +RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { } RWMutexImpl::~RWMutexImpl() { - delete static_cast<Mutex *>(data_); + delete static_cast<MutexImpl *>(data_); } bool RWMutexImpl::reader_acquire() { - return static_cast<Mutex *>(data_)->acquire(); + return static_cast<MutexImpl *>(data_)->acquire(); } bool RWMutexImpl::reader_release() { - return static_cast<Mutex *>(data_)->release(); + return static_cast<MutexImpl *>(data_)->release(); } bool RWMutexImpl::writer_acquire() { - return static_cast<Mutex *>(data_)->acquire(); + return static_cast<MutexImpl *>(data_)->acquire(); } bool RWMutexImpl::writer_release() { - return static_cast<Mutex *>(data_)->release(); + return static_cast<MutexImpl *>(data_)->release(); } } diff --git a/contrib/llvm/lib/Support/Unix/Signals.inc b/contrib/llvm/lib/Support/Unix/Signals.inc index 1841fea..e8f4643 100644 --- a/contrib/llvm/lib/Support/Unix/Signals.inc +++ b/contrib/llvm/lib/Support/Unix/Signals.inc @@ -14,7 +14,14 @@ #include "Unix.h" #include "llvm/ADT/STLExtras.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" +#include "llvm/Support/UniqueLock.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> #include <string> #include <vector> @@ -36,18 +43,22 @@ #if HAVE_MACH_MACH_H #include <mach/mach.h> #endif +#if HAVE_LINK_H +#include <link.h> +#endif using namespace llvm; static RETSIGTYPE SignalHandler(int Sig); // defined below. -static SmartMutex<true> SignalsMutex; +static ManagedStatic<SmartMutex<true> > SignalsMutex; /// InterruptFunction - The function to call if ctrl-c is pressed. static void (*InterruptFunction)() = nullptr; -static std::vector<std::string> FilesToRemove; -static std::vector<std::pair<void(*)(void*), void*> > CallBacksToRun; +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 @@ -55,7 +66,6 @@ static std::vector<std::pair<void(*)(void*), void*> > CallBacksToRun; static const int IntSigs[] = { SIGHUP, SIGINT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2 }; -static const int *const IntSigsEnd = std::end(IntSigs); // KillSigs - Signals that represent that we have a bug, and our prompt // termination has been ordered. @@ -74,7 +84,6 @@ static const int KillSigs[] = { , SIGEMT #endif }; -static const int *const KillSigsEnd = std::end(KillSigs); static unsigned NumRegisteredSignals = 0; static struct { @@ -105,8 +114,8 @@ static void RegisterHandlers() { // If the handlers are already registered, we're done. if (NumRegisteredSignals != 0) return; - std::for_each(IntSigs, IntSigsEnd, RegisterHandler); - std::for_each(KillSigs, KillSigsEnd, RegisterHandler); + for (auto S : IntSigs) RegisterHandler(S); + for (auto S : KillSigs) RegisterHandler(S); } static void UnregisterHandlers() { @@ -125,11 +134,12 @@ static void UnregisterHandlers() { static void RemoveFilesToRemove() { // We avoid iterators in case of debug iterators that allocate or release // memory. - for (unsigned i = 0, e = FilesToRemove.size(); i != e; ++i) { + 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 = FilesToRemove[i].c_str(); + const char *path = FilesToRemoveRef[i].c_str(); // Get the status so we can determine if it's a file or directory. If we // can't stat the file, ignore it. @@ -162,28 +172,31 @@ static RETSIGTYPE SignalHandler(int Sig) { sigfillset(&SigMask); sigprocmask(SIG_UNBLOCK, &SigMask, nullptr); - SignalsMutex.acquire(); - RemoveFilesToRemove(); - - if (std::find(IntSigs, IntSigsEnd, Sig) != IntSigsEnd) { - if (InterruptFunction) { - void (*IF)() = InterruptFunction; - SignalsMutex.release(); - InterruptFunction = nullptr; - IF(); // run the interrupt function. + { + unique_lock<SmartMutex<true>> Guard(*SignalsMutex); + RemoveFilesToRemove(); + + if (std::find(std::begin(IntSigs), std::end(IntSigs), Sig) + != std::end(IntSigs)) { + if (InterruptFunction) { + void (*IF)() = InterruptFunction; + Guard.unlock(); + InterruptFunction = nullptr; + IF(); // run the interrupt function. + return; + } + + Guard.unlock(); + raise(Sig); // Execute the default handler. return; - } - - SignalsMutex.release(); - raise(Sig); // Execute the default handler. - return; + } } - SignalsMutex.release(); - // Otherwise if it is a fault (like SEGV) run any handler. - for (unsigned i = 0, e = CallBacksToRun.size(); i != e; ++i) - CallBacksToRun[i].first(CallBacksToRun[i].second); + std::vector<std::pair<void (*)(void *), void *>>& CallBacksToRunRef = + *CallBacksToRun; + for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i) + CallBacksToRunRef[i].first(CallBacksToRunRef[i].second); #ifdef __s390__ // On S/390, certain signals are delivered with PSW Address pointing to @@ -196,37 +209,39 @@ static RETSIGTYPE SignalHandler(int Sig) { } void llvm::sys::RunInterruptHandlers() { - SignalsMutex.acquire(); + sys::SmartScopedLock<true> Guard(*SignalsMutex); RemoveFilesToRemove(); - SignalsMutex.release(); } void llvm::sys::SetInterruptFunction(void (*IF)()) { - SignalsMutex.acquire(); - InterruptFunction = IF; - SignalsMutex.release(); + { + sys::SmartScopedLock<true> Guard(*SignalsMutex); + InterruptFunction = IF; + } RegisterHandlers(); } // RemoveFileOnSignal - The public API bool llvm::sys::RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg) { - SignalsMutex.acquire(); - std::string *OldPtr = FilesToRemove.empty() ? nullptr : &FilesToRemove[0]; - FilesToRemove.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 == &FilesToRemove[0]) - FilesToRemove.back().c_str(); - else - for (unsigned i = 0, e = FilesToRemove.size(); i != e; ++i) - FilesToRemove[i].c_str(); - - SignalsMutex.release(); + { + 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(); + } RegisterHandlers(); return false; @@ -234,31 +249,166 @@ bool llvm::sys::RemoveFileOnSignal(StringRef Filename, // DontRemoveFileOnSignal - The public API void llvm::sys::DontRemoveFileOnSignal(StringRef Filename) { - SignalsMutex.acquire(); + sys::SmartScopedLock<true> Guard(*SignalsMutex); std::vector<std::string>::reverse_iterator RI = - std::find(FilesToRemove.rbegin(), FilesToRemove.rend(), Filename); - std::vector<std::string>::iterator I = FilesToRemove.end(); - if (RI != FilesToRemove.rend()) - I = FilesToRemove.erase(RI.base()-1); + std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), 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) + for (std::vector<std::string>::iterator E = FilesToRemove->end(); I != E; ++I) I->c_str(); - - SignalsMutex.release(); } /// AddSignalHandler - Add a function to be called when a signal is delivered /// to the process. The handler can have a cookie passed to it to identify /// what instance of the handler it is. void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { - CallBacksToRun.push_back(std::make_pair(FnPtr, Cookie)); + CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie)); RegisterHandlers(); } +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) + +#if HAVE_LINK_H && (defined(__linux__) || defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || defined(__NetBSD__)) +struct DlIteratePhdrData { + void **StackTrace; + int depth; + bool first; + const char **modules; + intptr_t *offsets; + const char *main_exec_name; +}; + +static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { + DlIteratePhdrData *data = (DlIteratePhdrData*)arg; + const char *name = data->first ? data->main_exec_name : info->dlpi_name; + data->first = false; + for (int i = 0; i < info->dlpi_phnum; i++) { + const auto *phdr = &info->dlpi_phdr[i]; + if (phdr->p_type != PT_LOAD) + continue; + intptr_t beg = info->dlpi_addr + phdr->p_vaddr; + intptr_t end = beg + phdr->p_memsz; + for (int j = 0; j < data->depth; j++) { + if (data->modules[j]) + continue; + intptr_t addr = (intptr_t)data->StackTrace[j]; + if (beg <= addr && addr < end) { + data->modules[j] = name; + data->offsets[j] = addr - info->dlpi_addr; + } + } + } + return 0; +} + +static bool findModulesAndOffsets(void **StackTrace, int Depth, + const char **Modules, intptr_t *Offsets, + const char *MainExecutableName) { + DlIteratePhdrData data = {StackTrace, Depth, true, + Modules, Offsets, MainExecutableName}; + dl_iterate_phdr(dl_iterate_phdr_cb, &data); + return true; +} +#else +static bool findModulesAndOffsets(void **StackTrace, int Depth, + const char **Modules, intptr_t *Offsets, + const char *MainExecutableName) { + return false; +} +#endif + +static bool printSymbolizedStackTrace(void **StackTrace, int Depth, FILE *FD) { + // 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]) { + fprintf(FD, "#%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; + fprintf(FD, "#%d %p ", frame_no++, StackTrace[i]); + if (!FunctionName.startswith("??")) + fprintf(FD, "%s ", FunctionName.str().c_str()); + if (CurLine == Lines.end()) + return false; + StringRef FileLineInfo = *CurLine++; + if (!FileLineInfo.startswith("??")) + fprintf(FD, "%s", FileLineInfo.str().c_str()); + else + fprintf(FD, "(%s+%p)", Modules[i], (void *)Offsets[i]); + fprintf(FD, "\n"); + } + } + return true; +} +#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. @@ -271,6 +421,8 @@ void llvm::sys::PrintStackTrace(FILE *FD) { // Use backtrace() to output a backtrace on Linux systems with glibc. int depth = backtrace(StackTrace, static_cast<int>(array_lengthof(StackTrace))); + if (printSymbolizedStackTrace(StackTrace, depth, FD)) + return; #if HAVE_DLFCN_H && __GNUG__ int width = 0; for (int i = 0; i < depth; ++i) { diff --git a/contrib/llvm/lib/Support/Unix/ThreadLocal.inc b/contrib/llvm/lib/Support/Unix/ThreadLocal.inc index f14d0fa..31c3f38 100644 --- a/contrib/llvm/lib/Support/Unix/ThreadLocal.inc +++ b/contrib/llvm/lib/Support/Unix/ThreadLocal.inc @@ -16,11 +16,54 @@ //=== is guaranteed to work on *all* UNIX variants. //===----------------------------------------------------------------------===// +#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_GETSPECIFIC) + +#include <cassert> +#include <pthread.h> +#include <stdlib.h> + +namespace llvm { +using namespace sys; + +ThreadLocalImpl::ThreadLocalImpl() : data() { + static_assert(sizeof(pthread_key_t) <= sizeof(data), "size too big"); + pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data); + int errorcode = pthread_key_create(key, nullptr); + assert(errorcode == 0); + (void) errorcode; +} + +ThreadLocalImpl::~ThreadLocalImpl() { + pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data); + int errorcode = pthread_key_delete(*key); + assert(errorcode == 0); + (void) errorcode; +} + +void ThreadLocalImpl::setInstance(const void* d) { + pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data); + int errorcode = pthread_setspecific(*key, d); + assert(errorcode == 0); + (void) errorcode; +} + +void *ThreadLocalImpl::getInstance() { + pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data); + return pthread_getspecific(*key); +} + +void ThreadLocalImpl::removeInstance() { + setInstance(nullptr); +} + +} +#else namespace llvm { using namespace sys; ThreadLocalImpl::ThreadLocalImpl() : data() { } ThreadLocalImpl::~ThreadLocalImpl() { } void ThreadLocalImpl::setInstance(const void* d) { data = const_cast<void*>(d);} -const void* ThreadLocalImpl::getInstance() { return data; } +void *ThreadLocalImpl::getInstance() { return data; } void ThreadLocalImpl::removeInstance() { setInstance(0); } } +#endif diff --git a/contrib/llvm/lib/Support/Unix/TimeValue.inc b/contrib/llvm/lib/Support/Unix/TimeValue.inc index 7d4acf7..042e0da 100644 --- a/contrib/llvm/lib/Support/Unix/TimeValue.inc +++ b/contrib/llvm/lib/Support/Unix/TimeValue.inc @@ -41,7 +41,7 @@ TimeValue TimeValue::now() { // errors concern the timezone parameter which we're passing in as 0. // In the unlikely case it does happen, just return MinTime, no error // message needed. - return MinTime; + return MinTime(); } return TimeValue( diff --git a/contrib/llvm/lib/Support/Unix/Unix.h b/contrib/llvm/lib/Support/Unix/Unix.h index ba688e3..e16a226 100644 --- a/contrib/llvm/lib/Support/Unix/Unix.h +++ b/contrib/llvm/lib/Support/Unix/Unix.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_UNIX_UNIX_H -#define LLVM_SYSTEM_UNIX_UNIX_H +#ifndef LLVM_LIB_SUPPORT_UNIX_UNIX_H +#define LLVM_LIB_SUPPORT_UNIX_UNIX_H //===----------------------------------------------------------------------===// //=== WARNING: Implementation here must contain only generic UNIX code that diff --git a/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc b/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc index 5ed0b70..79d5f79 100644 --- a/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc +++ b/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc @@ -41,32 +41,11 @@ using namespace sys; static DenseSet<HMODULE> *OpenedHandles; -extern "C" { - - static BOOL CALLBACK ELM_Callback(WIN32_ELMCB_PCSTR ModuleName, - ULONG_PTR ModuleBase, - ULONG ModuleSize, - PVOID UserContext) - { - // Ignore VC++ runtimes prior to 7.1. Somehow some of them get loaded - // into the process. - if (stricmp(ModuleName, "msvci70") != 0 && - stricmp(ModuleName, "msvcirt") != 0 && - stricmp(ModuleName, "msvcp50") != 0 && - stricmp(ModuleName, "msvcp60") != 0 && - stricmp(ModuleName, "msvcp70") != 0 && - stricmp(ModuleName, "msvcr70") != 0 && -#ifndef __MINGW32__ - // Mingw32 uses msvcrt.dll by default. Don't ignore it. - // Otherwise the user should be aware what they are doing. - stricmp(ModuleName, "msvcrt") != 0 && -#endif - stricmp(ModuleName, "msvcrt20") != 0 && - stricmp(ModuleName, "msvcrt40") != 0) { - OpenedHandles->insert((HMODULE)ModuleBase); - } - return TRUE; - } +static BOOL CALLBACK +ELM_Callback(WIN32_ELMCB_PCSTR ModuleName, ULONG_PTR ModuleBase, + ULONG ModuleSize, PVOID UserContext) { + OpenedHandles->insert((HMODULE)ModuleBase); + return TRUE; } DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, @@ -115,10 +94,24 @@ DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, extern "C" { extern void *SYM; } #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) EXPLICIT_SYMBOL(SYMTO) +#ifdef _M_IX86 +// Win32 on x86 implements certain single-precision math functions as macros. +// These functions are not exported by the DLL, but will still be needed +// for symbol-resolution by the JIT loader. Therefore, this Support libray +// provides helper functions with the same implementation. + +#define INLINE_DEF_SYMBOL1(TYP, SYM) \ + extern "C" TYP inline_##SYM(TYP _X) { return SYM(_X); } +#define INLINE_DEF_SYMBOL2(TYP, SYM) \ + extern "C" TYP inline_##SYM(TYP _X, TYP _Y) { return SYM(_X, _Y); } +#endif + #include "explicit_symbols.inc" #undef EXPLICIT_SYMBOL #undef EXPLICIT_SYMBOL2 +#undef INLINE_DEF_SYMBOL1 +#undef INLINE_DEF_SYMBOL2 void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) { SmartScopedLock<true> Lock(*SymbolsMutex); @@ -142,22 +135,32 @@ void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) { } } - #define EXPLICIT_SYMBOL(SYM) \ - if (!strcmp(symbolName, #SYM)) return (void*)&SYM; - #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) \ - if (!strcmp(symbolName, #SYMFROM)) return (void*)&SYMTO; +#define EXPLICIT_SYMBOL(SYM) \ + if (!strcmp(symbolName, #SYM)) \ + return (void *)&SYM; +#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) \ + if (!strcmp(symbolName, #SYMFROM)) \ + return (void *)&SYMTO; + +#ifdef _M_IX86 +#define INLINE_DEF_SYMBOL1(TYP, SYM) \ + if (!strcmp(symbolName, #SYM)) \ + return (void *)&inline_##SYM; +#define INLINE_DEF_SYMBOL2(TYP, SYM) INLINE_DEF_SYMBOL1(TYP, SYM) +#endif { - #include "explicit_symbols.inc" +#include "explicit_symbols.inc" } - #undef EXPLICIT_SYMBOL - #undef EXPLICIT_SYMBOL2 +#undef EXPLICIT_SYMBOL +#undef EXPLICIT_SYMBOL2 +#undef INLINE_DEF_SYMBOL1 +#undef INLINE_DEF_SYMBOL2 return 0; } - void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { if (!isValid()) return NULL; @@ -166,5 +169,4 @@ void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { return (void *)(intptr_t)GetProcAddress((HMODULE)Data, symbolName); } - } diff --git a/contrib/llvm/lib/Support/Windows/Host.inc b/contrib/llvm/lib/Support/Windows/Host.inc index 0c02bf9..fe89fe0 100644 --- a/contrib/llvm/lib/Support/Windows/Host.inc +++ b/contrib/llvm/lib/Support/Windows/Host.inc @@ -1,4 +1,4 @@ -//===- llvm/Support/Win32/Host.inc -------------------------------*- C++ -*-===// +//===- llvm/Support/Win32/Host.inc ------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/lib/Support/Windows/Path.inc b/contrib/llvm/lib/Support/Windows/Path.inc index 7a1bc0447..d8b5702 100644 --- a/contrib/llvm/lib/Support/Windows/Path.inc +++ b/contrib/llvm/lib/Support/Windows/Path.inc @@ -44,28 +44,12 @@ using namespace llvm; using llvm::sys::windows::UTF8ToUTF16; using llvm::sys::windows::UTF16ToUTF8; +using llvm::sys::path::widenPath; static std::error_code windows_error(DWORD E) { return mapWindowsError(E); } -static std::error_code TempDir(SmallVectorImpl<char> &Result) { - SmallVector<wchar_t, 64> Res; -retry_temp_dir: - DWORD Len = ::GetTempPathW(Res.capacity(), Res.begin()); - - if (Len == 0) - return windows_error(::GetLastError()); - - if (Len > Res.capacity()) { - Res.reserve(Len); - goto retry_temp_dir; - } - - Res.set_size(Len); - return UTF16ToUTF8(Res.begin(), Res.size(), Result); -} - static bool is_separator(const wchar_t value) { switch (value) { case L'\\': @@ -78,6 +62,62 @@ static bool is_separator(const wchar_t value) { namespace llvm { namespace sys { +namespace path { + +// Convert a UTF-8 path to UTF-16. Also, if the absolute equivalent of the +// path is longer than CreateDirectory can tolerate, make it absolute and +// prefixed by '\\?\'. +std::error_code widenPath(const Twine &Path8, + SmallVectorImpl<wchar_t> &Path16) { + const size_t MaxDirLen = MAX_PATH - 12; // Must leave room for 8.3 filename. + + // Several operations would convert Path8 to SmallString; more efficient to + // do it once up front. + SmallString<128> Path8Str; + Path8.toVector(Path8Str); + + // If we made this path absolute, how much longer would it get? + size_t CurPathLen; + if (llvm::sys::path::is_absolute(Twine(Path8Str))) + CurPathLen = 0; // No contribution from current_path needed. + else { + CurPathLen = ::GetCurrentDirectoryW(0, NULL); + if (CurPathLen == 0) + return windows_error(::GetLastError()); + } + + // Would the absolute path be longer than our limit? + if ((Path8Str.size() + CurPathLen) >= MaxDirLen && + !Path8Str.startswith("\\\\?\\")) { + SmallString<2*MAX_PATH> FullPath("\\\\?\\"); + if (CurPathLen) { + SmallString<80> CurPath; + if (std::error_code EC = llvm::sys::fs::current_path(CurPath)) + return EC; + FullPath.append(CurPath); + } + // Traverse the requested path, canonicalizing . and .. as we go (because + // the \\?\ prefix is documented to treat them as real components). + // The iterators don't report separators and append() always attaches + // preferred_separator so we don't need to call native() on the result. + for (llvm::sys::path::const_iterator I = llvm::sys::path::begin(Path8Str), + E = llvm::sys::path::end(Path8Str); + I != E; ++I) { + if (I->size() == 1 && *I == ".") + continue; + if (I->size() == 2 && *I == "..") + llvm::sys::path::remove_filename(FullPath); + else + llvm::sys::path::append(FullPath, *I); + } + return UTF8ToUTF16(FullPath, Path16); + } + + // Just use the caller's original path. + return UTF8ToUTF16(Path8Str, Path16); +} +} // end namespace path + namespace fs { std::string getMainExecutable(const char *argv0, void *MainExecAddr) { @@ -147,11 +187,9 @@ std::error_code current_path(SmallVectorImpl<char> &result) { } std::error_code create_directory(const Twine &path, bool IgnoreExisting) { - SmallString<128> path_storage; SmallVector<wchar_t, 128> path_utf16; - if (std::error_code ec = - UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) + if (std::error_code ec = widenPath(path, path_utf16)) return ec; if (!::CreateDirectoryW(path_utf16.begin(), NULL)) { @@ -163,25 +201,14 @@ std::error_code create_directory(const Twine &path, bool IgnoreExisting) { return std::error_code(); } -std::error_code normalize_separators(SmallVectorImpl<char> &Path) { - (void) Path; - return std::error_code(); -} - // We can't use symbolic links for windows. std::error_code create_link(const Twine &to, const Twine &from) { - // Get arguments. - SmallString<128> from_storage; - SmallString<128> to_storage; - StringRef f = from.toStringRef(from_storage); - StringRef t = to.toStringRef(to_storage); - // Convert to utf-16. SmallVector<wchar_t, 128> wide_from; SmallVector<wchar_t, 128> wide_to; - if (std::error_code ec = UTF8ToUTF16(f, wide_from)) + if (std::error_code ec = widenPath(from, wide_from)) return ec; - if (std::error_code ec = UTF8ToUTF16(t, wide_to)) + if (std::error_code ec = widenPath(to, wide_to)) return ec; if (!::CreateHardLinkW(wide_from.begin(), wide_to.begin(), NULL)) @@ -191,7 +218,6 @@ std::error_code create_link(const Twine &to, const Twine &from) { } std::error_code remove(const Twine &path, bool IgnoreNonExisting) { - SmallString<128> path_storage; SmallVector<wchar_t, 128> path_utf16; file_status ST; @@ -201,8 +227,7 @@ std::error_code remove(const Twine &path, bool IgnoreNonExisting) { return std::error_code(); } - if (std::error_code ec = - UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) + if (std::error_code ec = widenPath(path, path_utf16)) return ec; if (ST.type() == file_type::directory_file) { @@ -222,18 +247,12 @@ std::error_code remove(const Twine &path, bool IgnoreNonExisting) { } std::error_code rename(const Twine &from, const Twine &to) { - // Get arguments. - SmallString<128> from_storage; - SmallString<128> to_storage; - StringRef f = from.toStringRef(from_storage); - StringRef t = to.toStringRef(to_storage); - // Convert to utf-16. SmallVector<wchar_t, 128> wide_from; SmallVector<wchar_t, 128> wide_to; - if (std::error_code ec = UTF8ToUTF16(f, wide_from)) + if (std::error_code ec = widenPath(from, wide_from)) return ec; - if (std::error_code ec = UTF8ToUTF16(t, wide_to)) + if (std::error_code ec = widenPath(to, wide_to)) return ec; std::error_code ec = std::error_code(); @@ -253,69 +272,36 @@ std::error_code rename(const Twine &from, const Twine &to) { return ec; } -std::error_code resize_file(const Twine &path, uint64_t size) { - SmallString<128> path_storage; - SmallVector<wchar_t, 128> path_utf16; - - if (std::error_code ec = - UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) - return ec; - - int fd = ::_wopen(path_utf16.begin(), O_BINARY | _O_RDWR, S_IWRITE); - if (fd == -1) - return std::error_code(errno, std::generic_category()); +std::error_code resize_file(int FD, uint64_t Size) { #ifdef HAVE__CHSIZE_S - errno_t error = ::_chsize_s(fd, size); + errno_t error = ::_chsize_s(FD, Size); #else - errno_t error = ::_chsize(fd, size); + errno_t error = ::_chsize(FD, Size); #endif - ::close(fd); return std::error_code(error, std::generic_category()); } -std::error_code exists(const Twine &path, bool &result) { - SmallString<128> path_storage; - SmallVector<wchar_t, 128> path_utf16; +std::error_code access(const Twine &Path, AccessMode Mode) { + SmallVector<wchar_t, 128> PathUtf16; - if (std::error_code ec = - UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) - return ec; + if (std::error_code EC = widenPath(Path, PathUtf16)) + return EC; - DWORD attributes = ::GetFileAttributesW(path_utf16.begin()); + DWORD Attributes = ::GetFileAttributesW(PathUtf16.begin()); - if (attributes == INVALID_FILE_ATTRIBUTES) { + if (Attributes == INVALID_FILE_ATTRIBUTES) { // See if the file didn't actually exist. DWORD LastError = ::GetLastError(); if (LastError != ERROR_FILE_NOT_FOUND && LastError != ERROR_PATH_NOT_FOUND) return windows_error(LastError); - result = false; - } else - result = true; - return std::error_code(); -} - -bool can_write(const Twine &Path) { - // FIXME: take security attributes into account. - SmallString<128> PathStorage; - SmallVector<wchar_t, 128> PathUtf16; - - if (UTF8ToUTF16(Path.toStringRef(PathStorage), PathUtf16)) - return false; - - DWORD Attr = ::GetFileAttributesW(PathUtf16.begin()); - return (Attr != INVALID_FILE_ATTRIBUTES) && !(Attr & FILE_ATTRIBUTE_READONLY); -} - -bool can_execute(const Twine &Path) { - SmallString<128> PathStorage; - SmallVector<wchar_t, 128> PathUtf16; + return errc::no_such_file_or_directory; + } - if (UTF8ToUTF16(Path.toStringRef(PathStorage), PathUtf16)) - return false; + if (Mode == AccessMode::Write && (Attributes & FILE_ATTRIBUTE_READONLY)) + return errc::permission_denied; - DWORD Attr = ::GetFileAttributesW(PathUtf16.begin()); - return Attr != INVALID_FILE_ATTRIBUTES; + return std::error_code(); } bool equivalent(file_status A, file_status B) { @@ -424,7 +410,7 @@ std::error_code status(const Twine &path, file_status &result) { return std::error_code(); } - if (std::error_code ec = UTF8ToUTF16(path8, path_utf16)) + if (std::error_code ec = widenPath(path8, path_utf16)) return ec; DWORD attr = ::GetFileAttributesW(path_utf16.begin()); @@ -472,17 +458,15 @@ std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time) { return std::error_code(); } -std::error_code mapped_file_region::init(int FD, bool CloseFD, uint64_t Offset) { - FileDescriptor = FD; +std::error_code mapped_file_region::init(int FD, uint64_t Offset, + mapmode Mode) { // Make sure that the requested size fits within SIZE_T. - if (Size > std::numeric_limits<SIZE_T>::max()) { - if (FileDescriptor) { - if (CloseFD) - _close(FileDescriptor); - } else - ::CloseHandle(FileHandle); + if (Size > std::numeric_limits<SIZE_T>::max()) return make_error_code(errc::invalid_argument); - } + + HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); + if (FileHandle == INVALID_HANDLE_VALUE) + return make_error_code(errc::bad_file_descriptor); DWORD flprotect; switch (Mode) { @@ -491,18 +475,13 @@ std::error_code mapped_file_region::init(int FD, bool CloseFD, uint64_t Offset) case priv: flprotect = PAGE_WRITECOPY; break; } - FileMappingHandle = + HANDLE FileMappingHandle = ::CreateFileMappingW(FileHandle, 0, flprotect, (Offset + Size) >> 32, (Offset + Size) & 0xffffffff, 0); if (FileMappingHandle == NULL) { std::error_code ec = windows_error(GetLastError()); - if (FileDescriptor) { - if (CloseFD) - _close(FileDescriptor); - } else - ::CloseHandle(FileHandle); return ec; } @@ -520,11 +499,6 @@ std::error_code mapped_file_region::init(int FD, bool CloseFD, uint64_t Offset) if (Mapping == NULL) { std::error_code ec = windows_error(GetLastError()); ::CloseHandle(FileMappingHandle); - if (FileDescriptor) { - if (CloseFD) - _close(FileDescriptor); - } else - ::CloseHandle(FileHandle); return ec; } @@ -535,11 +509,6 @@ std::error_code mapped_file_region::init(int FD, bool CloseFD, uint64_t Offset) std::error_code ec = windows_error(GetLastError()); ::UnmapViewOfFile(Mapping); ::CloseHandle(FileMappingHandle); - if (FileDescriptor) { - if (CloseFD) - _close(FileDescriptor); - } else - ::CloseHandle(FileHandle); return ec; } Size = mbi.RegionSize; @@ -548,85 +517,15 @@ std::error_code mapped_file_region::init(int FD, bool CloseFD, uint64_t Offset) // Close all the handles except for the view. It will keep the other handles // alive. ::CloseHandle(FileMappingHandle); - if (FileDescriptor) { - if (CloseFD) - _close(FileDescriptor); // Also closes FileHandle. - } else - ::CloseHandle(FileHandle); return std::error_code(); } -mapped_file_region::mapped_file_region(const Twine &path, - mapmode mode, - uint64_t length, - uint64_t offset, - std::error_code &ec) - : Mode(mode) - , Size(length) - , Mapping() - , FileDescriptor() - , FileHandle(INVALID_HANDLE_VALUE) - , FileMappingHandle() { - SmallString<128> path_storage; - SmallVector<wchar_t, 128> path_utf16; - - // Convert path to UTF-16. - if ((ec = UTF8ToUTF16(path.toStringRef(path_storage), path_utf16))) - return; - - // Get file handle for creating a file mapping. - FileHandle = ::CreateFileW(c_str(path_utf16), - Mode == readonly ? GENERIC_READ - : GENERIC_READ | GENERIC_WRITE, - Mode == readonly ? FILE_SHARE_READ - : 0, - 0, - Mode == readonly ? OPEN_EXISTING - : OPEN_ALWAYS, - Mode == readonly ? FILE_ATTRIBUTE_READONLY - : FILE_ATTRIBUTE_NORMAL, - 0); - if (FileHandle == INVALID_HANDLE_VALUE) { - ec = windows_error(::GetLastError()); - return; - } - - FileDescriptor = 0; - ec = init(FileDescriptor, true, offset); - if (ec) { - Mapping = FileMappingHandle = 0; - FileHandle = INVALID_HANDLE_VALUE; - FileDescriptor = 0; - } -} - -mapped_file_region::mapped_file_region(int fd, - bool closefd, - mapmode mode, - uint64_t length, - uint64_t offset, - std::error_code &ec) - : Mode(mode) - , Size(length) - , Mapping() - , FileDescriptor(fd) - , FileHandle(INVALID_HANDLE_VALUE) - , FileMappingHandle() { - FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); - if (FileHandle == INVALID_HANDLE_VALUE) { - if (closefd) - _close(FileDescriptor); - FileDescriptor = 0; - ec = make_error_code(errc::bad_file_descriptor); - return; - } - - ec = init(FileDescriptor, closefd, offset); - if (ec) { - Mapping = FileMappingHandle = 0; - FileHandle = INVALID_HANDLE_VALUE; - FileDescriptor = 0; - } +mapped_file_region::mapped_file_region(int fd, mapmode mode, uint64_t length, + uint64_t offset, std::error_code &ec) + : Size(length), Mapping() { + ec = init(fd, offset, mode); + if (ec) + Mapping = 0; } mapped_file_region::~mapped_file_region() { @@ -634,30 +533,12 @@ mapped_file_region::~mapped_file_region() { ::UnmapViewOfFile(Mapping); } -mapped_file_region::mapped_file_region(mapped_file_region &&other) - : Mode(other.Mode) - , Size(other.Size) - , Mapping(other.Mapping) - , FileDescriptor(other.FileDescriptor) - , FileHandle(other.FileHandle) - , FileMappingHandle(other.FileMappingHandle) { - other.Mapping = other.FileMappingHandle = 0; - other.FileHandle = INVALID_HANDLE_VALUE; - other.FileDescriptor = 0; -} - -mapped_file_region::mapmode mapped_file_region::flags() const { - assert(Mapping && "Mapping failed but used anyway!"); - return Mode; -} - uint64_t mapped_file_region::size() const { assert(Mapping && "Mapping failed but used anyway!"); return Size; } char *mapped_file_region::data() const { - assert(Mode != readonly && "Cannot get non-const data for readonly mapping!"); assert(Mapping && "Mapping failed but used anyway!"); return reinterpret_cast<char*>(Mapping); } @@ -677,7 +558,7 @@ std::error_code detail::directory_iterator_construct(detail::DirIterState &it, StringRef path){ SmallVector<wchar_t, 128> path_utf16; - if (std::error_code ec = UTF8ToUTF16(path, path_utf16)) + if (std::error_code ec = widenPath(path, path_utf16)) return ec; // Convert path to the format that Windows is happy with. @@ -760,11 +641,9 @@ std::error_code detail::directory_iterator_increment(detail::DirIterState &it) { } std::error_code openFileForRead(const Twine &Name, int &ResultFD) { - SmallString<128> PathStorage; SmallVector<wchar_t, 128> PathUTF16; - if (std::error_code EC = - UTF8ToUTF16(Name.toStringRef(PathStorage), PathUTF16)) + if (std::error_code EC = widenPath(Name, PathUTF16)) return EC; HANDLE H = ::CreateFileW(PathUTF16.begin(), GENERIC_READ, @@ -799,11 +678,9 @@ std::error_code openFileForWrite(const Twine &Name, int &ResultFD, assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) && "Cannot specify both 'excl' and 'append' file creation flags!"); - SmallString<128> PathStorage; SmallVector<wchar_t, 128> PathUTF16; - if (std::error_code EC = - UTF8ToUTF16(Name.toStringRef(PathStorage), PathUTF16)) + if (std::error_code EC = widenPath(Name, PathUTF16)) return EC; DWORD CreationDisposition; @@ -867,6 +744,51 @@ bool home_directory(SmallVectorImpl<char> &result) { return true; } +static bool getTempDirEnvVar(const char *Var, SmallVectorImpl<char> &Res) { + SmallVector<wchar_t, 128> NameUTF16; + if (windows::UTF8ToUTF16(Var, NameUTF16)) + return false; + + SmallVector<wchar_t, 1024> Buf; + size_t Size = 1024; + do { + Buf.reserve(Size); + Size = + GetEnvironmentVariableW(NameUTF16.data(), Buf.data(), Buf.capacity()); + if (Size == 0) + return false; + + // Try again with larger buffer. + } while (Size > Buf.capacity()); + Buf.set_size(Size); + + if (windows::UTF16ToUTF8(Buf.data(), Size, Res)) + return false; + return true; +} + +static bool getTempDirEnvVar(SmallVectorImpl<char> &Res) { + const char *EnvironmentVariables[] = {"TMP", "TEMP", "USERPROFILE"}; + for (const char *Env : EnvironmentVariables) { + if (getTempDirEnvVar(Env, Res)) + return true; + } + return false; +} + +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)) + return; + + // Fall back to a system default. + const char *DefaultResult = "C:\\TEMP"; + Result.append(DefaultResult, DefaultResult + strlen(DefaultResult)); +} } // end namespace path namespace windows { @@ -896,11 +818,13 @@ std::error_code UTF8ToUTF16(llvm::StringRef utf8, return std::error_code(); } -std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, - llvm::SmallVectorImpl<char> &utf8) { +static +std::error_code UTF16ToCodePage(unsigned codepage, const wchar_t *utf16, + size_t utf16_len, + llvm::SmallVectorImpl<char> &utf8) { if (utf16_len) { // Get length. - int len = ::WideCharToMultiByte(CP_UTF8, 0, utf16, utf16_len, utf8.begin(), + int len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.begin(), 0, NULL, NULL); if (len == 0) @@ -910,7 +834,7 @@ std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, utf8.set_size(len); // Now do the actual conversion. - len = ::WideCharToMultiByte(CP_UTF8, 0, utf16, utf16_len, utf8.data(), + len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.data(), utf8.size(), NULL, NULL); if (len == 0) @@ -923,6 +847,16 @@ std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, return std::error_code(); } + +std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, + llvm::SmallVectorImpl<char> &utf8) { + return UTF16ToCodePage(CP_UTF8, utf16, utf16_len, utf8); +} + +std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len, + llvm::SmallVectorImpl<char> &utf8) { + return UTF16ToCodePage(CP_ACP, utf16, utf16_len, utf8); +} } // end namespace windows } // end namespace sys } // end namespace llvm diff --git a/contrib/llvm/lib/Support/Windows/Process.inc b/contrib/llvm/lib/Support/Windows/Process.inc index 61749a7..854eac7 100644 --- a/contrib/llvm/lib/Support/Windows/Process.inc +++ b/contrib/llvm/lib/Support/Windows/Process.inc @@ -49,10 +49,6 @@ using namespace llvm; using namespace sys; -process::id_type self_process::get_id() { - return GetCurrentProcessId(); -} - static TimeValue getTimeValueFromFILETIME(FILETIME Time) { ULARGE_INTEGER TimeInteger; TimeInteger.LowPart = Time.dwLowDateTime; @@ -65,28 +61,10 @@ static TimeValue getTimeValueFromFILETIME(FILETIME Time) { (TimeInteger.QuadPart % 10000000) * 100)); } -TimeValue self_process::get_user_time() const { - FILETIME ProcCreate, ProcExit, KernelTime, UserTime; - if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, - &UserTime) == 0) - return TimeValue(); - - return getTimeValueFromFILETIME(UserTime); -} - -TimeValue self_process::get_system_time() const { - FILETIME ProcCreate, ProcExit, KernelTime, UserTime; - if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, - &UserTime) == 0) - return TimeValue(); - - return getTimeValueFromFILETIME(KernelTime); -} - // This function retrieves the page size using GetNativeSystemInfo() and is // present solely so it can be called once to initialize the self_process member // below. -static unsigned getPageSize() { +static unsigned computePageSize() { // GetNativeSystemInfo() provides the physical page size which may differ // from GetSystemInfo() in 32-bit applications running under WOW64. SYSTEM_INFO info; @@ -96,12 +74,11 @@ static unsigned getPageSize() { return static_cast<unsigned>(info.dwPageSize); } -// This constructor guaranteed to be run exactly once on a single thread, and -// sets up various process invariants that can be queried cheaply from then on. -self_process::self_process() : PageSize(getPageSize()) { +unsigned Process::getPageSize() { + static unsigned Ret = computePageSize(); + return Ret; } - size_t Process::GetMallocUsage() { @@ -273,6 +250,16 @@ Process::GetArgumentVector(SmallVectorImpl<const char *> &Args, return ec; } +std::error_code Process::FixupStandardFileDescriptors() { + return std::error_code(); +} + +std::error_code Process::SafelyCloseFileDescriptor(int FD) { + if (::close(FD) < 0) + return std::error_code(errno, std::generic_category()); + return std::error_code(); +} + bool Process::StandardInIsUserInput() { return FileDescriptorIsDisplayed(0); } diff --git a/contrib/llvm/lib/Support/Windows/Program.inc b/contrib/llvm/lib/Support/Windows/Program.inc index b2f71ae..c370077 100644 --- a/contrib/llvm/lib/Support/Windows/Program.inc +++ b/contrib/llvm/lib/Support/Windows/Program.inc @@ -12,7 +12,11 @@ //===----------------------------------------------------------------------===// #include "WindowsSupport.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/ConvertUTF.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/WindowsError.h" +#include "llvm/Support/raw_ostream.h" #include <cstdio> #include <fcntl.h> #include <io.h> @@ -28,43 +32,68 @@ using namespace sys; ProcessInfo::ProcessInfo() : ProcessHandle(0), Pid(0), ReturnCode(0) {} -// This function just uses the PATH environment variable to find the program. -std::string sys::FindProgramByName(const std::string &progName) { - // Check some degenerate cases - if (progName.length() == 0) // no program - return ""; - std::string temp = progName; - // Return paths with slashes verbatim. - if (progName.find('\\') != std::string::npos || - progName.find('/') != std::string::npos) - return temp; - - // At this point, the file name is valid and does not contain slashes. - // Let Windows search for it. - SmallVector<wchar_t, MAX_PATH> progNameUnicode; - if (windows::UTF8ToUTF16(progName, progNameUnicode)) - return ""; - - SmallVector<wchar_t, MAX_PATH> buffer; - DWORD len = MAX_PATH; - do { - buffer.reserve(len); - len = ::SearchPathW(NULL, progNameUnicode.data(), L".exe", - buffer.capacity(), buffer.data(), NULL); - - // See if it wasn't found. - if (len == 0) - return ""; - - // Buffer was too small; grow and retry. - } while (len > buffer.capacity()); - - buffer.set_size(len); - SmallVector<char, MAX_PATH> result; - if (windows::UTF16ToUTF8(buffer.begin(), buffer.size(), result)) - return ""; - - return std::string(result.data(), result.size()); +ErrorOr<std::string> sys::findProgramByName(StringRef Name, + ArrayRef<StringRef> Paths) { + assert(!Name.empty() && "Must have a name!"); + + if (Name.find_first_of("/\\") != StringRef::npos) + return std::string(Name); + + const wchar_t *Path = nullptr; + std::wstring PathStorage; + if (!Paths.empty()) { + PathStorage.reserve(Paths.size() * MAX_PATH); + for (unsigned i = 0; i < Paths.size(); ++i) { + if (i) + PathStorage.push_back(L';'); + StringRef P = Paths[i]; + SmallVector<wchar_t, MAX_PATH> TmpPath; + if (std::error_code EC = windows::UTF8ToUTF16(P, TmpPath)) + return EC; + PathStorage.append(TmpPath.begin(), TmpPath.end()); + } + Path = PathStorage.c_str(); + } + + SmallVector<wchar_t, MAX_PATH> U16Name; + if (std::error_code EC = windows::UTF8ToUTF16(Name, U16Name)) + return EC; + + SmallVector<StringRef, 12> PathExts; + PathExts.push_back(""); + PathExts.push_back(".exe"); // FIXME: This must be in %PATHEXT%. + if (const char *PathExtEnv = std::getenv("PATHEXT")) + SplitString(PathExtEnv, PathExts, ";"); + + SmallVector<wchar_t, MAX_PATH> U16Result; + DWORD Len = MAX_PATH; + for (StringRef Ext : PathExts) { + SmallVector<wchar_t, MAX_PATH> U16Ext; + if (std::error_code EC = windows::UTF8ToUTF16(Ext, U16Ext)) + return EC; + + do { + U16Result.reserve(Len); + Len = ::SearchPathW(Path, c_str(U16Name), + U16Ext.empty() ? nullptr : c_str(U16Ext), + U16Result.capacity(), U16Result.data(), nullptr); + } while (Len > U16Result.capacity()); + + if (Len != 0) + break; // Found it. + } + + if (Len == 0) + return mapWindowsError(::GetLastError()); + + U16Result.set_size(Len); + + SmallVector<char, MAX_PATH> U8Result; + if (std::error_code EC = + windows::UTF16ToUTF8(U16Result.data(), U16Result.size(), U8Result)) + return EC; + + return std::string(U8Result.begin(), U8Result.end()); } static HANDLE RedirectIO(const StringRef *path, int fd, std::string* ErrMsg) { @@ -89,14 +118,19 @@ static HANDLE RedirectIO(const StringRef *path, int fd, std::string* ErrMsg) { sa.bInheritHandle = TRUE; SmallVector<wchar_t, 128> fnameUnicode; - if (windows::UTF8ToUTF16(fname, fnameUnicode)) - return INVALID_HANDLE_VALUE; - + if (path->empty()) { + // Don't play long-path tricks on "NUL". + if (windows::UTF8ToUTF16(fname, fnameUnicode)) + return INVALID_HANDLE_VALUE; + } else { + if (path::widenPath(fname, fnameUnicode)) + return INVALID_HANDLE_VALUE; + } h = CreateFileW(fnameUnicode.data(), fd ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ, &sa, fd == 0 ? OPEN_EXISTING : CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) { - MakeErrMsg(ErrMsg, std::string(fname) + ": Can't open file for " + + MakeErrMsg(ErrMsg, fname + ": Can't open file for " + (fd ? "input: " : "output: ")); } @@ -166,19 +200,7 @@ static unsigned int ArgLenWithQuotes(const char *Str) { } -static bool Execute(ProcessInfo &PI, StringRef Program, const char **args, - const char **envp, const StringRef **redirects, - unsigned memoryLimit, std::string *ErrMsg) { - if (!sys::fs::can_execute(Program)) { - if (ErrMsg) - *ErrMsg = "program not executable"; - return false; - } - - // 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). - +static std::unique_ptr<char[]> flattenArgs(const char **args) { // First, determine the length of the command line. unsigned len = 0; for (unsigned i = 0; args[i]; i++) { @@ -216,6 +238,22 @@ static bool Execute(ProcessInfo &PI, StringRef Program, const char **args, } *p = 0; + return command; +} + +static bool Execute(ProcessInfo &PI, StringRef Program, const char **args, + const char **envp, const StringRef **redirects, + unsigned memoryLimit, std::string *ErrMsg) { + if (!sys::fs::can_execute(Program)) { + if (ErrMsg) + *ErrMsg = "program not executable"; + return false; + } + + // 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). + std::unique_ptr<char[]> command = flattenArgs(args); // The pointer to the environment block for the new process. std::vector<wchar_t> EnvBlock; @@ -290,7 +328,7 @@ static bool Execute(ProcessInfo &PI, StringRef Program, const char **args, fflush(stderr); SmallVector<wchar_t, MAX_PATH> ProgramUtf16; - if (std::error_code ec = windows::UTF8ToUTF16(Program, ProgramUtf16)) { + if (std::error_code ec = path::widenPath(Program, ProgramUtf16)) { SetLastError(ec.value()); MakeErrMsg(ErrMsg, std::string("Unable to convert application name to UTF-16")); @@ -422,20 +460,64 @@ ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, return WaitResult; } - std::error_code sys::ChangeStdinToBinary(){ - int result = _setmode( _fileno(stdin), _O_BINARY ); +std::error_code sys::ChangeStdinToBinary() { + int result = _setmode(_fileno(stdin), _O_BINARY); if (result == -1) return std::error_code(errno, std::generic_category()); return std::error_code(); } - std::error_code sys::ChangeStdoutToBinary(){ - int result = _setmode( _fileno(stdout), _O_BINARY ); +std::error_code sys::ChangeStdoutToBinary() { + int result = _setmode(_fileno(stdout), _O_BINARY); if (result == -1) return std::error_code(errno, std::generic_category()); return std::error_code(); } +std::error_code +llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents, + WindowsEncodingMethod Encoding) { + std::error_code EC; + llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text); + if (EC) + return EC; + + if (Encoding == WEM_UTF8) { + OS << Contents; + } else if (Encoding == WEM_CurrentCodePage) { + SmallVector<wchar_t, 1> ArgsUTF16; + SmallVector<char, 1> ArgsCurCP; + + if ((EC = windows::UTF8ToUTF16(Contents, ArgsUTF16))) + return EC; + + if ((EC = windows::UTF16ToCurCP( + ArgsUTF16.data(), ArgsUTF16.size(), ArgsCurCP))) + return EC; + + OS.write(ArgsCurCP.data(), ArgsCurCP.size()); + } else if (Encoding == WEM_UTF16) { + SmallVector<wchar_t, 1> ArgsUTF16; + + if ((EC = windows::UTF8ToUTF16(Contents, ArgsUTF16))) + return EC; + + // Endianness guessing + char BOM[2]; + uint16_t src = UNI_UTF16_BYTE_ORDER_MARK_NATIVE; + memcpy(BOM, &src, 2); + OS.write(BOM, 2); + OS.write((char *)ArgsUTF16.data(), ArgsUTF16.size() << 1); + } else { + llvm_unreachable("Unknown encoding"); + } + + if (OS.has_error()) + return std::make_error_code(std::errc::io_error); + + return EC; +} + bool llvm::sys::argumentsFitWithinSystemLimits(ArrayRef<const char*> Args) { // The documented max length of the command line passed to CreateProcess. static const size_t MaxCommandStringLength = 32768; diff --git a/contrib/llvm/lib/Support/Windows/RWMutex.inc b/contrib/llvm/lib/Support/Windows/RWMutex.inc index 00d0e93..2d1d25f 100644 --- a/contrib/llvm/lib/Support/Windows/RWMutex.inc +++ b/contrib/llvm/lib/Support/Windows/RWMutex.inc @@ -84,12 +84,10 @@ RWMutexImpl::RWMutexImpl() { } RWMutexImpl::~RWMutexImpl() { - if (sHasSRW) { - // Nothing to do in the case of slim reader/writers - } else { + if (!sHasSRW) DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); - free(data_); - } + // Nothing to do in the case of slim reader/writers except free the memory. + free(data_); } bool RWMutexImpl::reader_acquire() { diff --git a/contrib/llvm/lib/Support/Windows/ThreadLocal.inc b/contrib/llvm/lib/Support/Windows/ThreadLocal.inc index 14ce619..b9cb8ff 100644 --- a/contrib/llvm/lib/Support/Windows/ThreadLocal.inc +++ b/contrib/llvm/lib/Support/Windows/ThreadLocal.inc @@ -34,7 +34,7 @@ ThreadLocalImpl::~ThreadLocalImpl() { TlsFree(*tls); } -const void* ThreadLocalImpl::getInstance() { +void *ThreadLocalImpl::getInstance() { DWORD* tls = reinterpret_cast<DWORD*>(&data); return TlsGetValue(*tls); } diff --git a/contrib/llvm/lib/Support/Windows/WindowsSupport.h b/contrib/llvm/lib/Support/Windows/WindowsSupport.h index f68835b..1d1cedc 100644 --- a/contrib/llvm/lib/Support/Windows/WindowsSupport.h +++ b/contrib/llvm/lib/Support/Windows/WindowsSupport.h @@ -30,6 +30,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" #include "llvm/Config/config.h" // Get build system configuration settings #include "llvm/Support/Compiler.h" #include <system_error> @@ -162,10 +163,18 @@ c_str(SmallVectorImpl<T> &str) { } namespace sys { +namespace path { +std::error_code widenPath(const Twine &Path8, + SmallVectorImpl<wchar_t> &Path16); +} // end namespace path + namespace windows { std::error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl<wchar_t> &utf16); std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, SmallVectorImpl<char> &utf8); +/// Convert from UTF16 to the current code page used in the system +std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len, + SmallVectorImpl<char> &utf8); } // end namespace windows } // end namespace sys } // end namespace llvm. diff --git a/contrib/llvm/lib/Support/Windows/explicit_symbols.inc b/contrib/llvm/lib/Support/Windows/explicit_symbols.inc index 379645d..cd56b13 100644 --- a/contrib/llvm/lib/Support/Windows/explicit_symbols.inc +++ b/contrib/llvm/lib/Support/Windows/explicit_symbols.inc @@ -63,4 +63,34 @@ /* msvcrt */ #if defined(_MSC_VER) EXPLICIT_SYMBOL2(alloca, _alloca_probe) + +#ifdef _M_IX86 +#define INLINE_DEF_FLOAT_SYMBOL(SYM, ARGC) INLINE_DEF_SYMBOL##ARGC(float, SYM) + INLINE_DEF_FLOAT_SYMBOL(acosf, 1) + INLINE_DEF_FLOAT_SYMBOL(asinf, 1) + INLINE_DEF_FLOAT_SYMBOL(atanf, 1) + INLINE_DEF_FLOAT_SYMBOL(atan2f, 2) + INLINE_DEF_FLOAT_SYMBOL(ceilf, 1) + INLINE_DEF_FLOAT_SYMBOL(cosf, 1) + INLINE_DEF_FLOAT_SYMBOL(coshf, 1) + INLINE_DEF_FLOAT_SYMBOL(expf, 1) + INLINE_DEF_FLOAT_SYMBOL(floorf, 1) + INLINE_DEF_FLOAT_SYMBOL(fmodf, 2) + INLINE_DEF_FLOAT_SYMBOL(logf, 1) + INLINE_DEF_FLOAT_SYMBOL(powf, 2) + INLINE_DEF_FLOAT_SYMBOL(sinf, 1) + INLINE_DEF_FLOAT_SYMBOL(sinhf, 1) + INLINE_DEF_FLOAT_SYMBOL(sqrtf, 1) + INLINE_DEF_FLOAT_SYMBOL(tanf, 1) + INLINE_DEF_FLOAT_SYMBOL(tanhf, 1) + + // These were added in VS 2013. +#if (1800 <= _MSC_VER && _MSC_VER < 1900) + INLINE_DEF_FLOAT_SYMBOL(copysignf, 2) + INLINE_DEF_FLOAT_SYMBOL(fminf, 2) + INLINE_DEF_FLOAT_SYMBOL(fmaxf, 2) +#endif +#undef INLINE_DEF_FLOAT_SYMBOL +#endif + #endif diff --git a/contrib/llvm/lib/Support/YAMLParser.cpp b/contrib/llvm/lib/Support/YAMLParser.cpp index 3be02ee..4688ff1 100644 --- a/contrib/llvm/lib/Support/YAMLParser.cpp +++ b/contrib/llvm/lib/Support/YAMLParser.cpp @@ -259,8 +259,8 @@ namespace yaml { /// @brief Scans YAML tokens from a MemoryBuffer. class Scanner { public: - Scanner(const StringRef Input, SourceMgr &SM); - Scanner(MemoryBuffer *Buffer, SourceMgr &SM_); + Scanner(StringRef Input, SourceMgr &SM); + Scanner(MemoryBufferRef Buffer, SourceMgr &SM_); /// @brief Parse the next token and return it without popping it. Token &peekNext(); @@ -294,6 +294,8 @@ public: } private: + void init(MemoryBufferRef Buffer); + StringRef currentInput() { return StringRef(Current, End - Current); } @@ -469,7 +471,7 @@ private: SourceMgr &SM; /// @brief The original input. - MemoryBuffer *InputBuffer; + MemoryBufferRef InputBuffer; /// @brief The current position of the scanner. StringRef::iterator Current; @@ -699,34 +701,28 @@ std::string yaml::escape(StringRef Input) { return EscapedInput; } -Scanner::Scanner(StringRef Input, SourceMgr &sm) - : SM(sm) - , Indent(-1) - , Column(0) - , Line(0) - , FlowLevel(0) - , IsStartOfStream(true) - , IsSimpleKeyAllowed(true) - , Failed(false) { - InputBuffer = MemoryBuffer::getMemBuffer(Input, "YAML"); - SM.AddNewSourceBuffer(InputBuffer, SMLoc()); - Current = InputBuffer->getBufferStart(); - End = InputBuffer->getBufferEnd(); -} - -Scanner::Scanner(MemoryBuffer *Buffer, SourceMgr &SM_) - : SM(SM_) - , InputBuffer(Buffer) - , Current(InputBuffer->getBufferStart()) - , End(InputBuffer->getBufferEnd()) - , Indent(-1) - , Column(0) - , Line(0) - , FlowLevel(0) - , IsStartOfStream(true) - , IsSimpleKeyAllowed(true) - , Failed(false) { - SM.AddNewSourceBuffer(InputBuffer, SMLoc()); +Scanner::Scanner(StringRef Input, SourceMgr &sm) : SM(sm) { + init(MemoryBufferRef(Input, "YAML")); +} + +Scanner::Scanner(MemoryBufferRef Buffer, SourceMgr &SM_) : SM(SM_) { + init(Buffer); +} + +void Scanner::init(MemoryBufferRef Buffer) { + InputBuffer = Buffer; + Current = InputBuffer.getBufferStart(); + End = InputBuffer.getBufferEnd(); + Indent = -1; + Column = 0; + Line = 0; + FlowLevel = 0; + IsStartOfStream = true; + IsSimpleKeyAllowed = true; + Failed = false; + std::unique_ptr<MemoryBuffer> InputBufferOwner = + MemoryBuffer::getMemBuffer(Buffer); + SM.AddNewSourceBuffer(std::move(InputBufferOwner), SMLoc()); } Token &Scanner::peekNext() { @@ -1524,7 +1520,7 @@ bool Scanner::fetchMoreTokens() { Stream::Stream(StringRef Input, SourceMgr &SM) : scanner(new Scanner(Input, SM)), CurrentDoc() {} -Stream::Stream(MemoryBuffer *InputBuffer, SourceMgr &SM) +Stream::Stream(MemoryBufferRef InputBuffer, SourceMgr &SM) : scanner(new Scanner(InputBuffer, SM)), CurrentDoc() {} Stream::~Stream() {} diff --git a/contrib/llvm/lib/Support/YAMLTraits.cpp b/contrib/llvm/lib/Support/YAMLTraits.cpp index 5212624..c87790e 100644 --- a/contrib/llvm/lib/Support/YAMLTraits.cpp +++ b/contrib/llvm/lib/Support/YAMLTraits.cpp @@ -8,12 +8,12 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Errc.h" -#include "llvm/Support/YAMLTraits.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/YAMLParser.h" +#include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" #include <cctype> #include <cstring> @@ -63,6 +63,8 @@ std::error_code Input::error() { return EC; } void Input::HNode::anchor() {} void Input::EmptyHNode::anchor() {} void Input::ScalarHNode::anchor() {} +void Input::MapHNode::anchor() {} +void Input::SequenceHNode::anchor() {} bool Input::outputting() { return false; @@ -82,7 +84,7 @@ bool Input::setCurrentDocument() { ++DocIterator; return setCurrentDocument(); } - TopNode.reset(this->createHNodes(N)); + TopNode = this->createHNodes(N); CurrentNode = TopNode.get(); return true; } @@ -133,7 +135,7 @@ bool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault, return false; } MN->ValidKeys.push_back(Key); - HNode *Value = MN->Mapping[Key]; + HNode *Value = MN->Mapping[Key].get(); if (!Value) { if (Required) setError(CurrentNode, Twine("missing required key '") + Key + "'"); @@ -159,7 +161,7 @@ void Input::endMapping() { return; for (const auto &NN : MN->Mapping) { if (!MN->isValidKey(NN.first())) { - setError(NN.second, Twine("unknown key '") + NN.first() + "'"); + setError(NN.second.get(), Twine("unknown key '") + NN.first() + "'"); break; } } @@ -180,7 +182,7 @@ bool Input::preflightElement(unsigned Index, void *&SaveInfo) { return false; if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { SaveInfo = CurrentNode; - CurrentNode = SQ->Entries[Index]; + CurrentNode = SQ->Entries[Index].get(); return true; } return false; @@ -202,7 +204,7 @@ bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) { return false; if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { SaveInfo = CurrentNode; - CurrentNode = SQ->Entries[index]; + CurrentNode = SQ->Entries[index].get(); return true; } return false; @@ -253,8 +255,8 @@ bool Input::bitSetMatch(const char *Str, bool) { return false; if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) { unsigned Index = 0; - for (HNode *N : SQ->Entries) { - if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N)) { + for (auto &N : SQ->Entries) { + if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N.get())) { if (SN->value().equals(Str)) { BitValuesUsed[Index] = true; return true; @@ -277,7 +279,7 @@ void Input::endBitSetScalar() { assert(BitValuesUsed.size() == SQ->Entries.size()); for (unsigned i = 0; i < SQ->Entries.size(); ++i) { if (!BitValuesUsed[i]) { - setError(SQ->Entries[i], "unknown bit value"); + setError(SQ->Entries[i].get(), "unknown bit value"); return; } } @@ -302,7 +304,7 @@ void Input::setError(Node *node, const Twine &message) { EC = make_error_code(errc::invalid_argument); } -Input::HNode *Input::createHNodes(Node *N) { +std::unique_ptr<Input::HNode> Input::createHNodes(Node *N) { SmallString<128> StringStorage; if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) { StringRef KeyStr = SN->getValue(StringStorage); @@ -313,20 +315,25 @@ Input::HNode *Input::createHNodes(Node *N) { memcpy(Buf, &StringStorage[0], Len); KeyStr = StringRef(Buf, Len); } - return new ScalarHNode(N, KeyStr); + return llvm::make_unique<ScalarHNode>(N, KeyStr); } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) { - SequenceHNode *SQHNode = new SequenceHNode(N); + auto SQHNode = llvm::make_unique<SequenceHNode>(N); for (Node &SN : *SQ) { - HNode *Entry = this->createHNodes(&SN); + auto Entry = this->createHNodes(&SN); if (EC) break; - SQHNode->Entries.push_back(Entry); + SQHNode->Entries.push_back(std::move(Entry)); } - return SQHNode; + return std::move(SQHNode); } else if (MappingNode *Map = dyn_cast<MappingNode>(N)) { - MapHNode *mapHNode = new MapHNode(N); + auto mapHNode = llvm::make_unique<MapHNode>(N); for (KeyValueNode &KVN : *Map) { - ScalarNode *KeyScalar = dyn_cast<ScalarNode>(KVN.getKey()); + Node *KeyNode = KVN.getKey(); + ScalarNode *KeyScalar = dyn_cast<ScalarNode>(KeyNode); + if (!KeyScalar) { + setError(KeyNode, "Map key must be a scalar"); + break; + } StringStorage.clear(); StringRef KeyStr = KeyScalar->getValue(StringStorage); if (!StringStorage.empty()) { @@ -336,14 +343,14 @@ Input::HNode *Input::createHNodes(Node *N) { memcpy(Buf, &StringStorage[0], Len); KeyStr = StringRef(Buf, Len); } - HNode *ValueHNode = this->createHNodes(KVN.getValue()); + auto ValueHNode = this->createHNodes(KVN.getValue()); if (EC) break; - mapHNode->Mapping[KeyStr] = ValueHNode; + mapHNode->Mapping[KeyStr] = std::move(ValueHNode); } - return mapHNode; + return std::move(mapHNode); } else if (isa<NullNode>(N)) { - return new EmptyHNode(N); + return llvm::make_unique<EmptyHNode>(N); } else { setError(N, "unknown node kind"); return nullptr; @@ -366,18 +373,6 @@ bool Input::canElideEmptySequence() { return false; } -Input::MapHNode::~MapHNode() { - for (auto &N : Mapping) - delete N.second; -} - -Input::SequenceHNode::~SequenceHNode() { - for (HNode *N : Entries) - delete N; -} - - - //===----------------------------------------------------------------------===// // Output //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/Support/raw_ostream.cpp b/contrib/llvm/lib/Support/raw_ostream.cpp index 0790be5..1bcc31b 100644 --- a/contrib/llvm/lib/Support/raw_ostream.cpp +++ b/contrib/llvm/lib/Support/raw_ostream.cpp @@ -20,6 +20,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" #include <cctype> @@ -311,6 +312,7 @@ raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) { // than the buffer. Directly write the chunk that is a multiple of the // preferred buffer size and put the remainder in the buffer. if (LLVM_UNLIKELY(OutBufCur == OutBufStart)) { + assert(NumBytes != 0 && "undefined behavior"); size_t BytesToWrite = Size - (Size % NumBytes); write_impl(Ptr, BytesToWrite); size_t BytesRemaining = Size - BytesToWrite; @@ -394,6 +396,62 @@ raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) { } } +raw_ostream &raw_ostream::operator<<(const FormattedString &FS) { + unsigned Len = FS.Str.size(); + int PadAmount = FS.Width - Len; + if (FS.RightJustify && (PadAmount > 0)) + this->indent(PadAmount); + this->operator<<(FS.Str); + if (!FS.RightJustify && (PadAmount > 0)) + this->indent(PadAmount); + return *this; +} + +raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) { + if (FN.Hex) { + unsigned Nibbles = (64 - countLeadingZeros(FN.HexValue)+3)/4; + unsigned Width = (FN.Width > Nibbles+2) ? FN.Width : Nibbles+2; + + char NumberBuffer[20] = "0x0000000000000000"; + char *EndPtr = NumberBuffer+Width; + char *CurPtr = EndPtr; + const char A = FN.Upper ? 'A' : 'a'; + unsigned long long N = FN.HexValue; + while (N) { + uintptr_t x = N % 16; + *--CurPtr = (x < 10 ? '0' + x : A + x - 10); + N /= 16; + } + + return write(NumberBuffer, Width); + } else { + // Zero is a special case. + if (FN.DecValue == 0) { + this->indent(FN.Width-1); + return *this << '0'; + } + char NumberBuffer[32]; + char *EndPtr = NumberBuffer+sizeof(NumberBuffer); + char *CurPtr = EndPtr; + bool Neg = (FN.DecValue < 0); + uint64_t N = Neg ? -static_cast<uint64_t>(FN.DecValue) : FN.DecValue; + while (N) { + *--CurPtr = '0' + char(N % 10); + N /= 10; + } + int Len = EndPtr - CurPtr; + int Pad = FN.Width - Len; + if (Neg) + --Pad; + if (Pad > 0) + this->indent(Pad); + if (Neg) + *this << '-'; + return write(CurPtr, Len); + } +} + + /// indent - Insert 'NumSpaces' spaces. raw_ostream &raw_ostream::indent(unsigned NumSpaces) { static const char Spaces[] = " " @@ -426,20 +484,14 @@ void format_object_base::home() { // raw_fd_ostream //===----------------------------------------------------------------------===// -/// raw_fd_ostream - Open the specified file for writing. If an error -/// occurs, information about the error is put into ErrorInfo, and the -/// stream should be immediately destroyed; the string will be empty -/// if no error occurred. -raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo, +raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC, sys::fs::OpenFlags Flags) : Error(false), UseAtomicWrites(false), pos(0) { - assert(Filename && "Filename is null"); - ErrorInfo.clear(); - + EC = std::error_code(); // Handle "-" as stdout. Note that when we do this, we consider ourself // the owner of stdout. This means that we can do things like close the // file descriptor when we're done and set the "binary" flag globally. - if (Filename[0] == '-' && Filename[1] == 0) { + if (Filename == "-") { FD = STDOUT_FILENO; // If user requested binary then put stdout into binary mode if // possible. @@ -450,11 +502,9 @@ raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo, return; } - std::error_code EC = sys::fs::openFileForWrite(Filename, FD, Flags); + EC = sys::fs::openFileForWrite(Filename, FD, Flags); if (EC) { - ErrorInfo = "Error opening output file '" + std::string(Filename) + "': " + - EC.message(); ShouldClose = false; return; } @@ -487,12 +537,8 @@ raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered) raw_fd_ostream::~raw_fd_ostream() { if (FD >= 0) { flush(); - if (ShouldClose) - while (::close(FD) != 0) - if (errno != EINTR) { - error_detected(); - break; - } + if (ShouldClose && sys::Process::SafelyCloseFileDescriptor(FD)) + error_detected(); } #ifdef __MINGW32__ @@ -566,11 +612,8 @@ void raw_fd_ostream::close() { assert(ShouldClose); ShouldClose = false; flush(); - while (::close(FD) != 0) - if (errno != EINTR) { - error_detected(); - break; - } + if (sys::Process::SafelyCloseFileDescriptor(FD)) + error_detected(); FD = -1; } |