aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Campos <victor.campos@arm.com>2024-09-26 14:44:33 +0100
committerVictor Campos <victor.campos@arm.com>2024-10-01 14:28:49 +0100
commit1d394d0cbfb4a47d77f466b265671d0c13ebbb3b (patch)
tree87d6eee53c86ee5e96b97d099f65889d757a2c10
parent002079817c4d849973941795bb4d19bd822112d5 (diff)
downloadllvm-users/vhscampos/multilib-flags-processing.zip
llvm-users/vhscampos/multilib-flags-processing.tar.gz
llvm-users/vhscampos/multilib-flags-processing.tar.bz2
[Multilib] Custom flags processing for library selectionusers/vhscampos/multilib-flags-processing
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
-rw-r--r--clang/include/clang/Basic/DiagnosticDriverKinds.td3
-rw-r--r--clang/include/clang/Driver/Multilib.h3
-rw-r--r--clang/lib/Driver/Multilib.cpp77
-rw-r--r--clang/test/Driver/baremetal-multilib-custom-flags.yaml57
4 files changed, 139 insertions, 1 deletions
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 97573fc..2a724e2 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 53ab51a..88115fa 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -150,6 +150,9 @@ public:
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 4175bc1..0e3f305 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 0000000..4b4d823
--- /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