michaelplatings created this revision.
michaelplatings added reviewers: phosek, lenary, simon_tatham.
Herald added subscribers: abrachet, mgrang.
Herald added a project: All.
michaelplatings requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142933

Files:
  clang/include/clang/Driver/Options.td
  clang/include/clang/Driver/ToolChain.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.h
  clang/test/Driver/print-multi-selection-flags.c

Index: clang/test/Driver/print-multi-selection-flags.c
===================================================================
--- /dev/null
+++ clang/test/Driver/print-multi-selection-flags.c
@@ -0,0 +1,41 @@
+// RUN: %clang -print-multi-selection-flags --target=aarch64-linux -fc++-abi=itanium -fsanitize=address | FileCheck --check-prefix=CHECK-LINUX %s
+// CHECK-LINUX: fc++-abi=itanium
+// CHECK-LINUX-NEXT: fexceptions
+// CHECK-LINUX-NEXT: fno-experimental-relative-c++-abi-vtables
+// CHECK-LINUX-NEXT: frtti
+// CHECK-LINUX-NEXT: fsanitize=address
+// CHECK-LINUX-NEXT: target=aarch64-unknown-linux
+
+// RUN: %clang -print-multi-selection-flags --target=aarch64-fuchsia -fsanitize=hwaddress | FileCheck --check-prefix=CHECK-FUCHSIA %s
+// CHECK-FUCHSIA: fexperimental-relative-c++-abi-vtables
+// CHECK-FUCHSIA: fsanitize=hwaddress
+// CHECK-FUCHSIA: target=aarch64-unknown-fuchsia
+
+// RUN: %clang -print-multi-selection-flags --target=arm-none-eabi -mfloat-abi=soft -fno-exceptions -fno-rtti | FileCheck --check-prefix=CHECK-ARMV4T %s
+// CHECK-ARMV4T: fno-exceptions
+// CHECK-ARMV4T: fno-rtti
+// CHECK-ARMV4T: mfloat-abi=soft
+// CHECK-ARMV4T: mfpu=none
+// CHECK-ARMV4T: target=armv4t-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags --target=armv7em-none-eabi -mfloat-abi=softfp | FileCheck --check-prefix=CHECK-SOFTFP %s
+// CHECK-SOFTFP: mfloat-abi=softfp
+// CHECK-SOFTFP: mfpu=fpv4-sp-d16
+// CHECK-SOFTFP: target=thumbv7em-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags --target=arm-none-eabihf -march=armv7em -mfpu=fpv5-d16 | FileCheck --check-prefix=CHECK-HARD %s
+// CHECK-HARD: mfloat-abi=hard
+// CHECK-HARD: mfpu=fpv5-d16
+// CHECK-HARD: target=thumbv7em-none-unknown-eabihf
+
+// RUN: %clang -print-multi-selection-flags --target=arm-none-eabi -mfloat-abi=hard -march=armv8.1m.main+mve.fp | FileCheck --check-prefix=CHECK-MVE %s
+// CHECK-MVE: march=+mve
+// CHECK-MVE: march=+mve.fp
+// CHECK-MVE: mfloat-abi=hard
+// CHECK-MVE: mfpu=fp-armv8-fullfp16-sp-d16
+// CHECK-MVE: target=thumbv8.1m.main-none-unknown-eabihf
+
+// RUN: %clang -print-multi-selection-flags --target=arm-none-eabi -march=armv8.1m.main+mve+nofp | FileCheck --check-prefix=CHECK-MVENOFP %s
+// CHECK-MVENOFP: march=+mve
+// CHECK-MVENOFP-NOT: march=+mve.fp
+// CHECK-MVENOFP: mfpu=none
Index: clang/lib/Driver/ToolChains/Arch/ARM.h
===================================================================
--- clang/lib/Driver/ToolChains/Arch/ARM.h
+++ clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -64,9 +64,11 @@
 void getARMArchCPUFromArgs(const llvm::opt::ArgList &Args,
                            llvm::StringRef &Arch, llvm::StringRef &CPU,
                            bool FromAs = false);
+// Optionally returns the FPUKind
 void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
                           const llvm::opt::ArgList &Args,
-                          std::vector<llvm::StringRef> &Features, bool ForAS);
+                          std::vector<llvm::StringRef> &Features, bool ForAS,
+                          unsigned *OutFPUKind = nullptr);
 int getARMSubArchVersionNumber(const llvm::Triple &Triple);
 bool isARMMProfile(const llvm::Triple &Triple);
 bool isARMAProfile(const llvm::Triple &Triple);
