michaelplatings updated this revision to Diff 494371. michaelplatings added a comment.
Put "experimental" in the argument name. The intention is to include the new multilib as an experimental feature in LLVM 17 and stabilise it in LLVM 18. Also remove support for -f(no-)experimental-relative-c++-abi-vtables from the new multilib since Fuchsia no longer needs it. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D142933/new/ https://reviews.llvm.org/D142933 Files: 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 clang/test/Driver/print-multi-selection-flags.c
Index: clang/test/Driver/print-multi-selection-flags.c =================================================================== --- /dev/null +++ clang/test/Driver/print-multi-selection-flags.c @@ -0,0 +1,39 @@ +// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-linux -fc++-abi=itanium -fsanitize=address | FileCheck --check-prefix=CHECK-LINUX %s +// CHECK-LINUX: fc++-abi=itanium +// CHECK-LINUX-NEXT: fexceptions +// CHECK-LINUX-NEXT: frtti +// CHECK-LINUX-NEXT: fsanitize=address +// CHECK-LINUX-NEXT: target=aarch64-unknown-linux + +// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-fuchsia -fsanitize=hwaddress | FileCheck --check-prefix=CHECK-FUCHSIA %s +// CHECK-FUCHSIA: fsanitize=hwaddress +// CHECK-FUCHSIA: target=aarch64-unknown-fuchsia + +// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -mfloat-abi=soft -fno-exceptions -fno-rtti | FileCheck --check-prefix=CHECK-ARMV4T %s +// CHECK-ARMV4T: fno-exceptions +// CHECK-ARMV4T: fno-rtti +// CHECK-ARMV4T: mfloat-abi=soft +// CHECK-ARMV4T: mfpu=none +// CHECK-ARMV4T: target=armv4t-none-unknown-eabi + +// RUN: %clang -print-multi-selection-flags-experimental --target=armv7em-none-eabi -mfloat-abi=softfp | FileCheck --check-prefix=CHECK-SOFTFP %s +// CHECK-SOFTFP: mfloat-abi=softfp +// CHECK-SOFTFP: mfpu=fpv4-sp-d16 +// CHECK-SOFTFP: target=thumbv7em-none-unknown-eabi + +// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabihf -march=armv7em -mfpu=fpv5-d16 | FileCheck --check-prefix=CHECK-HARD %s +// CHECK-HARD: mfloat-abi=hard +// CHECK-HARD: mfpu=fpv5-d16 +// CHECK-HARD: target=thumbv7em-none-unknown-eabihf + +// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -mfloat-abi=hard -march=armv8.1m.main+mve.fp | FileCheck --check-prefix=CHECK-MVE %s +// CHECK-MVE: march=+mve +// CHECK-MVE: march=+mve.fp +// CHECK-MVE: mfloat-abi=hard +// CHECK-MVE: mfpu=fp-armv8-fullfp16-sp-d16 +// CHECK-MVE: target=thumbv8.1m.main-none-unknown-eabihf + +// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -march=armv8.1m.main+mve+nofp | FileCheck --check-prefix=CHECK-MVENOFP %s +// CHECK-MVENOFP: march=+mve +// CHECK-MVENOFP-NOT: march=+mve.fp +// CHECK-MVENOFP: mfpu=none Index: clang/lib/Driver/ToolChains/Arch/ARM.h =================================================================== --- clang/lib/Driver/ToolChains/Arch/ARM.h +++ clang/lib/Driver/ToolChains/Arch/ARM.h @@ -64,9 +64,11 @@ void getARMArchCPUFromArgs(const llvm::opt::ArgList &Args, llvm::StringRef &Arch, llvm::StringRef &CPU, bool FromAs = false); +// Optionally returns the FPUKind void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args, - std::vector<llvm::StringRef> &Features, bool ForAS); + std::vector<llvm::StringRef> &Features, bool ForAS, + unsigned *OutFPUKind = nullptr); int getARMSubArchVersionNumber(const llvm::Triple &Triple); bool isARMMProfile(const llvm::Triple &Triple); bool isARMAProfile(const llvm::Triple &Triple); Index: clang/lib/Driver/ToolChains/Arch/ARM.cpp =================================================================== --- clang/lib/Driver/ToolChains/Arch/ARM.cpp +++ clang/lib/Driver/ToolChains/Arch/ARM.cpp @@ -438,7 +438,8 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple, const ArgList &Args, - std::vector<StringRef> &Features, bool ForAS) { + std::vector<StringRef> &Features, bool ForAS, + unsigned *OutFPUKind) { bool KernelOrKext = Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); arm::FloatABI ABI = arm::getARMFloatABI(D, Triple, Args); @@ -643,6 +644,7 @@ {"-dotprod", "-fp16fml", "-bf16", "-mve.fp"}); if (!hasIntegerMVE(Features)) Features.emplace_back("-fpregs"); + FPUID = llvm::ARM::FK_NONE; } // En/disable crc code generation. @@ -899,6 +901,10 @@ if (Args.getLastArg(options::OPT_mno_bti_at_return_twice)) Features.push_back("+no-bti-at-return-twice"); + + if (OutFPUKind) { + *OutFPUKind = FPUID; + } } std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) { Index: clang/lib/Driver/ToolChain.cpp =================================================================== --- clang/lib/Driver/ToolChain.cpp +++ clang/lib/Driver/ToolChain.cpp @@ -9,6 +9,7 @@ #include "clang/Driver/ToolChain.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" @@ -170,6 +171,109 @@ return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux(); } +std::vector<std::string> +ToolChain::getMultiSelectionFlags(const llvm::opt::ArgList &Args) const { + std::vector<std::string> Result; + + using namespace clang::driver::options; + + const llvm::Triple Triple(ComputeEffectiveClangTriple(Args)); + + // Enumerate boolean flags we care about for the purposes of multilib here. + // There must be a smarter way to do it but this gets us started. + const struct HasFlag { + ID Pos, Neg; + bool Default; + } HasFlagList[] = { + {OPT_fexceptions, OPT_fno_exceptions, true}, + {OPT_frtti, OPT_fno_rtti, true}, + }; + + // Options we care about that have a single last-wins value. + static const ID GetLastArgValue[] = { + OPT_fcxx_abi_EQ, + }; + + for (const HasFlag &HF : HasFlagList) { + ID Option = Args.hasFlag(HF.Pos, HF.Neg, HF.Default) ? HF.Pos : HF.Neg; + Result.push_back( + clang::driver::getDriverOptTable().getOptionName(Option).str()); + } + + for (ID Option : GetLastArgValue) { + StringRef Value = Args.getLastArgValue(Option); + if (!Value.empty()) { + Result.push_back( + (clang::driver::getDriverOptTable().getOptionName(Option) + Value) + .str()); + } + } + + const SanitizerArgs SanArgs(getSanitizerArgs(Args)); + if (SanArgs.needsAsanRt()) { + Result.push_back("fsanitize=address"); + } + if (SanArgs.needsHwasanRt()) { + Result.push_back("fsanitize=hwaddress"); + } + + switch (Triple.getArch()) { + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: { + std::vector<StringRef> Features; + unsigned FPUKind = llvm::ARM::FK_INVALID; + tools::arm::getARMTargetFeatures(D, Triple, Args, Features, false, + &FPUKind); + const auto UnifiedFeatures = tools::unifyTargetFeatures(Features); + llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(), + UnifiedFeatures.end()); + for (const auto &Ext : ARM::ARCHExtNames) { + if (FeatureSet.find(Ext.Feature) != FeatureSet.end()) { + Result.push_back(("march=+" + Ext.Name).str()); + } + } + + 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"); + } + } break; + default: + break; + } + + Result.push_back("target=" + Triple.str()); + + // Sort alphabetically + std::sort(Result.begin(), Result.end()); + + // Remove duplicate entries + 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); Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -2209,6 +2209,12 @@ return false; } + if (C.getArgs().hasArg(options::OPT_print_multi_selection_flags)) { + for (StringRef Attr : TC.getMultiSelectionFlags(C.getArgs())) + llvm::outs() << Attr << '\n'; + return false; + } + if (C.getArgs().hasArg(options::OPT_print_multi_directory)) { const Multilib &Multilib = TC.getMultilib(); if (Multilib.gccSuffix().empty()) Index: clang/include/clang/Driver/ToolChain.h =================================================================== --- clang/include/clang/Driver/ToolChain.h +++ clang/include/clang/Driver/ToolChain.h @@ -285,6 +285,27 @@ const Multilib &getMultilib() const { return SelectedMultilib; } + /// Get flags suitable for multilib selection, based on the provided clang + /// command line arguments. The 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 but different: + /// * It's incomplete. Only certain arguments are processed. If more arguments + /// are needed for multilib selection then this function should be extended. + /// * The flags aren't prefixed with "-". + /// * Where a single command line argument would contain a list, the elements + /// are split out. For example, Arm extensions are appended to -march like + /// -march=armv8m.main+crc+crypto+sha2+mve. Since this function is + /// incomplete, a later clang version may infer the presence of more + /// extensions than an earlier version. If all extensions were in a single + /// flag then that would be unstable. Instead, each extension will be + /// returned separately. There may not be valid syntax to express this as a + /// clang argument so an pseudo argument syntax must be used instead. + /// To allow users to find out what flags are returned, clang accepts a + /// -print-multi-selection-flags-experimental argument. + std::vector<std::string> + getMultiSelectionFlags(const llvm::opt::ArgList &) const; + SanitizerArgs getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const; const XRayArgs& getXRayArgs() const; Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -4159,6 +4159,8 @@ "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_selection_flags : Flag<["-", "--"], "print-multi-selection-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">,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits