[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

Victor Campos via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Oct 1 06:32:17 PDT 2024


https://github.com/vhscampos updated https://github.com/llvm/llvm-project/pull/110659

>From 1d394d0cbfb4a47d77f466b265671d0c13ebbb3b Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Thu, 26 Sep 2024 14:44:33 +0100
Subject: [PATCH] [Multilib] Custom flags processing for library selection

Select library variants in the multilib system using the flags passed in
the '-fmultilib-flag=' format.

Multilib flags that were not passed in the command-line have their
default value  fed into the library selection mechanism.

A warning is shown if the flag's value is invalid. The closest valid
value is suggested (string edit distance).

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 .../clang/Basic/DiagnosticDriverKinds.td      |  3 +
 clang/include/clang/Driver/Multilib.h         |  3 +
 clang/lib/Driver/Multilib.cpp                 | 77 ++++++++++++++++++-
 .../baremetal-multilib-custom-flags.yaml      | 57 ++++++++++++++
 4 files changed, 139 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/Driver/baremetal-multilib-custom-flags.yaml

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 97573fcf20c1fb..2a724e2f483970 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -14,6 +14,9 @@ def err_drv_no_such_file_with_suggestion : Error<
 def err_drv_unsupported_opt : Error<"unsupported option '%0'">;
 def err_drv_unsupported_opt_with_suggestion : Error<
   "unsupported option '%0'; did you mean '%1'?">;
+def warn_drv_unsupported_opt_with_suggestion : Warning<
+  "unsupported option '%0'; did you mean '%1'?">,
+  InGroup<UnusedCommandLineArgument>;
 def err_drv_unsupported_opt_for_target : Error<
   "unsupported option '%0' for target '%1'">;
 def err_drv_unsupported_opt_for_language_mode : Error<
diff --git a/clang/include/clang/Driver/Multilib.h b/clang/include/clang/Driver/Multilib.h
index 53ab51a33eea67..88115fa7c31eee 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -150,6 +150,9 @@ class MultilibSet {
   const_iterator begin() const { return Multilibs.begin(); }
   const_iterator end() const { return Multilibs.end(); }
 
+  Multilib::flags_list
+  processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const;
+
   /// Select compatible variants, \returns false if none are compatible
   bool select(const Driver &D, const Multilib::flags_list &Flags,
               llvm::SmallVectorImpl<Multilib> &) const;
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 4175bc13834ed2..0e3f305848c974 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -11,6 +11,7 @@
 #include "clang/Basic/Version.h"
 #include "clang/Driver/Driver.h"
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
@@ -96,9 +97,83 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
 
 void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
 
+static void WarnUnclaimedMultilibCustomFlags(
+    const Driver &D, const SmallVector<StringRef> &UnclaimedCustomFlagValues,
+    const SmallVector<MultilibSet::CustomFlagDeclaration> &CustomFlagDecls,
+    const StringRef MultilibFlagOptionStr) {
+  struct EditDistanceInfo {
+    StringRef FlagValue;
+    unsigned EditDistance;
+  };
+
+  for (StringRef Unclaimed : UnclaimedCustomFlagValues) {
+    std::optional<EditDistanceInfo> BestCandidate;
+    for (const auto &Decl : CustomFlagDecls) {
+      for (StringRef FlagValue : Decl.Values) {
+        unsigned EditDistance =
+            Unclaimed.edit_distance(FlagValue, /*AllowReplacements=*/false);
+        if (!BestCandidate || EditDistance < BestCandidate->EditDistance) {
+          BestCandidate = {std::move(FlagValue), EditDistance};
+        }
+      }
+    }
+    if (!BestCandidate)
+      continue;
+    D.Diag(clang::diag::warn_drv_unsupported_opt_with_suggestion)
+        << (MultilibFlagOptionStr + Unclaimed).str()
+        << (MultilibFlagOptionStr + BestCandidate->FlagValue).str();
+  }
+}
+
+Multilib::flags_list
+MultilibSet::processCustomFlags(const Driver &D,
+                                const Multilib::flags_list &Flags) const {
+  Multilib::flags_list Result;
+  constexpr StringRef MultilibFlagOptionStr = "-fmultilib-flag=";
+  SmallVector<StringRef> CustomFlags;
+
+  for (StringRef Flag : Flags) {
+    if (Flag.starts_with(MultilibFlagOptionStr))
+      CustomFlags.push_back(std::move(Flag));
+    else
+      Result.push_back(Flag.str());
+  }
+
+  SmallVector<StringRef> UnclaimedCustomFlagValues;
+  llvm::SmallSet<StringRef, 8> TriggeredCustomFlagDecls;
+
+  for (StringRef Flag : llvm::reverse(CustomFlags)) {
+    StringRef CustomFlagValue = Flag.drop_front(MultilibFlagOptionStr.size());
+    bool Claimed = false;
+    for (const CustomFlagDeclaration &Decl : CustomFlagDecls) {
+      if (llvm::is_contained(Decl.Values, CustomFlagValue)) {
+        Result.push_back(Flag.str());
+        TriggeredCustomFlagDecls.insert(Decl.Name);
+        Claimed = true;
+        break;
+      }
+    }
+    if (!Claimed) {
+      UnclaimedCustomFlagValues.push_back(std::move(CustomFlagValue));
+    }
+  }
+
+  for (const CustomFlagDeclaration &Decl : CustomFlagDecls) {
+    if (TriggeredCustomFlagDecls.contains(Decl.Name))
+      continue;
+    Result.push_back(MultilibFlagOptionStr.str() + Decl.DefaultValue);
+  }
+
+  WarnUnclaimedMultilibCustomFlags(D, UnclaimedCustomFlagValues,
+                                   CustomFlagDecls, MultilibFlagOptionStr);
+
+  return Result;
+}
+
 bool MultilibSet::select(const Driver &D, const Multilib::flags_list &Flags,
                          llvm::SmallVectorImpl<Multilib> &Selected) const {
-  llvm::StringSet<> FlagSet(expandFlags(Flags));
+  Multilib::flags_list FlagsWithCustom = processCustomFlags(D, Flags);
+  llvm::StringSet<> FlagSet(expandFlags(FlagsWithCustom));
   Selected.clear();
 
   // Decide which multilibs we're going to select at all.
diff --git a/clang/test/Driver/baremetal-multilib-custom-flags.yaml b/clang/test/Driver/baremetal-multilib-custom-flags.yaml
new file mode 100644
index 00000000000000..4b4d823cd08e1e
--- /dev/null
+++ b/clang/test/Driver/baremetal-multilib-custom-flags.yaml
@@ -0,0 +1,57 @@
+# REQUIRES: shell
+# UNSUPPORTED: system-windows
+
+# RUN: rm -rf %T/baremetal_multilib
+# RUN: mkdir -p %T/baremetal_multilib/bin
+# RUN: mkdir -p %T/baremetal_multilib/lib/clang-runtimes
+# RUN: ln -s %clang %T/baremetal_multilib/bin/clang
+# RUN: ln -s %s %T/baremetal_multilib/lib/clang-runtimes/multilib.yaml
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x c %s -### -o %t.out 2>&1 \
+# RUN:     --target=thumbv8m.main-none-eabi -mfpu=none --sysroot= \
+# RUN:   | FileCheck -DSYSROOT=%T/baremetal_multilib --check-prefix=CHECK-DEFAULT %s
+
+# CHECK-DEFAULT:      "-cc1" "-triple" "thumbv8m.main-unknown-none-eabi"
+# CHECK-DEFAULT-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/nofp/include"
+# CHECK-DEFAULT-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/nofp/lib"
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x c %s -### -o %t.out 2>&1 \
+# RUN:     --target=thumbv8m.main-none-eabi -mfpu=none -fmultilib-flag=no-multithreaded --sysroot= \
+# RUN:   | FileCheck -DSYSROOT=%T/baremetal_multilib --check-prefix=CHECK-NOMULTI %s
+
+# CHECK-NOMULTI:      "-cc1" "-triple" "thumbv8m.main-unknown-none-eabi"
+# CHECK-NOMULTI-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/nofp/include"
+# CHECK-NOMULTI-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/nofp/lib"
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x c %s -### -o %t.out 2>&1 \
+# RUN:     --target=thumbv8m.main-none-eabi -mfpu=none -fmultilib-flag=multithreaded --sysroot= \
+# RUN:   | FileCheck -DSYSROOT=%T/baremetal_multilib --check-prefix=CHECK-MULTI %s
+
+# CHECK-MULTI:      "-cc1" "-triple" "thumbv8m.main-unknown-none-eabi"
+# CHECK-MULTI-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/multithreaded/thumb/v8-m.main/nofp/include"
+# CHECK-MULTI-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/multithreaded/thumb/v8-m.main/nofp/lib"
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x c %s -### -o %t.out 2>&1 \
+# RUN:     --target=thumbv8m.main-none-eabi -mfpu=none -fmultilib-flag=multi-threaded --sysroot= \
+# RUN:   | FileCheck -DSYSROOT=%T/baremetal_multilib --check-prefix=CHECK-WARNING %s
+# CHECK-WARNING: warning: unsupported option '-fmultilib-flag=multi-threaded'; did you mean '-fmultilib-flag=multithreaded'?
+
+---
+MultilibVersion: 1.0
+
+Groups:
+- Name: stdlib
+  Type: Exclusive
+
+Variants:
+- Dir: arm-none-eabi/thumb/v8-m.main/nofp
+  Flags: [--target=thumbv8m.main-unknown-none-eabi, -mfpu=none, -fmultilib-flag=no-multithreaded]
+  Group: stdlib
+- Dir: arm-none-eabi/multithreaded/thumb/v8-m.main/nofp
+  Flags: [--target=thumbv8m.main-unknown-none-eabi, -mfpu=none, -fmultilib-flag=multithreaded]
+  Group: stdlib
+
+Flags:
+ - Name: multithreading
+   Values: [no-multithreaded, multithreaded]
+   Default: no-multithreaded



More information about the llvm-branch-commits mailing list