LLVM  4.0.0
OptTable.cpp
Go to the documentation of this file.
1 //===--- OptTable.cpp - Option Table Implementation -----------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/Option/OptTable.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/Option/Arg.h"
13 #include "llvm/Option/ArgList.h"
14 #include "llvm/Option/Option.h"
17 #include <algorithm>
18 #include <cctype>
19 #include <map>
20 
21 using namespace llvm;
22 using namespace llvm::opt;
23 
24 namespace llvm {
25 namespace opt {
26 
27 // Ordering on Info. The ordering is *almost* case-insensitive lexicographic,
28 // with an exceptions. '\0' comes at the end of the alphabet instead of the
29 // beginning (thus options precede any other options which prefix them).
30 static int StrCmpOptionNameIgnoreCase(const char *A, const char *B) {
31  const char *X = A, *Y = B;
32  char a = tolower(*A), b = tolower(*B);
33  while (a == b) {
34  if (a == '\0')
35  return 0;
36 
37  a = tolower(*++X);
38  b = tolower(*++Y);
39  }
40 
41  if (a == '\0') // A is a prefix of B.
42  return 1;
43  if (b == '\0') // B is a prefix of A.
44  return -1;
45 
46  // Otherwise lexicographic.
47  return (a < b) ? -1 : 1;
48 }
49 
50 #ifndef NDEBUG
51 static int StrCmpOptionName(const char *A, const char *B) {
52  if (int N = StrCmpOptionNameIgnoreCase(A, B))
53  return N;
54  return strcmp(A, B);
55 }
56 
57 static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
58  if (&A == &B)
59  return false;
60 
61  if (int N = StrCmpOptionName(A.Name, B.Name))
62  return N < 0;
63 
64  for (const char * const *APre = A.Prefixes,
65  * const *BPre = B.Prefixes;
66  *APre != nullptr && *BPre != nullptr; ++APre, ++BPre){
67  if (int N = StrCmpOptionName(*APre, *BPre))
68  return N < 0;
69  }
70 
71  // Names are the same, check that classes are in order; exactly one
72  // should be joined, and it should succeed the other.
74  "Unexpected classes for options with same name.");
75  return B.Kind == Option::JoinedClass;
76 }
77 #endif
78 
79 // Support lower_bound between info and an option name.
80 static inline bool operator<(const OptTable::Info &I, const char *Name) {
81  return StrCmpOptionNameIgnoreCase(I.Name, Name) < 0;
82 }
83 }
84 }
85 
86 OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
87 
88 OptTable::OptTable(ArrayRef<Info> OptionInfos, bool IgnoreCase)
89  : OptionInfos(OptionInfos), IgnoreCase(IgnoreCase), TheInputOptionID(0),
90  TheUnknownOptionID(0), FirstSearchableIndex(0) {
91  // Explicitly zero initialize the error to work around a bug in array
92  // value-initialization on MinGW with gcc 4.3.5.
93 
94  // Find start of normal options.
95  for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
96  unsigned Kind = getInfo(i + 1).Kind;
97  if (Kind == Option::InputClass) {
98  assert(!TheInputOptionID && "Cannot have multiple input options!");
99  TheInputOptionID = getInfo(i + 1).ID;
100  } else if (Kind == Option::UnknownClass) {
101  assert(!TheUnknownOptionID && "Cannot have multiple unknown options!");
102  TheUnknownOptionID = getInfo(i + 1).ID;
103  } else if (Kind != Option::GroupClass) {
104  FirstSearchableIndex = i;
105  break;
106  }
107  }
108  assert(FirstSearchableIndex != 0 && "No searchable options?");
109 
110 #ifndef NDEBUG
111  // Check that everything after the first searchable option is a
112  // regular option class.
113  for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) {
115  assert((Kind != Option::InputClass && Kind != Option::UnknownClass &&
116  Kind != Option::GroupClass) &&
117  "Special options should be defined first!");
118  }
119 
120  // Check that options are in order.
121  for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions(); i != e; ++i){
122  if (!(getInfo(i) < getInfo(i + 1))) {
123  getOption(i).dump();
124  getOption(i + 1).dump();
125  llvm_unreachable("Options are not in order!");
126  }
127  }
128 #endif
129 
130  // Build prefixes.
131  for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions() + 1;
132  i != e; ++i) {
133  if (const char *const *P = getInfo(i).Prefixes) {
134  for (; *P != nullptr; ++P) {
135  PrefixesUnion.insert(*P);
136  }
137  }
138  }
139 
140  // Build prefix chars.
141  for (llvm::StringSet<>::const_iterator I = PrefixesUnion.begin(),
142  E = PrefixesUnion.end(); I != E; ++I) {
143  StringRef Prefix = I->getKey();
144  for (StringRef::const_iterator C = Prefix.begin(), CE = Prefix.end();
145  C != CE; ++C)
146  if (!is_contained(PrefixChars, *C))
147  PrefixChars.push_back(*C);
148  }
149 }
150 
152 }
153 
155  unsigned id = Opt.getID();
156  if (id == 0)
157  return Option(nullptr, nullptr);
158  assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID.");
159  return Option(&getInfo(id), this);
160 }
161 
162 static bool isInput(const llvm::StringSet<> &Prefixes, StringRef Arg) {
163  if (Arg == "-")
164  return true;
165  for (llvm::StringSet<>::const_iterator I = Prefixes.begin(),
166  E = Prefixes.end(); I != E; ++I)
167  if (Arg.startswith(I->getKey()))
168  return false;
169  return true;
170 }
171 
172 /// \returns Matched size. 0 means no match.
173 static unsigned matchOption(const OptTable::Info *I, StringRef Str,
174  bool IgnoreCase) {
175  for (const char * const *Pre = I->Prefixes; *Pre != nullptr; ++Pre) {
176  StringRef Prefix(*Pre);
177  if (Str.startswith(Prefix)) {
178  StringRef Rest = Str.substr(Prefix.size());
179  bool Matched = IgnoreCase
180  ? Rest.startswith_lower(I->Name)
181  : Rest.startswith(I->Name);
182  if (Matched)
183  return Prefix.size() + StringRef(I->Name).size();
184  }
185  }
186  return 0;
187 }
188 
189 Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
190  unsigned FlagsToInclude,
191  unsigned FlagsToExclude) const {
192  unsigned Prev = Index;
193  const char *Str = Args.getArgString(Index);
194 
195  // Anything that doesn't start with PrefixesUnion is an input, as is '-'
196  // itself.
197  if (isInput(PrefixesUnion, Str))
198  return new Arg(getOption(TheInputOptionID), Str, Index++, Str);
199 
200  const Info *Start = OptionInfos.begin() + FirstSearchableIndex;
201  const Info *End = OptionInfos.end();
202  StringRef Name = StringRef(Str).ltrim(PrefixChars);
203 
204  // Search for the first next option which could be a prefix.
205  Start = std::lower_bound(Start, End, Name.data());
206 
207  // Options are stored in sorted order, with '\0' at the end of the
208  // alphabet. Since the only options which can accept a string must
209  // prefix it, we iteratively search for the next option which could
210  // be a prefix.
211  //
212  // FIXME: This is searching much more than necessary, but I am
213  // blanking on the simplest way to make it fast. We can solve this
214  // problem when we move to TableGen.
215  for (; Start != End; ++Start) {
216  unsigned ArgSize = 0;
217  // Scan for first option which is a proper prefix.
218  for (; Start != End; ++Start)
219  if ((ArgSize = matchOption(Start, Str, IgnoreCase)))
220  break;
221  if (Start == End)
222  break;
223 
224  Option Opt(Start, this);
225 
226  if (FlagsToInclude && !Opt.hasFlag(FlagsToInclude))
227  continue;
228  if (Opt.hasFlag(FlagsToExclude))
229  continue;
230 
231  // See if this option matches.
232  if (Arg *A = Opt.accept(Args, Index, ArgSize))
233  return A;
234 
235  // Otherwise, see if this argument was missing values.
236  if (Prev != Index)
237  return nullptr;
238  }
239 
240  // If we failed to find an option and this arg started with /, then it's
241  // probably an input path.
242  if (Str[0] == '/')
243  return new Arg(getOption(TheInputOptionID), Str, Index++, Str);
244 
245  return new Arg(getOption(TheUnknownOptionID), Str, Index++, Str);
246 }
247 
249  unsigned &MissingArgIndex,
250  unsigned &MissingArgCount,
251  unsigned FlagsToInclude,
252  unsigned FlagsToExclude) const {
253  InputArgList Args(ArgArr.begin(), ArgArr.end());
254 
255  // FIXME: Handle '@' args (or at least error on them).
256 
257  MissingArgIndex = MissingArgCount = 0;
258  unsigned Index = 0, End = ArgArr.size();
259  while (Index < End) {
260  // Ingore nullptrs, they are response file's EOL markers
261  if (Args.getArgString(Index) == nullptr) {
262  ++Index;
263  continue;
264  }
265  // Ignore empty arguments (other things may still take them as arguments).
266  StringRef Str = Args.getArgString(Index);
267  if (Str == "") {
268  ++Index;
269  continue;
270  }
271 
272  unsigned Prev = Index;
273  Arg *A = ParseOneArg(Args, Index, FlagsToInclude, FlagsToExclude);
274  assert(Index > Prev && "Parser failed to consume argument.");
275 
276  // Check for missing argument error.
277  if (!A) {
278  assert(Index >= End && "Unexpected parser error.");
279  assert(Index - Prev - 1 && "No missing arguments!");
280  MissingArgIndex = Prev;
281  MissingArgCount = Index - Prev - 1;
282  break;
283  }
284 
285  Args.append(A);
286  }
287 
288  return Args;
289 }
290 
291 static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
292  const Option O = Opts.getOption(Id);
293  std::string Name = O.getPrefixedName();
294 
295  // Add metavar, if used.
296  switch (O.getKind()) {
298  llvm_unreachable("Invalid option with help text.");
299 
301  if (const char *MetaVarName = Opts.getOptionMetaVar(Id)) {
302  // For MultiArgs, metavar is full list of all argument names.
303  Name += ' ';
304  Name += MetaVarName;
305  }
306  else {
307  // For MultiArgs<N>, if metavar not supplied, print <value> N times.
308  for (unsigned i=0, e=O.getNumArgs(); i< e; ++i) {
309  Name += " <value>";
310  }
311  }
312  break;
313 
314  case Option::FlagClass:
315  break;
316 
319  Name += ' ';
323  if (const char *MetaVarName = Opts.getOptionMetaVar(Id))
324  Name += MetaVarName;
325  else
326  Name += "<value>";
327  break;
328  }
329 
330  return Name;
331 }
332 
334  std::vector<std::pair<std::string,
335  const char*> > &OptionHelp) {
336  OS << Title << ":\n";
337 
338  // Find the maximum option length.
339  unsigned OptionFieldWidth = 0;
340  for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
341  // Skip titles.
342  if (!OptionHelp[i].second)
343  continue;
344 
345  // Limit the amount of padding we are willing to give up for alignment.
346  unsigned Length = OptionHelp[i].first.size();
347  if (Length <= 23)
348  OptionFieldWidth = std::max(OptionFieldWidth, Length);
349  }
350 
351  const unsigned InitialPad = 2;
352  for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
353  const std::string &Option = OptionHelp[i].first;
354  int Pad = OptionFieldWidth - int(Option.size());
355  OS.indent(InitialPad) << Option;
356 
357  // Break on long option names.
358  if (Pad < 0) {
359  OS << "\n";
360  Pad = OptionFieldWidth + InitialPad;
361  }
362  OS.indent(Pad + 1) << OptionHelp[i].second << '\n';
363  }
364 }
365 
366 static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) {
367  unsigned GroupID = Opts.getOptionGroupID(Id);
368 
369  // If not in a group, return the default help group.
370  if (!GroupID)
371  return "OPTIONS";
372 
373  // Abuse the help text of the option groups to store the "help group"
374  // name.
375  //
376  // FIXME: Split out option groups.
377  if (const char *GroupHelp = Opts.getOptionHelpText(GroupID))
378  return GroupHelp;
379 
380  // Otherwise keep looking.
381  return getOptionHelpGroup(Opts, GroupID);
382 }
383 
384 void OptTable::PrintHelp(raw_ostream &OS, const char *Name, const char *Title,
385  bool ShowHidden) const {
386  PrintHelp(OS, Name, Title, /*Include*/ 0, /*Exclude*/
387  (ShowHidden ? 0 : HelpHidden));
388 }
389 
390 
391 void OptTable::PrintHelp(raw_ostream &OS, const char *Name, const char *Title,
392  unsigned FlagsToInclude,
393  unsigned FlagsToExclude) const {
394  OS << "OVERVIEW: " << Title << "\n";
395  OS << '\n';
396  OS << "USAGE: " << Name << " [options] <inputs>\n";
397  OS << '\n';
398 
399  // Render help text into a map of group-name to a list of (option, help)
400  // pairs.
401  typedef std::map<std::string,
402  std::vector<std::pair<std::string, const char*> > > helpmap_ty;
403  helpmap_ty GroupedOptionHelp;
404 
405  for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
406  unsigned Id = i + 1;
407 
408  // FIXME: Split out option groups.
410  continue;
411 
412  unsigned Flags = getInfo(Id).Flags;
413  if (FlagsToInclude && !(Flags & FlagsToInclude))
414  continue;
415  if (Flags & FlagsToExclude)
416  continue;
417 
418  if (const char *Text = getOptionHelpText(Id)) {
419  const char *HelpGroup = getOptionHelpGroup(*this, Id);
420  const std::string &OptName = getOptionHelpName(*this, Id);
421  GroupedOptionHelp[HelpGroup].push_back(std::make_pair(OptName, Text));
422  }
423  }
424 
425  for (helpmap_ty::iterator it = GroupedOptionHelp .begin(),
426  ie = GroupedOptionHelp.end(); it != ie; ++it) {
427  if (it != GroupedOptionHelp .begin())
428  OS << "\n";
429  PrintHelpOptionList(OS, it->first, it->second);
430  }
431 
432  OS.flush();
433 }
void dump() const
Definition: Option.cpp:86
unsigned short Flags
Definition: OptTable.h:45
size_t i
static bool operator<(const OptTable::Info &A, const OptTable::Info &B)
Definition: OptTable.cpp:57
iterator end() const
Definition: ArrayRef.h:130
bool hasFlag(unsigned Val) const
Test if this option has the flag Val.
Definition: Option.h:161
static unsigned matchOption(const OptTable::Info *I, StringRef Str, bool IgnoreCase)
Definition: OptTable.cpp:173
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
const_iterator begin(StringRef path)
Get begin iterator over path.
Definition: Path.cpp:233
InputArgList ParseArgs(ArrayRef< const char * > Args, unsigned &MissingArgIndex, unsigned &MissingArgCount, unsigned FlagsToInclude=0, unsigned FlagsToExclude=0) const
Parse an list of arguments into an InputArgList.
Definition: OptTable.cpp:248
OptionClass getKind() const
Definition: Option.h:84
Maximum length of the test input libFuzzer tries to guess a good value based on the corpus and reports it always prefer smaller inputs during the corpus shuffle When libFuzzer itself reports a bug this exit code will be used If indicates the maximal total time in seconds to run the fuzzer minimizes the provided crash input Use with strcmp
static bool isInput(const llvm::StringSet<> &Prefixes, StringRef Arg)
Definition: OptTable.cpp:162
struct fuzzer::@269 Flags
const char * getOptionHelpText(OptSpecifier id) const
Get the help text to use to describe this option.
Definition: OptTable.h:106
static int getID(struct InternalInstruction *insn, const void *miiArg)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:264
unsigned char Kind
Definition: OptTable.h:43
unsigned getNumArgs() const
Definition: Option.h:130
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
OptTable(ArrayRef< Info > OptionInfos, bool IgnoreCase=false)
Definition: OptTable.cpp:88
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:135
static const char * getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id)
Definition: OptTable.cpp:366
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:141
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
iterator begin() const
Definition: StringRef.h:103
#define P(N)
friend const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:241
Option - Abstract representation for a single form of driver argument.
Definition: Option.h:44
A concrete instance of a particular driver option.
Definition: Arg.h:31
Provide access to the Option info table.
Definition: OptTable.h:32
std::string getPrefixedName() const
Get the name of this option with the default prefix.
Definition: Option.h:124
const char *const * Prefixes
A null terminated array of prefix strings to apply to name while matching.
Definition: OptTable.h:38
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:587
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
static const unsigned End
iterator begin() const
Definition: ArrayRef.h:129
static int StrCmpOptionName(const char *A, const char *B)
Definition: OptTable.cpp:51
unsigned getID() const
Definition: OptSpecifier.h:33
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::pair< typename base::iterator, bool > insert(StringRef Key)
Definition: StringSet.h:32
const char * const_iterator
Definition: StringRef.h:50
virtual const char * getArgString(unsigned Index) const =0
getArgString - Return the input argument string at Index.
static int StrCmpOptionNameIgnoreCase(const char *A, const char *B)
Definition: OptTable.cpp:30
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
void PrintHelp(raw_ostream &OS, const char *Name, const char *Title, unsigned FlagsToInclude, unsigned FlagsToExclude) const
Render the help text for an option table.
Definition: OptTable.cpp:391
unsigned getNumOptions() const
Return the total number of option classes.
Definition: OptTable.h:82
Defines the llvm::Arg class for parsed arguments.
unsigned getOptionKind(OptSpecifier id) const
Get the kind of the given option.
Definition: OptTable.h:96
OptSpecifier - Wrapper class for abstracting references to option IDs.
Definition: OptSpecifier.h:20
iterator begin()
Definition: StringMap.h:302
const Option getOption(OptSpecifier Opt) const
Get the given Opt's Option instance, lazily creating it if necessary.
Definition: OptTable.cpp:154
Entry for a single option instance in the option data table.
Definition: OptTable.h:35
#define I(x, y, z)
Definition: MD5.cpp:54
#define N
LLVM_NODISCARD StringRef ltrim(char Char) const
Return string with consecutive Char characters starting from the the left removed.
Definition: StringRef.h:797
Arg * ParseOneArg(const ArgList &Args, unsigned &Index, unsigned FlagsToInclude=0, unsigned FlagsToExclude=0) const
Parse a single argument; returning the new argument and updating Index.
Definition: OptTable.cpp:189
static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id)
Definition: OptTable.cpp:291
const unsigned Kind
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static void PrintHelpOptionList(raw_ostream &OS, StringRef Title, std::vector< std::pair< std::string, const char * > > &OptionHelp)
Definition: OptTable.cpp:333
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition: Compiler.h:239
StringSet - A wrapper for StringMap that provides set-like functionality.
Definition: StringSet.h:23
iterator end() const
Definition: StringRef.h:105
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:44
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:125
Arg * accept(const ArgList &Args, unsigned &Index, unsigned ArgSize) const
accept - Potentially accept the current argument, returning a new Arg instance, or 0 if the option do...
Definition: Option.cpp:104
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
ArgList - Ordered collection of driver arguments.
Definition: ArgList.h:94
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml","ocaml 3.10-compatible collector")
unsigned getOptionGroupID(OptSpecifier id) const
Get the group id for the given option.
Definition: OptTable.h:101
LLVM_NODISCARD bool startswith_lower(StringRef Prefix) const
Check if this string starts with the given Prefix, ignoring case.
Definition: StringRef.cpp:61
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
iterator end()
Definition: StringMap.h:305
const char * getOptionMetaVar(OptSpecifier id) const
Get the meta-variable name to use when describing this options values in the help text...
Definition: OptTable.h:112
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
Definition: STLExtras.h:783