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