dang updated this revision to Diff 270445.
dang edited the summary of this revision.
dang added a comment.

Implemented a draft of normalizer generation for simple enum based options


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D79796/new/

https://reviews.llvm.org/D79796

Files:
  clang/include/clang/Driver/CC1Options.td
  clang/include/clang/Frontend/CompilerInvocation.h
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/unittests/Frontend/CMakeLists.txt
  clang/unittests/Frontend/CompilerInvocationTest.cpp
  llvm/include/llvm/Option/OptParser.td
  llvm/utils/TableGen/OptParserEmitter.cpp

Index: llvm/utils/TableGen/OptParserEmitter.cpp
===================================================================
--- llvm/utils/TableGen/OptParserEmitter.cpp
+++ llvm/utils/TableGen/OptParserEmitter.cpp
@@ -10,6 +10,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/TableGen/Record.h"
 #include "llvm/TableGen/TableGenBackend.h"
 #include <cctype>
@@ -33,6 +34,50 @@
   return OS;
 }
 
+static void emitMarshallingInfoFlag(raw_ostream &OS, const Record &R) {
+  OS << R.getValueAsBit("IsPositive");
+}
+
+static void emitMarshallingInfoString(raw_ostream &OS, const Record &R) {
+  OS << R.getValueAsString("Normalizer");
+  OS << ", ";
+  OS << R.getValueAsString("Denormalizer");
+}
+
+static void emitScopedNormalizedValue(raw_ostream &OS,
+                                      StringRef NormalizedValuesScope,
+                                      StringRef NormalizedValue) {
+  if (!NormalizedValuesScope.empty())
+    OS << NormalizedValuesScope << "::";
+  OS << NormalizedValue;
+}
+
+static void emitValueTable(raw_ostream &OS, StringRef OptionID,
+                           StringRef Values, StringRef NormalizedValuesScope,
+                           std::vector<StringRef> NormalizedValues) {
+  SmallVector<StringRef, 8> SplitValues;
+  Values.split(SplitValues, ',');
+  assert(SplitValues.size() == NormalizedValues.size() &&
+         "The number of associated definitions doesn't match the number of "
+         "values");
+
+  SmallString<64> MacroName("HANDLE_");
+  MacroName += OptionID.upper();
+  MacroName += "_VALUES";
+  OS << "#ifdef " << MacroName << "\n";
+  for (unsigned I = 0, E = SplitValues.size(); I != E; ++I) {
+    OS << MacroName << "(\"" << SplitValues[I] << "\",";
+    emitScopedNormalizedValue(OS, NormalizedValuesScope, NormalizedValues[I]);
+    OS << ")\n";
+  }
+  OS << "#endif\n";
+}
+
+struct MarshallingKindInfo {
+  const char *MacroName;
+  void (*Emit)(raw_ostream &OS, const Record &R);
+};
+
 /// OptParserEmitter - This tablegen backend takes an input .td file
 /// describing a list of options and emits a data structure for parsing and
 /// working with those options when given an input command line.
@@ -135,12 +180,8 @@
 
   OS << "//////////\n";
   OS << "// Options\n\n";
-  for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
-    const Record &R = *Opts[i];
-
-    // Start a single option entry.
-    OS << "OPTION(";
 
+  auto WriteOptRecordFields = [&](raw_ostream &OS, const Record &R) {
     // The option prefix;
     std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes");
     OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", ";
@@ -223,11 +264,119 @@
       write_cstring(OS, R.getValueAsString("Values"));
     else
       OS << "nullptr";
+  };
 
+  std::vector<const Record *> OptsWithMarshalling;
+  for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
+    const Record &R = *Opts[i];
+
+    // Start a single option entry.
+    OS << "OPTION(";
+    WriteOptRecordFields(OS, R);
     OS << ")\n";
+    if (!isa<UnsetInit>(R.getValueInit("MarshallingKind")))
+      OptsWithMarshalling.push_back(&R);
   }
   OS << "#endif // OPTION\n";
 
