1 //===- OptTable.h - Option Table --------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_OPTION_OPTTABLE_H 10 #define LLVM_OPTION_OPTTABLE_H 11 12 #include "llvm/ADT/ArrayRef.h" 13 #include "llvm/ADT/SmallString.h" 14 #include "llvm/ADT/StringRef.h" 15 #include "llvm/ADT/StringTable.h" 16 #include "llvm/Option/OptSpecifier.h" 17 #include "llvm/Support/StringSaver.h" 18 #include <cassert> 19 #include <string> 20 #include <vector> 21 22 namespace llvm { 23 24 class raw_ostream; 25 template <typename Fn> class function_ref; 26 27 namespace opt { 28 29 class Arg; 30 class ArgList; 31 class InputArgList; 32 class Option; 33 34 /// Helper for overload resolution while transitioning from 35 /// FlagsToInclude/FlagsToExclude APIs to VisibilityMask APIs. 36 class Visibility { 37 unsigned Mask = ~0U; 38 39 public: 40 explicit Visibility(unsigned Mask) : Mask(Mask) {} 41 Visibility() = default; 42 43 operator unsigned() const { return Mask; } 44 }; 45 46 /// Provide access to the Option info table. 47 /// 48 /// The OptTable class provides a layer of indirection which allows Option 49 /// instance to be created lazily. In the common case, only a few options will 50 /// be needed at runtime; the OptTable class maintains enough information to 51 /// parse command lines without instantiating Options, while letting other 52 /// parts of the driver still use Option instances where convenient. 53 class OptTable { 54 public: 55 /// Entry for a single option instance in the option data table. 56 struct Info { 57 unsigned PrefixesOffset; 58 StringTable::Offset PrefixedNameOffset; 59 const char *HelpText; 60 // Help text for specific visibilities. A list of pairs, where each pair 61 // is a list of visibilities and a specific help string for those 62 // visibilities. If no help text is found in this list for the visibility of 63 // the program, HelpText is used instead. This cannot use std::vector 64 // because OptTable is used in constexpr contexts. Increase the array sizes 65 // here if you need more entries and adjust the constants in 66 // OptionParserEmitter::EmitHelpTextsForVariants. 67 std::array<std::pair<std::array<unsigned int, 2 /*MaxVisibilityPerHelp*/>, 68 const char *>, 69 1 /*MaxVisibilityHelp*/> 70 HelpTextsForVariants; 71 const char *MetaVar; 72 unsigned ID; 73 unsigned char Kind; 74 unsigned char Param; 75 unsigned int Flags; 76 unsigned int Visibility; 77 unsigned short GroupID; 78 unsigned short AliasID; 79 const char *AliasArgs; 80 const char *Values; 81 82 bool hasNoPrefix() const { return PrefixesOffset == 0; } 83 84 unsigned getNumPrefixes(ArrayRef<StringTable::Offset> PrefixesTable) const { 85 // We embed the number of prefixes in the value of the first offset. 86 return PrefixesTable[PrefixesOffset].value(); 87 } 88 89 ArrayRef<StringTable::Offset> 90 getPrefixOffsets(ArrayRef<StringTable::Offset> PrefixesTable) const { 91 return hasNoPrefix() ? ArrayRef<StringTable::Offset>() 92 : PrefixesTable.slice(PrefixesOffset + 1, 93 getNumPrefixes(PrefixesTable)); 94 } 95 96 void appendPrefixes(const StringTable &StrTable, 97 ArrayRef<StringTable::Offset> PrefixesTable, 98 SmallVectorImpl<StringRef> &Prefixes) const { 99 for (auto PrefixOffset : getPrefixOffsets(PrefixesTable)) 100 Prefixes.push_back(StrTable[PrefixOffset]); 101 } 102 103 StringRef getPrefix(const StringTable &StrTable, 104 ArrayRef<StringTable::Offset> PrefixesTable, 105 unsigned PrefixIndex) const { 106 return StrTable[getPrefixOffsets(PrefixesTable)[PrefixIndex]]; 107 } 108 109 StringRef getPrefixedName(const StringTable &StrTable) const { 110 return StrTable[PrefixedNameOffset]; 111 } 112 113 StringRef getName(const StringTable &StrTable, 114 ArrayRef<StringTable::Offset> PrefixesTable) const { 115 unsigned PrefixLength = 116 hasNoPrefix() ? 0 : getPrefix(StrTable, PrefixesTable, 0).size(); 117 return getPrefixedName(StrTable).drop_front(PrefixLength); 118 } 119 }; 120 121 private: 122 // A unified string table for these options. Individual strings are stored as 123 // null terminated C-strings at offsets within this table. 124 const StringTable *StrTable; 125 126 // A table of different sets of prefixes. Each set starts with the number of 127 // prefixes in that set followed by that many offsets into the string table 128 // for each of the prefix strings. This is essentially a Pascal-string style 129 // encoding. 130 ArrayRef<StringTable::Offset> PrefixesTable; 131 132 /// The option information table. 133 ArrayRef<Info> OptionInfos; 134 135 bool IgnoreCase; 136 bool GroupedShortOptions = false; 137 bool DashDashParsing = false; 138 const char *EnvVar = nullptr; 139 140 unsigned InputOptionID = 0; 141 unsigned UnknownOptionID = 0; 142 143 protected: 144 /// The index of the first option which can be parsed (i.e., is not a 145 /// special option like 'input' or 'unknown', and is not an option group). 146 unsigned FirstSearchableIndex = 0; 147 148 /// The union of all option prefixes. If an argument does not begin with 149 /// one of these, it is an input. 150 SmallVector<StringRef> PrefixesUnion; 151 152 /// The union of the first element of all option prefixes. 153 SmallString<8> PrefixChars; 154 155 private: 156 const Info &getInfo(OptSpecifier Opt) const { 157 unsigned id = Opt.getID(); 158 assert(id > 0 && id - 1 < getNumOptions() && "Invalid Option ID."); 159 return OptionInfos[id - 1]; 160 } 161 162 std::unique_ptr<Arg> parseOneArgGrouped(InputArgList &Args, 163 unsigned &Index) const; 164 165 protected: 166 /// Initialize OptTable using Tablegen'ed OptionInfos. Child class must 167 /// manually call \c buildPrefixChars once they are fully constructed. 168 OptTable(const StringTable &StrTable, 169 ArrayRef<StringTable::Offset> PrefixesTable, 170 ArrayRef<Info> OptionInfos, bool IgnoreCase = false); 171 172 /// Build (or rebuild) the PrefixChars member. 173 void buildPrefixChars(); 174 175 public: 176 virtual ~OptTable(); 177 178 /// Return the string table used for option names. 179 const StringTable &getStrTable() const { return *StrTable; } 180 181 /// Return the prefixes table used for option names. 182 ArrayRef<StringTable::Offset> getPrefixesTable() const { 183 return PrefixesTable; 184 } 185 186 /// Return the total number of option classes. 187 unsigned getNumOptions() const { return OptionInfos.size(); } 188 189 /// Get the given Opt's Option instance, lazily creating it 190 /// if necessary. 191 /// 192 /// \return The option, or null for the INVALID option id. 193 const Option getOption(OptSpecifier Opt) const; 194 195 /// Lookup the name of the given option. 196 StringRef getOptionName(OptSpecifier id) const { 197 return getInfo(id).getName(*StrTable, PrefixesTable); 198 } 199 200 /// Lookup the prefix of the given option. 201 StringRef getOptionPrefix(OptSpecifier id) const { 202 const Info &I = getInfo(id); 203 return I.hasNoPrefix() ? StringRef() 204 : I.getPrefix(*StrTable, PrefixesTable, 0); 205 } 206 207 void appendOptionPrefixes(OptSpecifier id, 208 SmallVectorImpl<StringRef> &Prefixes) const { 209 const Info &I = getInfo(id); 210 I.appendPrefixes(*StrTable, PrefixesTable, Prefixes); 211 } 212 213 /// Lookup the prefixed name of the given option. 214 StringRef getOptionPrefixedName(OptSpecifier id) const { 215 return getInfo(id).getPrefixedName(*StrTable); 216 } 217 218 /// Get the kind of the given option. 219 unsigned getOptionKind(OptSpecifier id) const { 220 return getInfo(id).Kind; 221 } 222 223 /// Get the group id for the given option. 224 unsigned getOptionGroupID(OptSpecifier id) const { 225 return getInfo(id).GroupID; 226 } 227 228 /// Get the help text to use to describe this option. 229 const char *getOptionHelpText(OptSpecifier id) const { 230 return getOptionHelpText(id, Visibility(0)); 231 } 232 233 // Get the help text to use to describe this option. 234 // If it has visibility specific help text and that visibility is in the 235 // visibility mask, use that text instead of the generic text. 236 const char *getOptionHelpText(OptSpecifier id, 237 Visibility VisibilityMask) const { 238 auto Info = getInfo(id); 239 for (auto [Visibilities, Text] : Info.HelpTextsForVariants) 240 for (auto Visibility : Visibilities) 241 if (VisibilityMask & Visibility) 242 return Text; 243 return Info.HelpText; 244 } 245 246 /// Get the meta-variable name to use when describing 247 /// this options values in the help text. 248 const char *getOptionMetaVar(OptSpecifier id) const { 249 return getInfo(id).MetaVar; 250 } 251 252 /// Specify the environment variable where initial options should be read. 253 void setInitialOptionsFromEnvironment(const char *E) { EnvVar = E; } 254 255 /// Support grouped short options. e.g. -ab represents -a -b. 256 void setGroupedShortOptions(bool Value) { GroupedShortOptions = Value; } 257 258 /// Set whether "--" stops option parsing and treats all subsequent arguments 259 /// as positional. E.g. -- -a -b gives two positional inputs. 260 void setDashDashParsing(bool Value) { DashDashParsing = Value; } 261 262 /// Find possible value for given flags. This is used for shell 263 /// autocompletion. 264 /// 265 /// \param [in] Option - Key flag like "-stdlib=" when "-stdlib=l" 266 /// was passed to clang. 267 /// 268 /// \param [in] Arg - Value which we want to autocomplete like "l" 269 /// when "-stdlib=l" was passed to clang. 270 /// 271 /// \return The vector of possible values. 272 std::vector<std::string> suggestValueCompletions(StringRef Option, 273 StringRef Arg) const; 274 275 /// Find flags from OptTable which starts with Cur. 276 /// 277 /// \param [in] Cur - String prefix that all returned flags need 278 // to start with. 279 /// 280 /// \return The vector of flags which start with Cur. 281 std::vector<std::string> findByPrefix(StringRef Cur, 282 Visibility VisibilityMask, 283 unsigned int DisableFlags) const; 284 285 /// Find the OptTable option that most closely matches the given string. 286 /// 287 /// \param [in] Option - A string, such as "-stdlibs=l", that represents user 288 /// input of an option that may not exist in the OptTable. Note that the 289 /// string includes prefix dashes "-" as well as values "=l". 290 /// \param [out] NearestString - The nearest option string found in the 291 /// OptTable. 292 /// \param [in] VisibilityMask - Only include options with any of these 293 /// visibility flags set. 294 /// \param [in] MinimumLength - Don't find options shorter than this length. 295 /// For example, a minimum length of 3 prevents "-x" from being considered 296 /// near to "-S". 297 /// \param [in] MaximumDistance - Don't find options whose distance is greater 298 /// than this value. 299 /// 300 /// \return The edit distance of the nearest string found. 301 unsigned findNearest(StringRef Option, std::string &NearestString, 302 Visibility VisibilityMask = Visibility(), 303 unsigned MinimumLength = 4, 304 unsigned MaximumDistance = UINT_MAX) const; 305 306 unsigned findNearest(StringRef Option, std::string &NearestString, 307 unsigned FlagsToInclude, unsigned FlagsToExclude = 0, 308 unsigned MinimumLength = 4, 309 unsigned MaximumDistance = UINT_MAX) const; 310 311 private: 312 unsigned 313 internalFindNearest(StringRef Option, std::string &NearestString, 314 unsigned MinimumLength, unsigned MaximumDistance, 315 std::function<bool(const Info &)> ExcludeOption) const; 316 317 public: 318 bool findExact(StringRef Option, std::string &ExactString, 319 Visibility VisibilityMask = Visibility()) const { 320 return findNearest(Option, ExactString, VisibilityMask, 4, 0) == 0; 321 } 322 323 bool findExact(StringRef Option, std::string &ExactString, 324 unsigned FlagsToInclude, unsigned FlagsToExclude = 0) const { 325 return findNearest(Option, ExactString, FlagsToInclude, FlagsToExclude, 4, 326 0) == 0; 327 } 328 329 /// Parse a single argument; returning the new argument and 330 /// updating Index. 331 /// 332 /// \param [in,out] Index - The current parsing position in the argument 333 /// string list; on return this will be the index of the next argument 334 /// string to parse. 335 /// \param [in] VisibilityMask - Only include options with any of these 336 /// visibility flags set. 337 /// 338 /// \return The parsed argument, or 0 if the argument is missing values 339 /// (in which case Index still points at the conceptual next argument string 340 /// to parse). 341 std::unique_ptr<Arg> 342 ParseOneArg(const ArgList &Args, unsigned &Index, 343 Visibility VisibilityMask = Visibility()) const; 344 345 std::unique_ptr<Arg> ParseOneArg(const ArgList &Args, unsigned &Index, 346 unsigned FlagsToInclude, 347 unsigned FlagsToExclude) const; 348 349 private: 350 std::unique_ptr<Arg> 351 internalParseOneArg(const ArgList &Args, unsigned &Index, 352 std::function<bool(const Option &)> ExcludeOption) const; 353 354 public: 355 /// Parse an list of arguments into an InputArgList. 356 /// 357 /// The resulting InputArgList will reference the strings in [\p ArgBegin, 358 /// \p ArgEnd), and their lifetime should extend past that of the returned 359 /// InputArgList. 360 /// 361 /// The only error that can occur in this routine is if an argument is 362 /// missing values; in this case \p MissingArgCount will be non-zero. 363 /// 364 /// \param MissingArgIndex - On error, the index of the option which could 365 /// not be parsed. 366 /// \param MissingArgCount - On error, the number of missing options. 367 /// \param VisibilityMask - Only include options with any of these 368 /// visibility flags set. 369 /// \return An InputArgList; on error this will contain all the options 370 /// which could be parsed. 371 InputArgList ParseArgs(ArrayRef<const char *> Args, unsigned &MissingArgIndex, 372 unsigned &MissingArgCount, 373 Visibility VisibilityMask = Visibility()) const; 374 375 InputArgList ParseArgs(ArrayRef<const char *> Args, unsigned &MissingArgIndex, 376 unsigned &MissingArgCount, unsigned FlagsToInclude, 377 unsigned FlagsToExclude = 0) const; 378 379 private: 380 InputArgList 381 internalParseArgs(ArrayRef<const char *> Args, unsigned &MissingArgIndex, 382 unsigned &MissingArgCount, 383 std::function<bool(const Option &)> ExcludeOption) const; 384 385 public: 386 /// A convenience helper which handles optional initial options populated from 387 /// an environment variable, expands response files recursively and parses 388 /// options. 389 /// 390 /// \param ErrorFn - Called on a formatted error message for missing arguments 391 /// or unknown options. 392 /// \return An InputArgList; on error this will contain all the options which 393 /// could be parsed. 394 InputArgList parseArgs(int Argc, char *const *Argv, OptSpecifier Unknown, 395 StringSaver &Saver, 396 std::function<void(StringRef)> ErrorFn) const; 397 398 /// Render the help text for an option table. 399 /// 400 /// \param OS - The stream to write the help text to. 401 /// \param Usage - USAGE: Usage 402 /// \param Title - OVERVIEW: Title 403 /// \param VisibilityMask - Only in Visibility VisibilityMask,clude options with any of these 404 /// visibility flags set. 405 /// \param ShowHidden - If true, display options marked as HelpHidden 406 /// \param ShowAllAliases - If true, display all options including aliases 407 /// that don't have help texts. By default, we display 408 /// only options that are not hidden and have help 409 /// texts. 410 void printHelp(raw_ostream &OS, const char *Usage, const char *Title, 411 bool ShowHidden = false, bool ShowAllAliases = false, 412 Visibility VisibilityMask = Visibility()) const; 413 414 void printHelp(raw_ostream &OS, const char *Usage, const char *Title, 415 unsigned FlagsToInclude, unsigned FlagsToExclude, 416 bool ShowAllAliases) const; 417 418 private: 419 void internalPrintHelp(raw_ostream &OS, const char *Usage, const char *Title, 420 bool ShowHidden, bool ShowAllAliases, 421 std::function<bool(const Info &)> ExcludeOption, 422 Visibility VisibilityMask) const; 423 }; 424 425 /// Specialization of OptTable 426 class GenericOptTable : public OptTable { 427 protected: 428 GenericOptTable(const StringTable &StrTable, 429 ArrayRef<StringTable::Offset> PrefixesTable, 430 ArrayRef<Info> OptionInfos, bool IgnoreCase = false); 431 }; 432 433 class PrecomputedOptTable : public OptTable { 434 protected: 435 PrecomputedOptTable(const StringTable &StrTable, 436 ArrayRef<StringTable::Offset> PrefixesTable, 437 ArrayRef<Info> OptionInfos, 438 ArrayRef<StringTable::Offset> PrefixesUnionOffsets, 439 bool IgnoreCase = false) 440 : OptTable(StrTable, PrefixesTable, OptionInfos, IgnoreCase) { 441 for (auto PrefixOffset : PrefixesUnionOffsets) 442 PrefixesUnion.push_back(StrTable[PrefixOffset]); 443 buildPrefixChars(); 444 } 445 }; 446 447 } // end namespace opt 448 449 } // end namespace llvm 450 451 #define LLVM_MAKE_OPT_ID_WITH_ID_PREFIX( \ 452 ID_PREFIX, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, \ 453 ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \ 454 METAVAR, VALUES) \ 455 ID_PREFIX##ID 456 457 #define LLVM_MAKE_OPT_ID(PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, \ 458 GROUP, ALIAS, ALIASARGS, FLAGS, VISIBILITY, PARAM, \ 459 HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES) \ 460 LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OPT_, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, \ 461 ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \ 462 VISIBILITY, PARAM, HELPTEXT, \ 463 HELPTEXTSFORVARIANTS, METAVAR, VALUES) 464 465 #define LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX( \ 466 ID_PREFIX, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, \ 467 ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \ 468 METAVAR, VALUES) \ 469 llvm::opt::OptTable::Info { \ 470 PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, HELPTEXT, HELPTEXTSFORVARIANTS, \ 471 METAVAR, ID_PREFIX##ID, llvm::opt::Option::KIND##Class, PARAM, FLAGS, \ 472 VISIBILITY, ID_PREFIX##GROUP, ID_PREFIX##ALIAS, ALIASARGS, VALUES \ 473 } 474 475 #define LLVM_CONSTRUCT_OPT_INFO( \ 476 PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, ALIASARGS, \ 477 FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES) \ 478 LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX( \ 479 OPT_, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, \ 480 ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \ 481 METAVAR, VALUES) 482 483 #endif // LLVM_OPTION_OPTTABLE_H 484