[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 Dec 10 04:51:35 PST 2024
https://github.com/vhscampos updated https://github.com/llvm/llvm-project/pull/110659
>From 96e089e5b075cf5376109cae6eadea9b4b9a054d Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Mon, 9 Dec 2024 09:36:52 +0000
Subject: [PATCH 1/6] Change in specification: DriverArgs now MacroDefines
We've decided to restrict the driver arguments that can be specified to
only macro definitions. Hence this patch adjusts the YAML parsing for
that.
---
clang/include/clang/Driver/Multilib.h | 2 +-
clang/lib/Driver/Multilib.cpp | 2 +-
.../baremetal-multilib-custom-flags-parsing.yaml | 12 ++++++------
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/clang/include/clang/Driver/Multilib.h b/clang/include/clang/Driver/Multilib.h
index 69d0b9b31714ff..1dab45c062aeec 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -107,7 +107,7 @@ using DeclarationPtr = std::shared_ptr<Declaration>;
struct ValueDetail {
std::string Name;
- std::optional<SmallVector<std::string>> DriverArgs;
+ std::optional<SmallVector<std::string>> MacroDefines;
DeclarationPtr Decl;
};
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 0d7d590a0eed8b..b4b5dbd1bdb5e3 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -269,7 +269,7 @@ struct llvm::yaml::MappingContextTraits<custom_flag::ValueDetail,
static void mapping(llvm::yaml::IO &io, custom_flag::ValueDetail &V,
llvm::SmallSet<std::string, 32> &) {
io.mapRequired("Name", V.Name);
- io.mapOptional("DriverArgs", V.DriverArgs);
+ io.mapOptional("MacroDefines", V.MacroDefines);
}
static std::string validate(IO &io, custom_flag::ValueDetail &V,
llvm::SmallSet<std::string, 32> &NameSet) {
diff --git a/clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml b/clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml
index dc4d1b31a71165..fe6a9a8d7f1ee7 100644
--- a/clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml
+++ b/clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml
@@ -1,8 +1,8 @@
# RUN: split-file %s %t
-# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/multilib-without-extra-build-args.yaml %s -### -o /dev/null 2>&1 \
+# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/multilib-without-macro-defines.yaml %s -### -o /dev/null 2>&1 \
# RUN: | FileCheck %s
-# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/multilib-with-extra-build-args.yaml %s -### -o /dev/null 2>&1 \
+# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/multilib-with-macro-defines.yaml %s -### -o /dev/null 2>&1 \
# RUN: | FileCheck %s
# CHECK-NOT: error:
@@ -27,7 +27,7 @@
# CHECK-DUPLICATE-FLAG-VALUE-NAME: error: duplicate custom flag value name: "value-name"
# CHECK-DUPLICATE-FLAG-VALUE-NAME-NEXT: - Name: value-name
-#--- multilib-without-extra-build-args.yaml
+#--- multilib-without-macro-defines.yaml
---
MultilibVersion: 1.0
@@ -42,7 +42,7 @@ Flags:
- Name: b
Default: a
-#--- multilib-with-extra-build-args.yaml
+#--- multilib-with-macro-defines.yaml
---
MultilibVersion: 1.0
@@ -54,9 +54,9 @@ Flags:
- Name: flag
Values:
- Name: a
- DriverArgs: [-DFEATURE_A]
+ MacroDefines: [FEATURE_A]
- Name: b
- DriverArgs: [-DFEATURE_B]
+ MacroDefines: [FEATURE_B]
Default: a
#--- missing-flag-name.yaml
>From c0bb75d7ba6292a0267d71026324164a11910ce8 Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Thu, 26 Sep 2024 14:44:01 +0100
Subject: [PATCH 2/6] [Multilib] Add -fmultilib-flag command-line option
This option is passed through to the multilib system. It is then used in
conjunction with other options to select the proper library variant.
Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
clang/include/clang/Driver/Options.td | 2 ++
clang/lib/Driver/ToolChain.cpp | 12 ++++++++++++
clang/test/Driver/print-multi-selection-flags.c | 7 +++++++
3 files changed, 21 insertions(+)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index f2f9c20c9bc264..4ec23b270f2e6b 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5704,6 +5704,8 @@ def print_multi_directory : Flag<["-", "--"], "print-multi-directory">;
def print_multi_lib : Flag<["-", "--"], "print-multi-lib">;
def print_multi_flags : Flag<["-", "--"], "print-multi-flags-experimental">,
HelpText<"Print the flags used for selecting multilibs (experimental)">;
+def fmultilib_flag : Joined<["-", "--"], "fmultilib-flag=">,
+ Visibility<[ClangOption]>;
def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
Flags<[Unsupported]>;
def print_target_triple : Flag<["-", "--"], "print-target-triple">,
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 0d426a467e9a3b..bb8a4d6915e641 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -196,6 +196,15 @@ bool ToolChain::defaultToIEEELongDouble() const {
return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
}
+static void processMultilibCustomFlags(Multilib::flags_list &List,
+ const llvm::opt::ArgList &Args) {
+ for (const Arg *MultilibFlagArg :
+ Args.filtered(options::OPT_fmultilib_flag)) {
+ List.push_back(MultilibFlagArg->getAsString(Args));
+ MultilibFlagArg->claim();
+ }
+}
+
static void getAArch64MultilibFlags(const Driver &D,
const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
@@ -246,6 +255,8 @@ static void getAArch64MultilibFlags(const Driver &D,
if (ABIArg) {
Result.push_back(ABIArg->getAsString(Args));
}
+
+ processMultilibCustomFlags(Result, Args);
}
static void getARMMultilibFlags(const Driver &D,
@@ -313,6 +324,7 @@ static void getARMMultilibFlags(const Driver &D,
if (Endian->getOption().matches(options::OPT_mbig_endian))
Result.push_back(Endian->getAsString(Args));
}
+ processMultilibCustomFlags(Result, Args);
}
static void getRISCVMultilibFlags(const Driver &D, const llvm::Triple &Triple,
diff --git a/clang/test/Driver/print-multi-selection-flags.c b/clang/test/Driver/print-multi-selection-flags.c
index 5bf6dca5096a73..cf9522aa068524 100644
--- a/clang/test/Driver/print-multi-selection-flags.c
+++ b/clang/test/Driver/print-multi-selection-flags.c
@@ -90,3 +90,10 @@
// CHECK-RV32E-ORDER: --target=riscv32-unknown-none-elf
// CHECK-RV32E-ORDER: -mabi=ilp32e
// CHECK-RV32E-ORDER: -march=rv32e{{[0-9]+p[0-9]+}}_c{{[0-9]+p[0-9]+}}_zicsr{{[0-9]+p[0-9]+}}
+
+// RUN: %clang -print-multi-flags-experimental --target=armv8m.main-none-eabi -fmultilib-flag=foo -fmultilib-flag=bar | FileCheck --check-prefixes=CHECK-MULTILIB-CUSTOM-FLAG,CHECK-ARM-MULTILIB-CUSTOM-FLAG %s
+// RUN: %clang -print-multi-flags-experimental --target=aarch64-none-eabi -fmultilib-flag=foo -fmultilib-flag=bar | FileCheck --check-prefixes=CHECK-MULTILIB-CUSTOM-FLAG,CHECK-AARCH64-MULTILIB-CUSTOM-FLAG %s
+// CHECK-ARM-MULTILIB-CUSTOM-FLAG: --target=thumbv8m.main-unknown-none-eabi
+// CHECK-AARCH64-MULTILIB-CUSTOM-FLAG: --target=aarch64-unknown-none-eabi
+// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=foo
+// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=bar
>From c31b7fb1d76d17f2f883f1d85b48ffa4d92cea14 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 3/6] [Multilib] Custom flags processing for library selection
Select library variants in the multilib system using the flags passed
following 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 name is invalid. If the wrong
name is close enough to any valid one, according to edit distance, the
closest valid value name is suggested.
Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
clang/include/clang/Driver/Driver.h | 2 +-
clang/include/clang/Driver/Multilib.h | 11 +-
clang/include/clang/Driver/ToolChain.h | 7 +
clang/lib/Driver/Driver.cpp | 142 ++++++++++--------
clang/lib/Driver/Multilib.cpp | 136 ++++++++++++++++-
clang/lib/Driver/ToolChains/BareMetal.cpp | 22 ++-
clang/lib/Driver/ToolChains/BareMetal.h | 5 +
.../baremetal-multilib-custom-flags.yaml | 79 ++++++++++
8 files changed, 329 insertions(+), 75 deletions(-)
create mode 100644 clang/test/Driver/baremetal-multilib-custom-flags.yaml
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 9177d56718ee77..40e2b9546cead5 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -463,7 +463,7 @@ class Driver {
/// ArgList.
llvm::opt::InputArgList ParseArgStrings(ArrayRef<const char *> Args,
bool UseDriverMode,
- bool &ContainsError);
+ bool &ContainsError) const;
/// BuildInputs - Construct the list of inputs and their types from
/// the given arguments.
diff --git a/clang/include/clang/Driver/Multilib.h b/clang/include/clang/Driver/Multilib.h
index 1dab45c062aeec..36bdfdb6157b0b 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -163,9 +163,18 @@ class MultilibSet {
const_iterator begin() const { return Multilibs.begin(); }
const_iterator end() const { return Multilibs.end(); }
+ /// Process custom flags from \p Flags and returns an expanded flags list and
+ /// a list of extra compilation arguments.
+ /// Returns a pair where:
+ /// - first: the new flags list including custom flags after processing.
+ /// - second: the extra compilation arguments to be fed to the driver.
+ std::pair<Multilib::flags_list, SmallVector<StringRef>>
+ 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;
+ llvm::SmallVectorImpl<Multilib> &,
+ llvm::SmallVector<StringRef> * = nullptr) const;
unsigned size() const { return Multilibs.size(); }
diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index 5347e29be91439..25f51b7de3e9f5 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -686,6 +686,13 @@ class ToolChain {
/// Add warning options that need to be passed to cc1 for this target.
virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const;
+ // Get the list of extra driver arguments strings requested by the multilib
+ // configuration.
+ virtual SmallVector<std::string>
+ getMultilibDriverArgsStr(llvm::opt::ArgList &Args) const {
+ return {};
+ };
+
// GetRuntimeLibType - Determine the runtime library type to use with the
// given compilation arguments.
virtual RuntimeLibType
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index a0f4329e36136b..360f6519360d44 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -262,7 +262,7 @@ void Driver::setDriverMode(StringRef Value) {
}
InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,
- bool UseDriverMode, bool &ContainsError) {
+ bool UseDriverMode, bool &ContainsError) const {
llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
ContainsError = false;
@@ -1252,8 +1252,9 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr);
// All arguments, from both config file and command line.
- InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions)
- : std::move(*CLOptions));
+ auto UArgs = std::make_unique<InputArgList>(std::move(HasConfigFile ? std::move(*CfgOptions)
+ : std::move(*CLOptions)));
+ InputArgList &Args = *UArgs;
if (HasConfigFile)
for (auto *Opt : *CLOptions) {
@@ -1287,52 +1288,6 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
}
}
- // Check for working directory option before accessing any files
- if (Arg *WD = Args.getLastArg(options::OPT_working_directory))
- if (VFS->setCurrentWorkingDirectory(WD->getValue()))
- Diag(diag::err_drv_unable_to_set_working_directory) << WD->getValue();
-
- // Check for missing include directories.
- if (!Diags.isIgnored(diag::warn_missing_include_dirs, SourceLocation())) {
- for (auto IncludeDir : Args.getAllArgValues(options::OPT_I_Group)) {
- if (!VFS->exists(IncludeDir))
- Diag(diag::warn_missing_include_dirs) << IncludeDir;
- }
- }
-
- // FIXME: This stuff needs to go into the Compilation, not the driver.
- bool CCCPrintPhases;
-
- // -canonical-prefixes, -no-canonical-prefixes are used very early in main.
- Args.ClaimAllArgs(options::OPT_canonical_prefixes);
- Args.ClaimAllArgs(options::OPT_no_canonical_prefixes);
-
- // f(no-)integated-cc1 is also used very early in main.
- Args.ClaimAllArgs(options::OPT_fintegrated_cc1);
- Args.ClaimAllArgs(options::OPT_fno_integrated_cc1);
-
- // Ignore -pipe.
- Args.ClaimAllArgs(options::OPT_pipe);
-
- // Extract -ccc args.
- //
- // FIXME: We need to figure out where this behavior should live. Most of it
- // should be outside in the client; the parts that aren't should have proper
- // options, either by introducing new ones or by overloading gcc ones like -V
- // or -b.
- CCCPrintPhases = Args.hasArg(options::OPT_ccc_print_phases);
- CCCPrintBindings = Args.hasArg(options::OPT_ccc_print_bindings);
- if (const Arg *A = Args.getLastArg(options::OPT_ccc_gcc_name))
- CCCGenericGCCName = A->getValue();
-
- // Process -fproc-stat-report options.
- if (const Arg *A = Args.getLastArg(options::OPT_fproc_stat_report_EQ)) {
- CCPrintProcessStats = true;
- CCPrintStatReportFilename = A->getValue();
- }
- if (Args.hasArg(options::OPT_fproc_stat_report))
- CCPrintProcessStats = true;
-
// FIXME: TargetTriple is used by the target-prefixed calls to as/ld
// and getToolChain is const.
if (IsCLMode()) {
@@ -1385,6 +1340,79 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
TargetTriple = A->getValue();
if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir))
Dir = Dir = A->getValue();
+ if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
+ SysRoot = A->getValue();
+ if (const Arg *A = Args.getLastArg(options::OPT_resource_dir))
+ ResourceDir = A->getValue();
+ if (const Arg *A = Args.getLastArg(options::OPT__dyld_prefix_EQ))
+ DyldPrefix = A->getValue();
+
+ setLTOMode(Args);
+
+ // Owned by the host.
+ const ToolChain &TC =
+ getToolChain(Args, computeTargetTriple(*this, TargetTriple, Args));
+
+ SmallVector<std::string> MultilibDriverArgsStr =
+ TC.getMultilibDriverArgsStr(Args);
+ SmallVector<const char *> MLArgsChar(
+ llvm::map_range(MultilibDriverArgsStr, [&Args](const auto &S) {
+ return Args.MakeArgString(S);
+ }));
+ bool MLContainsError;
+ auto MultilibDriverArgList = std::make_unique<InputArgList>(
+ ParseArgStrings(MLArgsChar, /*UseDriverMode=*/false, MLContainsError));
+ if (!MLContainsError)
+ for (auto *Opt : *MultilibDriverArgList) {
+ appendOneArg(Args, Opt, nullptr);
+ }
+
+ // Check for working directory option before accessing any files
+ if (Arg *WD = Args.getLastArg(options::OPT_working_directory))
+ if (VFS->setCurrentWorkingDirectory(WD->getValue()))
+ Diag(diag::err_drv_unable_to_set_working_directory) << WD->getValue();
+
+ // Check for missing include directories.
+ if (!Diags.isIgnored(diag::warn_missing_include_dirs, SourceLocation())) {
+ for (auto IncludeDir : Args.getAllArgValues(options::OPT_I_Group)) {
+ if (!VFS->exists(IncludeDir))
+ Diag(diag::warn_missing_include_dirs) << IncludeDir;
+ }
+ }
+
+ // FIXME: This stuff needs to go into the Compilation, not the driver.
+ bool CCCPrintPhases;
+
+ // -canonical-prefixes, -no-canonical-prefixes are used very early in main.
+ Args.ClaimAllArgs(options::OPT_canonical_prefixes);
+ Args.ClaimAllArgs(options::OPT_no_canonical_prefixes);
+
+ // f(no-)integated-cc1 is also used very early in main.
+ Args.ClaimAllArgs(options::OPT_fintegrated_cc1);
+ Args.ClaimAllArgs(options::OPT_fno_integrated_cc1);
+
+ // Ignore -pipe.
+ Args.ClaimAllArgs(options::OPT_pipe);
+
+ // Extract -ccc args.
+ //
+ // FIXME: We need to figure out where this behavior should live. Most of it
+ // should be outside in the client; the parts that aren't should have proper
+ // options, either by introducing new ones or by overloading gcc ones like -V
+ // or -b.
+ CCCPrintPhases = Args.hasArg(options::OPT_ccc_print_phases);
+ CCCPrintBindings = Args.hasArg(options::OPT_ccc_print_bindings);
+ if (const Arg *A = Args.getLastArg(options::OPT_ccc_gcc_name))
+ CCCGenericGCCName = A->getValue();
+
+ // Process -fproc-stat-report options.
+ if (const Arg *A = Args.getLastArg(options::OPT_fproc_stat_report_EQ)) {
+ CCPrintProcessStats = true;
+ CCPrintStatReportFilename = A->getValue();
+ }
+ if (Args.hasArg(options::OPT_fproc_stat_report))
+ CCPrintProcessStats = true;
+
for (const Arg *A : Args.filtered(options::OPT_B)) {
A->claim();
PrefixDirs.push_back(A->getValue(0));
@@ -1399,13 +1427,6 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
CompilerPath = Split.second;
}
}
- if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
- SysRoot = A->getValue();
- if (const Arg *A = Args.getLastArg(options::OPT__dyld_prefix_EQ))
- DyldPrefix = A->getValue();
-
- if (const Arg *A = Args.getLastArg(options::OPT_resource_dir))
- ResourceDir = A->getValue();
if (const Arg *A = Args.getLastArg(options::OPT_save_temps_EQ)) {
SaveTemps = llvm::StringSwitch<SaveTempsMode>(A->getValue())
@@ -1425,8 +1446,6 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
Offload = OffloadHostDevice;
}
- setLTOMode(Args);
-
// Process -fembed-bitcode= flags.
if (Arg *A = Args.getLastArg(options::OPT_fembed_bitcode_EQ)) {
StringRef Name = A->getValue();
@@ -1480,16 +1499,9 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
}
}
- std::unique_ptr<llvm::opt::InputArgList> UArgs =
- std::make_unique<InputArgList>(std::move(Args));
-
// Perform the default argument translations.
DerivedArgList *TranslatedArgs = TranslateInputArgs(*UArgs);
- // Owned by the host.
- const ToolChain &TC = getToolChain(
- *UArgs, computeTargetTriple(*this, TargetTriple, *UArgs));
-
// Check if the environment version is valid except wasm case.
llvm::Triple Triple = TC.getTriple();
if (!Triple.isWasm()) {
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index b4b5dbd1bdb5e3..911196eae94b1d 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -11,6 +11,7 @@
#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"
#include "llvm/Support/ErrorHandling.h"
@@ -92,12 +93,141 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
-bool MultilibSet::select(const Driver &D, const Multilib::flags_list &Flags,
- llvm::SmallVectorImpl<Multilib> &Selected) const {
- llvm::StringSet<> FlagSet(expandFlags(Flags));
+static void DiagnoseUnclaimedMultilibCustomFlags(
+ const Driver &D, const SmallVector<StringRef> &UnclaimedCustomFlagValues,
+ const SmallVector<custom_flag::DeclarationPtr> &CustomFlagDecls) {
+ struct EditDistanceInfo {
+ StringRef FlagValue;
+ unsigned EditDistance;
+ };
+ const unsigned MaxEditDistance = 5;
+
+ for (StringRef Unclaimed : UnclaimedCustomFlagValues) {
+ std::optional<EditDistanceInfo> BestCandidate;
+ for (const auto &Decl : CustomFlagDecls) {
+ for (const auto &Value : Decl->ValueList) {
+ const std::string &FlagValueName = Value.Name;
+ unsigned EditDistance =
+ Unclaimed.edit_distance(FlagValueName, /*AllowReplacements=*/true,
+ /*MaxEditDistance=*/MaxEditDistance);
+ if (!BestCandidate || (EditDistance <= MaxEditDistance &&
+ EditDistance < BestCandidate->EditDistance)) {
+ BestCandidate = {FlagValueName, EditDistance};
+ }
+ }
+ }
+ if (!BestCandidate)
+ D.Diag(clang::diag::err_drv_unsupported_opt)
+ << (custom_flag::Prefix + Unclaimed).str();
+ else
+ D.Diag(clang::diag::err_drv_unsupported_opt_with_suggestion)
+ << (custom_flag::Prefix + Unclaimed).str()
+ << (custom_flag::Prefix + BestCandidate->FlagValue).str();
+ }
+}
+
+namespace clang::driver::custom_flag {
+// Map implemented using linear searches as the expected size is too small for
+// the overhead of a search tree or a hash table.
+class ValueNameToDetailMap {
+ SmallVector<std::pair<StringRef, const ValueDetail *>> Mapping;
+
+public:
+ template <typename It>
+ ValueNameToDetailMap(It FlagDeclsBegin, It FlagDeclsEnd) {
+ for (auto DeclIt = FlagDeclsBegin; DeclIt != FlagDeclsEnd; ++DeclIt) {
+ const DeclarationPtr &Decl = *DeclIt;
+ for (const auto &Value : Decl->ValueList)
+ Mapping.emplace_back(Value.Name, &Value);
+ }
+ }
+
+ const ValueDetail *get(StringRef Key) const {
+ auto Iter = llvm::find_if(
+ Mapping, [&](const auto &Pair) { return Pair.first == Key; });
+ return Iter != Mapping.end() ? Iter->second : nullptr;
+ }
+};
+} // namespace clang::driver::custom_flag
+
+std::pair<Multilib::flags_list, SmallVector<StringRef>>
+MultilibSet::processCustomFlags(const Driver &D,
+ const Multilib::flags_list &Flags) const {
+ Multilib::flags_list Result;
+ SmallVector<StringRef> CompilationArgs;
+
+ // Custom flag values detected in the flags list
+ SmallVector<const custom_flag::ValueDetail *> ClaimedCustomFlagValues;
+
+ // Arguments to -fmultilib-flag=<arg> that don't correspond to any valid
+ // custom flag value. An error will be printed out for each of these.
+ SmallVector<StringRef> UnclaimedCustomFlagValueStrs;
+
+ const auto ValueNameToValueDetail = custom_flag::ValueNameToDetailMap(
+ CustomFlagDecls.begin(), CustomFlagDecls.end());
+
+ for (StringRef Flag : Flags) {
+ if (!Flag.starts_with(custom_flag::Prefix)) {
+ Result.push_back(Flag.str());
+ continue;
+ }
+
+ StringRef CustomFlagValueStr = Flag.substr(custom_flag::Prefix.size());
+ const custom_flag::ValueDetail *Detail =
+ ValueNameToValueDetail.get(CustomFlagValueStr);
+ if (Detail)
+ ClaimedCustomFlagValues.push_back(Detail);
+ else
+ UnclaimedCustomFlagValueStrs.push_back(CustomFlagValueStr);
+ }
+
+ // Set of custom flag declarations for which a value was passed in the flags
+ // list. This is used to, firstly, detect multiple values for the same flag
+ // declaration (in this case, the last one wins), and secondly, to detect
+ // which declarations had no value passed in (in this case, the default value
+ // is selected).
+ llvm::SmallSet<custom_flag::DeclarationPtr, 32> TriggeredCustomFlagDecls;
+
+ // Detect multiple values for the same flag declaration. Last one wins.
+ for (auto *CustomFlagValue : llvm::reverse(ClaimedCustomFlagValues)) {
+ if (!TriggeredCustomFlagDecls.insert(CustomFlagValue->Decl).second)
+ continue;
+ Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue->Name);
+ if (CustomFlagValue->DriverArgs)
+ CompilationArgs.append(CustomFlagValue->DriverArgs->begin(),
+ CustomFlagValue->DriverArgs->end());
+ }
+
+ // Detect flag declarations with no value passed in. Select default value.
+ for (const auto &Decl : CustomFlagDecls) {
+ if (TriggeredCustomFlagDecls.contains(Decl))
+ continue;
+ custom_flag::ValueDetail &CustomFlagValue =
+ Decl->ValueList[*Decl->DefaultValueIdx];
+ Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue.Name);
+ if (CustomFlagValue.DriverArgs)
+ CompilationArgs.append(CustomFlagValue.DriverArgs->begin(),
+ CustomFlagValue.DriverArgs->end());
+ }
+
+ DiagnoseUnclaimedMultilibCustomFlags(D, UnclaimedCustomFlagValueStrs,
+ CustomFlagDecls);
+
+ return {Result, CompilationArgs};
+}
+
+bool MultilibSet::select(
+ const Driver &D, const Multilib::flags_list &Flags,
+ llvm::SmallVectorImpl<Multilib> &Selected,
+ llvm::SmallVector<StringRef> *CustomFlagCompilationArgs) const {
+ auto [FlagsWithCustom, CFCompilationArgs] = processCustomFlags(D, Flags);
+ llvm::StringSet<> FlagSet(expandFlags(FlagsWithCustom));
Selected.clear();
bool AnyErrors = false;
+ if (CustomFlagCompilationArgs)
+ *CustomFlagCompilationArgs = std::move(CFCompilationArgs);
+
// Decide which multilibs we're going to select at all.
llvm::DenseSet<StringRef> ExclusiveGroupsSelected;
for (const Multilib &M : llvm::reverse(Multilibs)) {
diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index f9a73f60973e4c..c5711d94e26602 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -183,9 +183,11 @@ static bool isPPCBareMetal(const llvm::Triple &Triple) {
Triple.getEnvironment() == llvm::Triple::EABI;
}
-static void findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
- StringRef MultilibPath, const ArgList &Args,
- DetectedMultilibs &Result) {
+static void
+findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
+ StringRef MultilibPath, const ArgList &Args,
+ DetectedMultilibs &Result,
+ SmallVector<StringRef> &CustomFlagsCompilationArgs) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MB =
D.getVFS().getBufferForFile(MultilibPath);
if (!MB)
@@ -196,7 +198,8 @@ static void findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
if (ErrorOrMultilibSet.getError())
return;
Result.Multilibs = ErrorOrMultilibSet.get();
- if (Result.Multilibs.select(D, Flags, Result.SelectedMultilibs))
+ if (Result.Multilibs.select(D, Flags, Result.SelectedMultilibs,
+ &CustomFlagsCompilationArgs))
return;
D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " ");
std::stringstream ss;
@@ -255,9 +258,13 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
// If multilib.yaml is found, update sysroot so it doesn't use a target
// specific suffix
SysRoot = computeBaseSysRoot(D, /*IncludeTriple=*/false);
- findMultilibsFromYAML(*this, D, *MultilibPath, Args, Result);
+ SmallVector<StringRef> CustomFlagDriverArgs;
+ findMultilibsFromYAML(*this, D, *MultilibPath, Args, Result,
+ CustomFlagDriverArgs);
SelectedMultilibs = Result.SelectedMultilibs;
Multilibs = Result.Multilibs;
+ MultilibDriverArgs.append(CustomFlagDriverArgs.begin(),
+ CustomFlagDriverArgs.end());
} else if (isRISCVBareMetal(Triple)) {
if (findRISCVMultilibs(D, Triple, Args, Result)) {
SelectedMultilibs = Result.SelectedMultilibs;
@@ -597,3 +604,8 @@ SanitizerMask BareMetal::getSupportedSanitizers() const {
}
return Res;
}
+
+SmallVector<std::string>
+BareMetal::getMultilibDriverArgsStr(llvm::opt::ArgList &Args) const {
+ return MultilibDriverArgs;
+}
\ No newline at end of file
diff --git a/clang/lib/Driver/ToolChains/BareMetal.h b/clang/lib/Driver/ToolChains/BareMetal.h
index b385c8cf76aab0..eb37124bbdc315 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.h
+++ b/clang/lib/Driver/ToolChains/BareMetal.h
@@ -74,12 +74,17 @@ class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain {
std::string computeSysRoot() const override;
SanitizerMask getSupportedSanitizers() const override;
+ SmallVector<std::string>
+ getMultilibDriverArgsStr(llvm::opt::ArgList &Args) const override;
+
private:
using OrderedMultilibs =
llvm::iterator_range<llvm::SmallVector<Multilib>::const_reverse_iterator>;
OrderedMultilibs getOrderedMultilibs() const;
std::string SysRoot;
+
+ SmallVector<std::string> MultilibDriverArgs;
};
} // namespace toolchains
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..94f7838c3cd96c
--- /dev/null
+++ b/clang/test/Driver/baremetal-multilib-custom-flags.yaml
@@ -0,0 +1,79 @@
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabi -mfpu=none --sysroot= \
+# RUN: | FileCheck --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: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabi -mfpu=none -fmultilib-flag=no-multithreaded --sysroot= \
+# RUN: | FileCheck --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: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabi -mfpu=none -fmultilib-flag=multithreaded --sysroot= \
+# RUN: | FileCheck --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: not %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabi -mfpu=none -fmultilib-flag=singlethreaded -fmultilib-flag=no-io --sysroot= \
+# RUN: | FileCheck --check-prefix=CHECK-ERROR %s
+# CHECK-ERROR-DAG: error: unsupported option '-fmultilib-flag=singlethreaded'
+# CHECK-ERROR-DAG: error: unsupported option '-fmultilib-flag=no-io'; did you mean '-fmultilib-flag=io-none'?
+
+# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabi -mfpu=none -print-multi-lib --sysroot= \
+# RUN: | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/nofp;@-target=thumbv8m.main-unknown-none-eabi at mfpu=none at fmultilib-flag=no-multithreaded
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/multithreaded/thumb/v8-m.main/nofp;@-target=thumbv8m.main-unknown-none-eabi at mfpu=none at fmultilib-flag=multithreaded
+
+# RUN: %clang --target=arm-none-eabi --multi-lib-config=%s -x c %s -fmultilib-flag=no-multithreaded -### -o /dev/null 2>&1 \
+# RUN: | FileCheck --check-prefix=CHECK-DRIVERARGS-NOMULTI %s
+# CHECK-DRIVERARGS-NOMULTI: "-D" "__SINGLE_THREAD__"
+
+# RUN: %clang --target=arm-none-eabi --multi-lib-config=%s -x c %s -fmultilib-flag=io-semihosting -### -o /dev/null 2>&1 \
+# RUN: | FileCheck --check-prefix=CHECK-DRIVERARGS-IO-SEMIHOSTING %s
+# CHECK-DRIVERARGS-IO-SEMIHOSTING: "-D" "SEMIHOSTING"
+
+# RUN: %clang --target=arm-none-eabi --multi-lib-config=%s -x c %s -fmultilib-flag=io-linux-syscalls -### -o /dev/null 2>&1 \
+# RUN: | FileCheck --check-prefix=CHECK-DRIVERARGS-IO-LINUX %s
+# CHECK-DRIVERARGS-IO-LINUX: "-U" "SEMIHOSTING"
+# CHECK-DRIVERARGS-IO-LINUX-SAME: "-D" "LINUX_SYSCALLS"
+
+---
+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:
+ - Name: no-multithreaded
+ DriverArgs: [-D__SINGLE_THREAD__]
+ - Name: multithreaded
+ Default: no-multithreaded
+ - Name: io
+ Values:
+ - Name: io-none
+ - Name: io-semihosting
+ DriverArgs: [-DSEMIHOSTING]
+ - Name: io-linux-syscalls
+ DriverArgs: [-USEMIHOSTING, -DLINUX_SYSCALLS]
+ Default: io-none
\ No newline at end of file
>From a432266f72a1f4ad856078c4fd8d10df2e35a7bb Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Mon, 25 Nov 2024 13:42:47 +0000
Subject: [PATCH 4/6] Fix clang-format errors
---
clang/lib/Driver/Driver.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 360f6519360d44..31e3d0e79072f4 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -262,7 +262,8 @@ void Driver::setDriverMode(StringRef Value) {
}
InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,
- bool UseDriverMode, bool &ContainsError) const {
+ bool UseDriverMode,
+ bool &ContainsError) const {
llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
ContainsError = false;
@@ -1252,8 +1253,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr);
// All arguments, from both config file and command line.
- auto UArgs = std::make_unique<InputArgList>(std::move(HasConfigFile ? std::move(*CfgOptions)
- : std::move(*CLOptions)));
+ auto UArgs = std::make_unique<InputArgList>(std::move(
+ HasConfigFile ? std::move(*CfgOptions) : std::move(*CLOptions)));
InputArgList &Args = *UArgs;
if (HasConfigFile)
>From dfc40b76699b1ea5c66083bd909cc9a638cfbb99 Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Mon, 25 Nov 2024 15:50:01 +0000
Subject: [PATCH 5/6] Disable test on Windows
The expected output is reliant on the syntax of file hierarchy. This
varies significantly between Linux and Windows. Following what other
multilib tests do, I am disabling the test on Windows.
---
clang/test/Driver/baremetal-multilib-custom-flags.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/test/Driver/baremetal-multilib-custom-flags.yaml b/clang/test/Driver/baremetal-multilib-custom-flags.yaml
index 94f7838c3cd96c..c44096e199a560 100644
--- a/clang/test/Driver/baremetal-multilib-custom-flags.yaml
+++ b/clang/test/Driver/baremetal-multilib-custom-flags.yaml
@@ -1,3 +1,5 @@
+# UNSUPPORTED: system-windows
+
# RUN: %clang --multi-lib-config=%s -no-canonical-prefixes -x c %s -### -o /dev/null 2>&1 \
# RUN: --target=thumbv8m.main-none-eabi -mfpu=none --sysroot= \
# RUN: | FileCheck --check-prefix=CHECK-DEFAULT %s
>From 3bc43d3eddf79dd85a30d17c47b853eabf68ebb8 Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Mon, 9 Dec 2024 10:19:48 +0000
Subject: [PATCH 6/6] Repurpose DriverArgs to MacroDefines
---
clang/include/clang/Driver/Multilib.h | 4 +-
clang/include/clang/Driver/ToolChain.h | 4 +-
clang/lib/Driver/Driver.cpp | 157 +++++++++---------
clang/lib/Driver/Multilib.cpp | 24 +--
clang/lib/Driver/ToolChains/BareMetal.cpp | 18 +-
clang/lib/Driver/ToolChains/BareMetal.h | 4 +-
.../baremetal-multilib-custom-flags.yaml | 20 +--
7 files changed, 118 insertions(+), 113 deletions(-)
diff --git a/clang/include/clang/Driver/Multilib.h b/clang/include/clang/Driver/Multilib.h
index 36bdfdb6157b0b..d9f937abd4bd1e 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -164,10 +164,10 @@ class MultilibSet {
const_iterator end() const { return Multilibs.end(); }
/// Process custom flags from \p Flags and returns an expanded flags list and
- /// a list of extra compilation arguments.
+ /// a list of macro defines.
/// Returns a pair where:
/// - first: the new flags list including custom flags after processing.
- /// - second: the extra compilation arguments to be fed to the driver.
+ /// - second: the extra macro defines to be fed to the driver.
std::pair<Multilib::flags_list, SmallVector<StringRef>>
processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const;
diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index 25f51b7de3e9f5..d7e2e8c077ed97 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -686,10 +686,10 @@ class ToolChain {
/// Add warning options that need to be passed to cc1 for this target.
virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const;
- // Get the list of extra driver arguments strings requested by the multilib
+ // Get the list of extra macro defines requested by the multilib
// configuration.
virtual SmallVector<std::string>
- getMultilibDriverArgsStr(llvm::opt::ArgList &Args) const {
+ getMultilibMacroDefinesStr(llvm::opt::ArgList &Args) const {
return {};
};
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 31e3d0e79072f4..86ccf8691b3404 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1253,9 +1253,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr);
// All arguments, from both config file and command line.
- auto UArgs = std::make_unique<InputArgList>(std::move(
- HasConfigFile ? std::move(*CfgOptions) : std::move(*CLOptions)));
- InputArgList &Args = *UArgs;
+ InputArgList Args = std::move(HasConfigFile ? *CfgOptions : *CLOptions);
if (HasConfigFile)
for (auto *Opt : *CLOptions) {
@@ -1289,6 +1287,52 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
}
}
+ // Check for working directory option before accessing any files
+ if (Arg *WD = Args.getLastArg(options::OPT_working_directory))
+ if (VFS->setCurrentWorkingDirectory(WD->getValue()))
+ Diag(diag::err_drv_unable_to_set_working_directory) << WD->getValue();
+
+ // Check for missing include directories.
+ if (!Diags.isIgnored(diag::warn_missing_include_dirs, SourceLocation())) {
+ for (auto IncludeDir : Args.getAllArgValues(options::OPT_I_Group)) {
+ if (!VFS->exists(IncludeDir))
+ Diag(diag::warn_missing_include_dirs) << IncludeDir;
+ }
+ }
+
+ // FIXME: This stuff needs to go into the Compilation, not the driver.
+ bool CCCPrintPhases;
+
+ // -canonical-prefixes, -no-canonical-prefixes are used very early in main.
+ Args.ClaimAllArgs(options::OPT_canonical_prefixes);
+ Args.ClaimAllArgs(options::OPT_no_canonical_prefixes);
+
+ // f(no-)integated-cc1 is also used very early in main.
+ Args.ClaimAllArgs(options::OPT_fintegrated_cc1);
+ Args.ClaimAllArgs(options::OPT_fno_integrated_cc1);
+
+ // Ignore -pipe.
+ Args.ClaimAllArgs(options::OPT_pipe);
+
+ // Extract -ccc args.
+ //
+ // FIXME: We need to figure out where this behavior should live. Most of it
+ // should be outside in the client; the parts that aren't should have proper
+ // options, either by introducing new ones or by overloading gcc ones like -V
+ // or -b.
+ CCCPrintPhases = Args.hasArg(options::OPT_ccc_print_phases);
+ CCCPrintBindings = Args.hasArg(options::OPT_ccc_print_bindings);
+ if (const Arg *A = Args.getLastArg(options::OPT_ccc_gcc_name))
+ CCCGenericGCCName = A->getValue();
+
+ // Process -fproc-stat-report options.
+ if (const Arg *A = Args.getLastArg(options::OPT_fproc_stat_report_EQ)) {
+ CCPrintProcessStats = true;
+ CCPrintStatReportFilename = A->getValue();
+ }
+ if (Args.hasArg(options::OPT_fproc_stat_report))
+ CCPrintProcessStats = true;
+
// FIXME: TargetTriple is used by the target-prefixed calls to as/ld
// and getToolChain is const.
if (IsCLMode()) {
@@ -1341,79 +1385,6 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
TargetTriple = A->getValue();
if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir))
Dir = Dir = A->getValue();
- if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
- SysRoot = A->getValue();
- if (const Arg *A = Args.getLastArg(options::OPT_resource_dir))
- ResourceDir = A->getValue();
- if (const Arg *A = Args.getLastArg(options::OPT__dyld_prefix_EQ))
- DyldPrefix = A->getValue();
-
- setLTOMode(Args);
-
- // Owned by the host.
- const ToolChain &TC =
- getToolChain(Args, computeTargetTriple(*this, TargetTriple, Args));
-
- SmallVector<std::string> MultilibDriverArgsStr =
- TC.getMultilibDriverArgsStr(Args);
- SmallVector<const char *> MLArgsChar(
- llvm::map_range(MultilibDriverArgsStr, [&Args](const auto &S) {
- return Args.MakeArgString(S);
- }));
- bool MLContainsError;
- auto MultilibDriverArgList = std::make_unique<InputArgList>(
- ParseArgStrings(MLArgsChar, /*UseDriverMode=*/false, MLContainsError));
- if (!MLContainsError)
- for (auto *Opt : *MultilibDriverArgList) {
- appendOneArg(Args, Opt, nullptr);
- }
-
- // Check for working directory option before accessing any files
- if (Arg *WD = Args.getLastArg(options::OPT_working_directory))
- if (VFS->setCurrentWorkingDirectory(WD->getValue()))
- Diag(diag::err_drv_unable_to_set_working_directory) << WD->getValue();
-
- // Check for missing include directories.
- if (!Diags.isIgnored(diag::warn_missing_include_dirs, SourceLocation())) {
- for (auto IncludeDir : Args.getAllArgValues(options::OPT_I_Group)) {
- if (!VFS->exists(IncludeDir))
- Diag(diag::warn_missing_include_dirs) << IncludeDir;
- }
- }
-
- // FIXME: This stuff needs to go into the Compilation, not the driver.
- bool CCCPrintPhases;
-
- // -canonical-prefixes, -no-canonical-prefixes are used very early in main.
- Args.ClaimAllArgs(options::OPT_canonical_prefixes);
- Args.ClaimAllArgs(options::OPT_no_canonical_prefixes);
-
- // f(no-)integated-cc1 is also used very early in main.
- Args.ClaimAllArgs(options::OPT_fintegrated_cc1);
- Args.ClaimAllArgs(options::OPT_fno_integrated_cc1);
-
- // Ignore -pipe.
- Args.ClaimAllArgs(options::OPT_pipe);
-
- // Extract -ccc args.
- //
- // FIXME: We need to figure out where this behavior should live. Most of it
- // should be outside in the client; the parts that aren't should have proper
- // options, either by introducing new ones or by overloading gcc ones like -V
- // or -b.
- CCCPrintPhases = Args.hasArg(options::OPT_ccc_print_phases);
- CCCPrintBindings = Args.hasArg(options::OPT_ccc_print_bindings);
- if (const Arg *A = Args.getLastArg(options::OPT_ccc_gcc_name))
- CCCGenericGCCName = A->getValue();
-
- // Process -fproc-stat-report options.
- if (const Arg *A = Args.getLastArg(options::OPT_fproc_stat_report_EQ)) {
- CCPrintProcessStats = true;
- CCPrintStatReportFilename = A->getValue();
- }
- if (Args.hasArg(options::OPT_fproc_stat_report))
- CCPrintProcessStats = true;
-
for (const Arg *A : Args.filtered(options::OPT_B)) {
A->claim();
PrefixDirs.push_back(A->getValue(0));
@@ -1428,6 +1399,13 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
CompilerPath = Split.second;
}
}
+ if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
+ SysRoot = A->getValue();
+ if (const Arg *A = Args.getLastArg(options::OPT__dyld_prefix_EQ))
+ DyldPrefix = A->getValue();
+
+ if (const Arg *A = Args.getLastArg(options::OPT_resource_dir))
+ ResourceDir = A->getValue();
if (const Arg *A = Args.getLastArg(options::OPT_save_temps_EQ)) {
SaveTemps = llvm::StringSwitch<SaveTempsMode>(A->getValue())
@@ -1447,6 +1425,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
Offload = OffloadHostDevice;
}
+ setLTOMode(Args);
+
// Process -fembed-bitcode= flags.
if (Arg *A = Args.getLastArg(options::OPT_fembed_bitcode_EQ)) {
StringRef Name = A->getValue();
@@ -1500,6 +1480,31 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
}
}
+ std::unique_ptr<llvm::opt::InputArgList> UArgs =
+ std::make_unique<InputArgList>(std::move(Args));
+
+ // Owned by the host.
+ const ToolChain &TC =
+ getToolChain(*UArgs, computeTargetTriple(*this, TargetTriple, *UArgs));
+
+ {
+ SmallVector<std::string> MultilibMacroDefinesStr =
+ TC.getMultilibMacroDefinesStr(*UArgs);
+ SmallVector<const char *> MLMacroDefinesChar(
+ llvm::map_range(MultilibMacroDefinesStr, [&UArgs](const auto &S) {
+ return UArgs->MakeArgString(Twine("-D") + Twine(S));
+ }));
+ bool MLContainsError;
+ auto MultilibMacroDefineList =
+ std::make_unique<InputArgList>(ParseArgStrings(
+ MLMacroDefinesChar, /*UseDriverMode=*/false, MLContainsError));
+ if (!MLContainsError) {
+ for (auto *Opt : *MultilibMacroDefineList) {
+ appendOneArg(*UArgs, Opt, nullptr);
+ }
+ }
+ }
+
// Perform the default argument translations.
DerivedArgList *TranslatedArgs = TranslateInputArgs(*UArgs);
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 911196eae94b1d..359643039e3c3c 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -154,7 +154,7 @@ std::pair<Multilib::flags_list, SmallVector<StringRef>>
MultilibSet::processCustomFlags(const Driver &D,
const Multilib::flags_list &Flags) const {
Multilib::flags_list Result;
- SmallVector<StringRef> CompilationArgs;
+ SmallVector<StringRef> MacroDefines;
// Custom flag values detected in the flags list
SmallVector<const custom_flag::ValueDetail *> ClaimedCustomFlagValues;
@@ -193,9 +193,9 @@ MultilibSet::processCustomFlags(const Driver &D,
if (!TriggeredCustomFlagDecls.insert(CustomFlagValue->Decl).second)
continue;
Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue->Name);
- if (CustomFlagValue->DriverArgs)
- CompilationArgs.append(CustomFlagValue->DriverArgs->begin(),
- CustomFlagValue->DriverArgs->end());
+ if (CustomFlagValue->MacroDefines)
+ MacroDefines.append(CustomFlagValue->MacroDefines->begin(),
+ CustomFlagValue->MacroDefines->end());
}
// Detect flag declarations with no value passed in. Select default value.
@@ -205,28 +205,28 @@ MultilibSet::processCustomFlags(const Driver &D,
custom_flag::ValueDetail &CustomFlagValue =
Decl->ValueList[*Decl->DefaultValueIdx];
Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue.Name);
- if (CustomFlagValue.DriverArgs)
- CompilationArgs.append(CustomFlagValue.DriverArgs->begin(),
- CustomFlagValue.DriverArgs->end());
+ if (CustomFlagValue.MacroDefines)
+ MacroDefines.append(CustomFlagValue.MacroDefines->begin(),
+ CustomFlagValue.MacroDefines->end());
}
DiagnoseUnclaimedMultilibCustomFlags(D, UnclaimedCustomFlagValueStrs,
CustomFlagDecls);
- return {Result, CompilationArgs};
+ return {Result, MacroDefines};
}
bool MultilibSet::select(
const Driver &D, const Multilib::flags_list &Flags,
llvm::SmallVectorImpl<Multilib> &Selected,
- llvm::SmallVector<StringRef> *CustomFlagCompilationArgs) const {
- auto [FlagsWithCustom, CFCompilationArgs] = processCustomFlags(D, Flags);
+ llvm::SmallVector<StringRef> *CustomFlagMacroDefines) const {
+ auto [FlagsWithCustom, CFMacroDefines] = processCustomFlags(D, Flags);
llvm::StringSet<> FlagSet(expandFlags(FlagsWithCustom));
Selected.clear();
bool AnyErrors = false;
- if (CustomFlagCompilationArgs)
- *CustomFlagCompilationArgs = std::move(CFCompilationArgs);
+ if (CustomFlagMacroDefines)
+ *CustomFlagMacroDefines = std::move(CFMacroDefines);
// Decide which multilibs we're going to select at all.
llvm::DenseSet<StringRef> ExclusiveGroupsSelected;
diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index c5711d94e26602..ca7ca37182b1e6 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -187,7 +187,7 @@ static void
findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
StringRef MultilibPath, const ArgList &Args,
DetectedMultilibs &Result,
- SmallVector<StringRef> &CustomFlagsCompilationArgs) {
+ SmallVector<StringRef> &CustomFlagsMacroDefines) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MB =
D.getVFS().getBufferForFile(MultilibPath);
if (!MB)
@@ -199,7 +199,7 @@ findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
return;
Result.Multilibs = ErrorOrMultilibSet.get();
if (Result.Multilibs.select(D, Flags, Result.SelectedMultilibs,
- &CustomFlagsCompilationArgs))
+ &CustomFlagsMacroDefines))
return;
D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " ");
std::stringstream ss;
@@ -258,13 +258,13 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
// If multilib.yaml is found, update sysroot so it doesn't use a target
// specific suffix
SysRoot = computeBaseSysRoot(D, /*IncludeTriple=*/false);
- SmallVector<StringRef> CustomFlagDriverArgs;
+ SmallVector<StringRef> CustomFlagMacroDefines;
findMultilibsFromYAML(*this, D, *MultilibPath, Args, Result,
- CustomFlagDriverArgs);
+ CustomFlagMacroDefines);
SelectedMultilibs = Result.SelectedMultilibs;
Multilibs = Result.Multilibs;
- MultilibDriverArgs.append(CustomFlagDriverArgs.begin(),
- CustomFlagDriverArgs.end());
+ MultilibMacroDefines.append(CustomFlagMacroDefines.begin(),
+ CustomFlagMacroDefines.end());
} else if (isRISCVBareMetal(Triple)) {
if (findRISCVMultilibs(D, Triple, Args, Result)) {
SelectedMultilibs = Result.SelectedMultilibs;
@@ -606,6 +606,6 @@ SanitizerMask BareMetal::getSupportedSanitizers() const {
}
SmallVector<std::string>
-BareMetal::getMultilibDriverArgsStr(llvm::opt::ArgList &Args) const {
- return MultilibDriverArgs;
-}
\ No newline at end of file
+BareMetal::getMultilibMacroDefinesStr(llvm::opt::ArgList &Args) const {
+ return MultilibMacroDefines;
+}
diff --git a/clang/lib/Driver/ToolChains/BareMetal.h b/clang/lib/Driver/ToolChains/BareMetal.h
index eb37124bbdc315..507e31c46800b6 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.h
+++ b/clang/lib/Driver/ToolChains/BareMetal.h
@@ -75,7 +75,7 @@ class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain {
SanitizerMask getSupportedSanitizers() const override;
SmallVector<std::string>
- getMultilibDriverArgsStr(llvm::opt::ArgList &Args) const override;
+ getMultilibMacroDefinesStr(llvm::opt::ArgList &Args) const override;
private:
using OrderedMultilibs =
@@ -84,7 +84,7 @@ class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain {
std::string SysRoot;
- SmallVector<std::string> MultilibDriverArgs;
+ SmallVector<std::string> MultilibMacroDefines;
};
} // namespace toolchains
diff --git a/clang/test/Driver/baremetal-multilib-custom-flags.yaml b/clang/test/Driver/baremetal-multilib-custom-flags.yaml
index c44096e199a560..9c0320ea16117a 100644
--- a/clang/test/Driver/baremetal-multilib-custom-flags.yaml
+++ b/clang/test/Driver/baremetal-multilib-custom-flags.yaml
@@ -37,17 +37,17 @@
# CHECK-PRINT-MULTI-LIB: arm-none-eabi/multithreaded/thumb/v8-m.main/nofp;@-target=thumbv8m.main-unknown-none-eabi at mfpu=none at fmultilib-flag=multithreaded
# RUN: %clang --target=arm-none-eabi --multi-lib-config=%s -x c %s -fmultilib-flag=no-multithreaded -### -o /dev/null 2>&1 \
-# RUN: | FileCheck --check-prefix=CHECK-DRIVERARGS-NOMULTI %s
-# CHECK-DRIVERARGS-NOMULTI: "-D" "__SINGLE_THREAD__"
+# RUN: | FileCheck --check-prefix=CHECK-MACRODEFINES-NOMULTI %s
+# CHECK-MACRODEFINES-NOMULTI: "-D" "__SINGLE_THREAD__"
# RUN: %clang --target=arm-none-eabi --multi-lib-config=%s -x c %s -fmultilib-flag=io-semihosting -### -o /dev/null 2>&1 \
-# RUN: | FileCheck --check-prefix=CHECK-DRIVERARGS-IO-SEMIHOSTING %s
-# CHECK-DRIVERARGS-IO-SEMIHOSTING: "-D" "SEMIHOSTING"
+# RUN: | FileCheck --check-prefix=CHECK-MACRODEFINES-IO-SEMIHOSTING %s
+# CHECK-MACRODEFINES-IO-SEMIHOSTING: "-D" "SEMIHOSTING"
# RUN: %clang --target=arm-none-eabi --multi-lib-config=%s -x c %s -fmultilib-flag=io-linux-syscalls -### -o /dev/null 2>&1 \
-# RUN: | FileCheck --check-prefix=CHECK-DRIVERARGS-IO-LINUX %s
-# CHECK-DRIVERARGS-IO-LINUX: "-U" "SEMIHOSTING"
-# CHECK-DRIVERARGS-IO-LINUX-SAME: "-D" "LINUX_SYSCALLS"
+# RUN: | FileCheck --check-prefix=CHECK-MACRODEFINES-IO-LINUX %s
+# CHECK-MACRODEFINES-IO-LINUX: "-D" "LINUX_SYSCALLS"
+# CHECK-MACRODEFINES-IO-LINUX-SAME: "-D" "HOSTED"
---
MultilibVersion: 1.0
@@ -68,14 +68,14 @@ Flags:
- Name: multithreading
Values:
- Name: no-multithreaded
- DriverArgs: [-D__SINGLE_THREAD__]
+ MacroDefines: [__SINGLE_THREAD__]
- Name: multithreaded
Default: no-multithreaded
- Name: io
Values:
- Name: io-none
- Name: io-semihosting
- DriverArgs: [-DSEMIHOSTING]
+ MacroDefines: [SEMIHOSTING]
- Name: io-linux-syscalls
- DriverArgs: [-USEMIHOSTING, -DLINUX_SYSCALLS]
+ MacroDefines: [LINUX_SYSCALLS, HOSTED]
Default: io-none
\ No newline at end of file
More information about the llvm-branch-commits
mailing list