+  std::vector<const Record *> AutoNormalizableOpts;
+  for (unsigned I = 0, E = OptsWithMarshalling.size(); I != E; ++I) {
+    const Record &R = *OptsWithMarshalling[I];
+    assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
+           !isa<UnsetInit>(R.getValueInit("DefaultValue")) &&
+           "Must provide at least a key-path and a default value for emitting "
+           "marshalling information");
+    StringRef KindStr = R.getValueAsString("MarshallingKind");
+    auto KindInfo = StringSwitch<MarshallingKindInfo>(KindStr)
+                        .Case("flag", {"OPTION_WITH_MARSHALLING_FLAG",
+                                       &emitMarshallingInfoFlag})
+                        .Case("string", {"OPTION_WITH_MARSHALLING_STRING",
+                                         &emitMarshallingInfoString})
+                        .Default({"", nullptr});
+    StringRef NormalizedValuesScope;
+    if (!isa<UnsetInit>(R.getValueInit("NormalizedValuesScope")))
+      NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");
+
+    OS << "#ifdef " << KindInfo.MacroName << "\n";
+    OS << KindInfo.MacroName << "(";
+    WriteOptRecordFields(OS, R);
+    OS << ", ";
+    OS << R.getValueAsBit("ShouldAlwaysEmit");
+    OS << ", ";
+    OS << R.getValueAsString("KeyPath");
+    OS << ", ";
+    emitScopedNormalizedValue(OS, NormalizedValuesScope,
+                              R.getValueAsString("DefaultValue"));
+    OS << ",";
+    KindInfo.Emit(OS, R);
+    OS << ")\n";
+    OS << "#endif\n";
+
+    if (!isa<UnsetInit>(R.getValueInit("NormalizedValues"))) {
+      assert(!isa<UnsetInit>(R.getValueInit("Values")) &&
+             "Cannot provide associated definitions for value-less options");
+      emitValueTable(OS, getOptionName(R), R.getValueAsString("Values"),
+                     NormalizedValuesScope,
+                     R.getValueAsListOfStrings("NormalizedValues"));
+    }
+
+    if (!isa<UnsetInit>(R.getValueInit("AutoNormalizerRetTy")))
+      AutoNormalizableOpts.push_back(&R);
+  }
+  OS << "\n";
+  OS << "#ifdef AUTO_NORMALIZING_OPTIONS";
+  OS << "\n\n";
+
+  for (unsigned I = 0, E = AutoNormalizableOpts.size(); I != E; ++I) {
+    const Record &R = *AutoNormalizableOpts[I];
+    StringRef NormalizedValuesScope =
+        R.getValueAsString("NormalizedValuesScope");
+    std::vector<StringRef> NormalizedValues =
+        R.getValueAsListOfStrings("NormalizedValues");
+    StringRef AutoNormalizerRetTy = R.getValueAsString("AutoNormalizerRetTy");
+    SmallString<64> MacroName("HANDLE_");
+    std::string OptionName = getOptionName(R);
+    MacroName += StringRef(OptionName).upper();
+    MacroName += "_VALUES";
+
+    OS << "static ";
+    emitScopedNormalizedValue(OS, NormalizedValuesScope, AutoNormalizerRetTy);
+    OS << " " << R.getValueAsString("Normalizer");
+    OS << "(const Arg *Arg, const ArgList &ArgList, DiagnosticsEngine "
+          "&Diags, llvm::Reloc::Model DefaultValue) {\n";
+    OS << "StringRef ArgValue = Arg->getValue();\n";
+    OS << "auto MaybeNormalized = llvm::StringSwitch<llvm::Optional<";
+    emitScopedNormalizedValue(OS, NormalizedValuesScope, AutoNormalizerRetTy);
+    OS << ">>(ArgValue)\n";
+    OS << "#define " << MacroName << "(V, D) .Case(V, D)\n";
+    emitValueTable(OS, OptionName, R.getValueAsString("Values"),
+                   NormalizedValuesScope, NormalizedValues);
+    OS << "#undef " << MacroName << "\n";
+    OS << ".Default(None);\n";
+
+    OS << "if (MaybeNormalized.hasValue()) return *MaybeNormalized;\n";
+
+    OS << "Diags.Report(diag::err_drv_invalid_value) << "
+          "Arg->getAsString(ArgList) << ArgValue;\n";
+    OS << "return DefaultValue;\n";
+    OS << "}";
+
+    OS << "\n\n";
+    OS << "static const char *" << R.getValueAsString("Denormalizer") << "(";
+    emitScopedNormalizedValue(OS, NormalizedValuesScope, AutoNormalizerRetTy);
+    OS << " NormalizedValue) {\n";
+    OS << "switch (NormalizedValue) {\n";
+    OS << "#define " << MacroName << "(V, D) case D: return V;\n";
+    emitValueTable(OS, OptionName, R.getValueAsString("Values"),
+                   NormalizedValuesScope, NormalizedValues);
+    OS << "#undef " << MacroName << "\n";
+    OS << "}\n";
+    OS << "}\n";
+  }
+  OS << "\n";
+  OS << "#endif // AUTO_NORMALIZING_OPTIONS\n";
+  OS << "\n";
+
   OS << "\n";
   OS << "#ifdef OPTTABLE_ARG_INIT\n";
   OS << "//////////\n";
