diff options
author | Victor Campos <victor.campos@arm.com> | 2024-09-26 14:44:33 +0100 |
---|---|---|
committer | Victor Campos <victor.campos@arm.com> | 2024-10-01 14:28:49 +0100 |
commit | 1d394d0cbfb4a47d77f466b265671d0c13ebbb3b (patch) | |
tree | 87d6eee53c86ee5e96b97d099f65889d757a2c10 | |
parent | 002079817c4d849973941795bb4d19bd822112d5 (diff) | |
download | llvm-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.td | 3 | ||||
-rw-r--r-- | clang/include/clang/Driver/Multilib.h | 3 | ||||
-rw-r--r-- | clang/lib/Driver/Multilib.cpp | 77 | ||||
-rw-r--r-- | clang/test/Driver/baremetal-multilib-custom-flags.yaml | 57 |
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 |