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