[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