39 explicit OptNameLess(
const StringTable &StrTable,
41 : StrTable(&StrTable), PrefixesTable(PrefixesTable) {}
44 inline bool operator()(
const OptTable::Info &
A,
45 const OptTable::Info &
B)
const {
50 B.getName(*StrTable, PrefixesTable)))
54 A.appendPrefixes(*StrTable, PrefixesTable, APrefixes);
55 B.appendPrefixes(*StrTable, PrefixesTable, BPrefixes);
64 "Unexpected classes for options with same name.");
70 inline bool operator()(
const OptTable::Info &
I, StringRef Name)
const {
85 : StrTable(&StrTable), PrefixesTable(PrefixesTable),
86 OptionInfos(OptionInfos), IgnoreCase(IgnoreCase),
87 SubCommands(SubCommands), SubCommandIDsTable(SubCommandIDsTable) {
93 unsigned Kind = getInfo(i + 1).Kind;
95 assert(!InputOptionID &&
"Cannot have multiple input options!");
96 InputOptionID = getInfo(i + 1).ID;
98 assert(!UnknownOptionID &&
"Cannot have multiple unknown options!");
99 UnknownOptionID = getInfo(i + 1).ID;
114 "Special options should be defined first!");
119 if (!(OptNameLess(StrTable, PrefixesTable)(getInfo(i), getInfo(i + 1)))) {
133 for (
char C : Prefix)
142 unsigned id = Opt.
getID();
144 return Option(
nullptr,
nullptr);
146 return Option(&getInfo(
id),
this);
153 if (
Arg.starts_with(Prefix))
163 StringRef Name =
I->getName(StrTable, PrefixesTable);
164 for (
auto PrefixOffset :
I->getPrefixOffsets(PrefixesTable)) {
165 StringRef Prefix = StrTable[PrefixOffset];
166 if (Str.starts_with(Prefix)) {
171 return Prefix.size() + Name.size();
181 StringRef Name = In.getName(StrTable, PrefixesTable);
182 if (
Option.consume_back(Name))
183 for (
auto PrefixOffset : In.getPrefixOffsets(PrefixesTable))
184 if (
Option == StrTable[PrefixOffset])
192std::vector<std::string>
196 const Info &In = OptionInfos[
I];
203 std::vector<std::string> Result;
205 if (Val.starts_with(
Arg) &&
Arg != Val)
206 Result.push_back(std::string(Val));
212std::vector<std::string>
214 unsigned int DisableFlags)
const {
215 std::vector<std::string> Ret;
217 const Info &In = OptionInfos[
I];
218 if (In.hasNoPrefix() || (!In.HelpText && !In.GroupID))
220 if (!(In.Visibility & VisibilityMask))
222 if (In.Flags & DisableFlags)
225 StringRef Name = In.getName(*StrTable, PrefixesTable);
226 for (
auto PrefixOffset : In.getPrefixOffsets(PrefixesTable)) {
227 StringRef Prefix = (*StrTable)[PrefixOffset];
228 std::string S = (
Twine(Prefix) + Name +
"\t").str();
240 unsigned MinimumLength,
241 unsigned MaximumDistance)
const {
242 return internalFindNearest(
243 Option, NearestString, MinimumLength, MaximumDistance,
244 [VisibilityMask](
const Info &CandidateInfo) {
245 return (CandidateInfo.
Visibility & VisibilityMask) == 0;
250 unsigned FlagsToInclude,
unsigned FlagsToExclude,
251 unsigned MinimumLength,
252 unsigned MaximumDistance)
const {
253 return internalFindNearest(
254 Option, NearestString, MinimumLength, MaximumDistance,
255 [FlagsToInclude, FlagsToExclude](
const Info &CandidateInfo) {
256 if (FlagsToInclude && !(CandidateInfo.
Flags & FlagsToInclude))
258 if (CandidateInfo.
Flags & FlagsToExclude)
264unsigned OptTable::internalFindNearest(
266 unsigned MaximumDistance,
267 std::function<
bool(
const Info &)> ExcludeOption)
const {
272 unsigned BestDistance =
273 MaximumDistance == UINT_MAX ? UINT_MAX : MaximumDistance + 1;
277 for (
const Info &CandidateInfo :
279 StringRef CandidateName = CandidateInfo.getName(*StrTable, PrefixesTable);
284 if (CandidateName.
size() < MinimumLength)
288 if (ExcludeOption(CandidateInfo))
293 if (CandidateInfo.hasNoPrefix())
300 bool CandidateHasDelimiter =
Last ==
'=' ||
Last ==
':';
302 if (CandidateHasDelimiter) {
303 std::tie(NormalizedName, RHS) =
Option.split(
Last);
305 NormalizedName +=
Last;
312 for (
auto CandidatePrefixOffset :
313 CandidateInfo.getPrefixOffsets(PrefixesTable)) {
314 StringRef CandidatePrefix = (*StrTable)[CandidatePrefixOffset];
319 size_t CandidateSize = CandidatePrefix.
size() + CandidateName.
size(),
320 NormalizedSize = NormalizedName.
size();
321 size_t AbsDiff = CandidateSize > NormalizedSize
322 ? CandidateSize - NormalizedSize
323 : NormalizedSize - CandidateSize;
324 if (AbsDiff > BestDistance) {
327 Candidate = CandidatePrefix;
328 Candidate += CandidateName;
330 NormalizedName,
true,
332 if (
RHS.empty() && CandidateHasDelimiter) {
341 if (Distance < BestDistance) {
342 BestDistance = Distance;
343 NearestString = (Candidate +
RHS).str();
354std::unique_ptr<Arg> OptTable::parseOneArgGrouped(
InputArgList &Args,
355 unsigned &Index)
const {
358 const char *CStr =
Args.getArgString(Index);
361 return std::make_unique<Arg>(
getOption(InputOptionID), Str, Index++, CStr);
363 const Info *End = OptionInfos.data() + OptionInfos.size();
367 OptNameLess(*StrTable, PrefixesTable));
369 unsigned Prev =
Index;
374 matchOption(*StrTable, PrefixesTable, Start, Str, IgnoreCase);
379 if (std::unique_ptr<Arg>
A =
380 Opt.accept(Args, StringRef(
Args.getArgString(Index), ArgSize),
398 return std::make_unique<Arg>(
getOption(UnknownOptionID), Str, Index++,
401 if (std::unique_ptr<Arg>
A = Opt.accept(
402 Args, Str.substr(0, 2),
true, Index)) {
403 Args.replaceArgString(Index, Twine(
'-') + Str.substr(2));
411 CStr =
Args.MakeArgString(Str.substr(0, 2));
412 Args.replaceArgString(Index, Twine(
'-') + Str.substr(2));
413 return std::make_unique<Arg>(
getOption(UnknownOptionID), CStr, Index, CStr);
416 return std::make_unique<Arg>(
getOption(UnknownOptionID), Str, Index++, CStr);
421 return internalParseOneArg(Args, Index, [VisibilityMask](
const Option &Opt) {
427 unsigned FlagsToInclude,
428 unsigned FlagsToExclude)
const {
429 return internalParseOneArg(
430 Args, Index, [FlagsToInclude, FlagsToExclude](
const Option &Opt) {
431 if (FlagsToInclude && !Opt.
hasFlag(FlagsToInclude))
433 if (Opt.
hasFlag(FlagsToExclude))
439std::unique_ptr<Arg> OptTable::internalParseOneArg(
440 const ArgList &Args,
unsigned &Index,
441 std::function<
bool(
const Option &)> ExcludeOption)
const {
442 unsigned Prev = Index;
443 StringRef Str = Args.getArgString(Index);
448 return std::make_unique<Arg>(
getOption(InputOptionID), Str, Index++,
452 const Info *End = OptionInfos.data() + OptionInfos.size();
457 std::lower_bound(Start, End, Name, OptNameLess(*StrTable, PrefixesTable));
467 for (; Start != End; ++Start) {
468 unsigned ArgSize = 0;
470 for (; Start != End; ++Start)
472 matchOption(*StrTable, PrefixesTable, Start, Str, IgnoreCase)))
479 if (ExcludeOption(Opt))
483 if (std::unique_ptr<Arg>
A =
484 Opt.accept(Args,
StringRef(Args.getArgString(Index), ArgSize),
496 return std::make_unique<Arg>(
getOption(InputOptionID), Str, Index++,
499 return std::make_unique<Arg>(
getOption(UnknownOptionID), Str, Index++,
504 unsigned &MissingArgIndex,
505 unsigned &MissingArgCount,
507 return internalParseArgs(
508 Args, MissingArgIndex, MissingArgCount,
509 [VisibilityMask](
const Option &Opt) {
515 unsigned &MissingArgIndex,
516 unsigned &MissingArgCount,
517 unsigned FlagsToInclude,
518 unsigned FlagsToExclude)
const {
519 return internalParseArgs(
520 Args, MissingArgIndex, MissingArgCount,
521 [FlagsToInclude, FlagsToExclude](
const Option &Opt) {
522 if (FlagsToInclude && !Opt.
hasFlag(FlagsToInclude))
524 if (Opt.
hasFlag(FlagsToExclude))
532 unsigned &MissingArgCount,
533 std::function<
bool(
const Option &)> ExcludeOption)
const {
538 MissingArgIndex = MissingArgCount = 0;
539 unsigned Index = 0, End = ArgArr.
size();
540 while (Index < End) {
542 if (Args.getArgString(Index) ==
nullptr) {
547 StringRef Str = Args.getArgString(Index);
555 if (DashDashParsing && Str ==
"--") {
556 while (++Index < End) {
557 Args.append(
new Arg(
getOption(InputOptionID), Str, Index,
558 Args.getArgString(Index)));
563 unsigned Prev =
Index;
564 std::unique_ptr<Arg>
A = GroupedShortOptions
565 ? parseOneArgGrouped(Args, Index)
566 : internalParseOneArg(
Args,
Index, ExcludeOption);
567 assert((Index > Prev || GroupedShortOptions) &&
568 "Parser failed to consume argument.");
572 assert(Index >= End &&
"Unexpected parser error.");
573 assert(Index - Prev - 1 &&
"No missing arguments!");
574 MissingArgIndex = Prev;
575 MissingArgCount =
Index - Prev - 1;
579 Args.append(
A.release());
587 std::function<
void(
StringRef)> ErrorFn)
const {
596 ErrorFn((
Twine(Args.getArgString(MAI)) +
": missing argument").str());
602 std::string
Spelling =
A->getAsString(Args);
604 ErrorFn(
"unknown argument '" +
Spelling +
"'");
606 ErrorFn(
"unknown argument '" +
Spelling +
"', did you mean '" + Nearest +
614 std::string Name = O.getPrefixedName().str();
617 switch (O.getKind()) {
629 for (
unsigned i=0, e=O.getNumArgs(); i< e; ++i) {
665 std::vector<OptionInfo> &OptionHelp) {
666 OS << Title <<
":\n";
669 unsigned OptionFieldWidth = 0;
670 for (
const OptionInfo &Opt : OptionHelp) {
672 unsigned Length = Opt.Name.size();
674 OptionFieldWidth = std::max(OptionFieldWidth,
Length);
677 const unsigned InitialPad = 2;
678 for (
const OptionInfo &Opt : OptionHelp) {
679 const std::string &
Option = Opt.Name;
680 int Pad = OptionFieldWidth + InitialPad;
681 int FirstLinePad = OptionFieldWidth - int(
Option.size());
685 if (FirstLinePad < 0) {
687 FirstLinePad = OptionFieldWidth + InitialPad;
692 Opt.HelpText.split(Lines,
'\n');
693 assert(Lines.size() &&
"Expected at least the first line in the help text");
694 auto *LinesIt = Lines.begin();
695 OS.
indent(FirstLinePad + 1) << *LinesIt <<
'\n';
696 while (Lines.end() != ++LinesIt)
697 OS.
indent(Pad + 1) << *LinesIt <<
'\n';
720 bool ShowHidden,
bool ShowAllAliases,
723 return internalPrintHelp(
724 OS, Usage, Title,
SubCommand, ShowHidden, ShowAllAliases,
725 [VisibilityMask](
const Info &CandidateInfo) ->
bool {
726 return (CandidateInfo.
Visibility & VisibilityMask) == 0;
732 unsigned FlagsToInclude,
unsigned FlagsToExclude,
733 bool ShowAllAliases)
const {
734 bool ShowHidden = !(FlagsToExclude &
HelpHidden);
736 return internalPrintHelp(
737 OS, Usage, Title, {}, ShowHidden, ShowAllAliases,
738 [FlagsToInclude, FlagsToExclude](
const Info &CandidateInfo) {
739 if (FlagsToInclude && !(CandidateInfo.Flags & FlagsToInclude))
741 if (CandidateInfo.Flags & FlagsToExclude)
748void OptTable::internalPrintHelp(
750 bool ShowHidden,
bool ShowAllAliases,
751 std::function<
bool(
const Info &)> ExcludeOption,
753 OS <<
"OVERVIEW: " << Title <<
"\n\n";
757 std::map<std::string, std::vector<OptionInfo>> GroupedOptionHelp;
759 auto ActiveSubCommand =
760 std::find_if(SubCommands.begin(), SubCommands.end(),
761 [&](
const auto &
C) { return SubCommand == C.Name; });
762 if (!SubCommand.
empty()) {
763 assert(ActiveSubCommand != SubCommands.end() &&
764 "Not a valid registered subcommand.");
765 OS << ActiveSubCommand->HelpText <<
"\n\n";
767 OS <<
"USAGE: " << ActiveSubCommand->Usage <<
"\n\n";
769 OS <<
"USAGE: " << Usage <<
"\n\n";
770 if (SubCommands.size() > 1) {
771 OS <<
"SUBCOMMANDS:\n\n";
772 for (
const auto &
C : SubCommands)
773 OS <<
C.Name <<
" - " <<
C.HelpText <<
"\n";
778 auto DoesOptionBelongToSubcommand = [&](
const Info &CandidateInfo) {
781 ArrayRef<unsigned> SubCommandIDs =
782 CandidateInfo.getSubCommandIDs(SubCommandIDsTable);
787 if (SubCommandIDs.
empty())
798 unsigned ActiveSubCommandID = ActiveSubCommand - &SubCommands[0];
801 return std::find(SubCommandIDs.
begin(), SubCommandIDs.
end(),
802 ActiveSubCommandID) != SubCommandIDs.
end();
810 const Info &CandidateInfo = getInfo(Id);
814 if (ExcludeOption(CandidateInfo))
817 if (!DoesOptionBelongToSubcommand(CandidateInfo))
823 if (!HelpText && ShowAllAliases) {
829 if (HelpText && (strlen(HelpText) != 0)) {
832 GroupedOptionHelp[HelpGroup].push_back({OptName, HelpText});
836 for (
auto& OptionGroup : GroupedOptionHelp) {
837 if (OptionGroup.first != GroupedOptionHelp.begin()->first)
850 :
OptTable(StrTable, PrefixesTable, OptionInfos, IgnoreCase, SubCommands,
851 SubCommandIDsTable) {
853 std::set<StringRef> TmpPrefixesUnion;
856 TmpPrefixesUnion.insert(StrTable[PrefixOffset]);
857 PrefixesUnion.append(TmpPrefixesUnion.begin(), TmpPrefixesUnion.end());
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Defines the llvm::Arg class for parsed arguments.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static const char * getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id)
static unsigned matchOption(const StringTable &StrTable, ArrayRef< StringTable::Offset > PrefixesTable, const OptTable::Info *I, StringRef Str, bool IgnoreCase)
static bool optionMatches(const StringTable &StrTable, ArrayRef< StringTable::Offset > PrefixesTable, const OptTable::Info &In, StringRef Option)
static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id)
static bool isInput(const ArrayRef< StringRef > &Prefixes, StringRef Arg)
static void PrintHelpOptionList(raw_ostream &OS, StringRef Title, std::vector< OptionInfo > &OptionHelp)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
LLVM_ABI bool starts_with_insensitive(StringRef Prefix) const
Check if this string starts with the given Prefix, ignoring case.
LLVM_ABI unsigned edit_distance(StringRef Other, bool AllowReplacements=true, unsigned MaxEditDistance=0) const
Determine the edit distance between this string and another string.
char back() const
back - Get the last character in the string.
constexpr size_t size() const
size - Get the string size.
Saves strings in the provided stable storage and returns a StringRef with a stable character pointer.
A table of densely packed, null-terminated strings indexed by offset.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
ArgList - Ordered collection of driver arguments.
A concrete instance of a particular driver option.
LLVM_ABI GenericOptTable(const StringTable &StrTable, ArrayRef< StringTable::Offset > PrefixesTable, ArrayRef< Info > OptionInfos, bool IgnoreCase=false, ArrayRef< SubCommand > SubCommands={}, ArrayRef< unsigned > SubCommandIDsTable={})
OptSpecifier - Wrapper class for abstracting references to option IDs.
Provide access to the Option info table.
void buildPrefixChars()
Build (or rebuild) the PrefixChars member.
InputArgList parseArgs(int Argc, char *const *Argv, OptSpecifier Unknown, StringSaver &Saver, std::function< void(StringRef)> ErrorFn) const
A convenience helper which handles optional initial options populated from an environment variable,...
unsigned getOptionKind(OptSpecifier id) const
Get the kind of the given option.
unsigned FirstSearchableIndex
The index of the first option which can be parsed (i.e., is not a special option like 'input' or 'unk...
const char * getOptionMetaVar(OptSpecifier id) const
Get the meta-variable name to use when describing this options values in the help text.
std::unique_ptr< Arg > ParseOneArg(const ArgList &Args, unsigned &Index, Visibility VisibilityMask=Visibility()) const
Parse a single argument; returning the new argument and updating Index.
unsigned findNearest(StringRef Option, std::string &NearestString, Visibility VisibilityMask=Visibility(), unsigned MinimumLength=4, unsigned MaximumDistance=UINT_MAX) const
Find the OptTable option that most closely matches the given string.
SmallVector< StringRef > PrefixesUnion
The union of all option prefixes.
const Option getOption(OptSpecifier Opt) const
Get the given Opt's Option instance, lazily creating it if necessary.
const char * getOptionHelpText(OptSpecifier id) const
Get the help text to use to describe this option.
OptTable(const StringTable &StrTable, ArrayRef< StringTable::Offset > PrefixesTable, ArrayRef< Info > OptionInfos, bool IgnoreCase=false, ArrayRef< SubCommand > SubCommands={}, ArrayRef< unsigned > SubCommandIDsTable={})
Initialize OptTable using Tablegen'ed OptionInfos.
unsigned getOptionGroupID(OptSpecifier id) const
Get the group id for the given option.
std::vector< std::string > suggestValueCompletions(StringRef Option, StringRef Arg) const
Find possible value for given flags.
InputArgList ParseArgs(ArrayRef< const char * > Args, unsigned &MissingArgIndex, unsigned &MissingArgCount, Visibility VisibilityMask=Visibility()) const
Parse an list of arguments into an InputArgList.
SmallString< 8 > PrefixChars
The union of the first element of all option prefixes.
void printHelp(raw_ostream &OS, const char *Usage, const char *Title, bool ShowHidden=false, bool ShowAllAliases=false, Visibility VisibilityMask=Visibility(), StringRef SubCommand={}) const
Render the help text for an option table.
unsigned getNumOptions() const
Return the total number of option classes.
std::vector< std::string > findByPrefix(StringRef Cur, Visibility VisibilityMask, unsigned int DisableFlags) const
Find flags from OptTable which starts with Cur.
Option - Abstract representation for a single form of driver argument.
const Option getAlias() const
LLVM_ABI void dump() const
bool hasFlag(unsigned Val) const
Test if this option has the flag Val.
@ RemainingArgsJoinedClass
bool hasVisibilityFlag(unsigned Val) const
Test if this option has the visibility flag Val.
Helper for overload resolution while transitioning from FlagsToInclude/FlagsToExclude APIs to Visibil...
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI bool expandResponseFiles(int Argc, const char *const *Argv, const char *EnvVar, SmallVectorImpl< const char * > &NewArgv)
A convenience helper which concatenates the options specified by the environment variable EnvVar and ...
This is an optimization pass for GlobalISel generic memory operations.
int StrCmpOptionName(StringRef A, StringRef B, bool FallbackCaseSensitive=true)
int StrCmpOptionPrefixes(ArrayRef< StringRef > APrefixes, ArrayRef< StringRef > BPrefixes)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
ArrayRef(const T &OneElt) -> ArrayRef< T >
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Entry for a single option instance in the option data table.
ArrayRef< StringTable::Offset > getPrefixOffsets(ArrayRef< StringTable::Offset > PrefixesTable) const
Represents a subcommand and its options in the option table.