Index: llvm/include/llvm/Option/OptParser.td
===================================================================
--- llvm/include/llvm/Option/OptParser.td
+++ llvm/include/llvm/Option/OptParser.td
@@ -97,6 +97,18 @@
   OptionGroup Group = ?;
   Option Alias = ?;
   list<string> AliasArgs = [];
+  string MarshallingKind = ?;
+  code KeyPath = ?;
+  code NormalizedValuesScope = ?;
+  code DefaultValue = ?;
+  bit ShouldAlwaysEmit = 0;
+  // Used by the Flag option kind.
+  bit IsPositive = 1;
+  // Used by the String option kind.
+  code Normalizer = "";
+  code Denormalizer = "";
+  list<code> NormalizedValues = ?;
+  code AutoNormalizerRetTy = ?;
 }
 
 // Helpers for defining options.
@@ -130,6 +142,34 @@
 class Values<string value> { string Values = value; }
 class ValuesCode<code valuecode> { code ValuesCode = valuecode; }
 
+// Helpers for defining marshalling information.
+
+class MarshallingInfo<code keypath, code defaultvalue> {
+  code KeyPath = keypath;
+  code DefaultValue = defaultvalue;
+}
+class MarshallingInfoString<code keypath, code defaultvalue>
+  : MarshallingInfo<keypath, defaultvalue> { string MarshallingKind = "string"; }
+
+class MarshallingInfoFlag<code keypath, code defaultvalue>
+  : MarshallingInfo<keypath, defaultvalue> {
+  string MarshallingKind = "flag";
+}
+
+// Mixins for additional marshalling attributes.
+
+class IsNegative { bit IsPositive = 0; }
+class AlwaysEmit { bit ShouldWaysEmit = 1; }
+class Normalizer<code normalizer> { code Normalizer = normalizer; }
+class Denormalizer<code denormalizer> { code Denormalizer = denormalizer; }
+class NormalizedValuesScope<code scope> { code NormalizedValuesScope = scope; }
+class NormalizedValues<list<code> definitions> { list<code> NormalizedValues = definitions; } 
+class AutoNormalizeEnum<code retty, string fnbasename> {
+  code Normalizer = "normalize"#fnbasename;
+  code Denormalizer = "denormalize"#fnbasename;
+  code AutoNormalizerRetTy = retty;
+}
+
 // Predefined options.
 
 // FIXME: Have generator validate that these appear in correct position (and
