[clang] a794ab9 - [Driver] Add -print-multi-flags-experimental option

Michael Platings via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 13 22:47:20 PDT 2023


Author: Michael Platings
Date: 2023-06-14T06:46:41+01:00
New Revision: a794ab92b41f00ba29b5852c34a510173638dcc0

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

LOG: [Driver] Add -print-multi-flags-experimental option

This option causes the flags used for selecting multilibs to be printed.
This is an experimental feature that is documented in detail in D143587.

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

Added: 
    clang/test/Driver/print-multi-selection-flags.c

Modified: 
    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

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 8f5db34551c07..cc6ee3c5d5c18 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4330,6 +4330,8 @@ def print_libgcc_file_name : Flag<["-", "--"], "print-libgcc-file-name">,
            "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_flags : Flag<["-", "--"], "print-multi-flags-experimental">,
+  HelpText<"Print the flags used for selecting multilibs (experimental)">;
 def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
   Flags<[Unsupported]>;
 def print_target_triple : Flag<["-", "--"], "print-target-triple">,

diff  --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index a4346a1bab8d2..3b3932f1e3432 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -285,6 +285,18 @@ class ToolChain {
 
   const Multilib &getMultilib() const { return SelectedMultilib; }
 
+  /// Get flags suitable for multilib selection, based on the provided clang
+  /// command line arguments. The command line 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 except that the list of arguments is
+  /// incomplete. Only certain command line arguments are processed. If more
+  /// command line arguments are needed for multilib selection then this
+  /// function should be extended.
+  /// To allow users to find out what flags are returned, clang accepts a
+  /// -print-multi-flags-experimental argument.
+  Multilib::flags_list getMultilibFlags(const llvm::opt::ArgList &) const;
+
   SanitizerArgs getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const;
 
   const XRayArgs& getXRayArgs() const;

diff  --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 243aebb3bc23f..87c31f993d758 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2217,6 +2217,17 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
     return false;
   }
 
+  if (C.getArgs().hasArg(options::OPT_print_multi_flags)) {
+    Multilib::flags_list ArgFlags = TC.getMultilibFlags(C.getArgs());
+    llvm::StringSet<> ExpandedFlags = TC.getMultilibs().expandFlags(ArgFlags);
+    std::set<llvm::StringRef> SortedFlags;
+    for (const auto &FlagEntry : ExpandedFlags)
+      SortedFlags.insert(FlagEntry.getKey());
+    for (auto Flag : SortedFlags)
+      llvm::outs() << Flag << '\n';
+    return false;
+  }
+
   if (C.getArgs().hasArg(options::OPT_print_multi_directory)) {
     const Multilib &Multilib = TC.getMultilib();
     if (Multilib.gccSuffix().empty())

diff  --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index ccaebb384d4dc..9276b9a2ab85b 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -7,8 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Driver/ToolChain.h"
+#include "ToolChains/Arch/AArch64.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"
@@ -39,6 +41,7 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/VersionTuple.h"
 #include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/TargetParser/AArch64TargetParser.h"
 #include "llvm/TargetParser/TargetParser.h"
 #include "llvm/TargetParser/Triple.h"
 #include <cassert>
@@ -171,6 +174,101 @@ bool ToolChain::defaultToIEEELongDouble() const {
   return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
 }
 
+static void getAArch64MultilibFlags(const Driver &D,
+                                          const llvm::Triple &Triple,
+                                          const llvm::opt::ArgList &Args,
+                                          Multilib::flags_list &Result) {
+  std::vector<StringRef> Features;
+  tools::aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, false);
+  const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);
+  llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),
+                                       UnifiedFeatures.end());
+  std::vector<std::string> MArch;
+  for (const auto &Ext : AArch64::Extensions)
+    if (FeatureSet.find(Ext.Feature) != FeatureSet.end())
+      MArch.push_back(Ext.Name.str());
+  for (const auto &Ext : AArch64::Extensions)
+    if (FeatureSet.find(Ext.NegFeature) != FeatureSet.end())
+      MArch.push_back(("no" + Ext.Name).str());
+  MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str());
+  Result.push_back(llvm::join(MArch, "+"));
+}
+
+static void getARMMultilibFlags(const Driver &D,
+                                      const llvm::Triple &Triple,
+                                      const llvm::opt::ArgList &Args,
+                                      Multilib::flags_list &Result) {
+  std::vector<StringRef> Features;
+  llvm::ARM::FPUKind FPUKind =
+      tools::arm::getARMTargetFeatures(D, Triple, Args, Features, false);
+  const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);
+  llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),
+                                       UnifiedFeatures.end());
+  std::vector<std::string> MArch;
+  for (const auto &Ext : ARM::ARCHExtNames)
+    if (FeatureSet.find(Ext.Feature) != FeatureSet.end())
+      MArch.push_back(Ext.Name.str());
+  for (const auto &Ext : ARM::ARCHExtNames)
+    if (FeatureSet.find(Ext.NegFeature) != FeatureSet.end())
+      MArch.push_back(("no" + Ext.Name).str());
+  MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str());
+  Result.push_back(llvm::join(MArch, "+"));
+
+  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");
+  }
+}
+
+Multilib::flags_list
+ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {
+  using namespace clang::driver::options;
+
+  std::vector<std::string> Result;
+  const llvm::Triple Triple(ComputeEffectiveClangTriple(Args));
+  Result.push_back("--target=" + Triple.str());
+
+  switch (Triple.getArch()) {
+  case llvm::Triple::aarch64:
+  case llvm::Triple::aarch64_32:
+  case llvm::Triple::aarch64_be:
+    getAArch64MultilibFlags(D, Triple, Args, Result);
+    break;
+  case llvm::Triple::arm:
+  case llvm::Triple::armeb:
+  case llvm::Triple::thumb:
+  case llvm::Triple::thumbeb:
+    getARMMultilibFlags(D, Triple, Args, Result);
+    break;
+  default:
+    break;
+  }
+
+  // Sort and remove duplicates.
+  std::sort(Result.begin(), Result.end());
+  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);

