diff options
Diffstat (limited to 'lib/Support')
44 files changed, 1103 insertions, 1430 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 295b16c..393ecf4 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -1823,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); diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index c20eeb2..50a639c 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -713,7 +713,7 @@ unsigned APInt::countLeadingZerosSlowCase() const { unsigned APInt::countLeadingOnes() const { if (isSingleWord()) - return CountLeadingOnes_64(VAL << (APINT_BITS_PER_WORD - BitWidth)); + return llvm::countLeadingOnes(VAL << (APINT_BITS_PER_WORD - BitWidth)); unsigned highWordBits = BitWidth % APINT_BITS_PER_WORD; unsigned shift; @@ -724,13 +724,13 @@ unsigned APInt::countLeadingOnes() const { shift = APINT_BITS_PER_WORD - highWordBits; } int i = getNumWords() - 1; - unsigned Count = CountLeadingOnes_64(pVal[i] << shift); + unsigned Count = llvm::countLeadingOnes(pVal[i] << shift); if (Count == highWordBits) { for (i--; i >= 0; --i) { if (pVal[i] == -1ULL) Count += APINT_BITS_PER_WORD; else { - Count += CountLeadingOnes_64(pVal[i]); + Count += llvm::countLeadingOnes(pVal[i]); break; } } @@ -756,14 +756,14 @@ unsigned APInt::countTrailingOnesSlowCase() const { for (; i < getNumWords() && pVal[i] == -1ULL; ++i) Count += APINT_BITS_PER_WORD; if (i < getNumWords()) - Count += CountTrailingOnes_64(pVal[i]); + Count += llvm::countTrailingOnes(pVal[i]); return std::min(Count, BitWidth); } unsigned APInt::countPopulationSlowCase() const { unsigned Count = 0; for (unsigned i = 0; i < getNumWords(); ++i) - Count += CountPopulation_64(pVal[i]); + Count += llvm::countPopulation(pVal[i]); return Count; } @@ -1956,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); diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt index fa62591..a44c1a3 100644 --- a/lib/Support/CMakeLists.txt +++ b/lib/Support/CMakeLists.txt @@ -121,30 +121,10 @@ add_llvm_library(LLVMSupport Valgrind.cpp Watchdog.cpp - ADDITIONAL_HEADERS - Unix/Host.inc - Unix/Memory.inc - Unix/Mutex.inc - Unix/Path.inc - Unix/Process.inc - Unix/Program.inc - Unix/RWMutex.inc - Unix/Signals.inc - Unix/ThreadLocal.inc - Unix/TimeValue.inc - Unix/Watchdog.inc - Windows/DynamicLibrary.inc - Windows/Host.inc - Windows/Memory.inc - Windows/Mutex.inc - Windows/Path.inc - Windows/Process.inc - Windows/Program.inc - Windows/RWMutex.inc - Windows/Signals.inc - Windows/ThreadLocal.inc - Windows/TimeValue.inc - Windows/Watchdog.inc + ADDITIONAL_HEADER_DIRS + Unix + Windows + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Support LINK_LIBS ${system_libs} ) diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index 985c877..b49ec36 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -44,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>); @@ -60,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() {} @@ -81,151 +83,193 @@ void StringSaver::anchor() {} //===----------------------------------------------------------------------===// -// Globals for name and overview of program. Program name is not a string to -// avoid static ctor/dtor issues. -static char ProgramName[80] = "<premain>"; -static const char *ProgramOverview = nullptr; +namespace { -// This collects additional help to be printed. -static ManagedStatic<std::vector<const char*> > MoreHelp; +class CommandLineParser { +public: + // Globals for name and overview of program. Program name is not a string to + // avoid static ctor/dtor issues. + std::string ProgramName; + const char *ProgramOverview; -extrahelp::extrahelp(const char *Help) - : morehelp(Help) { - MoreHelp->push_back(Help); -} + // This collects additional help to be printed. + std::vector<const char *> MoreHelp; -static bool OptionListChanged = false; + SmallVector<Option *, 4> PositionalOpts; + SmallVector<Option *, 4> SinkOpts; + StringMap<Option *> OptionsMap; -// MarkOptionsChanged - Internal helper function. -void cl::MarkOptionsChanged() { - OptionListChanged = true; -} + Option *ConsumeAfterOpt; // The ConsumeAfter option if it exists. -/// RegisteredOptionList - This is the list of the command line options that -/// have statically constructed themselves. -static Option *RegisteredOptionList = nullptr; + // This collects the different option categories that have been registered. + SmallPtrSet<OptionCategory *, 16> RegisteredOptionCategories; -void Option::addArgument() { - assert(!NextRegistered && "argument multiply registered!"); + CommandLineParser() : ProgramOverview(nullptr), ConsumeAfterOpt(nullptr) {} - NextRegistered = RegisteredOptionList; - RegisteredOptionList = this; - MarkOptionsChanged(); -} + void ParseCommandLineOptions(int argc, const char *const *argv, + const char *Overview); -void Option::removeArgument() { - if (RegisteredOptionList == this) { - RegisteredOptionList = NextRegistered; - MarkOptionsChanged(); - return; + void addLiteralOption(Option &Opt, const char *Name) { + if (!Opt.hasArgStr()) { + if (!OptionsMap.insert(std::make_pair(Name, &Opt)).second) { + errs() << ProgramName << ": CommandLine Error: Option '" << Name + << "' registered more than once!\n"; + report_fatal_error("inconsistency in registered CommandLine options"); + } + } } - Option *O = RegisteredOptionList; - for (; O->NextRegistered != this; O = O->NextRegistered) - ; - O->NextRegistered = NextRegistered; - MarkOptionsChanged(); -} - -// This collects the different option categories that have been registered. -typedef SmallPtrSet<OptionCategory*,16> OptionCatSet; -static ManagedStatic<OptionCatSet> RegisteredOptionCategories; - -// Initialise the general option category. -OptionCategory llvm::cl::GeneralCategory("General options"); - -void OptionCategory::registerCategory() { - assert(std::count_if(RegisteredOptionCategories->begin(), - RegisteredOptionCategories->end(), - [this](const OptionCategory *Category) { - return getName() == Category->getName(); - }) == 0 && "Duplicate option categories"); - RegisteredOptionCategories->insert(this); -} - -//===----------------------------------------------------------------------===// -// Basic, shared command line option processing machinery. -// - -/// GetOptionInfo - Scan the list of registered options, turning them into data -/// structures that are easier to handle. -static void GetOptionInfo(SmallVectorImpl<Option*> &PositionalOpts, - SmallVectorImpl<Option*> &SinkOpts, - StringMap<Option*> &OptionsMap) { - bool HadErrors = false; - SmallVector<const char*, 16> OptionNames; - Option *CAOpt = nullptr; // The ConsumeAfter option if it exists. - for (Option *O = RegisteredOptionList; O; O = O->getNextRegisteredOption()) { - // If this option wants to handle multiple option names, get the full set. - // This handles enum options like "-O1 -O2" etc. - O->getExtraOptionNames(OptionNames); - if (O->ArgStr[0]) - OptionNames.push_back(O->ArgStr); - - // Handle named options. - for (size_t i = 0, e = OptionNames.size(); i != e; ++i) { + void addOption(Option *O) { + bool HadErrors = false; + if (O->ArgStr[0]) { // Add argument to the argument map! - if (!OptionsMap.insert(std::make_pair(OptionNames[i], O)).second) { - errs() << ProgramName << ": CommandLine Error: Option '" - << OptionNames[i] << "' registered more than once!\n"; + if (!OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) { + errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr + << "' registered more than once!\n"; HadErrors = true; } } - OptionNames.clear(); - // Remember information about positional options. if (O->getFormattingFlag() == cl::Positional) PositionalOpts.push_back(O); else if (O->getMiscFlags() & cl::Sink) // Remember sink options SinkOpts.push_back(O); else if (O->getNumOccurrencesFlag() == cl::ConsumeAfter) { - if (CAOpt) { + if (ConsumeAfterOpt) { O->error("Cannot specify more than one option with cl::ConsumeAfter!"); HadErrors = true; } - CAOpt = O; + ConsumeAfterOpt = O; + } + + // Fail hard if there were errors. These are strictly unrecoverable and + // indicate serious issues such as conflicting option names or an + // incorrectly + // linked LLVM distribution. + if (HadErrors) + report_fatal_error("inconsistency in registered CommandLine options"); + } + + void removeOption(Option *O) { + SmallVector<const char *, 16> OptionNames; + O->getExtraOptionNames(OptionNames); + if (O->ArgStr[0]) + OptionNames.push_back(O->ArgStr); + for (auto Name : OptionNames) + OptionsMap.erase(StringRef(Name)); + + if (O->getFormattingFlag() == cl::Positional) + for (auto Opt = PositionalOpts.begin(); Opt != PositionalOpts.end(); + ++Opt) { + if (*Opt == O) { + PositionalOpts.erase(Opt); + break; + } + } + else if (O->getMiscFlags() & cl::Sink) + for (auto Opt = SinkOpts.begin(); Opt != SinkOpts.end(); ++Opt) { + if (*Opt == O) { + SinkOpts.erase(Opt); + break; + } + } + else if (O == ConsumeAfterOpt) + ConsumeAfterOpt = nullptr; + } + + bool hasOptions() { + return (!OptionsMap.empty() || !PositionalOpts.empty() || + nullptr != ConsumeAfterOpt); + } + + void updateArgStr(Option *O, const char *NewName) { + if (!OptionsMap.insert(std::make_pair(NewName, O)).second) { + errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr + << "' registered more than once!\n"; + report_fatal_error("inconsistency in registered CommandLine options"); } + OptionsMap.erase(StringRef(O->ArgStr)); } - if (CAOpt) - PositionalOpts.push_back(CAOpt); + void printOptionValues(); - // Make sure that they are in order of registration not backwards. - std::reverse(PositionalOpts.begin(), PositionalOpts.end()); + void registerCategory(OptionCategory *cat) { + assert(std::count_if(RegisteredOptionCategories.begin(), + RegisteredOptionCategories.end(), + [cat](const OptionCategory *Category) { + return cat->getName() == Category->getName(); + }) == 0 && + "Duplicate option categories"); + + RegisteredOptionCategories.insert(cat); + } - // Fail hard if there were errors. These are strictly unrecoverable and - // indicate serious issues such as conflicting option names or an incorrectly - // linked LLVM distribution. - if (HadErrors) - report_fatal_error("inconsistency in registered CommandLine options"); +private: + Option *LookupOption(StringRef &Arg, StringRef &Value); +}; + +} // namespace + +static ManagedStatic<CommandLineParser> GlobalParser; + +void cl::AddLiteralOption(Option &O, const char *Name) { + GlobalParser->addLiteralOption(O, Name); +} + +extrahelp::extrahelp(const char *Help) : morehelp(Help) { + GlobalParser->MoreHelp.push_back(Help); +} + +void Option::addArgument() { + GlobalParser->addOption(this); + FullyInitialized = true; +} + +void Option::removeArgument() { GlobalParser->removeOption(this); } + +void Option::setArgStr(const char *S) { + if (FullyInitialized) + GlobalParser->updateArgStr(this, S); + ArgStr = S; } +// Initialise the general option category. +OptionCategory llvm::cl::GeneralCategory("General options"); + +void OptionCategory::registerCategory() { + GlobalParser->registerCategory(this); +} + +//===----------------------------------------------------------------------===// +// Basic, shared command line option processing machinery. +// /// LookupOption - Lookup the option specified by the specified option on the /// command line. If there is a value specified (after an equal sign) return /// that as well. This assumes that leading dashes have already been stripped. -static Option *LookupOption(StringRef &Arg, StringRef &Value, - const StringMap<Option*> &OptionsMap) { +Option *CommandLineParser::LookupOption(StringRef &Arg, StringRef &Value) { // Reject all dashes. - if (Arg.empty()) return nullptr; + 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; } @@ -235,23 +279,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); @@ -261,7 +307,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; @@ -292,8 +338,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(','); } @@ -320,9 +366,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; @@ -332,8 +379,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; @@ -354,8 +401,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)) @@ -371,7 +419,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; @@ -387,39 +434,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 @@ -445,8 +495,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); @@ -456,8 +506,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; @@ -468,17 +516,11 @@ 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, @@ -493,13 +535,14 @@ void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, 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; } @@ -514,7 +557,8 @@ void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, Token.push_back(Src[I]); ++I; } - if (I == E) break; + if (I == E) + break; continue; } @@ -654,6 +698,12 @@ void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver, NewArgv.push_back(nullptr); } +// It is called byte order marker but the UTF-8 BOM is actually not affected +// by the host system's endianness. +static bool hasUTF8ByteOrderMark(ArrayRef<char> S) { + return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf'); +} + static bool ExpandResponseFile(const char *FName, StringSaver &Saver, TokenizerCallback Tokenizer, SmallVectorImpl<const char *> &NewArgv, @@ -673,6 +723,11 @@ static bool ExpandResponseFile(const char *FName, StringSaver &Saver, return false; Str = StringRef(UTF8Buf); } + // If we see UTF-8 BOM sequence at the beginning of a file, we shall remove + // these bytes before parsing. + // Reference: http://en.wikipedia.org/wiki/UTF-8#Byte_order_mark + else if (hasUTF8ByteOrderMark(BufRef)) + Str = StringRef(BufRef.data() + 3, BufRef.size() - 3); // Tokenize the contents into NewArgv. Tokenizer(Str, Saver, NewArgv, MarkEOLs); @@ -689,7 +744,7 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, 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) { @@ -726,22 +781,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 @@ -773,31 +829,25 @@ 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; - GetOptionInfo(PositionalOpts, SinkOpts, Opts); + GlobalParser->ParseCommandLineOptions(argc, argv, Overview); +} - assert((!Opts.empty() || !PositionalOpts.empty()) && - "No options specified!"); +void CommandLineParser::ParseCommandLineOptions(int argc, + const char *const *argv, + const char *Overview) { + assert(hasOptions() && "No options specified!"); // Expand response files. - SmallVector<const char *, 20> newArgv; - for (int i = 0; i != argc; ++i) - newArgv.push_back(argv[i]); + SmallVector<const char *, 20> newArgv(argv, argv + argc); StrDupSaver Saver; ExpandResponseFiles(Saver, TokenizeGNUCommandLine, newArgv); argv = &newArgv[0]; argc = static_cast<int>(newArgv.size()); // Copy the program name into ProgName, making sure not to overflow it. - StringRef ProgName = sys::path::filename(argv[0]); - size_t Len = std::min(ProgName.size(), size_t(79)); - memcpy(ProgramName, ProgName.data(), Len); - ProgramName[Len] = '\0'; + ProgramName = sys::path::filename(argv[0]); ProgramOverview = Overview; bool ErrorParsing = false; @@ -808,29 +858,26 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, // Determine whether or not there are an unlimited number of positionals bool HasUnlimitedPositionals = false; - Option *ConsumeAfterOpt = nullptr; + if (ConsumeAfterOpt) { + assert(PositionalOpts.size() > 0 && + "Cannot specify cl::ConsumeAfter without a positional argument!"); + } if (!PositionalOpts.empty()) { - if (PositionalOpts[0]->getNumOccurrencesFlag() == cl::ConsumeAfter) { - assert(PositionalOpts.size() > 1 && - "Cannot specify cl::ConsumeAfter without a positional argument!"); - ConsumeAfterOpt = PositionalOpts[0]; - } // Calculate how many positional values are _required_. bool UnboundedFound = false; - for (size_t i = ConsumeAfterOpt ? 1 : 0, e = PositionalOpts.size(); - i != e; ++i) { + for (size_t i = 0, e = PositionalOpts.size(); i != e; ++i) { Option *Opt = PositionalOpts[i]; if (RequiresValue(Opt)) ++NumPositionalRequired; else if (ConsumeAfterOpt) { // ConsumeAfter cannot be combined with "optional" positional options // unless there is only one positional argument... - if (PositionalOpts.size() > 2) - 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!"); + if (PositionalOpts.size() > 1) + 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 @@ -840,6 +887,9 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, "another positional argument will match an " "unbounded number of values, and this option" " does not require a value!"); + errs() << ProgramName << ": CommandLine Error: Option '" << Opt->ArgStr + << "' is all messed up!\n"; + errs() << PositionalOpts.size(); } UnboundedFound |= EatsUnboundedNumberOfValues(Opt); } @@ -849,7 +899,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 @@ -857,7 +907,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; @@ -865,17 +915,6 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, StringRef Value; StringRef ArgName = ""; - // If the option list changed, this means that some command line - // option has just been registered or deregistered. This can occur in - // response to things like -load, etc. If this happens, rescan the options. - if (OptionListChanged) { - PositionalOpts.clear(); - SinkOpts.clear(); - Opts.clear(); - GetOptionInfo(PositionalOpts, SinkOpts, Opts); - OptionListChanged = false; - } - // Check to see if this is a positional argument. This argument is // considered to be positional if it doesn't start with '-', if it is "-" // itself, or if we have seen "--" already. @@ -884,19 +923,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... @@ -904,59 +943,60 @@ 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); - Handler = LookupOption(ArgName, Value, Opts); + Handler = LookupOption(ArgName, Value); 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); - Handler = LookupOption(ArgName, Value, Opts); + Handler = LookupOption(ArgName, Value); // Check to see if this "option" is really a prefixed or grouped argument. if (!Handler) - Handler = HandlePrefixedOrGroupedOption(ArgName, Value, - ErrorParsing, Opts); + Handler = HandlePrefixedOrGroupedOption(ArgName, Value, ErrorParsing, + OptionsMap); // Otherwise, look for the closest available option to report to the user // in the upcoming error. if (!Handler && SinkOpts.empty()) - NearestHandler = LookupNearestOption(ArgName, Opts, - NearestHandlerString); + NearestHandler = + LookupNearestOption(ArgName, OptionsMap, 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; @@ -973,17 +1013,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) { @@ -994,7 +1033,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 @@ -1002,13 +1041,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); @@ -1016,7 +1055,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!"); } } } @@ -1036,8 +1075,8 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv, // positional option and keep the rest for the consume after. The above // loop would have assigned no values to positional options in this case. // - if (PositionalOpts.size() == 2 && ValNo == 0 && !PositionalVals.empty()) { - ErrorParsing |= ProvidePositionalOption(PositionalOpts[1], + if (PositionalOpts.size() == 1 && ValNo == 0 && !PositionalVals.empty()) { + ErrorParsing |= ProvidePositionalOption(PositionalOpts[0], PositionalVals[ValNo].first, PositionalVals[ValNo].second); ValNo++; @@ -1046,13 +1085,13 @@ 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! - for (const auto &Opt : Opts) { + for (const auto &Opt : OptionsMap) { switch (Opt.second->getNumOccurrencesFlag()) { case Required: case OneOrMore: @@ -1060,7 +1099,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; } @@ -1070,19 +1109,16 @@ 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! - Opts.clear(); - PositionalOpts.clear(); - MoreHelp->clear(); + MoreHelp.clear(); // If we had an error processing our arguments, don't let the program execute - if (ErrorParsing) exit(1); + if (ErrorParsing) + exit(1); } //===----------------------------------------------------------------------===// @@ -1090,20 +1126,21 @@ 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; + errs() << GlobalParser->ProgramName << ": for the -" << ArgName; errs() << " option: " << Message << "\n"; 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: @@ -1113,21 +1150,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; } @@ -1136,9 +1174,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) { @@ -1167,7 +1203,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; } @@ -1188,14 +1224,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; @@ -1212,8 +1247,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; @@ -1230,8 +1265,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; @@ -1239,8 +1274,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!"); @@ -1250,7 +1285,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!"); @@ -1269,13 +1305,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; @@ -1283,8 +1319,6 @@ bool parser<float>::parse(Option &O, StringRef ArgName, return false; } - - // generic_parser_base implementation // @@ -1301,18 +1335,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; } } @@ -1327,7 +1360,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'; } @@ -1347,12 +1380,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) { @@ -1377,25 +1409,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) @@ -1406,9 +1438,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; @@ -1421,8 +1453,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"; } @@ -1432,19 +1464,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) @@ -1458,8 +1489,8 @@ sortOpts(StringMap<Option*> &OptMap, 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. @@ -1471,7 +1502,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) @@ -1484,36 +1516,26 @@ public: // Invoke the printer. void operator=(bool Value) { - if (Value == false) return; - - // Get all the options. - SmallVector<Option*, 4> PositionalOpts; - SmallVector<Option*, 4> SinkOpts; - StringMap<Option*> OptMap; - GetOptionInfo(PositionalOpts, SinkOpts, OptMap); + if (Value == false) + return; StrOptionPairVector Opts; - sortOpts(OptMap, Opts, ShowHidden); - - if (ProgramOverview) - outs() << "OVERVIEW: " << ProgramOverview << "\n"; + sortOpts(GlobalParser->OptionsMap, Opts, ShowHidden); - outs() << "USAGE: " << ProgramName << " [options]"; + if (GlobalParser->ProgramOverview) + outs() << "OVERVIEW: " << GlobalParser->ProgramOverview << "\n"; - // Print out the positional options. - Option *CAOpt = nullptr; // The cl::ConsumeAfter option, if it exists... - if (!PositionalOpts.empty() && - PositionalOpts[0]->getNumOccurrencesFlag() == ConsumeAfter) - CAOpt = PositionalOpts[0]; + outs() << "USAGE: " << GlobalParser->ProgramName << " [options]"; - for (size_t i = CAOpt != nullptr, e = PositionalOpts.size(); i != e; ++i) { - if (PositionalOpts[i]->ArgStr[0]) - outs() << " --" << PositionalOpts[i]->ArgStr; - outs() << " " << PositionalOpts[i]->HelpStr; + for (auto Opt : GlobalParser->PositionalOpts) { + if (Opt->ArgStr[0]) + outs() << " --" << Opt->ArgStr; + outs() << " " << Opt->HelpStr; } // Print the consume after option info if it exists... - if (CAOpt) outs() << " " << CAOpt->HelpStr; + if (GlobalParser->ConsumeAfterOpt) + outs() << " " << GlobalParser->ConsumeAfterOpt->HelpStr; outs() << "\n\n"; @@ -1526,11 +1548,9 @@ public: printOptions(Opts, MaxArgLen); // Print any extra help the user has declared. - for (std::vector<const char *>::iterator I = MoreHelp->begin(), - E = MoreHelp->end(); - I != E; ++I) - outs() << *I; - MoreHelp->clear(); + for (auto I : GlobalParser->MoreHelp) + outs() << I; + GlobalParser->MoreHelp.clear(); // Halt the program since help information was printed exit(0); @@ -1549,17 +1569,17 @@ 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. - for (OptionCatSet::const_iterator I = RegisteredOptionCategories->begin(), - E = RegisteredOptionCategories->end(); + for (auto I = GlobalParser->RegisteredOptionCategories.begin(), + E = GlobalParser->RegisteredOptionCategories.end(); I != E; ++I) { SortedCategories.push_back(*I); } @@ -1631,9 +1651,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); @@ -1648,7 +1668,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, @@ -1656,41 +1675,45 @@ static HelpPrinterWrapper WrappedNormalPrinter(UncategorizedNormalPrinter, static HelpPrinterWrapper WrappedHiddenPrinter(UncategorizedHiddenPrinter, CategorizedHiddenPrinter); +// Define a category for generic options that all tools should have. +static cl::OptionCategory GenericCategory("Generic Options"); + // Define uncategorized help printers. // -help-list is hidden by default because if Option categories are being used // then -help behaves the same as -help-list. -static cl::opt<HelpPrinter, true, parser<bool> > -HLOp("help-list", - cl::desc("Display list of available options (-help-list-hidden for more)"), - cl::location(UncategorizedNormalPrinter), cl::Hidden, cl::ValueDisallowed); +static cl::opt<HelpPrinter, true, parser<bool>> HLOp( + "help-list", + cl::desc("Display list of available options (-help-list-hidden for more)"), + cl::location(UncategorizedNormalPrinter), cl::Hidden, cl::ValueDisallowed, + cl::cat(GenericCategory)); -static cl::opt<HelpPrinter, true, parser<bool> > -HLHOp("help-list-hidden", - cl::desc("Display list of all available options"), - cl::location(UncategorizedHiddenPrinter), cl::Hidden, cl::ValueDisallowed); +static cl::opt<HelpPrinter, true, parser<bool>> + HLHOp("help-list-hidden", cl::desc("Display list of all available options"), + cl::location(UncategorizedHiddenPrinter), cl::Hidden, + cl::ValueDisallowed, cl::cat(GenericCategory)); // Define uncategorized/categorized help printers. These printers change their // behaviour at runtime depending on whether one or more Option categories have // been declared. -static cl::opt<HelpPrinterWrapper, true, parser<bool> > -HOp("help", cl::desc("Display available options (-help-hidden for more)"), - cl::location(WrappedNormalPrinter), cl::ValueDisallowed); - -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> -PrintAllOptions("print-all-options", - cl::desc("Print all option values after command line parsing"), - cl::Hidden, cl::init(false)); +static cl::opt<HelpPrinterWrapper, true, parser<bool>> + HOp("help", cl::desc("Display available options (-help-hidden for more)"), + cl::location(WrappedNormalPrinter), cl::ValueDisallowed, + cl::cat(GenericCategory)); + +static cl::opt<HelpPrinterWrapper, true, parser<bool>> + HHOp("help-hidden", cl::desc("Display all available options"), + cl::location(WrappedHiddenPrinter), cl::Hidden, cl::ValueDisallowed, + cl::cat(GenericCategory)); + +static cl::opt<bool> PrintOptions( + "print-options", + cl::desc("Print non-default options after command line parsing"), + cl::Hidden, cl::init(false), cl::cat(GenericCategory)); + +static cl::opt<bool> PrintAllOptions( + "print-all-options", + cl::desc("Print all option values after command line parsing"), cl::Hidden, + cl::init(false), cl::cat(GenericCategory)); void HelpPrinterWrapper::operator=(bool Value) { if (Value == false) @@ -1699,29 +1722,25 @@ void HelpPrinterWrapper::operator=(bool Value) { // Decide which printer to invoke. If more than one option category is // registered then it is useful to show the categorized help instead of // uncategorized help. - if (RegisteredOptionCategories->size() > 1) { + if (GlobalParser->RegisteredOptionCategories.size() > 1) { // unhide -help-list option so user can have uncategorized output if they // want it. HLOp.setHiddenFlag(NotHidden); 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; +void cl::PrintOptionValues() { GlobalParser->printOptionValues(); } - // Get all the options. - SmallVector<Option*, 4> PositionalOpts; - SmallVector<Option*, 4> SinkOpts; - StringMap<Option*> OptMap; - GetOptionInfo(PositionalOpts, SinkOpts, OptMap); +void CommandLineParser::printOptionValues() { + if (!PrintOptions && !PrintAllOptions) + return; - SmallVector<std::pair<const char *, Option*>, 128> Opts; - sortOpts(OptMap, Opts, /*ShowHidden*/true); + SmallVector<std::pair<const char *, Option *>, 128> Opts; + sortOpts(OptionsMap, Opts, /*ShowHidden*/ true); // Compute the maximum argument length... size_t MaxArgLen = 0; @@ -1734,7 +1753,7 @@ void cl::PrintOptionValues() { static void (*OverrideVersionPrinter)() = nullptr; -static std::vector<void (*)()>* ExtraVersionPrinters = nullptr; +static std::vector<void (*)()> *ExtraVersionPrinters = nullptr; namespace { class VersionPrinter { @@ -1756,7 +1775,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" @@ -1765,7 +1785,8 @@ public: << " Host CPU: " << CPU << '\n'; } void operator=(bool OptionWasSpecified) { - if (!OptionWasSpecified) return; + if (!OptionWasSpecified) + return; if (OverrideVersionPrinter != nullptr) { (*OverrideVersionPrinter)(); @@ -1788,13 +1809,13 @@ 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, + cl::cat(GenericCategory)); // Utility function for printing the help message. void cl::PrintHelpMessage(bool Hidden, bool Categorized) { @@ -1816,13 +1837,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) @@ -1831,14 +1848,27 @@ void cl::AddExtraVersionPrinter(void (*func)()) { ExtraVersionPrinters->push_back(func); } -void cl::getRegisteredOptions(StringMap<Option*> &Map) -{ - // Get all the options. - SmallVector<Option*, 4> PositionalOpts; //NOT USED - SmallVector<Option*, 4> SinkOpts; //NOT USED - assert(Map.size() == 0 && "StringMap must be empty"); - GetOptionInfo(PositionalOpts, SinkOpts, Map); - return; +StringMap<Option *> &cl::getRegisteredOptions() { + return GlobalParser->OptionsMap; +} + +void cl::HideUnrelatedOptions(cl::OptionCategory &Category) { + for (auto &I : GlobalParser->OptionsMap) { + if (I.second->Category != &Category && + I.second->Category != &GenericCategory) + I.second->setHiddenFlag(cl::ReallyHidden); + } +} + +void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories) { + auto CategoriesBegin = Categories.begin(); + auto CategoriesEnd = Categories.end(); + for (auto &I : GlobalParser->OptionsMap) { + if (std::find(CategoriesBegin, CategoriesEnd, I.second->Category) == + CategoriesEnd && + I.second->Category != &GenericCategory) + I.second->setHiddenFlag(cl::ReallyHidden); + } } void LLVMParseCommandLineOptions(int argc, const char *const *argv, diff --git a/lib/Support/Compression.cpp b/lib/Support/Compression.cpp index c32eb213..17ae295 100644 --- a/lib/Support/Compression.cpp +++ b/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/lib/Support/ConvertUTFWrapper.cpp b/lib/Support/ConvertUTFWrapper.cpp index e45335d..1bbef23 100644 --- a/lib/Support/ConvertUTFWrapper.cpp +++ b/lib/Support/ConvertUTFWrapper.cpp @@ -109,8 +109,9 @@ bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out) { if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_NATIVE) Src++; - // Just allocate enough space up front. We'll shrink it later. - Out.resize(SrcBytes.size() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT); + // Just allocate enough space up front. We'll shrink it later. Allocate + // enough that we can fit a null terminator without reallocating. + Out.resize(SrcBytes.size() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1); UTF8 *Dst = reinterpret_cast<UTF8 *>(&Out[0]); UTF8 *DstEnd = Dst + Out.size(); @@ -124,6 +125,46 @@ bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out) { } Out.resize(reinterpret_cast<char *>(Dst) - &Out[0]); + Out.push_back(0); + Out.pop_back(); + return true; +} + +bool convertUTF8ToUTF16String(StringRef SrcUTF8, + SmallVectorImpl<UTF16> &DstUTF16) { + assert(DstUTF16.empty()); + + // Avoid OOB by returning early on empty input. + if (SrcUTF8.empty()) { + DstUTF16.push_back(0); + DstUTF16.pop_back(); + return true; + } + + const UTF8 *Src = reinterpret_cast<const UTF8 *>(SrcUTF8.begin()); + const UTF8 *SrcEnd = reinterpret_cast<const UTF8 *>(SrcUTF8.end()); + + // Allocate the same number of UTF-16 code units as UTF-8 code units. Encoding + // as UTF-16 should always require the same amount or less code units than the + // UTF-8 encoding. Allocate one extra byte for the null terminator though, + // so that someone calling DstUTF16.data() gets a null terminated string. + // We resize down later so we don't have to worry that this over allocates. + DstUTF16.resize(SrcUTF8.size()+1); + UTF16 *Dst = &DstUTF16[0]; + UTF16 *DstEnd = Dst + DstUTF16.size(); + + ConversionResult CR = + ConvertUTF8toUTF16(&Src, SrcEnd, &Dst, DstEnd, strictConversion); + assert(CR != targetExhausted); + + if (CR != conversionOK) { + DstUTF16.clear(); + return false; + } + + DstUTF16.resize(Dst - &DstUTF16[0]); + DstUTF16.push_back(0); + DstUTF16.pop_back(); return true; } diff --git a/lib/Support/Debug.cpp b/lib/Support/Debug.cpp index 8246542..9c58ae8 100644 --- a/lib/Support/Debug.cpp +++ b/lib/Support/Debug.cpp @@ -25,15 +25,51 @@ #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" -#include "llvm/Support/ManagedStatic.h" + +#undef isCurrentDebugType +#undef setCurrentDebugType using namespace llvm; +// Even though LLVM might be built with NDEBUG, define symbols that the code +// built without NDEBUG can depend on via the llvm/Support/Debug.h header. +namespace llvm { +/// Exported boolean set by the -debug option. +bool DebugFlag = false; + +static ManagedStatic<std::vector<std::string>> CurrentDebugType; + +/// Return true if the specified string is the debug type +/// specified on the command line, or if none was specified on the command line +/// with the -debug-only=X option. +bool isCurrentDebugType(const char *DebugType) { + if (CurrentDebugType->empty()) + return true; + // see if DebugType is in list. Note: do not use find() as that forces us to + // unnecessarily create an std::string instance. + for (auto d : *CurrentDebugType) { + if (d == DebugType) + return true; + } + return false; +} + +/// Set the current debug type, as if the -debug-only=X +/// option were specified. Note that DebugFlag also needs to be set to true for +/// debug output to be produced. +/// +void setCurrentDebugType(const char *Type) { + CurrentDebugType->clear(); + CurrentDebugType->push_back(Type); +} + +} // namespace llvm + // All Debug.h functionality is a no-op in NDEBUG mode. #ifndef NDEBUG -bool llvm::DebugFlag; // DebugFlag - Exported boolean set by the -debug option // -debug - Command line option to enable the DEBUG statements in the passes. // This flag may only be enabled in debug builds. @@ -51,14 +87,14 @@ DebugBufferSize("debug-buffer-size", cl::Hidden, cl::init(0)); -static ManagedStatic<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); } }; @@ -68,7 +104,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. @@ -82,22 +118,6 @@ static void debug_user_sig_handler(void *Cookie) { dbgout->flushBufferWithBanner(); } -// isCurrentDebugType - Return true if the specified string is the debug type -// specified on the command line, or if none was specified on the command line -// with the -debug-only=X option. -// -bool llvm::isCurrentDebugType(const char *DebugType) { - return CurrentDebugType->empty() || DebugType == *CurrentDebugType; -} - -/// setCurrentDebugType - Set the current debug type, as if the -debug-only=X -/// option were specified. Note that DebugFlag also needs to be set to true for -/// debug output to be produced. -/// -void llvm::setCurrentDebugType(const char *Type) { - *CurrentDebugType = Type; -} - /// dbgs - Return a circular-buffered debug stream. raw_ostream &llvm::dbgs() { // Do one-time initialization in a thread-safe way. diff --git a/lib/Support/Dwarf.cpp b/lib/Support/Dwarf.cpp index 4b6337e..95c4bc3 100644 --- a/lib/Support/Dwarf.cpp +++ b/lib/Support/Dwarf.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Dwarf.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm; @@ -19,87 +20,19 @@ using namespace dwarf; const char *llvm::dwarf::TagString(unsigned Tag) { switch (Tag) { - case DW_TAG_array_type: return "DW_TAG_array_type"; - case DW_TAG_class_type: return "DW_TAG_class_type"; - case DW_TAG_entry_point: return "DW_TAG_entry_point"; - case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type"; - case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter"; - case DW_TAG_imported_declaration: return "DW_TAG_imported_declaration"; - case DW_TAG_label: return "DW_TAG_label"; - case DW_TAG_lexical_block: return "DW_TAG_lexical_block"; - case DW_TAG_member: return "DW_TAG_member"; - case DW_TAG_pointer_type: return "DW_TAG_pointer_type"; - case DW_TAG_reference_type: return "DW_TAG_reference_type"; - case DW_TAG_compile_unit: return "DW_TAG_compile_unit"; - case DW_TAG_string_type: return "DW_TAG_string_type"; - case DW_TAG_structure_type: return "DW_TAG_structure_type"; - case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type"; - case DW_TAG_typedef: return "DW_TAG_typedef"; - case DW_TAG_union_type: return "DW_TAG_union_type"; - case DW_TAG_unspecified_parameters: return "DW_TAG_unspecified_parameters"; - case DW_TAG_variant: return "DW_TAG_variant"; - case DW_TAG_common_block: return "DW_TAG_common_block"; - case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion"; - case DW_TAG_inheritance: return "DW_TAG_inheritance"; - case DW_TAG_inlined_subroutine: return "DW_TAG_inlined_subroutine"; - case DW_TAG_module: return "DW_TAG_module"; - case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type"; - case DW_TAG_set_type: return "DW_TAG_set_type"; - case DW_TAG_subrange_type: return "DW_TAG_subrange_type"; - case DW_TAG_with_stmt: return "DW_TAG_with_stmt"; - case DW_TAG_access_declaration: return "DW_TAG_access_declaration"; - case DW_TAG_base_type: return "DW_TAG_base_type"; - case DW_TAG_catch_block: return "DW_TAG_catch_block"; - case DW_TAG_const_type: return "DW_TAG_const_type"; - case DW_TAG_constant: return "DW_TAG_constant"; - case DW_TAG_enumerator: return "DW_TAG_enumerator"; - case DW_TAG_file_type: return "DW_TAG_file_type"; - case DW_TAG_friend: return "DW_TAG_friend"; - case DW_TAG_namelist: return "DW_TAG_namelist"; - case DW_TAG_namelist_item: return "DW_TAG_namelist_item"; - case DW_TAG_packed_type: return "DW_TAG_packed_type"; - case DW_TAG_subprogram: return "DW_TAG_subprogram"; - case DW_TAG_template_type_parameter: return "DW_TAG_template_type_parameter"; - case DW_TAG_template_value_parameter: return "DW_TAG_template_value_parameter"; - case DW_TAG_thrown_type: return "DW_TAG_thrown_type"; - case DW_TAG_try_block: return "DW_TAG_try_block"; - case DW_TAG_variant_part: return "DW_TAG_variant_part"; - case DW_TAG_variable: return "DW_TAG_variable"; - case DW_TAG_volatile_type: return "DW_TAG_volatile_type"; - case DW_TAG_dwarf_procedure: return "DW_TAG_dwarf_procedure"; - case DW_TAG_restrict_type: return "DW_TAG_restrict_type"; - case DW_TAG_interface_type: return "DW_TAG_interface_type"; - case DW_TAG_namespace: return "DW_TAG_namespace"; - case DW_TAG_imported_module: return "DW_TAG_imported_module"; - case DW_TAG_unspecified_type: return "DW_TAG_unspecified_type"; - case DW_TAG_partial_unit: return "DW_TAG_partial_unit"; - case DW_TAG_imported_unit: return "DW_TAG_imported_unit"; - case DW_TAG_condition: return "DW_TAG_condition"; - case DW_TAG_shared_type: return "DW_TAG_shared_type"; - case DW_TAG_lo_user: return "DW_TAG_lo_user"; - case DW_TAG_hi_user: return "DW_TAG_hi_user"; - case DW_TAG_auto_variable: return "DW_TAG_auto_variable"; - case DW_TAG_arg_variable: return "DW_TAG_arg_variable"; - case DW_TAG_expression: return "DW_TAG_expression"; - case DW_TAG_rvalue_reference_type: return "DW_TAG_rvalue_reference_type"; - case DW_TAG_template_alias: return "DW_TAG_template_alias"; - case DW_TAG_coarray_type: return "DW_TAG_coarray_type"; - case DW_TAG_generic_subrange: return "DW_TAG_generic_subrange"; - case DW_TAG_dynamic_type: return "DW_TAG_dynamic_type"; - case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop"; - case DW_TAG_type_unit: return "DW_TAG_type_unit"; - case DW_TAG_format_label: return "DW_TAG_format_label"; - case DW_TAG_function_template: return "DW_TAG_function_template"; - case DW_TAG_class_template: return "DW_TAG_class_template"; - case DW_TAG_GNU_template_template_param: - return "DW_TAG_GNU_template_template_param"; - case DW_TAG_GNU_template_parameter_pack: - return "DW_TAG_GNU_template_parameter_pack"; - case DW_TAG_GNU_formal_parameter_pack: - return "DW_TAG_GNU_formal_parameter_pack"; - case DW_TAG_APPLE_property: return "DW_TAG_APPLE_property"; + default: return nullptr; +#define HANDLE_DW_TAG(ID, NAME) \ + case DW_TAG_##NAME: \ + return "DW_TAG_" #NAME; +#include "llvm/Support/Dwarf.def" } - return nullptr; +} + +unsigned llvm::dwarf::getTag(StringRef TagString) { + return StringSwitch<unsigned>(TagString) +#define HANDLE_DW_TAG(ID, NAME) .Case("DW_TAG_" #NAME, DW_TAG_##NAME) +#include "llvm/Support/Dwarf.def" + .Default(DW_TAG_invalid); } const char *llvm::dwarf::ChildrenString(unsigned Children) { @@ -306,193 +239,36 @@ const char *llvm::dwarf::FormEncodingString(unsigned Encoding) { const char *llvm::dwarf::OperationEncodingString(unsigned Encoding) { switch (Encoding) { - case DW_OP_addr: return "DW_OP_addr"; - case DW_OP_deref: return "DW_OP_deref"; - case DW_OP_const1u: return "DW_OP_const1u"; - case DW_OP_const1s: return "DW_OP_const1s"; - case DW_OP_const2u: return "DW_OP_const2u"; - case DW_OP_const2s: return "DW_OP_const2s"; - case DW_OP_const4u: return "DW_OP_const4u"; - case DW_OP_const4s: return "DW_OP_const4s"; - case DW_OP_const8u: return "DW_OP_const8u"; - case DW_OP_const8s: return "DW_OP_const8s"; - case DW_OP_constu: return "DW_OP_constu"; - case DW_OP_consts: return "DW_OP_consts"; - case DW_OP_dup: return "DW_OP_dup"; - case DW_OP_drop: return "DW_OP_drop"; - case DW_OP_over: return "DW_OP_over"; - case DW_OP_pick: return "DW_OP_pick"; - case DW_OP_swap: return "DW_OP_swap"; - case DW_OP_rot: return "DW_OP_rot"; - case DW_OP_xderef: return "DW_OP_xderef"; - case DW_OP_abs: return "DW_OP_abs"; - case DW_OP_and: return "DW_OP_and"; - case DW_OP_div: return "DW_OP_div"; - case DW_OP_minus: return "DW_OP_minus"; - case DW_OP_mod: return "DW_OP_mod"; - case DW_OP_mul: return "DW_OP_mul"; - case DW_OP_neg: return "DW_OP_neg"; - case DW_OP_not: return "DW_OP_not"; - case DW_OP_or: return "DW_OP_or"; - case DW_OP_plus: return "DW_OP_plus"; - case DW_OP_plus_uconst: return "DW_OP_plus_uconst"; - case DW_OP_shl: return "DW_OP_shl"; - case DW_OP_shr: return "DW_OP_shr"; - case DW_OP_shra: return "DW_OP_shra"; - case DW_OP_xor: return "DW_OP_xor"; - case DW_OP_skip: return "DW_OP_skip"; - case DW_OP_bra: return "DW_OP_bra"; - case DW_OP_eq: return "DW_OP_eq"; - case DW_OP_ge: return "DW_OP_ge"; - case DW_OP_gt: return "DW_OP_gt"; - case DW_OP_le: return "DW_OP_le"; - case DW_OP_lt: return "DW_OP_lt"; - case DW_OP_ne: return "DW_OP_ne"; - case DW_OP_lit0: return "DW_OP_lit0"; - case DW_OP_lit1: return "DW_OP_lit1"; - case DW_OP_lit2: return "DW_OP_lit2"; - case DW_OP_lit3: return "DW_OP_lit3"; - case DW_OP_lit4: return "DW_OP_lit4"; - case DW_OP_lit5: return "DW_OP_lit5"; - case DW_OP_lit6: return "DW_OP_lit6"; - case DW_OP_lit7: return "DW_OP_lit7"; - case DW_OP_lit8: return "DW_OP_lit8"; - case DW_OP_lit9: return "DW_OP_lit9"; - case DW_OP_lit10: return "DW_OP_lit10"; - case DW_OP_lit11: return "DW_OP_lit11"; - case DW_OP_lit12: return "DW_OP_lit12"; - case DW_OP_lit13: return "DW_OP_lit13"; - case DW_OP_lit14: return "DW_OP_lit14"; - case DW_OP_lit15: return "DW_OP_lit15"; - case DW_OP_lit16: return "DW_OP_lit16"; - case DW_OP_lit17: return "DW_OP_lit17"; - case DW_OP_lit18: return "DW_OP_lit18"; - case DW_OP_lit19: return "DW_OP_lit19"; - case DW_OP_lit20: return "DW_OP_lit20"; - case DW_OP_lit21: return "DW_OP_lit21"; - case DW_OP_lit22: return "DW_OP_lit22"; - case DW_OP_lit23: return "DW_OP_lit23"; - case DW_OP_lit24: return "DW_OP_lit24"; - case DW_OP_lit25: return "DW_OP_lit25"; - case DW_OP_lit26: return "DW_OP_lit26"; - case DW_OP_lit27: return "DW_OP_lit27"; - case DW_OP_lit28: return "DW_OP_lit28"; - case DW_OP_lit29: return "DW_OP_lit29"; - case DW_OP_lit30: return "DW_OP_lit30"; - case DW_OP_lit31: return "DW_OP_lit31"; - case DW_OP_reg0: return "DW_OP_reg0"; - case DW_OP_reg1: return "DW_OP_reg1"; - case DW_OP_reg2: return "DW_OP_reg2"; - case DW_OP_reg3: return "DW_OP_reg3"; - case DW_OP_reg4: return "DW_OP_reg4"; - case DW_OP_reg5: return "DW_OP_reg5"; - case DW_OP_reg6: return "DW_OP_reg6"; - case DW_OP_reg7: return "DW_OP_reg7"; - case DW_OP_reg8: return "DW_OP_reg8"; - case DW_OP_reg9: return "DW_OP_reg9"; - case DW_OP_reg10: return "DW_OP_reg10"; - case DW_OP_reg11: return "DW_OP_reg11"; - case DW_OP_reg12: return "DW_OP_reg12"; - case DW_OP_reg13: return "DW_OP_reg13"; - case DW_OP_reg14: return "DW_OP_reg14"; - case DW_OP_reg15: return "DW_OP_reg15"; - case DW_OP_reg16: return "DW_OP_reg16"; - case DW_OP_reg17: return "DW_OP_reg17"; - case DW_OP_reg18: return "DW_OP_reg18"; - case DW_OP_reg19: return "DW_OP_reg19"; - case DW_OP_reg20: return "DW_OP_reg20"; - case DW_OP_reg21: return "DW_OP_reg21"; - case DW_OP_reg22: return "DW_OP_reg22"; - case DW_OP_reg23: return "DW_OP_reg23"; - case DW_OP_reg24: return "DW_OP_reg24"; - case DW_OP_reg25: return "DW_OP_reg25"; - case DW_OP_reg26: return "DW_OP_reg26"; - case DW_OP_reg27: return "DW_OP_reg27"; - case DW_OP_reg28: return "DW_OP_reg28"; - case DW_OP_reg29: return "DW_OP_reg29"; - case DW_OP_reg30: return "DW_OP_reg30"; - case DW_OP_reg31: return "DW_OP_reg31"; - case DW_OP_breg0: return "DW_OP_breg0"; - case DW_OP_breg1: return "DW_OP_breg1"; - case DW_OP_breg2: return "DW_OP_breg2"; - case DW_OP_breg3: return "DW_OP_breg3"; - case DW_OP_breg4: return "DW_OP_breg4"; - case DW_OP_breg5: return "DW_OP_breg5"; - case DW_OP_breg6: return "DW_OP_breg6"; - case DW_OP_breg7: return "DW_OP_breg7"; - case DW_OP_breg8: return "DW_OP_breg8"; - case DW_OP_breg9: return "DW_OP_breg9"; - case DW_OP_breg10: return "DW_OP_breg10"; - case DW_OP_breg11: return "DW_OP_breg11"; - case DW_OP_breg12: return "DW_OP_breg12"; - case DW_OP_breg13: return "DW_OP_breg13"; - case DW_OP_breg14: return "DW_OP_breg14"; - case DW_OP_breg15: return "DW_OP_breg15"; - case DW_OP_breg16: return "DW_OP_breg16"; - case DW_OP_breg17: return "DW_OP_breg17"; - case DW_OP_breg18: return "DW_OP_breg18"; - case DW_OP_breg19: return "DW_OP_breg19"; - case DW_OP_breg20: return "DW_OP_breg20"; - case DW_OP_breg21: return "DW_OP_breg21"; - case DW_OP_breg22: return "DW_OP_breg22"; - case DW_OP_breg23: return "DW_OP_breg23"; - case DW_OP_breg24: return "DW_OP_breg24"; - case DW_OP_breg25: return "DW_OP_breg25"; - case DW_OP_breg26: return "DW_OP_breg26"; - case DW_OP_breg27: return "DW_OP_breg27"; - case DW_OP_breg28: return "DW_OP_breg28"; - case DW_OP_breg29: return "DW_OP_breg29"; - case DW_OP_breg30: return "DW_OP_breg30"; - case DW_OP_breg31: return "DW_OP_breg31"; - case DW_OP_regx: return "DW_OP_regx"; - case DW_OP_fbreg: return "DW_OP_fbreg"; - case DW_OP_bregx: return "DW_OP_bregx"; - case DW_OP_piece: return "DW_OP_piece"; - case DW_OP_deref_size: return "DW_OP_deref_size"; - case DW_OP_xderef_size: return "DW_OP_xderef_size"; - case DW_OP_nop: return "DW_OP_nop"; - case DW_OP_push_object_address: return "DW_OP_push_object_address"; - case DW_OP_call2: return "DW_OP_call2"; - case DW_OP_call4: return "DW_OP_call4"; - case DW_OP_call_ref: return "DW_OP_call_ref"; - case DW_OP_form_tls_address: return "DW_OP_form_tls_address"; - case DW_OP_call_frame_cfa: return "DW_OP_call_frame_cfa"; - case DW_OP_bit_piece: return "DW_OP_bit_piece"; - case DW_OP_implicit_value: return "DW_OP_implicit_value"; - case DW_OP_stack_value: return "DW_OP_stack_value"; - - // GNU thread-local storage - case DW_OP_GNU_push_tls_address: return "DW_OP_GNU_push_tls_address"; - - // DWARF5 Fission Proposal Op Extensions - case DW_OP_GNU_addr_index: return "DW_OP_GNU_addr_index"; - case DW_OP_GNU_const_index: return "DW_OP_GNU_const_index"; + default: return nullptr; +#define HANDLE_DW_OP(ID, NAME) \ + case DW_OP_##NAME: \ + return "DW_OP_" #NAME; +#include "llvm/Support/Dwarf.def" } - return nullptr; +} + +unsigned llvm::dwarf::getOperationEncoding(StringRef OperationEncodingString) { + return StringSwitch<unsigned>(OperationEncodingString) +#define HANDLE_DW_OP(ID, NAME) .Case("DW_OP_" #NAME, DW_OP_##NAME) +#include "llvm/Support/Dwarf.def" + .Default(0); } const char *llvm::dwarf::AttributeEncodingString(unsigned Encoding) { switch (Encoding) { - case DW_ATE_address: return "DW_ATE_address"; - case DW_ATE_boolean: return "DW_ATE_boolean"; - case DW_ATE_complex_float: return "DW_ATE_complex_float"; - case DW_ATE_float: return "DW_ATE_float"; - case DW_ATE_signed: return "DW_ATE_signed"; - case DW_ATE_signed_char: return "DW_ATE_signed_char"; - case DW_ATE_unsigned: return "DW_ATE_unsigned"; - case DW_ATE_unsigned_char: return "DW_ATE_unsigned_char"; - case DW_ATE_imaginary_float: return "DW_ATE_imaginary_float"; - case DW_ATE_UTF: return "DW_ATE_UTF"; - case DW_ATE_packed_decimal: return "DW_ATE_packed_decimal"; - case DW_ATE_numeric_string: return "DW_ATE_numeric_string"; - case DW_ATE_edited: return "DW_ATE_edited"; - case DW_ATE_signed_fixed: return "DW_ATE_signed_fixed"; - case DW_ATE_unsigned_fixed: return "DW_ATE_unsigned_fixed"; - case DW_ATE_decimal_float: return "DW_ATE_decimal_float"; - case DW_ATE_lo_user: return "DW_ATE_lo_user"; - case DW_ATE_hi_user: return "DW_ATE_hi_user"; + default: return nullptr; +#define HANDLE_DW_ATE(ID, NAME) \ + case DW_ATE_##NAME: \ + return "DW_ATE_" #NAME; +#include "llvm/Support/Dwarf.def" } - return nullptr; +} + +unsigned llvm::dwarf::getAttributeEncoding(StringRef EncodingString) { + return StringSwitch<unsigned>(EncodingString) +#define HANDLE_DW_ATE(ID, NAME) .Case("DW_ATE_" #NAME, DW_ATE_##NAME) +#include "llvm/Support/Dwarf.def" + .Default(0); } const char *llvm::dwarf::DecimalSignString(unsigned Sign) { @@ -538,47 +314,39 @@ const char *llvm::dwarf::VisibilityString(unsigned Visibility) { const char *llvm::dwarf::VirtualityString(unsigned Virtuality) { switch (Virtuality) { - case DW_VIRTUALITY_none: return "DW_VIRTUALITY_none"; - case DW_VIRTUALITY_virtual: return "DW_VIRTUALITY_virtual"; - case DW_VIRTUALITY_pure_virtual: return "DW_VIRTUALITY_pure_virtual"; + default: + return nullptr; +#define HANDLE_DW_VIRTUALITY(ID, NAME) \ + case DW_VIRTUALITY_##NAME: \ + return "DW_VIRTUALITY_" #NAME; +#include "llvm/Support/Dwarf.def" } - return nullptr; +} + +unsigned llvm::dwarf::getVirtuality(StringRef VirtualityString) { + return StringSwitch<unsigned>(VirtualityString) +#define HANDLE_DW_VIRTUALITY(ID, NAME) \ + .Case("DW_VIRTUALITY_" #NAME, DW_VIRTUALITY_##NAME) +#include "llvm/Support/Dwarf.def" + .Default(DW_VIRTUALITY_invalid); } const char *llvm::dwarf::LanguageString(unsigned Language) { switch (Language) { - case DW_LANG_C89: return "DW_LANG_C89"; - case DW_LANG_C: return "DW_LANG_C"; - case DW_LANG_Ada83: return "DW_LANG_Ada83"; - case DW_LANG_C_plus_plus: return "DW_LANG_C_plus_plus"; - case DW_LANG_Cobol74: return "DW_LANG_Cobol74"; - case DW_LANG_Cobol85: return "DW_LANG_Cobol85"; - case DW_LANG_Fortran77: return "DW_LANG_Fortran77"; - case DW_LANG_Fortran90: return "DW_LANG_Fortran90"; - case DW_LANG_Pascal83: return "DW_LANG_Pascal83"; - case DW_LANG_Modula2: return "DW_LANG_Modula2"; - case DW_LANG_Java: return "DW_LANG_Java"; - case DW_LANG_C99: return "DW_LANG_C99"; - case DW_LANG_Ada95: return "DW_LANG_Ada95"; - case DW_LANG_Fortran95: return "DW_LANG_Fortran95"; - case DW_LANG_PLI: return "DW_LANG_PLI"; - case DW_LANG_ObjC: return "DW_LANG_ObjC"; - case DW_LANG_ObjC_plus_plus: return "DW_LANG_ObjC_plus_plus"; - case DW_LANG_UPC: return "DW_LANG_UPC"; - case DW_LANG_D: return "DW_LANG_D"; - case DW_LANG_Python: return "DW_LANG_Python"; - case DW_LANG_OpenCL: return "DW_LANG_OpenCL"; - case DW_LANG_Go: return "DW_LANG_Go"; - case DW_LANG_Modula3: return "DW_LANG_Modula3"; - case DW_LANG_Haskell: return "DW_LANG_Haskell"; - case DW_LANG_C_plus_plus_03: return "DW_LANG_C_plus_plus_03"; - case DW_LANG_C_plus_plus_11: return "DW_LANG_C_plus_plus_11"; - case DW_LANG_OCaml: return "DW_LANG_OCaml"; - case DW_LANG_lo_user: return "DW_LANG_lo_user"; - case DW_LANG_Mips_Assembler: return "DW_LANG_Mips_Assembler"; - case DW_LANG_hi_user: return "DW_LANG_hi_user"; + default: + return nullptr; +#define HANDLE_DW_LANG(ID, NAME) \ + case DW_LANG_##NAME: \ + return "DW_LANG_" #NAME; +#include "llvm/Support/Dwarf.def" } - return nullptr; +} + +unsigned llvm::dwarf::getLanguage(StringRef LanguageString) { + return StringSwitch<unsigned>(LanguageString) +#define HANDLE_DW_LANG(ID, NAME) .Case("DW_LANG_" #NAME, DW_LANG_##NAME) +#include "llvm/Support/Dwarf.def" + .Default(0); } const char *llvm::dwarf::CaseString(unsigned Case) { diff --git a/lib/Support/Errno.cpp b/lib/Support/Errno.cpp index 1eefa3e..3ba2a12 100644 --- a/lib/Support/Errno.cpp +++ b/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/lib/Support/ErrorHandling.cpp b/lib/Support/ErrorHandling.cpp index 8e65066..a25e21a 100644 --- a/lib/Support/ErrorHandling.cpp +++ b/lib/Support/ErrorHandling.cpp @@ -19,10 +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" diff --git a/lib/Support/FileOutputBuffer.cpp b/lib/Support/FileOutputBuffer.cpp index c62655d..b176a8b 100644 --- a/lib/Support/FileOutputBuffer.cpp +++ b/lib/Support/FileOutputBuffer.cpp @@ -12,12 +12,18 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Errc.h" -#include "llvm/Support/FileOutputBuffer.h" -#include "llvm/ADT/SmallVector.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 { @@ -71,10 +77,17 @@ FileOutputBuffer::create(StringRef FilePath, size_t Size, if (EC) return EC; + EC = sys::fs::resize_file(FD, Size); + if (EC) + return EC; + auto MappedFile = llvm::make_unique<mapped_file_region>( - FD, true, mapped_file_region::readwrite, Size, 0, EC); + 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)); @@ -82,16 +95,10 @@ FileOutputBuffer::create(StringRef FilePath, size_t Size, 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/lib/Support/Host.cpp b/lib/Support/Host.cpp index 8782e2e..42bc342 100644 --- a/lib/Support/Host.cpp +++ b/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) @@ -117,18 +137,13 @@ static bool GetX86CpuIDAndInfoEx(unsigned value, unsigned subleaf, "c" (subleaf)); return false; #elif defined(_MSC_VER) - // __cpuidex was added in MSVC++ 9.0 SP1 - #if (_MSC_VER > 1500) || (_MSC_VER == 1500 && _MSC_FULL_VER >= 150030729) - int registers[4]; - __cpuidex(registers, value, subleaf); - *rEAX = registers[0]; - *rEBX = registers[1]; - *rECX = registers[2]; - *rEDX = registers[3]; - return false; - #else - return true; - #endif + int registers[4]; + __cpuidex(registers, value, subleaf); + *rEAX = registers[0]; + *rEBX = registers[1]; + *rECX = registers[2]; + *rEDX = registers[3]; + return false; #else return true; #endif @@ -489,22 +504,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 +583,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 +639,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 +677,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); diff --git a/lib/Support/LockFileManager.cpp b/lib/Support/LockFileManager.cpp index 5b82c36..ec3158c 100644 --- a/lib/Support/LockFileManager.cpp +++ b/lib/Support/LockFileManager.cpp @@ -186,9 +186,8 @@ LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock() { Interval.tv_sec = 0; Interval.tv_nsec = 1000000; #endif - // Don't wait more than five minutes for the file to appear. - unsigned MaxSeconds = 300; - bool LockFileGone = false; + // Don't wait more than one minute for the file to appear. + const unsigned MaxSeconds = 60; do { // Sleep for the designated interval, to allow the owning process time to // finish up and remove the lock file. @@ -199,47 +198,18 @@ LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock() { #else nanosleep(&Interval, nullptr); #endif - bool LockFileJustDisappeared = false; - // If the lock file is still expected to be there, check whether it still - // is. - if (!LockFileGone) { - if (sys::fs::access(LockFileName.c_str(), sys::fs::AccessMode::Exist) == - errc::no_such_file_or_directory) { - LockFileGone = true; - LockFileJustDisappeared = true; - } + if (sys::fs::access(LockFileName.c_str(), sys::fs::AccessMode::Exist) == + errc::no_such_file_or_directory) { + // If the original file wasn't created, somone thought the lock was dead. + if (!sys::fs::exists(FileName.str())) + return Res_OwnerDied; + return Res_Success; } - // If the lock file is no longer there, check if the original file is - // available now. - if (LockFileGone) { - if (sys::fs::exists(FileName.str())) { - return Res_Success; - } - - // The lock file is gone, so now we're waiting for the original file to - // show up. If this just happened, reset our waiting intervals and keep - // waiting. - if (LockFileJustDisappeared) { - MaxSeconds = 5; - -#if LLVM_ON_WIN32 - Interval = 1; -#else - Interval.tv_sec = 0; - Interval.tv_nsec = 1000000; -#endif - continue; - } - } - - // If we're looking for the lock file to disappear, but the process - // owning the lock died without cleaning up, just bail out. - if (!LockFileGone && - !processStillExecuting((*Owner).first, (*Owner).second)) { + // If the process owning the lock died without cleaning up, just bail out. + if (!processStillExecuting((*Owner).first, (*Owner).second)) return Res_OwnerDied; - } // Exponentially increase the time we wait for the lock to be removed. #if LLVM_ON_WIN32 @@ -263,3 +233,7 @@ LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock() { // Give up. return Res_Timeout; } + +std::error_code LockFileManager::unsafeRemoveLockFile() { + return sys::fs::remove(LockFileName.str()); +} diff --git a/lib/Support/MemoryBuffer.cpp b/lib/Support/MemoryBuffer.cpp index 7eb0752..379db88 100644 --- a/lib/Support/MemoryBuffer.cpp +++ b/lib/Support/MemoryBuffer.cpp @@ -203,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); @@ -330,7 +330,7 @@ static ErrorOr<std::unique_ptr<MemoryBuffer>> 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)) { diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp index a7a9919..a11bb7f 100644 --- a/lib/Support/Path.cpp +++ b/lib/Support/Path.cpp @@ -14,9 +14,9 @@ #include "llvm/Support/COFF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Errc.h" -#include "llvm/Support/Path.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> @@ -888,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); @@ -952,7 +960,7 @@ file_magic identify_magic(StringRef Magic) { unsigned low = Data2MSB ? 17 : 16; if (Magic[high] == 0) switch (Magic[low]) { - default: break; + default: return file_magic::elf; case 1: return file_magic::elf_relocatable; case 2: return file_magic::elf_executable; case 3: return file_magic::elf_shared_object; @@ -1004,6 +1012,7 @@ file_magic identify_magic(StringRef Magic) { case 8: return file_magic::macho_bundle; case 9: return file_magic::macho_dynamically_linked_shared_lib_stub; case 10: return file_magic::macho_dsym_companion; + case 11: return file_magic::macho_kext_bundle; } break; } diff --git a/lib/Support/PrettyStackTrace.cpp b/lib/Support/PrettyStackTrace.cpp index 987778a..f9f8cab 100644 --- a/lib/Support/PrettyStackTrace.cpp +++ b/lib/Support/PrettyStackTrace.cpp @@ -16,9 +16,8 @@ #include "llvm-c/Core.h" #include "llvm/ADT/SmallString.h" #include "llvm/Config/config.h" // Get autoconf configuration settings -#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Signals.h" -#include "llvm/Support/ThreadLocal.h" #include "llvm/Support/Watchdog.h" #include "llvm/Support/raw_ostream.h" @@ -28,7 +27,17 @@ using namespace llvm; -static ManagedStatic<sys::ThreadLocal<const PrettyStackTraceEntry> > PrettyStackTraceHead; +// If backtrace support is not enabled, compile out support for pretty stack +// traces. This has the secondary effect of not requiring thread local storage +// when backtrace support is disabled. +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) + +// We need a thread local pointer to manage the stack of our stack trace +// objects, but we *really* cannot tolerate destructors running and do not want +// to pay any overhead of synchronizing. As a consequence, we use a raw +// thread-local variable. +static LLVM_THREAD_LOCAL const PrettyStackTraceEntry *PrettyStackTraceHead = + nullptr; static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){ unsigned NextID = 0; @@ -46,12 +55,12 @@ static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){ /// PrintCurStackTrace - Print the current stack trace to the specified stream. static void PrintCurStackTrace(raw_ostream &OS) { // Don't print an empty trace. - if (!PrettyStackTraceHead->get()) return; + if (!PrettyStackTraceHead) return; // If there are pretty stack frames registered, walk and emit them. OS << "Stack dump:\n"; - PrintStack(PrettyStackTraceHead->get(), OS); + PrintStack(PrettyStackTraceHead, OS); OS.flush(); } @@ -99,28 +108,23 @@ static void CrashHandler(void *) { #endif } +// defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) +#endif + PrettyStackTraceEntry::PrettyStackTraceEntry() { +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) // Link ourselves. - NextEntry = PrettyStackTraceHead->get(); - PrettyStackTraceHead->set(this); + NextEntry = PrettyStackTraceHead; + PrettyStackTraceHead = this; +#endif } PrettyStackTraceEntry::~PrettyStackTraceEntry() { - // Do nothing if PrettyStackTraceHead is uninitialized. This can only happen - // if a shutdown occurred after we created the PrettyStackTraceEntry. That - // does occur in the following idiom: - // - // PrettyStackTraceProgram X(...); - // llvm_shutdown_obj Y; - // - // Without this check, we may end up removing ourselves from the stack trace - // after PrettyStackTraceHead has already been destroyed. - if (!PrettyStackTraceHead.isConstructed()) - return; - - assert(PrettyStackTraceHead->get() == this && +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) + assert(PrettyStackTraceHead == this && "Pretty stack trace entry destruction is out of order"); - PrettyStackTraceHead->set(getNextEntry()); + PrettyStackTraceHead = getNextEntry(); +#endif } void PrettyStackTraceString::print(raw_ostream &OS) const { @@ -135,15 +139,19 @@ void PrettyStackTraceProgram::print(raw_ostream &OS) const { OS << '\n'; } +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) static bool RegisterCrashPrinter() { sys::AddSignalHandler(CrashHandler, nullptr); return false; } +#endif void llvm::EnablePrettyStackTrace() { +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) // The first time this is called, we register the crash printer. static bool HandlerRegistered = RegisterCrashPrinter(); (void)HandlerRegistered; +#endif } void LLVMEnablePrettyStackTrace() { diff --git a/lib/Support/Process.cpp b/lib/Support/Process.cpp index 0d42e0e..ad67e1b 100644 --- a/lib/Support/Process.cpp +++ b/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/lib/Support/RandomNumberGenerator.cpp b/lib/Support/RandomNumberGenerator.cpp index c50e7cb..2943137 100644 --- a/lib/Support/RandomNumberGenerator.cpp +++ b/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/lib/Support/ScaledNumber.cpp b/lib/Support/ScaledNumber.cpp index fc6d4e7..6f6699c 100644 --- a/lib/Support/ScaledNumber.cpp +++ b/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; diff --git a/lib/Support/SmallPtrSet.cpp b/lib/Support/SmallPtrSet.cpp index c87ee7d..358c8e8 100644 --- a/lib/Support/SmallPtrSet.cpp +++ b/lib/Support/SmallPtrSet.cpp @@ -50,11 +50,12 @@ SmallPtrSetImplBase::insert_imp(const void *Ptr) { } // Otherwise, hit the big set case, which will call grow. } - - if (NumElements*4 >= CurArraySize*3) { + + if (LLVM_UNLIKELY(NumElements * 4 >= CurArraySize * 3)) { // If more than 3/4 of the array is full, grow. Grow(CurArraySize < 64 ? 128 : CurArraySize*2); - } else if (CurArraySize-(NumElements+NumTombstones) < CurArraySize/8) { + } else if (LLVM_UNLIKELY(CurArraySize - (NumElements + NumTombstones) < + CurArraySize / 8)) { // If fewer of 1/8 of the array is empty (meaning that many are filled with // tombstones), rehash. Grow(CurArraySize); @@ -107,16 +108,16 @@ const void * const *SmallPtrSetImplBase::FindBucketFor(const void *Ptr) const { const void *const *Array = CurArray; const void *const *Tombstone = nullptr; while (1) { - // Found Ptr's bucket? - if (Array[Bucket] == Ptr) - return Array+Bucket; - // If we found an empty bucket, the pointer doesn't exist in the set. // Return a tombstone if we've seen one so far, or the empty bucket if // not. - if (Array[Bucket] == getEmptyMarker()) + if (LLVM_LIKELY(Array[Bucket] == getEmptyMarker())) return Tombstone ? Tombstone : Array+Bucket; - + + // Found Ptr's bucket? + if (LLVM_LIKELY(Array[Bucket] == Ptr)) + return Array+Bucket; + // If this is a tombstone, remember it. If Ptr ends up not in the set, we // prefer to return it than something that would require more probing. if (Array[Bucket] == getTombstoneMarker() && !Tombstone) diff --git a/lib/Support/SpecialCaseList.cpp b/lib/Support/SpecialCaseList.cpp index 785cc60..c312cc1 100644 --- a/lib/Support/SpecialCaseList.cpp +++ b/lib/Support/SpecialCaseList.cpp @@ -46,19 +46,27 @@ struct SpecialCaseList::Entry { } }; -SpecialCaseList::SpecialCaseList() : Entries() {} +SpecialCaseList::SpecialCaseList() : Entries(), Regexps(), IsCompiled(false) {} -std::unique_ptr<SpecialCaseList> SpecialCaseList::create(StringRef Path, - std::string &Error) { - if (Path.empty()) - return std::unique_ptr<SpecialCaseList>(new SpecialCaseList()); - ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = - MemoryBuffer::getFile(Path); - if (std::error_code EC = FileOrErr.getError()) { - Error = (Twine("Can't open file '") + Path + "': " + EC.message()).str(); - return nullptr; +std::unique_ptr<SpecialCaseList> +SpecialCaseList::create(const std::vector<std::string> &Paths, + std::string &Error) { + std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList()); + for (auto Path : Paths) { + ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = + MemoryBuffer::getFile(Path); + if (std::error_code EC = FileOrErr.getError()) { + Error = (Twine("can't open file '") + Path + "': " + EC.message()).str(); + return nullptr; + } + std::string ParseError; + if (!SCL->parse(FileOrErr.get().get(), ParseError)) { + Error = (Twine("error parsing file '") + Path + "': " + ParseError).str(); + return nullptr; + } } - return create(FileOrErr.get().get(), Error); + SCL->compile(); + return SCL; } std::unique_ptr<SpecialCaseList> SpecialCaseList::create(const MemoryBuffer *MB, @@ -66,12 +74,14 @@ std::unique_ptr<SpecialCaseList> SpecialCaseList::create(const MemoryBuffer *MB, std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList()); if (!SCL->parse(MB, Error)) return nullptr; + SCL->compile(); return SCL; } -std::unique_ptr<SpecialCaseList> SpecialCaseList::createOrDie(StringRef Path) { +std::unique_ptr<SpecialCaseList> +SpecialCaseList::createOrDie(const std::vector<std::string> &Paths) { std::string Error; - if (auto SCL = create(Path, Error)) + if (auto SCL = create(Paths, Error)) return SCL; report_fatal_error(Error); } @@ -80,12 +90,8 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) { // Iterate through each line in the blacklist file. SmallVector<StringRef, 16> Lines; SplitString(MB->getBuffer(), Lines, "\n\r"); - StringMap<StringMap<std::string> > Regexps; - assert(Entries.empty() && - "parse() should be called on an empty SpecialCaseList"); int LineNo = 1; - for (SmallVectorImpl<StringRef>::iterator I = Lines.begin(), E = Lines.end(); - I != E; ++I, ++LineNo) { + for (auto I = Lines.begin(), E = Lines.end(); I != E; ++I, ++LineNo) { // Ignore empty lines and lines starting with "#" if (I->empty() || I->startswith("#")) continue; @@ -94,7 +100,7 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) { StringRef Prefix = SplitLine.first; if (SplitLine.second.empty()) { // Missing ':' in the line. - Error = (Twine("Malformed line ") + Twine(LineNo) + ": '" + + Error = (Twine("malformed line ") + Twine(LineNo) + ": '" + SplitLine.first + "'").str(); return false; } @@ -119,7 +125,7 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) { Regex CheckRE(Regexp); std::string REError; if (!CheckRE.isValid(REError)) { - Error = (Twine("Malformed regex in line ") + Twine(LineNo) + ": '" + + Error = (Twine("malformed regex in line ") + Twine(LineNo) + ": '" + SplitLine.second + "': " + REError).str(); return false; } @@ -129,10 +135,14 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) { Regexps[Prefix][Category] += "|"; Regexps[Prefix][Category] += "^" + Regexp + "$"; } + return true; +} +void SpecialCaseList::compile() { + assert(!IsCompiled && "compile() should only be called once"); // Iterate through each of the prefixes, and create Regexs for them. - for (StringMap<StringMap<std::string> >::const_iterator I = Regexps.begin(), - E = Regexps.end(); + for (StringMap<StringMap<std::string>>::const_iterator I = Regexps.begin(), + E = Regexps.end(); I != E; ++I) { for (StringMap<std::string>::const_iterator II = I->second.begin(), IE = I->second.end(); @@ -140,13 +150,15 @@ bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) { Entries[I->getKey()][II->getKey()].RegEx.reset(new Regex(II->getValue())); } } - return true; + Regexps.clear(); + IsCompiled = true; } SpecialCaseList::~SpecialCaseList() {} bool SpecialCaseList::inSection(StringRef Section, StringRef Query, StringRef Category) const { + assert(IsCompiled && "SpecialCaseList::compile() was not called!"); StringMap<StringMap<Entry> >::const_iterator I = Entries.find(Section); if (I == Entries.end()) return false; StringMap<Entry>::const_iterator II = I->second.find(Category); diff --git a/lib/Support/StreamingMemoryObject.cpp b/lib/Support/StreamingMemoryObject.cpp index 68beeef..f39bc56 100644 --- a/lib/Support/StreamingMemoryObject.cpp +++ b/lib/Support/StreamingMemoryObject.cpp @@ -45,8 +45,8 @@ private: return static_cast<std::ptrdiff_t>(address) < LastChar - FirstChar; } - RawMemoryObject(const RawMemoryObject&) LLVM_DELETED_FUNCTION; - void operator=(const RawMemoryObject&) LLVM_DELETED_FUNCTION; + RawMemoryObject(const RawMemoryObject&) = delete; + void operator=(const RawMemoryObject&) = delete; }; uint64_t RawMemoryObject::readBytes(uint8_t *Buf, uint64_t Size, diff --git a/lib/Support/StringMap.cpp b/lib/Support/StringMap.cpp index ddb7349..7be9466 100644 --- a/lib/Support/StringMap.cpp +++ b/lib/Support/StringMap.cpp @@ -188,9 +188,10 @@ unsigned StringMapImpl::RehashTable(unsigned BucketNo) { // If the hash table is now more than 3/4 full, or if fewer than 1/8 of // the buckets are empty (meaning that many are filled with tombstones), // grow/rehash the table. - if (NumItems*4 > NumBuckets*3) { + if (LLVM_UNLIKELY(NumItems * 4 > NumBuckets * 3)) { NewSize = NumBuckets*2; - } else if (NumBuckets-(NumItems+NumTombstones) <= NumBuckets/8) { + } else if (LLVM_UNLIKELY(NumBuckets - (NumItems + NumTombstones) <= + NumBuckets / 8)) { NewSize = NumBuckets; } else { return BucketNo; diff --git a/lib/Support/ThreadLocal.cpp b/lib/Support/ThreadLocal.cpp index 2dec9eb..9da1603 100644 --- a/lib/Support/ThreadLocal.cpp +++ b/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/lib/Support/Triple.cpp b/lib/Support/Triple.cpp index 4a4773e..e74b23c 100644 --- a/lib/Support/Triple.cpp +++ b/lib/Support/Triple.cpp @@ -23,6 +23,7 @@ const char *Triple::getArchTypeName(ArchType Kind) { case aarch64_be: return "aarch64_be"; case arm: return "arm"; case armeb: return "armeb"; + case bpf: return "bpf"; case hexagon: return "hexagon"; case mips: return "mips"; case mipsel: return "mipsel"; @@ -33,6 +34,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"; @@ -82,7 +84,10 @@ const char *Triple::getArchTypePrefix(ArchType Kind) { case hexagon: return "hexagon"; - case r600: return "r600"; + case amdgcn: + case r600: return "amdgpu"; + + case bpf: return "bpf"; case sparcv9: case sparc: return "sparc"; @@ -157,6 +162,8 @@ const char *Triple::getOSTypeName(OSType Kind) { case AIX: return "aix"; case CUDA: return "cuda"; case NVCL: return "nvcl"; + case AMDHSA: return "amdhsa"; + case PS4: return "ps4"; } llvm_unreachable("Invalid OSType"); @@ -188,6 +195,7 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { .Case("arm64", aarch64) // "arm64" is an alias for "aarch64" .Case("arm", arm) .Case("armeb", armeb) + .Case("bpf", bpf) .Case("mips", mips) .Case("mipsel", mipsel) .Case("mips64", mips64) @@ -198,6 +206,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) @@ -242,13 +251,21 @@ static Triple::ArchType parseARMArch(StringRef ArchName) { if (ArchName.startswith("armv")) { offset = 3; - arch = Triple::arm; + if (ArchName.endswith("eb")) { + arch = Triple::armeb; + ArchName = ArchName.substr(0, ArchName.size() - 2); + } else + arch = Triple::arm; } else if (ArchName.startswith("armebv")) { offset = 5; arch = Triple::armeb; } else if (ArchName.startswith("thumbv")) { offset = 5; - arch = Triple::thumb; + if (ArchName.endswith("eb")) { + arch = Triple::thumbeb; + ArchName = ArchName.substr(0, ArchName.size() - 2); + } else + arch = Triple::thumb; } else if (ArchName.startswith("thumbebv")) { offset = 7; arch = Triple::thumbeb; @@ -258,7 +275,7 @@ static Triple::ArchType parseARMArch(StringRef ArchName) { .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("v6", "v6j", "v6k", "v6m", "v6sm", arch) .Cases("v6t2", "v6z", "v6zk", arch) .Cases("v7", "v7a", "v7em", "v7l", arch) .Cases("v7m", "v7r", "v7s", arch) @@ -267,6 +284,8 @@ static Triple::ArchType parseARMArch(StringRef ArchName) { } static Triple::ArchType parseArch(StringRef ArchName) { + Triple::ArchType ARMArch(parseARMArch(ArchName)); + return StringSwitch<Triple::ArchType>(ArchName) .Cases("i386", "i486", "i586", "i686", Triple::x86) // FIXME: Do we need to support these? @@ -276,15 +295,18 @@ static Triple::ArchType parseArch(StringRef ArchName) { .Cases("powerpc64", "ppu", Triple::ppc64) .Case("powerpc64le", Triple::ppc64le) .Case("xscale", Triple::arm) - .StartsWith("arm", parseARMArch(ArchName)) - .StartsWith("thumb", parseARMArch(ArchName)) - .StartsWith("aarch64", parseARMArch(ArchName)) + .Case("xscaleeb", Triple::armeb) + .StartsWith("arm", ARMArch) + .StartsWith("thumb", ARMArch) + .StartsWith("aarch64", ARMArch) .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("bpf", Triple::bpf) .Case("hexagon", Triple::hexagon) .Case("s390x", Triple::systemz) .Case("sparc", Triple::sparc) @@ -345,6 +367,8 @@ static Triple::OSType parseOS(StringRef OSName) { .StartsWith("aix", Triple::AIX) .StartsWith("cuda", Triple::CUDA) .StartsWith("nvcl", Triple::NVCL) + .StartsWith("amdhsa", Triple::AMDHSA) + .StartsWith("ps4", Triple::PS4) .Default(Triple::UnknownOS); } @@ -373,6 +397,9 @@ static Triple::ObjectFormatType parseFormat(StringRef EnvironmentName) { } static Triple::SubArchType parseSubArch(StringRef SubArchName) { + if (SubArchName.endswith("eb")) + SubArchName = SubArchName.substr(0, SubArchName.size() - 2); + return StringSwitch<Triple::SubArchType>(SubArchName) .EndsWith("v8", Triple::ARMSubArch_v8) .EndsWith("v8a", Triple::ARMSubArch_v8) @@ -385,6 +412,7 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) { .EndsWith("v7s", Triple::ARMSubArch_v7s) .EndsWith("v6", Triple::ARMSubArch_v6) .EndsWith("v6m", Triple::ARMSubArch_v6m) + .EndsWith("v6sm", Triple::ARMSubArch_v6m) .EndsWith("v6t2", Triple::ARMSubArch_v6t2) .EndsWith("v5", Triple::ARMSubArch_v5) .EndsWith("v5e", Triple::ARMSubArch_v5) @@ -788,7 +816,11 @@ void Triple::setOS(OSType Kind) { } void Triple::setEnvironment(EnvironmentType Kind) { - setEnvironmentName(getEnvironmentTypeName(Kind)); + if (ObjectFormat == getDefaultFormat(*this)) + return setEnvironmentName(getEnvironmentTypeName(Kind)); + + setEnvironmentName((getEnvironmentTypeName(Kind) + Twine("-") + + getObjectFormatTypeName(ObjectFormat)).str()); } void Triple::setObjectFormat(ObjectFormatType Kind) { @@ -862,6 +894,8 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) { case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: + case llvm::Triple::amdgcn: + case llvm::Triple::bpf: case llvm::Triple::le64: case llvm::Triple::mips64: case llvm::Triple::mips64el: @@ -897,6 +931,8 @@ Triple Triple::get32BitArchVariant() const { case Triple::UnknownArch: case Triple::aarch64: case Triple::aarch64_be: + case Triple::amdgcn: + case Triple::bpf: case Triple::msp430: case Triple::systemz: case Triple::ppc64le: @@ -958,8 +994,10 @@ Triple Triple::get64BitArchVariant() const { case Triple::aarch64: case Triple::aarch64_be: + case Triple::bpf: case Triple::le64: case Triple::amdil64: + case Triple::amdgcn: case Triple::hsail64: case Triple::spir64: case Triple::mips64: @@ -1013,6 +1051,8 @@ const char *Triple::getARMCPUForArch(StringRef MArch) const { offset = 5; if (offset != StringRef::npos && MArch.substr(offset, 2) == "eb") offset += 2; + if (MArch.endswith("eb")) + MArch = MArch.substr(0, MArch.size() - 2); if (offset != StringRef::npos) result = llvm::StringSwitch<const char *>(MArch.substr(offset)) .Cases("v2", "v2a", "arm2") @@ -1027,7 +1067,7 @@ const char *Triple::getARMCPUForArch(StringRef MArch) const { .Case("v6j", "arm1136j-s") .Cases("v6z", "v6zk", "arm1176jzf-s") .Case("v6t2", "arm1156t2-s") - .Cases("v6m", "v6-m", "cortex-m0") + .Cases("v6m", "v6-m", "v6sm", "v6s-m", "cortex-m0") .Cases("v7", "v7a", "v7-a", "v7l", "v7-l", "cortex-a8") .Cases("v7s", "v7-s", "swift") .Cases("v7r", "v7-r", "cortex-r4") diff --git a/lib/Support/Unix/Host.inc b/lib/Support/Unix/Host.inc index fcb3638..4572171 100644 --- a/lib/Support/Unix/Host.inc +++ b/lib/Support/Unix/Host.inc @@ -16,12 +16,12 @@ //=== 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 <sys/utsname.h> using namespace llvm; @@ -35,29 +35,15 @@ static std::string getOSVersion() { } std::string sys::getDefaultTargetTriple() { - StringRef TargetTripleString(LLVM_DEFAULT_TARGET_TRIPLE); - std::pair<StringRef, StringRef> ArchSplit = TargetTripleString.split('-'); - - // Normalize the arch, since the target triple may not actually match the - // target. - std::string Arch = ArchSplit.first; - - std::string Triple(Arch); - Triple += '-'; - Triple += ArchSplit.second; - - // Force i<N>86 to i386. - if (Triple[0] == 'i' && isdigit(Triple[1]) && - Triple[2] == '8' && Triple[3] == '6') - Triple[1] = '3'; + std::string TargetTripleString(LLVM_DEFAULT_TARGET_TRIPLE); // On darwin, we want to update the version to match that of the // target. - std::string::size_type DarwinDashIdx = Triple.find("-darwin"); + std::string::size_type DarwinDashIdx = TargetTripleString.find("-darwin"); if (DarwinDashIdx != std::string::npos) { - Triple.resize(DarwinDashIdx + strlen("-darwin")); - Triple += getOSVersion(); + TargetTripleString.resize(DarwinDashIdx + strlen("-darwin")); + TargetTripleString += getOSVersion(); } - return Triple::normalize(Triple); + return Triple::normalize(TargetTripleString); } diff --git a/lib/Support/Unix/Memory.inc b/lib/Support/Unix/Memory.inc index c9d89a8..c421ee8 100644 --- a/lib/Support/Unix/Memory.inc +++ b/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; @@ -333,23 +333,12 @@ void Memory::InvalidateInstructionCache(const void *Addr, for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) asm volatile("icbi 0, %0" : : "r"(Line)); asm volatile("isync"); -# elif (defined(__arm__) || defined(__aarch64__)) && defined(__GNUC__) +# elif (defined(__arm__) || defined(__aarch64__) || defined(__mips__)) && \ + defined(__GNUC__) // FIXME: Can we safely always call this for __GNUC__ everywhere? const char *Start = static_cast<const char *>(Addr); const char *End = Start + Len; __clear_cache(const_cast<char *>(Start), const_cast<char *>(End)); -# elif defined(__mips__) - const char *Start = static_cast<const char *>(Addr); -# if defined(ANDROID) - // The declaration of "cacheflush" in Android bionic: - // extern int cacheflush(long start, long end, long flags); - const char *End = Start + Len; - long LStart = reinterpret_cast<long>(const_cast<char *>(Start)); - long LEnd = reinterpret_cast<long>(const_cast<char *>(End)); - cacheflush(LStart, LEnd, BCACHE); -# else - cacheflush(const_cast<char *>(Start), Len, BCACHE); -# endif # endif #endif // end apple diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc index 634d404..973d010 100644 --- a/lib/Support/Unix/Path.inc +++ b/lib/Support/Unix/Path.inc @@ -62,31 +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;} - }; -} - namespace llvm { namespace sys { namespace fs { @@ -175,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) @@ -311,11 +286,8 @@ 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(); @@ -440,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() { - // 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() { +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; } - ec = init(fd, closefd, offset); + ec = init(fd, offset, mode); if (ec) Mapping = nullptr; } @@ -523,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; @@ -540,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); } @@ -550,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, diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index a429bb3..df13bd2 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -39,6 +39,9 @@ !defined(__OpenBSD__) && !defined(__Bitrig__) #include <malloc.h> #endif +#if defined(HAVE_MALLCTL) +#include <malloc_np.h> +#endif #ifdef HAVE_MALLOC_MALLOC_H #include <malloc/malloc.h> #endif @@ -57,10 +60,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; @@ -80,43 +79,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; @@ -126,6 +101,12 @@ size_t Process::GetMallocUsage() { malloc_statistics_t Stats; malloc_zone_statistics(malloc_default_zone(), &Stats); return Stats.size_in_use; // darwin +#elif defined(HAVE_MALLCTL) + size_t alloc, sz; + sz = sizeof(size_t); + if (mallctl("stats.allocated", &alloc, &sz, NULL, 0) == 0) + return alloc; + return 0; #elif defined(HAVE_SBRK) // Note this is only an approximation and more closely resembles // the value returned by mallinfo in the arena field. @@ -133,8 +114,7 @@ size_t Process::GetMallocUsage() { char *EndOfMemory = (char*)sbrk(0); if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1)) return EndOfMemory - StartOfMemory; - else - return 0; + return 0; #else #warning Cannot get malloc info on this platform return 0; @@ -219,8 +199,8 @@ public: } private: - FDCloser(const FDCloser &) LLVM_DELETED_FUNCTION; - void operator=(const FDCloser &) LLVM_DELETED_FUNCTION; + FDCloser(const FDCloser &) = delete; + void operator=(const FDCloser &) = delete; int &FD; bool KeepOpen; diff --git a/lib/Support/Unix/Program.inc b/lib/Support/Unix/Program.inc index 0670ad3..baf2767 100644 --- a/lib/Support/Unix/Program.inc +++ b/lib/Support/Unix/Program.inc @@ -42,7 +42,18 @@ #define _RESTRICT_KYWD #endif #include <spawn.h> -#if !defined(__APPLE__) + +#if defined(__APPLE__) +#include <TargetConditionals.h> +#endif + +#if defined(__APPLE__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) +#define USE_NSGETENVIRON 1 +#else +#define USE_NSGETENVIRON 0 +#endif + +#if !USE_NSGETENVIRON extern char **environ; #else #include <crt_externs.h> // _NSGetEnviron @@ -63,11 +74,12 @@ ErrorOr<std::string> sys::findProgramByName(StringRef Name, if (Name.find('/') != StringRef::npos) return std::string(Name); - if (Paths.empty()) { - SmallVector<StringRef, 16> SearchPaths; - SplitString(std::getenv("PATH"), SearchPaths, ":"); - return findProgramByName(Name, SearchPaths); - } + SmallVector<StringRef, 16> EnvironmentPaths; + if (Paths.empty()) + if (const char *PathEnv = std::getenv("PATH")) { + SplitString(PathEnv, EnvironmentPaths, ":"); + Paths = EnvironmentPaths; + } for (auto Path : Paths) { if (Path.empty()) @@ -216,7 +228,7 @@ static bool Execute(ProcessInfo &PI, StringRef Program, const char **args, } if (!envp) -#if !defined(__APPLE__) +#if !USE_NSGETENVIRON envp = const_cast<const char **>(environ); #else // environ is missing in dylibs. diff --git a/lib/Support/Unix/Signals.inc b/lib/Support/Unix/Signals.inc index e8f4643..665c7de 100644 --- a/lib/Support/Unix/Signals.inc +++ b/lib/Support/Unix/Signals.inc @@ -480,6 +480,8 @@ static void PrintStackTraceSignalHandler(void *) { PrintStackTrace(stderr); } +void llvm::sys::DisableSystemDialogsOnCrash() {} + /// PrintStackTraceOnErrorSignal - When an error signal (such as SIGABRT or /// SIGSEGV) is delivered to the process, print a stack trace and then exit. void llvm::sys::PrintStackTraceOnErrorSignal() { diff --git a/lib/Support/Unix/ThreadLocal.inc b/lib/Support/Unix/ThreadLocal.inc index f14d0fa..31c3f38 100644 --- a/lib/Support/Unix/ThreadLocal.inc +++ b/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/lib/Support/Valgrind.cpp b/lib/Support/Valgrind.cpp index 2c6d6aa..facf8d9 100644 --- a/lib/Support/Valgrind.cpp +++ b/lib/Support/Valgrind.cpp @@ -53,7 +53,6 @@ void llvm::sys::ValgrindDiscardTranslations(const void *Addr, size_t Len) { #endif // !HAVE_VALGRIND_VALGRIND_H -#if LLVM_ENABLE_THREADS != 0 && !defined(NDEBUG) // These functions require no implementation, tsan just looks at the arguments // they're called with. However, they are required to be weak as some other // application or library may already be providing these definitions for the @@ -72,4 +71,4 @@ void AnnotateIgnoreWritesBegin(const char *file, int line) {} LLVM_ATTRIBUTE_WEAK void AnnotateIgnoreWritesEnd(const char *file, int line); void AnnotateIgnoreWritesEnd(const char *file, int line) {} } -#endif + diff --git a/lib/Support/Windows/Path.inc b/lib/Support/Windows/Path.inc index 365031c..d8b5702 100644 --- a/lib/Support/Windows/Path.inc +++ b/lib/Support/Windows/Path.inc @@ -44,6 +44,7 @@ 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); @@ -59,11 +60,15 @@ 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 '\\?\'. -static std::error_code widenPath(const Twine &Path8, - SmallVectorImpl<wchar_t> &Path16) { +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 @@ -111,9 +116,8 @@ static std::error_code widenPath(const Twine &Path8, // Just use the caller's original path. return UTF8ToUTF16(Path8Str, Path16); } +} // end namespace path -namespace llvm { -namespace sys { namespace fs { std::string getMainExecutable(const char *argv0, void *MainExecAddr) { @@ -268,21 +272,12 @@ std::error_code rename(const Twine &from, const Twine &to) { return ec; } -std::error_code resize_file(const Twine &path, uint64_t size) { - SmallVector<wchar_t, 128> path_utf16; - - if (std::error_code ec = widenPath(path, 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()); } @@ -463,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) { @@ -482,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; } @@ -511,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; } @@ -526,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; @@ -539,84 +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() { - SmallVector<wchar_t, 128> path_utf16; - - // Convert path to UTF-16. - if ((ec = widenPath(path, 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() { @@ -624,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); } diff --git a/lib/Support/Windows/Process.inc b/lib/Support/Windows/Process.inc index 3819e63..854eac7 100644 --- a/lib/Support/Windows/Process.inc +++ b/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() { diff --git a/lib/Support/Windows/Program.inc b/lib/Support/Windows/Program.inc index 72c2a58..c370077 100644 --- a/lib/Support/Windows/Program.inc +++ b/lib/Support/Windows/Program.inc @@ -15,8 +15,8 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/WindowsError.h" +#include "llvm/Support/raw_ostream.h" #include <cstdio> #include <fcntl.h> #include <io.h> @@ -62,7 +62,8 @@ ErrorOr<std::string> sys::findProgramByName(StringRef Name, SmallVector<StringRef, 12> PathExts; PathExts.push_back(""); PathExts.push_back(".exe"); // FIXME: This must be in %PATHEXT%. - SplitString(std::getenv("PATHEXT"), PathExts, ";"); + if (const char *PathExtEnv = std::getenv("PATHEXT")) + SplitString(PathExtEnv, PathExts, ";"); SmallVector<wchar_t, MAX_PATH> U16Result; DWORD Len = MAX_PATH; @@ -117,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: ")); } @@ -322,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")); diff --git a/lib/Support/Windows/Signals.inc b/lib/Support/Windows/Signals.inc index 35ba6f8..aa1aa72 100644 --- a/lib/Support/Windows/Signals.inc +++ b/lib/Support/Windows/Signals.inc @@ -13,6 +13,7 @@ #include "llvm/Support/FileSystem.h" #include <algorithm> +#include <signal.h> #include <stdio.h> #include <vector> @@ -165,7 +166,6 @@ static std::vector<std::string> *FilesToRemove = NULL; static std::vector<std::pair<void(*)(void*), void*> > *CallBacksToRun = 0; static bool RegisteredUnhandledExceptionFilter = false; static bool CleanupExecuted = false; -static bool ExitOnUnhandledExceptions = false; static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL; // Windows creates a new thread to execute the console handler when an event @@ -184,7 +184,8 @@ namespace llvm { /// AvoidMessageBoxHook - Emulates hitting "retry" from an "abort, retry, /// ignore" CRT debug report dialog. "retry" raises an exception which /// ultimately triggers our stack dumper. -static int AvoidMessageBoxHook(int ReportType, char *Message, int *Return) { +static LLVM_ATTRIBUTE_UNUSED int +AvoidMessageBoxHook(int ReportType, char *Message, int *Return) { // Set *Return to the retry code for the return value of _CrtDbgReport: // http://msdn.microsoft.com/en-us/library/8hyw4sy7(v=vs.71).aspx // This may also trigger just-in-time debugging via DebugBreak(). @@ -196,6 +197,12 @@ static int AvoidMessageBoxHook(int ReportType, char *Message, int *Return) { #endif +extern "C" void HandleAbort(int Sig) { + if (Sig == SIGABRT) { + LLVM_BUILTIN_TRAP; + } +} + static void RegisterHandler() { #if __MINGW32__ && !defined(__MINGW64_VERSION_MAJOR) // On MinGW.org, we need to load up the symbols explicitly, because the @@ -226,17 +233,6 @@ static void RegisterHandler() { OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter); SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE); - // Environment variable to disable any kind of crash dialog. - if (getenv("LLVM_DISABLE_CRASH_REPORT")) { -#ifdef _MSC_VER - _CrtSetReportHook(AvoidMessageBoxHook); -#endif - SetErrorMode(SEM_FAILCRITICALERRORS | - SEM_NOGPFAULTERRORBOX | - SEM_NOOPENFILEERRORBOX); - ExitOnUnhandledExceptions = true; - } - // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or // else multi-threading problems will ensue. } @@ -276,9 +272,29 @@ void sys::DontRemoveFileOnSignal(StringRef Filename) { LeaveCriticalSection(&CriticalSection); } +void sys::DisableSystemDialogsOnCrash() { + // Crash to stack trace handler on abort. + signal(SIGABRT, HandleAbort); + + // The following functions are not reliably accessible on MinGW. +#ifdef _MSC_VER + // We're already handling writing a "something went wrong" message. + _set_abort_behavior(0, _WRITE_ABORT_MSG); + // Disable Dr. Watson. + _set_abort_behavior(0, _CALL_REPORTFAULT); + _CrtSetReportHook(AvoidMessageBoxHook); +#endif + + // Disable standard error dialog box. + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | + SEM_NOOPENFILEERRORBOX); + _set_error_mode(_OUT_TO_STDERR); +} + /// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or /// SIGSEGV) is delivered to the process, print a stack trace and then exit. void sys::PrintStackTraceOnErrorSignal() { + DisableSystemDialogsOnCrash(); RegisterHandler(); LeaveCriticalSection(&CriticalSection); } @@ -437,14 +453,7 @@ static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { fputc('\n', stderr); } - if (ExitOnUnhandledExceptions) - _exit(ep->ExceptionRecord->ExceptionCode); - - // Allow dialog box to pop up allowing choice to start debugger. - if (OldFilter) - return (*OldFilter)(ep); - else - return EXCEPTION_CONTINUE_SEARCH; + _exit(ep->ExceptionRecord->ExceptionCode); } static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) { diff --git a/lib/Support/Windows/ThreadLocal.inc b/lib/Support/Windows/ThreadLocal.inc index 14ce619..b9cb8ff 100644 --- a/lib/Support/Windows/ThreadLocal.inc +++ b/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/lib/Support/Windows/WindowsSupport.h b/lib/Support/Windows/WindowsSupport.h index 6d9c5fb..5bb0b8d 100644 --- a/lib/Support/Windows/WindowsSupport.h +++ b/lib/Support/Windows/WindowsSupport.h @@ -19,6 +19,9 @@ //=== is guaranteed to work on *all* Win32 variants. //===----------------------------------------------------------------------===// +#ifndef LLVM_SUPPORT_WINDOWSSUPPORT_H +#define LLVM_SUPPORT_WINDOWSSUPPORT_H + // mingw-w64 tends to define it as 0x0502 in its headers. #undef _WIN32_WINNT #undef _WIN32_IE @@ -30,6 +33,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> @@ -88,7 +92,7 @@ public: } // True if Handle is valid. - LLVM_EXPLICIT operator bool() const { + explicit operator bool() const { return HandleTraits::IsValid(Handle) ? true : false; } @@ -162,6 +166,11 @@ 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, @@ -172,3 +181,5 @@ std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len, } // end namespace windows } // end namespace sys } // end namespace llvm. + +#endif diff --git a/lib/Support/Windows/explicit_symbols.inc b/lib/Support/Windows/explicit_symbols.inc index cd56b13..bbbf7ea 100644 --- a/lib/Support/Windows/explicit_symbols.inc +++ b/lib/Support/Windows/explicit_symbols.inc @@ -10,9 +10,15 @@ #ifdef HAVE___CHKSTK EXPLICIT_SYMBOL(__chkstk) #endif +#ifdef HAVE___CHKSTK_MS + EXPLICIT_SYMBOL(__chkstk_ms) +#endif #ifdef HAVE____CHKSTK EXPLICIT_SYMBOL(___chkstk) #endif +#ifdef HAVE____CHKSTK_MS + EXPLICIT_SYMBOL(___chkstk_ms) +#endif #ifdef HAVE___MAIN EXPLICIT_SYMBOL(__main) // FIXME: Don't call it. #endif diff --git a/lib/Support/YAMLParser.cpp b/lib/Support/YAMLParser.cpp index 4688ff1..6ae7945 100644 --- a/lib/Support/YAMLParser.cpp +++ b/lib/Support/YAMLParser.cpp @@ -1528,12 +1528,10 @@ Stream::~Stream() {} bool Stream::failed() { return scanner->failed(); } void Stream::printError(Node *N, const Twine &Msg) { - SmallVector<SMRange, 1> Ranges; - Ranges.push_back(N->getSourceRange()); scanner->printError( N->getSourceRange().Start , SourceMgr::DK_Error , Msg - , Ranges); + , N->getSourceRange()); } document_iterator Stream::begin() { @@ -1570,11 +1568,11 @@ std::string Node::getVerbatimTag() const { if (Raw.find_last_of('!') == 0) { Ret = Doc->getTagMap().find("!")->second; Ret += Raw.substr(1); - return std::move(Ret); + return Ret; } else if (Raw.startswith("!!")) { Ret = Doc->getTagMap().find("!!")->second; Ret += Raw.substr(2); - return std::move(Ret); + return Ret; } else { StringRef TagHandle = Raw.substr(0, Raw.find_last_of('!') + 1); std::map<StringRef, StringRef>::const_iterator It = @@ -1588,7 +1586,7 @@ std::string Node::getVerbatimTag() const { setError(Twine("Unknown tag handle ") + TagHandle, T); } Ret += Raw.substr(Raw.find_last_of('!') + 1); - return std::move(Ret); + return Ret; } } diff --git a/lib/Support/YAMLTraits.cpp b/lib/Support/YAMLTraits.cpp index 81edca2..43a0e10 100644 --- a/lib/Support/YAMLTraits.cpp +++ b/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> @@ -233,6 +233,13 @@ bool Input::matchEnumScalar(const char *Str, bool) { return false; } +bool Input::matchEnumFallback() { + if (ScalarMatchFound) + return false; + ScalarMatchFound = true; + return true; +} + void Input::endEnumScalar() { if (!ScalarMatchFound) { setError(CurrentNode, "unknown enumerated scalar"); @@ -508,6 +515,13 @@ bool Output::matchEnumScalar(const char *Str, bool Match) { return false; } +bool Output::matchEnumFallback() { + if (EnumerationMatchFound) + return false; + EnumerationMatchFound = true; + return true; +} + void Output::endEnumScalar() { if (!EnumerationMatchFound) llvm_unreachable("bad runtime enum value"); @@ -669,7 +683,7 @@ StringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *, Val = Scalar; return StringRef(); } - + void ScalarTraits<std::string>::output(const std::string &Val, void *, raw_ostream &Out) { Out << Val; diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp index bbbbe4a..051e2dd 100644 --- a/lib/Support/raw_ostream.cpp +++ b/lib/Support/raw_ostream.cpp @@ -242,7 +242,7 @@ raw_ostream &raw_ostream::operator<<(double N) { char buf[16]; unsigned len; - len = snprintf(buf, sizeof(buf), "%e", N); + len = format("%e", N).snprint(buf, sizeof(buf)); if (len <= sizeof(buf) - 2) { if (len >= 5 && buf[len - 5] == 'e' && buf[len - 3] == '0') { int cs = buf[len - 4]; @@ -312,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; @@ -409,9 +410,12 @@ raw_ostream &raw_ostream::operator<<(const FormattedString &FS) { raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) { if (FN.Hex) { unsigned Nibbles = (64 - countLeadingZeros(FN.HexValue)+3)/4; - unsigned Width = (FN.Width > Nibbles+2) ? FN.Width : Nibbles+2; - + unsigned PrefixChars = FN.HexPrefix ? 2 : 0; + unsigned Width = std::max(FN.Width, Nibbles + PrefixChars); + char NumberBuffer[20] = "0x0000000000000000"; + if (!FN.HexPrefix) + NumberBuffer[1] = '0'; char *EndPtr = NumberBuffer+Width; char *CurPtr = EndPtr; const char A = FN.Upper ? 'A' : 'a'; diff --git a/lib/Support/regcomp.c b/lib/Support/regcomp.c index 0b5b765..ebde64f 100644 --- a/lib/Support/regcomp.c +++ b/lib/Support/regcomp.c @@ -49,6 +49,14 @@ #include "regcclass.h" #include "regcname.h" +#include "llvm/Config/config.h" +#if HAVE_STDINT_H +#include <stdint.h> +#else +/* Pessimistically bound memory use */ +#define SIZE_MAX UINT_MAX +#endif + /* * parse structure, passed up and down to avoid global variables and * other clumsinesses @@ -1069,6 +1077,8 @@ allocset(struct parse *p) p->ncsalloc += CHAR_BIT; nc = p->ncsalloc; + if (nc > SIZE_MAX / sizeof(cset)) + goto nomem; assert(nc % CHAR_BIT == 0); nbytes = nc / CHAR_BIT * css; @@ -1412,6 +1422,11 @@ enlarge(struct parse *p, sopno size) if (p->ssize >= size) return; + if ((uintptr_t)size > SIZE_MAX / sizeof(sop)) { + SETERROR(REG_ESPACE); + return; + } + sp = (sop *)realloc(p->strip, size*sizeof(sop)); if (sp == NULL) { SETERROR(REG_ESPACE); @@ -1428,6 +1443,12 @@ static void stripsnug(struct parse *p, struct re_guts *g) { g->nstates = p->slen; + if ((uintptr_t)p->slen > SIZE_MAX / sizeof(sop)) { + g->strip = p->strip; + SETERROR(REG_ESPACE); + return; + } + g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop)); if (g->strip == NULL) { SETERROR(REG_ESPACE); |