Index: clang/lib/Driver/ToolChains/Arch/ARM.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -438,7 +438,8 @@
 
 void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
                                const ArgList &Args,
-                               std::vector<StringRef> &Features, bool ForAS) {
+                               std::vector<StringRef> &Features, bool ForAS,
+                               unsigned *OutFPUKind) {
   bool KernelOrKext =
       Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
   arm::FloatABI ABI = arm::getARMFloatABI(D, Triple, Args);
@@ -643,6 +644,7 @@
                     {"-dotprod", "-fp16fml", "-bf16", "-mve.fp"});
     if (!hasIntegerMVE(Features))
       Features.emplace_back("-fpregs");
+    FPUID = llvm::ARM::FK_NONE;
   }
 
   // En/disable crc code generation.
@@ -899,6 +901,10 @@
 
   if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
     Features.push_back("+no-bti-at-return-twice");
+
+  if (OutFPUKind) {
+    *OutFPUKind = FPUID;
+  }
 }
 
 std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) {
Index: clang/lib/Driver/ToolChain.cpp
===================================================================
--- clang/lib/Driver/ToolChain.cpp
+++ clang/lib/Driver/ToolChain.cpp
@@ -9,10 +9,12 @@
 #include "clang/Driver/ToolChain.h"
 #include "ToolChains/Arch/ARM.h"
 #include "ToolChains/Clang.h"
+#include "ToolChains/CommonArgs.h"
 #include "ToolChains/Flang.h"
 #include "ToolChains/InterfaceStubs.h"
 #include "clang/Basic/ObjCRuntime.h"
 #include "clang/Basic/Sanitizers.h"
+#include "clang/Basic/TargetCXXABI.h"
 #include "clang/Config/config.h"
 #include "clang/Driver/Action.h"
 #include "clang/Driver/Driver.h"
@@ -170,6 +172,112 @@
   return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
 }
 
+std::vector<std::string>
+ToolChain::getMultiSelectionFlags(const llvm::opt::ArgList &Args) const {
+  std::vector<std::string> Result;
+
+  using namespace clang::driver::options;
+
+  const llvm::Triple Triple(ComputeEffectiveClangTriple(Args));
+
+  // Enumerate boolean flags we care about for the purposes of multilib here.
+  // There must be a smarter way to do it but this gets us started.
+  const struct HasFlag {
+    ID Pos, Neg;
+    bool Default;
+  } HasFlagList[] = {
+      {OPT_fexceptions, OPT_fno_exceptions, true},
+      {OPT_frtti, OPT_fno_rtti, true},
+      {OPT_fexperimental_relative_cxx_abi_vtables,
+       OPT_fno_experimental_relative_cxx_abi_vtables,
+       TargetCXXABI::usesRelativeVTables(Triple)},
+  };
+
+  // Options we care about that have a single last-wins value.
+  static const ID GetLastArgValue[] = {
+      OPT_fcxx_abi_EQ,
+  };
+
+  for (const HasFlag &HF : HasFlagList) {
+    ID Option = Args.hasFlag(HF.Pos, HF.Neg, HF.Default) ? HF.Pos : HF.Neg;
+    Result.push_back(
+        clang::driver::getDriverOptTable().getOptionName(Option).str());
+  }
+
+  for (ID Option : GetLastArgValue) {
+    StringRef Value = Args.getLastArgValue(Option);
+    if (!Value.empty()) {
+      Result.push_back(
+          (clang::driver::getDriverOptTable().getOptionName(Option) + Value)
+              .str());
+    }
+  }
+
+  const SanitizerArgs SanArgs(getSanitizerArgs(Args));
+  if (SanArgs.needsAsanRt()) {
+    Result.push_back("fsanitize=address");
+  }
+  if (SanArgs.needsHwasanRt()) {
+    Result.push_back("fsanitize=hwaddress");
+  }
+
+  switch (Triple.getArch()) {
+  case llvm::Triple::arm:
+  case llvm::Triple::armeb:
+  case llvm::Triple::thumb:
+  case llvm::Triple::thumbeb: {
+    std::vector<StringRef> Features;
+    unsigned FPUKind = llvm::ARM::FK_INVALID;
+    tools::arm::getARMTargetFeatures(D, Triple, Args, Features, false,
+                                     &FPUKind);
+    const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);
+    llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),
+                                         UnifiedFeatures.end());
+    for (const auto &Ext : ARM::ARCHExtNames) {
+      if (FeatureSet.find(Ext.Feature) != FeatureSet.end()) {
+        Result.push_back(("march=+" + Ext.Name).str());
+      }
+    }
+
+    switch (FPUKind) {
+#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION)                \
+  case llvm::ARM::KIND:                                                        \
+    Result.push_back("mfpu=" NAME);                                            \
+    break;
+#include "llvm/TargetParser/ARMTargetParser.def"
+    default:
+      llvm_unreachable("Invalid FPUKind");
+    }
+
+    switch (arm::getARMFloatABI(D, Triple, Args)) {
+    case arm::FloatABI::Soft:
+      Result.push_back("mfloat-abi=soft");
+      break;
+    case arm::FloatABI::SoftFP:
+      Result.push_back("mfloat-abi=softfp");
+      break;
+    case arm::FloatABI::Hard:
+      Result.push_back("mfloat-abi=hard");
+      break;
+    case arm::FloatABI::Invalid:
+      llvm_unreachable("Invalid float ABI");
+    }
+  } break;
+  default:
+    break;
+  }
+
+  Result.push_back("target=" + Triple.str());
+
+  // Sort alphabetically
+  std::sort(Result.begin(), Result.end());
+
+  // Remove duplicate entries
+  Result.erase(std::unique(Result.begin(), Result.end()), Result.end());
+
+  return Result;
+}
+
 SanitizerArgs
 ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const {
   SanitizerArgs SanArgs(*this, JobArgs, !SanitizerArgsChecked);
Index: clang/lib/Driver/Driver.cpp
===================================================================
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -2209,6 +2209,12 @@
     return false;
   }
 