Index: clang/unittests/Frontend/CompilerInvocationTest.cpp
===================================================================
--- /dev/null
+++ clang/unittests/Frontend/CompilerInvocationTest.cpp
@@ -0,0 +1,102 @@
+//===- unittests/Frontend/CompilerInvocationTest.cpp - CI tests //---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "llvm/Support/Host.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace clang;
+
+using ::testing::Contains;
+using ::testing::Each;
+using ::testing::StrEq;
+using ::testing::StrNe;
+
+namespace {
+
+class CC1CommandLineGenerationTest : public ::testing::Test {
+public:
+  IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
+  SmallVector<const char *, 32> GeneratedArgs;
+  SmallVector<std::string, 32> GeneratedArgsStorage;
+
+  const char *operator()(const Twine &Arg) {
+    return GeneratedArgsStorage.emplace_back(Arg.str()).c_str();
+  }
+
+  CC1CommandLineGenerationTest()
+      : Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions())) {}
+};
+
+TEST_F(CC1CommandLineGenerationTest, CanGenerateCC1CommandLineFlag) {
+  const char *Args[] = {"clang", "-xc++", "-fmodules-strict-context-hash", "-"};
+
+  CompilerInvocation CInvok;
+  CompilerInvocation::CreateFromArgs(CInvok, Args, *Diags);
+
+  CInvok.generateCC1CommandLine(GeneratedArgs, *this);
+
+  ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fmodules-strict-context-hash")));
+}
+
+TEST_F(CC1CommandLineGenerationTest, CanGenerateCC1CommandLineSeparate) {
+  const char *TripleCStr = "i686-apple-darwin9";
+  const char *Args[] = {"clang", "-xc++", "-triple", TripleCStr, "-"};
+
+  CompilerInvocation CInvok;
+  CompilerInvocation::CreateFromArgs(CInvok, Args, *Diags);
+
+  CInvok.generateCC1CommandLine(GeneratedArgs, *this);
+
+  ASSERT_THAT(GeneratedArgs, Contains(StrEq(TripleCStr)));
+}
+
+TEST_F(CC1CommandLineGenerationTest,
+       CanGenerateCC1CommandLineSeparateRequired) {
+  const char *TripleCStr =
+      llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()).c_str();
+  const char *Args[] = {"clang", "-xc++", "-triple", TripleCStr, "-"};
+
+  CompilerInvocation CInvok;
+  CompilerInvocation::CreateFromArgs(CInvok, Args, *Diags);
+
+  CInvok.generateCC1CommandLine(GeneratedArgs, *this);
+
+  // Triple should always be emitted even if it is the default
+  ASSERT_THAT(GeneratedArgs, Contains(StrEq(TripleCStr)));
+}
+
+TEST_F(CC1CommandLineGenerationTest, CanGenerateCC1CommandLineSeparateEnum) {
+  const char *RelocationModelCStr = "static";
+  const char *Args[] = {"clang", "-xc++", "-mrelocation-model",
+                        RelocationModelCStr, "-"};
+
+  CompilerInvocation CInvok;
+  CompilerInvocation::CreateFromArgs(CInvok, Args, *Diags);
+
+  CInvok.generateCC1CommandLine(GeneratedArgs, *this);
+
+  // Non default relocation model
+  ASSERT_THAT(GeneratedArgs, Contains(StrEq(RelocationModelCStr)));
+  GeneratedArgs.clear();
+
+  RelocationModelCStr = "pic";
+  Args[3] = RelocationModelCStr;
+
+  CompilerInvocation CInvok1;
+  CompilerInvocation::CreateFromArgs(CInvok1, Args, *Diags);
+
+  CInvok1.generateCC1CommandLine(GeneratedArgs, *this);
+  ASSERT_THAT(GeneratedArgs, Each(StrNe(RelocationModelCStr)));
+}
+
+} // anonymous namespace
Index: clang/unittests/Frontend/CMakeLists.txt
===================================================================
--- clang/unittests/Frontend/CMakeLists.txt
+++ clang/unittests/Frontend/CMakeLists.txt
@@ -4,6 +4,7 @@
 
 add_clang_unittest(FrontendTests
   ASTUnitTest.cpp
+  CompilerInvocationTest.cpp
   CompilerInstanceTest.cpp
   FixedPointString.cpp
   FrontendActionTest.cpp
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -51,6 +51,7 @@
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/None.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
@@ -117,6 +118,20 @@
 
 CompilerInvocationBase::~CompilerInvocationBase() = default;
 
+//===----------------------------------------------------------------------===//
+// Normalizers
+//===----------------------------------------------------------------------===//
+
+static std::string normalizeTriple(const Arg *Arg, const ArgList &ArgList,
+                                   DiagnosticsEngine &Diags,
+                                   StringRef DefaultTriple) {
+  return llvm::Triple::normalize(Arg->getValue());
+}
+
+#define AUTO_NORMALIZING_OPTIONS
+#include "clang/Driver/Options.inc"
+#undef AUTO_NORMALIZING_OPTIONS
+
 //===----------------------------------------------------------------------===//
 // Deserialization (from args)
 //===----------------------------------------------------------------------===//
@@ -528,25 +543,6 @@
   Opts.ParseAllComments = Args.hasArg(OPT_fparse_all_comments);
 }
 