diff  --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index 705457805ed64..62eee13664523 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -463,9 +463,11 @@ static bool hasIntegerMVE(const std::vector<StringRef> &F) {
          (NoMVE == F.rend() || std::distance(MVE, NoMVE) > 0);
 }
 
-void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
-                               const ArgList &Args,
-                               std::vector<StringRef> &Features, bool ForAS) {
+llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver &D,
+                                             const llvm::Triple &Triple,
+                                             const ArgList &Args,
+                                             std::vector<StringRef> &Features,
+                                             bool ForAS) {
   bool KernelOrKext =
       Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
   arm::FloatABI ABI = arm::getARMFloatABI(D, Triple, Args);
@@ -661,6 +663,7 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
     Features.insert(Features.end(),
                     {"-dotprod", "-fp16fml", "-bf16", "-mve", "-mve.fp"});
     HasFPRegs = false;
+    FPUKind = llvm::ARM::FK_NONE;
   } else if (FPUKind == llvm::ARM::FK_NONE ||
              ArchArgFPUKind == llvm::ARM::FK_NONE ||
              CPUArgFPUKind == llvm::ARM::FK_NONE) {
@@ -671,6 +674,7 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
     Features.insert(Features.end(),
                     {"-dotprod", "-fp16fml", "-bf16", "-mve.fp"});
     HasFPRegs = hasIntegerMVE(Features);
+    FPUKind = llvm::ARM::FK_NONE;
   }
   if (!HasFPRegs)
     Features.emplace_back("-fpregs");
@@ -931,6 +935,8 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
     Features.push_back("+no-bti-at-return-twice");
 
   checkARMFloatABI(D, Args, HasFPRegs);
+
+  return FPUKind;
 }
 
 std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) {

diff  --git a/clang/lib/Driver/ToolChains/Arch/ARM.h b/clang/lib/Driver/ToolChains/Arch/ARM.h
index 18a358c55c1b4..0f18305579a2a 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.h
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -63,9 +63,11 @@ bool useAAPCSForMachO(const llvm::Triple &T);
 void getARMArchCPUFromArgs(const llvm::opt::ArgList &Args,
                            llvm::StringRef &Arch, llvm::StringRef &CPU,
                            bool FromAs = false);
-void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
-                          const llvm::opt::ArgList &Args,
-                          std::vector<llvm::StringRef> &Features, bool ForAS);
+llvm::ARM::FPUKind getARMTargetFeatures(const Driver &D,
+                                        const llvm::Triple &Triple,
+                                        const llvm::opt::ArgList &Args,
+                                        std::vector<llvm::StringRef> &Features,
+                                        bool ForAS);
 int getARMSubArchVersionNumber(const llvm::Triple &Triple);
 bool isARMMProfile(const llvm::Triple &Triple);
 bool isARMAProfile(const llvm::Triple &Triple);