+  if (C.getArgs().hasArg(options::OPT_print_multi_selection_flags)) {
+    for (StringRef Attr : TC.getMultiSelectionFlags(C.getArgs()))
+      llvm::outs() << Attr << '\n';
+    return false;
+  }
+
   if (C.getArgs().hasArg(options::OPT_print_multi_directory)) {
     const Multilib &Multilib = TC.getMultilib();
     if (Multilib.gccSuffix().empty())
Index: clang/include/clang/Driver/ToolChain.h
===================================================================
--- clang/include/clang/Driver/ToolChain.h
+++ clang/include/clang/Driver/ToolChain.h
@@ -285,6 +285,27 @@
 
   const Multilib &getMultilib() const { return SelectedMultilib; }
 
+  /// Get flags suitable for multilib selection, based on the provided clang
+  /// command line arguments. The arguments aren't suitable to be used directly
+  /// for multilib selection because they are not normalized and normalization
+  /// is a complex process. The result of this function is similar to clang
+  /// command line arguments but different:
+  /// * It's incomplete. Only certain arguments are processed. If more arguments
+  ///   are needed for multilib selection then this function should be extended.
+  /// * The flags aren't prefixed with "-".
+  /// * Where a single command line argument would contain a list, the elements
+  ///   are split out. For example, Arm extensions are appended to -march like
+  ///   -march=armv8m.main+crc+crypto+sha2+mve. Since this function is
+  ///   incomplete, a later clang version may infer the presence of more
+  ///   extensions than an earlier version. If all extensions were in a single
+  ///   flag then that would be unstable. Instead, each extension will be
+  ///   returned separately. There may not be valid syntax to express this as a
+  ///   clang argument so an pseudo argument syntax must be used instead.
+  /// To allow users to find out what flags are returned, clang accepts a
+  /// -print-multi-selection-flags argument.
+  std::vector<std::string>
+  getMultiSelectionFlags(const llvm::opt::ArgList &) const;
+
   SanitizerArgs getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const;
 
   const XRayArgs& getXRayArgs() const;
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -4155,6 +4155,8 @@
            "library (\"libgcc.a\" or \"libclang_rt.builtins.*.a\")">;
 def print_multi_directory : Flag<["-", "--"], "print-multi-directory">;
 def print_multi_lib : Flag<["-", "--"], "print-multi-lib">;
+def print_multi_selection_flags : Flag<["-", "--"], "print-multi-selection-flags">,
+  HelpText<"Print the flags used for selecting multilibs">;
 def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
   Flags<[Unsupported]>;
 def print_target_triple : Flag<["-", "--"], "print-target-triple">,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to