-static llvm::Reloc::Model getRelocModel(ArgList &Args,
-                                        DiagnosticsEngine &Diags) {
-  if (Arg *A = Args.getLastArg(OPT_mrelocation_model)) {
-    StringRef Value = A->getValue();
-    auto RM = llvm::StringSwitch<llvm::Optional<llvm::Reloc::Model>>(Value)
-                  .Case("static", llvm::Reloc::Static)
-                  .Case("pic", llvm::Reloc::PIC_)
-                  .Case("ropi", llvm::Reloc::ROPI)
-                  .Case("rwpi", llvm::Reloc::RWPI)
-                  .Case("ropi-rwpi", llvm::Reloc::ROPI_RWPI)
-                  .Case("dynamic-no-pic", llvm::Reloc::DynamicNoPIC)
-                  .Default(None);
-    if (RM.hasValue())
-      return *RM;
-    Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Value;
-  }
-  return llvm::Reloc::PIC_;
-}
-
 /// Create a new Regex instance out of the string value in \p RpassArg.
 /// It returns a pointer to the newly generated Regex instance.
 static std::shared_ptr<llvm::Regex>
@@ -927,7 +923,6 @@
   Opts.StrictVTablePointers = Args.hasArg(OPT_fstrict_vtable_pointers);
   Opts.ForceEmitVTables = Args.hasArg(OPT_fforce_emit_vtables);
   Opts.UnwindTables = Args.hasArg(OPT_munwind_tables);
-  Opts.RelocationModel = getRelocModel(Args, Diags);
   Opts.ThreadModel =
       std::string(Args.getLastArgValue(OPT_mthread_model, "posix"));
   if (Opts.ThreadModel != "posix" && Opts.ThreadModel != "single")
@@ -2104,7 +2099,6 @@
     Opts.AddPrebuiltModulePath(A->getValue());
   Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
   Opts.ModulesHashContent = Args.hasArg(OPT_fmodules_hash_content);
-  Opts.ModulesStrictContextHash = Args.hasArg(OPT_fmodules_strict_context_hash);
   Opts.ModulesValidateDiagnosticOptions =
       !Args.hasArg(OPT_fmodules_disable_diagnostic_validation);
   Opts.ImplicitModuleMaps = Args.hasArg(OPT_fimplicit_module_maps);
@@ -3624,6 +3618,31 @@
   }
 }
 
+bool CompilerInvocation::parseSimpleArgs(const ArgList &Args,
+                                         DiagnosticsEngine &Diags) {
+#define OPTION_WITH_MARSHALLING_FLAG(PREFIX_TYPE, NAME, ID, KIND, GROUP,       \
+                                     ALIAS, ALIASARGS, FLAGS, PARAM, HELPTEXT, \
+                                     METAVAR, VALUES, ALWAYS_EMIT, KEYPATH,    \
+                                     DEFAULT_VALUE, IS_POSITIVE)               \
+  this->KEYPATH = Args.hasArg(OPT_##ID) && IS_POSITIVE;
+
+#define OPTION_WITH_MARSHALLING_STRING(                                        \
+    PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,        \
+    HELPTEXT, METAVAR, VALUES, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE,            \
+    NORMALIZER, DENORMALIZER)                                                  \
+  {                                                                            \
+    auto Arg = Args.getLastArg(OPT_##ID);                                      \
+    this->KEYPATH =                                                            \
+        !Arg ? DEFAULT_VALUE : NORMALIZER(Arg, Args, Diags, DEFAULT_VALUE);    \
+  }
+
+#include "clang/Driver/Options.inc"
+#undef OPTION_WITH_MARSHALLING_STRING
+#undef OPTION_WITH_MARSHALLING_FLAG
+#undef OPTION_WITH_MARSHALLING
+  return true;
+}
+
 bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
                                         ArrayRef<const char *> CommandLineArgs,
                                         DiagnosticsEngine &Diags) {
@@ -3656,6 +3675,7 @@
     Success = false;
   }
 
