[clang] 083e035 - [clang][cli] Unify boolean marshalling

Jan Svoboda via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 8 04:47:44 PST 2020


Author: Jan Svoboda
Date: 2020-12-08T13:47:30+01:00
New Revision: 083e035c47f6c73084ecf5ab7f41cddca19ce332

URL: https://github.com/llvm/llvm-project/commit/083e035c47f6c73084ecf5ab7f41cddca19ce332
DIFF: https://github.com/llvm/llvm-project/commit/083e035c47f6c73084ecf5ab7f41cddca19ce332.diff

LOG: [clang][cli] Unify boolean marshalling

Use lambdas with captures to replace the redundant infrastructure for marshalling of two boolean flags that control the same keypath.

Reviewed By: dexonsmith

Differential Revision: https://reviews.llvm.org/D92773

Added: 
    

Modified: 
    clang/include/clang/Driver/Options.td
    clang/lib/Frontend/CompilerInvocation.cpp
    llvm/include/llvm/Option/OptParser.td
    llvm/utils/TableGen/OptParserEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index c6159f50b781..794aa24f997d 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -271,7 +271,7 @@ multiclass OptOutFFlag<string name, string pos_prefix, string neg_prefix,
 multiclass BooleanMarshalledFFlag<string name, code keypath, code default_value, string pos_help = "", string neg_help=""> {
   def fno_#NAME : Flag<["-"], "fno-"#name>, HelpText<neg_help>;
   def f#NAME : Flag<["-"], "f"#name>, HelpText<pos_help>,
-    MarshallingInfoBooleanFlag<keypath, default_value, !cast<Option>("fno_"#NAME)>;
+    MarshallingInfoBooleanFlag<keypath, default_value, "fno_"#NAME, "-fno-"#name>;
 }
 
 /////////

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index e31f6aa34b36..547dadd37931 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -185,25 +185,21 @@ static FlagToValueNormalizer<T> makeFlagToValueNormalizer(T Value) {
   return FlagToValueNormalizer<T>{std::move(Value)};
 }
 
-static Optional<bool> normalizeBooleanFlag(OptSpecifier PosOpt,
-                                           OptSpecifier NegOpt,
-                                           unsigned TableIndex,
-                                           const ArgList &Args,
-                                           DiagnosticsEngine &Diags) {
-  if (const Arg *A = Args.getLastArg(PosOpt, NegOpt))
-    return A->getOption().matches(PosOpt);
-  return None;
+static auto makeBooleanFlagNormalizer(OptSpecifier NegOpt) {
+  return [NegOpt](OptSpecifier PosOpt, unsigned, const ArgList &Args,
+                  DiagnosticsEngine &) -> Optional<bool> {
+    if (const Arg *A = Args.getLastArg(PosOpt, NegOpt))
+      return A->getOption().matches(PosOpt);
+    return None;
+  };
 }
 
-static void denormalizeBooleanFlag(SmallVectorImpl<const char *> &Args,
-                                   const char *Spelling,
-                                   const char *NegSpelling,
-                                   CompilerInvocation::StringAllocator SA,
-                                   unsigned TableIndex, unsigned Value) {
-  if (Value)
-    Args.push_back(Spelling);
-  else
-    Args.push_back(NegSpelling);
+static auto makeBooleanFlagDenormalizer(const char *NegSpelling) {
+  return [NegSpelling](
+             SmallVectorImpl<const char *> &Args, const char *PosSpelling,
+             CompilerInvocation::StringAllocator, unsigned, unsigned Value) {
+    Args.push_back(Value ? PosSpelling : NegSpelling);
+  };
 }
 
 static Optional<SimpleEnumValue>
@@ -3779,23 +3775,7 @@ bool CompilerInvocation::parseSimpleArgs(const ArgList &Args,
           this->KEYPATH, static_cast<decltype(this->KEYPATH)>(*MaybeValue));   \
   }
 
-#define OPTION_WITH_MARSHALLING_BOOLEAN(                                       \
-    PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,        \
-    HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE,  \
-    IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, \
-    TABLE_INDEX, NEG_ID, NEG_SPELLING)                                         \
-  {                                                                            \
-    this->KEYPATH = MERGER(this->KEYPATH, DEFAULT_VALUE);                      \
-    if (IMPLIED_CHECK)                                                         \
-      this->KEYPATH = MERGER(this->KEYPATH, IMPLIED_VALUE);                    \
-    if (auto MaybeValue =                                                      \
-            NORMALIZER(OPT_##ID, OPT_##NEG_ID, TABLE_INDEX, Args, Diags))      \
-      this->KEYPATH = MERGER(                                                  \
-          this->KEYPATH, static_cast<decltype(this->KEYPATH)>(*MaybeValue));   \
-  }
-
 #include "clang/Driver/Options.inc"
-#undef OPTION_WITH_MARSHALLING_BOOLEAN
 #undef OPTION_WITH_MARSHALLING
   return true;
 }
@@ -4060,20 +4040,7 @@ void CompilerInvocation::generateCC1CommandLine(
     }(EXTRACTOR(this->KEYPATH));                                               \
   }
 
-#define OPTION_WITH_MARSHALLING_BOOLEAN(                                       \
-    PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,        \
-    HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE,  \
-    IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, \
-    TABLE_INDEX, NEG_ID, NEG_SPELLING)                                         \
-  if ((FLAGS)&options::CC1Option) {                                            \
-    bool Extracted = EXTRACTOR(this->KEYPATH);                                 \
-    if (ALWAYS_EMIT ||                                                         \
-        (Extracted != ((IMPLIED_CHECK) ? (IMPLIED_VALUE) : (DEFAULT_VALUE))))  \
-      DENORMALIZER(Args, SPELLING, NEG_SPELLING, SA, TABLE_INDEX, Extracted);  \
-  }
-
 #include "clang/Driver/Options.inc"
