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