diff  --git a/clang/test/Driver/print-multi-selection-flags.c b/clang/test/Driver/print-multi-selection-flags.c
new file mode 100644
index 0000000000000..819ff242ced00
--- /dev/null
+++ b/clang/test/Driver/print-multi-selection-flags.c
@@ -0,0 +1,44 @@
+// RUN: %clang -print-multi-flags-experimental --target=aarch64-linux -fc++-abi=itanium -fsanitize=address | FileCheck --check-prefix=CHECK-LINUX %s
+// CHECK-LINUX: --target=aarch64-unknown-linux
+
+// RUN: %clang -print-multi-flags-experimental --target=aarch64-fuchsia -fsanitize=hwaddress | FileCheck --check-prefix=CHECK-FUCHSIA %s
+// CHECK-FUCHSIA: --target=aarch64-unknown-fuchsia
+
+// RUN: %clang -print-multi-flags-experimental --target=arm-none-eabi -mfloat-abi=soft -fno-exceptions -fno-rtti | FileCheck --check-prefix=CHECK-ARMV4T %s
+// CHECK-ARMV4T: --target=armv4t-none-unknown-eabi
+// CHECK-ARMV4T: -mfloat-abi=soft
+// CHECK-ARMV4T: -mfpu=none
+
+// RUN: %clang -print-multi-flags-experimental --target=armv7em-none-eabi -mfloat-abi=softfp | FileCheck --check-prefix=CHECK-SOFTFP %s
+// CHECK-SOFTFP: --target=thumbv7em-none-unknown-eabi
+// CHECK-SOFTFP: -mfloat-abi=softfp
+// CHECK-SOFTFP: -mfpu=fpv4-sp-d16
+
+// RUN: %clang -print-multi-flags-experimental --target=arm-none-eabihf -march=armv7em -mfpu=fpv5-d16 | FileCheck --check-prefix=CHECK-HARD %s
+// CHECK-HARD: --target=thumbv7em-none-unknown-eabihf
+// CHECK-HARD: -mfloat-abi=hard
+// CHECK-HARD: -mfpu=fpv5-d16
+
+// RUN: %clang -print-multi-flags-experimental --target=arm-none-eabi -mfloat-abi=soft -march=armv8-m.main+nofp | FileCheck --check-prefix=CHECK-V8MMAIN-NOFP %s
+// CHECK-V8MMAIN-NOFP: --target=thumbv8m.main-none-unknown-eabi
+// CHECK-V8MMAIN-NOFP: -mfloat-abi=soft
+// CHECK-V8MMAIN-NOFP: -mfpu=none
+
+// RUN: %clang -print-multi-flags-experimental --target=arm-none-eabi -mfloat-abi=hard -march=armv8.1m.main+mve.fp | FileCheck --check-prefix=CHECK-MVE %s
+// CHECK-MVE: --target=thumbv8.1m.main-none-unknown-eabihf
+// CHECK-MVE: -march=thumbv8.1m.main{{.*}}+mve{{.*}}+mve.fp{{.*}}
+// CHECK-MVE: -mfloat-abi=hard
+// CHECK-MVE: -mfpu=fp-armv8-fullfp16-sp-d16
+
+// RUN: %clang -print-multi-flags-experimental --target=arm-none-eabi -march=armv8.1m.main+mve+nofp | FileCheck --check-prefix=CHECK-MVENOFP %s
+// CHECK-MVENOFP: -march=thumbv8.1m.main{{.*}}+mve{{.*}}
+// CHECK-MVENOFP-NOT: -march=thumbv8.1m.main{{.*}}+mve.fp{{.*}}
+// CHECK-MVENOFP: -mfpu=none
+
+// RUN: %clang -print-multi-flags-experimental --target=aarch64-none-elf -march=armv8-a+lse | FileCheck --check-prefix=CHECK-LSE %s
+// CHECK-LSE: -march=aarch64{{.*}}+lse{{.*}}
+
+// RUN: %clang -print-multi-flags-experimental --target=aarch64-none-elf -march=armv8.5-a+sve+sve2 | FileCheck --check-prefix=CHECK-SVE2 %s
+// RUN: %clang -print-multi-flags-experimental --target=aarch64-none-elf -march=armv9-a            | FileCheck --check-prefix=CHECK-SVE2 %s
+// CHECK-SVE2: --target=aarch64-none-unknown-elf
+// CHECK-SVE2: -march=aarch64{{.*}}+simd{{.*}}+sve{{.*}}+sve2{{.*}}


        


More information about the cfe-commits mailing list