+  Success &= Res.parseSimpleArgs(Args, Diags);
   Success &= ParseAnalyzerArgs(*Res.getAnalyzerOpts(), Args, Diags);
   Success &= ParseMigratorArgs(Res.getMigratorOpts(), Args);
   ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args);
@@ -3858,6 +3878,39 @@
   return llvm::APInt(64, code).toString(36, /*Signed=*/false);
 }
 
+void CompilerInvocation::generateCC1CommandLine(
+    SmallVectorImpl<const char *> &Args,
+    llvm::function_ref<const char *(const Twine &)> StringAllocator) const {
+#define PREFIX(PREFIX_TYPE, BRACED_INIT)                                       \
+  const char *PREFIX_TYPE[4] = BRACED_INIT;
+
+#define OPTION_WITH_MARSHALLING_FLAG(PREFIX_TYPE, NAME, ID, KIND, GROUP,       \
+                                     ALIAS, ALIASARGS, FLAGS, PARAM, HELPTEXT, \
+                                     METAVAR, VALUES, ALWAYS_EMIT, KEYPATH,    \
+                                     DEFAULT_VALUE, IS_POSITIVE)               \
+  if (FLAGS & options::CC1Option && IS_POSITIVE != DEFAULT_VALUE &&            \
+      (this->KEYPATH != DEFAULT_VALUE || ALWAYS_EMIT))                         \
+    Args.push_back(StringAllocator(Twine(PREFIX_TYPE[0]) + NAME));
+
+#define OPTION_WITH_MARSHALLING_STRING(                                        \
+    PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,        \
+    HELPTEXT, METAVAR, VALUES, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE,            \
+    NORMALIZER, DENORMALIZER)                                                  \
+  if ((FLAGS & options::CC1Option) &&                                          \
+      (this->KEYPATH != DEFAULT_VALUE || ALWAYS_EMIT)) {                       \
+    if (Option::KIND##Class == Option::SeparateClass) {                        \
+      Args.push_back(StringAllocator(Twine(PREFIX_TYPE[0]) + NAME));           \
+      Args.push_back(StringAllocator(DENORMALIZER(this->KEYPATH)));            \
+    }                                                                          \
+  }
+
+#include "clang/Driver/Options.inc"
+#undef OPTION_WITH_MARSHALLING_STRING
+#undef OPTION_WITH_MARSHALLING_FLAG
+#undef OPTION_WITH_MARSHALLING
+#undef PREFIX
+}
+
 namespace clang {
 
 IntrusiveRefCntPtr<llvm::vfs::FileSystem>
Index: clang/include/clang/Frontend/CompilerInvocation.h
===================================================================
--- clang/include/clang/Frontend/CompilerInvocation.h
+++ clang/include/clang/Frontend/CompilerInvocation.h
@@ -153,6 +153,8 @@
   /// one of the vaild-to-access (albeit arbitrary) states.
   ///
   /// \param [out] Res - The resulting invocation.
+  /// \param [in] CommandLineArgs - Array of argument strings, this must not
+  /// contain "-cc1".
   static bool CreateFromArgs(CompilerInvocation &Res,
                              ArrayRef<const char *> CommandLineArgs,
                              DiagnosticsEngine &Diags);
@@ -183,6 +185,20 @@
   /// identifying the conditions under which the module was built.
   std::string getModuleHash() const;
 
+  /// Generate a cc1-compatible command line arguments from this instance.
+  ///
+  /// \param [out] Args - The generated arguments. Note that the caller is
+  /// responsible for insersting the path to the clang executable and "-cc1" if
+  /// desired.
+  /// \param StringAllocator - A function that given a Twine can allocate
+  /// storage for a given command line argument and return a pointer to the
+  /// newly allocated string. The returned pointer is what gets appended to
+  /// Args.
+  void
+  generateCC1CommandLine(llvm::SmallVectorImpl<const char *> &Args,
+                         llvm::function_ref<const char *(const llvm::Twine &)>
+                             StringAllocator) const;
+
   /// @}
   /// @name Option Subgroups
   /// @{
@@ -221,6 +237,16 @@
   }
 
   /// @}