-#undef OPTION_WITH_MARSHALLING_BOOLEAN
 #undef OPTION_WITH_MARSHALLING
 }
 

diff  --git a/llvm/include/llvm/Option/OptParser.td b/llvm/include/llvm/Option/OptParser.td
index 717b5facf53e..9a935b5d9e6e 100644
--- a/llvm/include/llvm/Option/OptParser.td
+++ b/llvm/include/llvm/Option/OptParser.td
@@ -97,7 +97,6 @@ class Option<list<string> prefixes, string name, OptionKind kind> {
   OptionGroup Group = ?;
   Option Alias = ?;
   list<string> AliasArgs = [];
-  string MarshallingInfoKind = ?;
   code KeyPath = ?;
   code DefaultValue = ?;
   code ImpliedValue = ?;
@@ -110,8 +109,6 @@ class Option<list<string> prefixes, string name, OptionKind kind> {
   code ValueMerger = "mergeForwardValue";
   code ValueExtractor = "extractForwardValue";
   list<code> NormalizedValues = ?;
-  // Used for BooleanFlagKind
-  Option NegOption = ?;
 }
 
 // Helpers for defining options.
@@ -154,7 +151,6 @@ class ImpliedByAnyOf<list<Option> options, code value = "true"> {
 }
 
 class MarshallingInfo<code keypath, code defaultvalue> {
-  string MarshallingInfoKind = "Default";
   code KeyPath = keypath;
   code DefaultValue = defaultvalue;
 }
@@ -175,13 +171,11 @@ class MarshallingInfoBitfieldFlag<code keypath, code value>
   code ValueExtractor = "(extractMaskValue<unsigned, decltype("#value#"), "#value#">)";
 }
 
-class MarshallingInfoBooleanFlag<code keypath, code defaultvalue, Option negopt>
+class MarshallingInfoBooleanFlag<code keypath, code defaultvalue, code neg_name, string neg_spelling>
   : MarshallingInfoFlag<keypath, defaultvalue> {
   bit ShouldAlwaysEmit = 1;
-  string MarshallingInfoKind = "BooleanFlag";
-  code Normalizer = "normalizeBooleanFlag";
-  code Denormalizer = "denormalizeBooleanFlag";
-  Option NegOption = negopt;
+  code Normalizer = "makeBooleanFlagNormalizer(OPT_"#neg_name#")";
+  code Denormalizer = "makeBooleanFlagDenormalizer(\""#neg_spelling#"\")";
 }
 
 // Mixins for additional marshalling attributes.

