File indexing completed on 2026-05-10 08:44:22
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_OPTION_OPTTABLE_H
0010 #define LLVM_OPTION_OPTTABLE_H
0011
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/ADT/SmallString.h"
0014 #include "llvm/ADT/StringRef.h"
0015 #include "llvm/ADT/StringTable.h"
0016 #include "llvm/Option/OptSpecifier.h"
0017 #include "llvm/Support/StringSaver.h"
0018 #include <cassert>
0019 #include <string>
0020 #include <vector>
0021
0022 namespace llvm {
0023
0024 class raw_ostream;
0025 template <typename Fn> class function_ref;
0026
0027 namespace opt {
0028
0029 class Arg;
0030 class ArgList;
0031 class InputArgList;
0032 class Option;
0033
0034
0035
0036 class Visibility {
0037 unsigned Mask = ~0U;
0038
0039 public:
0040 explicit Visibility(unsigned Mask) : Mask(Mask) {}
0041 Visibility() = default;
0042
0043 operator unsigned() const { return Mask; }
0044 };
0045
0046
0047
0048
0049
0050
0051
0052
0053 class OptTable {
0054 public:
0055
0056 struct Info {
0057 unsigned PrefixesOffset;
0058 StringTable::Offset PrefixedNameOffset;
0059 const char *HelpText;
0060
0061
0062
0063
0064
0065
0066
0067 std::array<std::pair<std::array<unsigned int, 2 >,
0068 const char *>,
0069 1 >
0070 HelpTextsForVariants;
0071 const char *MetaVar;
0072 unsigned ID;
0073 unsigned char Kind;
0074 unsigned char Param;
0075 unsigned int Flags;
0076 unsigned int Visibility;
0077 unsigned short GroupID;
0078 unsigned short AliasID;
0079 const char *AliasArgs;
0080 const char *Values;
0081
0082 bool hasNoPrefix() const { return PrefixesOffset == 0; }
0083
0084 unsigned getNumPrefixes(ArrayRef<StringTable::Offset> PrefixesTable) const {
0085
0086 return PrefixesTable[PrefixesOffset].value();
0087 }
0088
0089 ArrayRef<StringTable::Offset>
0090 getPrefixOffsets(ArrayRef<StringTable::Offset> PrefixesTable) const {
0091 return hasNoPrefix() ? ArrayRef<StringTable::Offset>()
0092 : PrefixesTable.slice(PrefixesOffset + 1,
0093 getNumPrefixes(PrefixesTable));
0094 }
0095
0096 void appendPrefixes(const StringTable &StrTable,
0097 ArrayRef<StringTable::Offset> PrefixesTable,
0098 SmallVectorImpl<StringRef> &Prefixes) const {
0099 for (auto PrefixOffset : getPrefixOffsets(PrefixesTable))
0100 Prefixes.push_back(StrTable[PrefixOffset]);
0101 }
0102
0103 StringRef getPrefix(const StringTable &StrTable,
0104 ArrayRef<StringTable::Offset> PrefixesTable,
0105 unsigned PrefixIndex) const {
0106 return StrTable[getPrefixOffsets(PrefixesTable)[PrefixIndex]];
0107 }
0108
0109 StringRef getPrefixedName(const StringTable &StrTable) const {
0110 return StrTable[PrefixedNameOffset];
0111 }
0112
0113 StringRef getName(const StringTable &StrTable,
0114 ArrayRef<StringTable::Offset> PrefixesTable) const {
0115 unsigned PrefixLength =
0116 hasNoPrefix() ? 0 : getPrefix(StrTable, PrefixesTable, 0).size();
0117 return getPrefixedName(StrTable).drop_front(PrefixLength);
0118 }
0119 };
0120
0121 private:
0122
0123
0124 const StringTable *StrTable;
0125
0126
0127
0128
0129
0130 ArrayRef<StringTable::Offset> PrefixesTable;
0131
0132
0133 ArrayRef<Info> OptionInfos;
0134
0135 bool IgnoreCase;
0136 bool GroupedShortOptions = false;
0137 bool DashDashParsing = false;
0138 const char *EnvVar = nullptr;
0139
0140 unsigned InputOptionID = 0;
0141 unsigned UnknownOptionID = 0;
0142
0143 protected:
0144
0145
0146 unsigned FirstSearchableIndex = 0;
0147
0148
0149
0150 SmallVector<StringRef> PrefixesUnion;
0151
0152
0153 SmallString<8> PrefixChars;
0154
0155 private:
0156 const Info &getInfo(OptSpecifier Opt) const {
0157 unsigned id = Opt.getID();
0158 assert(id > 0 && id - 1 < getNumOptions() && "Invalid Option ID.");
0159 return OptionInfos[id - 1];
0160 }
0161
0162 std::unique_ptr<Arg> parseOneArgGrouped(InputArgList &Args,
0163 unsigned &Index) const;
0164
0165 protected:
0166
0167
0168 OptTable(const StringTable &StrTable,
0169 ArrayRef<StringTable::Offset> PrefixesTable,
0170 ArrayRef<Info> OptionInfos, bool IgnoreCase = false);
0171
0172
0173 void buildPrefixChars();
0174
0175 public:
0176 virtual ~OptTable();
0177
0178
0179 const StringTable &getStrTable() const { return *StrTable; }
0180
0181
0182 ArrayRef<StringTable::Offset> getPrefixesTable() const {
0183 return PrefixesTable;
0184 }
0185
0186
0187 unsigned getNumOptions() const { return OptionInfos.size(); }
0188
0189
0190
0191
0192
0193 const Option getOption(OptSpecifier Opt) const;
0194
0195
0196 StringRef getOptionName(OptSpecifier id) const {
0197 return getInfo(id).getName(*StrTable, PrefixesTable);
0198 }
0199
0200
0201 StringRef getOptionPrefix(OptSpecifier id) const {
0202 const Info &I = getInfo(id);
0203 return I.hasNoPrefix() ? StringRef()
0204 : I.getPrefix(*StrTable, PrefixesTable, 0);
0205 }
0206
0207 void appendOptionPrefixes(OptSpecifier id,
0208 SmallVectorImpl<StringRef> &Prefixes) const {
0209 const Info &I = getInfo(id);
0210 I.appendPrefixes(*StrTable, PrefixesTable, Prefixes);
0211 }
0212
0213
0214 StringRef getOptionPrefixedName(OptSpecifier id) const {
0215 return getInfo(id).getPrefixedName(*StrTable);
0216 }
0217
0218
0219 unsigned getOptionKind(OptSpecifier id) const {
0220 return getInfo(id).Kind;
0221 }
0222
0223
0224 unsigned getOptionGroupID(OptSpecifier id) const {
0225 return getInfo(id).GroupID;
0226 }
0227
0228
0229 const char *getOptionHelpText(OptSpecifier id) const {
0230 return getOptionHelpText(id, Visibility(0));
0231 }
0232
0233
0234
0235
0236 const char *getOptionHelpText(OptSpecifier id,
0237 Visibility VisibilityMask) const {
0238 auto Info = getInfo(id);
0239 for (auto [Visibilities, Text] : Info.HelpTextsForVariants)
0240 for (auto Visibility : Visibilities)
0241 if (VisibilityMask & Visibility)
0242 return Text;
0243 return Info.HelpText;
0244 }
0245
0246
0247
0248 const char *getOptionMetaVar(OptSpecifier id) const {
0249 return getInfo(id).MetaVar;
0250 }
0251
0252
0253 void setInitialOptionsFromEnvironment(const char *E) { EnvVar = E; }
0254
0255
0256 void setGroupedShortOptions(bool Value) { GroupedShortOptions = Value; }
0257
0258
0259
0260 void setDashDashParsing(bool Value) { DashDashParsing = Value; }
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272 std::vector<std::string> suggestValueCompletions(StringRef Option,
0273 StringRef Arg) const;
0274
0275
0276
0277
0278
0279
0280
0281 std::vector<std::string> findByPrefix(StringRef Cur,
0282 Visibility VisibilityMask,
0283 unsigned int DisableFlags) const;
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301 unsigned findNearest(StringRef Option, std::string &NearestString,
0302 Visibility VisibilityMask = Visibility(),
0303 unsigned MinimumLength = 4,
0304 unsigned MaximumDistance = UINT_MAX) const;
0305
0306 unsigned findNearest(StringRef Option, std::string &NearestString,
0307 unsigned FlagsToInclude, unsigned FlagsToExclude = 0,
0308 unsigned MinimumLength = 4,
0309 unsigned MaximumDistance = UINT_MAX) const;
0310
0311 private:
0312 unsigned
0313 internalFindNearest(StringRef Option, std::string &NearestString,
0314 unsigned MinimumLength, unsigned MaximumDistance,
0315 std::function<bool(const Info &)> ExcludeOption) const;
0316
0317 public:
0318 bool findExact(StringRef Option, std::string &ExactString,
0319 Visibility VisibilityMask = Visibility()) const {
0320 return findNearest(Option, ExactString, VisibilityMask, 4, 0) == 0;
0321 }
0322
0323 bool findExact(StringRef Option, std::string &ExactString,
0324 unsigned FlagsToInclude, unsigned FlagsToExclude = 0) const {
0325 return findNearest(Option, ExactString, FlagsToInclude, FlagsToExclude, 4,
0326 0) == 0;
0327 }
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341 std::unique_ptr<Arg>
0342 ParseOneArg(const ArgList &Args, unsigned &Index,
0343 Visibility VisibilityMask = Visibility()) const;
0344
0345 std::unique_ptr<Arg> ParseOneArg(const ArgList &Args, unsigned &Index,
0346 unsigned FlagsToInclude,
0347 unsigned FlagsToExclude) const;
0348
0349 private:
0350 std::unique_ptr<Arg>
0351 internalParseOneArg(const ArgList &Args, unsigned &Index,
0352 std::function<bool(const Option &)> ExcludeOption) const;
0353
0354 public:
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371 InputArgList ParseArgs(ArrayRef<const char *> Args, unsigned &MissingArgIndex,
0372 unsigned &MissingArgCount,
0373 Visibility VisibilityMask = Visibility()) const;
0374
0375 InputArgList ParseArgs(ArrayRef<const char *> Args, unsigned &MissingArgIndex,
0376 unsigned &MissingArgCount, unsigned FlagsToInclude,
0377 unsigned FlagsToExclude = 0) const;
0378
0379 private:
0380 InputArgList
0381 internalParseArgs(ArrayRef<const char *> Args, unsigned &MissingArgIndex,
0382 unsigned &MissingArgCount,
0383 std::function<bool(const Option &)> ExcludeOption) const;
0384
0385 public:
0386
0387
0388
0389
0390
0391
0392
0393
0394 InputArgList parseArgs(int Argc, char *const *Argv, OptSpecifier Unknown,
0395 StringSaver &Saver,
0396 std::function<void(StringRef)> ErrorFn) const;
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410 void printHelp(raw_ostream &OS, const char *Usage, const char *Title,
0411 bool ShowHidden = false, bool ShowAllAliases = false,
0412 Visibility VisibilityMask = Visibility()) const;
0413
0414 void printHelp(raw_ostream &OS, const char *Usage, const char *Title,
0415 unsigned FlagsToInclude, unsigned FlagsToExclude,
0416 bool ShowAllAliases) const;
0417
0418 private:
0419 void internalPrintHelp(raw_ostream &OS, const char *Usage, const char *Title,
0420 bool ShowHidden, bool ShowAllAliases,
0421 std::function<bool(const Info &)> ExcludeOption,
0422 Visibility VisibilityMask) const;
0423 };
0424
0425
0426 class GenericOptTable : public OptTable {
0427 protected:
0428 GenericOptTable(const StringTable &StrTable,
0429 ArrayRef<StringTable::Offset> PrefixesTable,
0430 ArrayRef<Info> OptionInfos, bool IgnoreCase = false);
0431 };
0432
0433 class PrecomputedOptTable : public OptTable {
0434 protected:
0435 PrecomputedOptTable(const StringTable &StrTable,
0436 ArrayRef<StringTable::Offset> PrefixesTable,
0437 ArrayRef<Info> OptionInfos,
0438 ArrayRef<StringTable::Offset> PrefixesUnionOffsets,
0439 bool IgnoreCase = false)
0440 : OptTable(StrTable, PrefixesTable, OptionInfos, IgnoreCase) {
0441 for (auto PrefixOffset : PrefixesUnionOffsets)
0442 PrefixesUnion.push_back(StrTable[PrefixOffset]);
0443 buildPrefixChars();
0444 }
0445 };
0446
0447 }
0448
0449 }
0450
0451 #define LLVM_MAKE_OPT_ID_WITH_ID_PREFIX( \
0452 ID_PREFIX, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, \
0453 ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \
0454 METAVAR, VALUES) \
0455 ID_PREFIX##ID
0456
0457 #define LLVM_MAKE_OPT_ID(PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, \
0458 GROUP, ALIAS, ALIASARGS, FLAGS, VISIBILITY, PARAM, \
0459 HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES) \
0460 LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OPT_, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, \
0461 ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \
0462 VISIBILITY, PARAM, HELPTEXT, \
0463 HELPTEXTSFORVARIANTS, METAVAR, VALUES)
0464
0465 #define LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX( \
0466 ID_PREFIX, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, \
0467 ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \
0468 METAVAR, VALUES) \
0469 llvm::opt::OptTable::Info { \
0470 PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, HELPTEXT, HELPTEXTSFORVARIANTS, \
0471 METAVAR, ID_PREFIX##ID, llvm::opt::Option::KIND##Class, PARAM, FLAGS, \
0472 VISIBILITY, ID_PREFIX##GROUP, ID_PREFIX##ALIAS, ALIASARGS, VALUES \
0473 }
0474
0475 #define LLVM_CONSTRUCT_OPT_INFO( \
0476 PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, ALIASARGS, \
0477 FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES) \
0478 LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX( \
0479 OPT_, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, \
0480 ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \
0481 METAVAR, VALUES)
0482
0483 #endif