+
+private:
+  /// Parse options for flags that expose marshalling information in their
+  /// table-gen definition
+  ///
+  /// \param Args - The argument list containing the arguments to parse
+  /// \param Diags - The DiagnosticsEngine associated with CreateFromArgs
+  /// \returns - True if parsing was successful, false otherwise
+  bool parseSimpleArgs(const llvm::opt::ArgList &Args,
+                       DiagnosticsEngine &Diags);
 };
 
 IntrusiveRefCntPtr<llvm::vfs::FileSystem>
Index: clang/include/clang/Driver/CC1Options.td
===================================================================
--- clang/include/clang/Driver/CC1Options.td
+++ clang/include/clang/Driver/CC1Options.td
@@ -23,7 +23,10 @@
 def target_feature : Separate<["-"], "target-feature">,
   HelpText<"Target specific attributes">;
 def triple : Separate<["-"], "triple">,
-  HelpText<"Specify target triple (e.g. i686-apple-darwin9)">;
+  HelpText<"Specify target triple (e.g. i686-apple-darwin9)">,
+  NormalizedValuesScope<"llvm::sys">,
+  MarshallingInfoString<"TargetOpts->Triple", "getDefaultTargetTriple()">,
+  AlwaysEmit, Normalizer<"normalizeTriple">;
 def target_abi : Separate<["-"], "target-abi">,
   HelpText<"Target a particular ABI type">;
 def target_sdk_version_EQ : Joined<["-"], "target-sdk-version=">,
@@ -212,7 +215,11 @@
            "Note this may change .s semantics and shouldn't generally be used "
            "on compiler-generated code.">;
 def mrelocation_model : Separate<["-"], "mrelocation-model">,
-  HelpText<"The relocation model to use">, Values<"static,pic,ropi,rwpi,ropi-rwpi,dynamic-no-pic">;
+  HelpText<"The relocation model to use">, Values<"static,pic,ropi,rwpi,ropi-rwpi,dynamic-no-pic">,
+  NormalizedValuesScope<"llvm::Reloc">,
+  NormalizedValues<["Static", "PIC_", "ROPI", "RWPI", "ROPI_RWPI", "DynamicNoPIC"]>,
+  MarshallingInfoString<"CodeGenOpts.RelocationModel", "PIC_">,
+  AutoNormalizeEnum<"Model", "RelocationModel">;
 def fno_math_builtin : Flag<["-"], "fno-math-builtin">,
   HelpText<"Disable implicit builtin knowledge of math functions">;
 }
@@ -835,7 +842,8 @@
   HelpText<"Enable hashing the content of a module file">;
 def fmodules_strict_context_hash : Flag<["-"], "fmodules-strict-context-hash">,
   HelpText<"Enable hashing of all compiler options that could impact the "
-           "semantics of a module in an implicit build">;
+           "semantics of a module in an implicit build">,
+  MarshallingInfoFlag<"HeaderSearchOpts->ModulesStrictContextHash", "false">;
 def c_isystem : JoinedOrSeparate<["-"], "c-isystem">, MetaVarName<"<directory>">,
   HelpText<"Add directory to the C SYSTEM include search path">;
 def objc_isystem : JoinedOrSeparate<["-"], "objc-isystem">,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to