diff  --git a/llvm/utils/TableGen/OptParserEmitter.cpp b/llvm/utils/TableGen/OptParserEmitter.cpp
index edbe66630572..b3fe9d7a91d1 100644
--- a/llvm/utils/TableGen/OptParserEmitter.cpp
+++ b/llvm/utils/TableGen/OptParserEmitter.cpp
@@ -63,9 +63,7 @@ static void emitNameUsingSpelling(raw_ostream &OS, const Record &R) {
 
 class MarshallingInfo {
 public:
-  using Ptr = std::unique_ptr<MarshallingInfo>;
-
-  const char *MacroName;
+  static constexpr const char *MacroName = "OPTION_WITH_MARSHALLING";
   const Record &R;
   bool ShouldAlwaysEmit;
   StringRef KeyPath;
@@ -99,14 +97,9 @@ struct SimpleEnumValueTable {
   static constexpr const char *ValueTablesDecl =
       "static const SimpleEnumValueTable SimpleEnumValueTables[] = ";
 
-  MarshallingInfo(const Record &R)
-      : MacroName("OPTION_WITH_MARSHALLING"), R(R) {}
-  MarshallingInfo(const char *MacroName, const Record &R)
-      : MacroName(MacroName), R(R){};
-
-  virtual ~MarshallingInfo() = default;
+  MarshallingInfo(const Record &R) : R(R) {}
 
-  virtual void emit(raw_ostream &OS) const {
+  void emit(raw_ostream &OS) const {
     write_cstring(OS, StringRef(getOptionSpelling(R)));
     OS << ", ";
     OS << ShouldAlwaysEmit;
@@ -157,59 +150,35 @@ struct SimpleEnumValueTable {
 
 size_t MarshallingInfo::NextTableIndex = 0;
 
-class MarshallingInfoBooleanFlag : public MarshallingInfo {
-public:
-  const Record &NegOption;
-
-  MarshallingInfoBooleanFlag(const Record &Option, const Record &NegOption)
-      : MarshallingInfo("OPTION_WITH_MARSHALLING_BOOLEAN", Option),
-        NegOption(NegOption) {}
-
-  void emit(raw_ostream &OS) const override {
-    MarshallingInfo::emit(OS);
-    OS << ", ";
-    OS << getOptionName(NegOption);
-    OS << ", ";
-    write_cstring(OS, getOptionSpelling(NegOption));
-  }
-};
-
-static MarshallingInfo::Ptr createMarshallingInfo(const Record &R) {
+static MarshallingInfo createMarshallingInfo(const Record &R) {
   assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
          !isa<UnsetInit>(R.getValueInit("DefaultValue")) &&
          !isa<UnsetInit>(R.getValueInit("ValueMerger")) &&
          "MarshallingInfo must have a provide a keypath, default value and a "
          "value merger");
 
-  MarshallingInfo::Ptr Ret;
-  StringRef KindString = R.getValueAsString("MarshallingInfoKind");
-  if (KindString == "Default") {
-    Ret = std::make_unique<MarshallingInfo>(R);
-  } else if (KindString == "BooleanFlag") {
-    Ret = std::make_unique<MarshallingInfoBooleanFlag>(
-        R, *R.getValueAsDef("NegOption"));
-  }
+  MarshallingInfo Ret(R);
 
-  Ret->ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit");
-  Ret->KeyPath = R.getValueAsString("KeyPath");
-  Ret->DefaultValue = R.getValueAsString("DefaultValue");
-  Ret->NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");
-  Ret->ImpliedCheck = R.getValueAsString("ImpliedCheck");
-  Ret->ImpliedValue =
-      R.getValueAsOptionalString("ImpliedValue").getValueOr(Ret->DefaultValue);
+  Ret.ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit");
+  Ret.KeyPath = R.getValueAsString("KeyPath");
+  Ret.DefaultValue = R.getValueAsString("DefaultValue");
+  Ret.NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");
+  Ret.ImpliedCheck = R.getValueAsString("ImpliedCheck");
+  Ret.ImpliedValue =
+      R.getValueAsOptionalString("ImpliedValue").getValueOr(Ret.DefaultValue);
 
-  Ret->Normalizer = R.getValueAsString("Normalizer");
-  Ret->Denormalizer = R.getValueAsString("Denormalizer");
-  Ret->ValueMerger = R.getValueAsString("ValueMerger");
-  Ret->ValueExtractor = R.getValueAsString("ValueExtractor");
+  Ret.Normalizer = R.getValueAsString("Normalizer");
+  Ret.Denormalizer = R.getValueAsString("Denormalizer");
+  Ret.ValueMerger = R.getValueAsString("ValueMerger");
+  Ret.ValueExtractor = R.getValueAsString("ValueExtractor");
 
   if (!isa<UnsetInit>(R.getValueInit("NormalizedValues"))) {
     assert(!isa<UnsetInit>(R.getValueInit("Values")) &&
            "Cannot provide normalized values for value-less options");
-    Ret->TableIndex = MarshallingInfo::NextTableIndex++;
-    Ret->NormalizedValues = R.getValueAsListOfStrings("NormalizedValues");
-    Ret->Values.reserve(Ret->NormalizedValues.size());
-    Ret->ValueTableName = getOptionName(R) + "ValueTable";
+    Ret.TableIndex = MarshallingInfo::NextTableIndex++;
+    Ret.NormalizedValues = R.getValueAsListOfStrings("NormalizedValues");
+    Ret.Values.reserve(Ret.NormalizedValues.size());
+    Ret.ValueTableName = getOptionName(R) + "ValueTable";
 
     StringRef ValuesStr = R.getValueAsString("Values");
     for (;;) {
@@ -217,22 +186,18 @@ static MarshallingInfo::Ptr createMarshallingInfo(const Record &R) {
       if (Idx == StringRef::npos)
         break;
       if (Idx > 0)
-        Ret->Values.push_back(ValuesStr.slice(0, Idx));
+        Ret.Values.push_back(ValuesStr.slice(0, Idx));
       ValuesStr = ValuesStr.slice(Idx + 1, StringRef::npos);
     }
     if (!ValuesStr.empty())
-      Ret->Values.push_back(ValuesStr);
+      Ret.Values.push_back(ValuesStr);
 
-    assert(Ret->Values.size() == Ret->NormalizedValues.size() &&
+    assert(Ret.Values.size() == Ret.NormalizedValues.size() &&
            "The number of normalized values doesn't match the number of "
            "values");
   }
 
-  // FIXME: This is a workaround for a bug in older versions of clang (< 3.9)
-  //   The constructor that is supposed to allow for Derived to Base
-  //   conversion does not work. Remove this if we drop support for such
-  //   configurations.
-  return MarshallingInfo::Ptr(Ret.release());
+  return Ret;
 }
 
 /// OptParserEmitter - This tablegen backend takes an input .td file
@@ -458,18 +423,18 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
   array_pod_sort(OptsWithMarshalling.begin(), OptsWithMarshalling.end(),
                  CmpMarshallingOpts);
 
-  std::vector<MarshallingInfo::Ptr> MarshallingInfos;
+  std::vector<MarshallingInfo> MarshallingInfos;
   for (const auto *R : OptsWithMarshalling)
     MarshallingInfos.push_back(createMarshallingInfo(*R));
 
   for (const auto &MI : MarshallingInfos) {
-    OS << "#ifdef " << MI->MacroName << "\n";
-    OS << MI->MacroName << "(";
-    WriteOptRecordFields(OS, MI->R);
+    OS << "#ifdef " << MarshallingInfo::MacroName << "\n";
+    OS << MarshallingInfo::MacroName << "(";
+    WriteOptRecordFields(OS, MI.R);
     OS << ", ";
-    MI->emit(OS);
+    MI.emit(OS);
     OS << ")\n";
-    OS << "#endif // " << MI->MacroName << "\n";
+    OS << "#endif // " << MarshallingInfo::MacroName << "\n";
   }
 
   OS << "\n";
@@ -478,7 +443,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
   OS << MarshallingInfo::ValueTablePreamble;
   std::vector<StringRef> ValueTableNames;
   for (const auto &MI : MarshallingInfos)
-    if (auto MaybeValueTableName = MI->emitValueTable(OS))
+    if (auto MaybeValueTableName = MI.emitValueTable(OS))
       ValueTableNames.push_back(*MaybeValueTableName);
 
   OS << MarshallingInfo::ValueTablesDecl << "{";


        


More information about the cfe-commits mailing list