[clang] [Multilib] Custom flags processing for library selection (PR #110659)
Victor Campos via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 14 06:09:26 PST 2025
https://github.com/vhscampos updated https://github.com/llvm/llvm-project/pull/110659
>From 16aa4a010c22288ba363e4ab680a38fe0b6a327d Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Mon, 13 Jan 2025 13:51:52 +0000
Subject: [PATCH 1/8] [Multilib] Custom flags YAML parsing
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch is the first step to extend the current multilib system to
support the selection of library variants which do not correspond to
existing command-line options.
Proposal can be found in
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
The multilib mechanism supports libraries that target code generation or
language options such as `--target`, `-mcpu`, `-mfpu`,
`-mbranch-protection`. However, some library variants are particular to
features that do not correspond to any command-line options. Examples
include variants for multithreading and semihosting.
This work introduces a way to instruct the multilib system to consider
these features in library selection. This particular patch comprises a
new section in `multilib.yaml` to declare flags for which no option
exists. Henceforth this sort of flag will be called `custom flag` for
clarity.
The `multilib.yaml` file will have a new section called Flags which
contains the declarations of the target’s custom flags:
```yaml
Flags:
- Name: multithreaded
Values:
- Name: no-multithreaded
MacroDefines: [__SINGLE_THREAD__]
- Name: multithreaded
Default: no-multithreaded
- Name: io
Values:
- Name: io-none
- Name: io-semihosting
MacroDefines: [SEMIHOSTING]
- Name: io-linux-syscalls
MacroDefines: [LINUX_SYSCALLS, HOSTED=1]
Default: io-none
```
- Name: the name to categorize a flag.
- Values: a list of possible values.
- Default: it specifies which value this flag should take if not
specified in the command-line invocation. It must be one value from the
Values field.
Each flag Value follows this description:
- Name (required): the name of the custom flag value (string). This is
the string to be used in `-fmultilib-flag=<string>`.
- MacroDefines (optional): a list of strings to be used as macro
definitions. Each string
is fed into the driver as ``-D<string>``.
A Default value is useful to save users from specifying custom flags
that have a most commonly used value.
The namespace of flag values is common across all flags. This means that
flag values must be unique.
---
clang/include/clang/Driver/Multilib.h | 33 ++++-
clang/lib/Driver/Multilib.cpp | 109 ++++++++++++--
...remetal-multilib-custom-flags-parsing.yaml | 133 ++++++++++++++++++
3 files changed, 264 insertions(+), 11 deletions(-)
create mode 100644 clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml
diff --git a/clang/include/clang/Driver/Multilib.h b/clang/include/clang/Driver/Multilib.h
index dbed70f4f9008f..0a533ed2804e25 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -101,6 +101,30 @@ class Multilib {
raw_ostream &operator<<(raw_ostream &OS, const Multilib &M);
+namespace custom_flag {
+struct Declaration;
+
+struct ValueDetail {
+ std::string Name;
+ std::optional<SmallVector<std::string>> MacroDefines;
+ Declaration *Decl;
+};
+
+struct Declaration {
+ std::string Name;
+ SmallVector<ValueDetail> ValueList;
+ std::optional<size_t> DefaultValueIdx;
+
+ Declaration() = default;
+ Declaration(const Declaration &);
+ Declaration(Declaration &&);
+ Declaration &operator=(const Declaration &);
+ Declaration &operator=(Declaration &&);
+};
+
+static constexpr StringRef Prefix = "-fmultilib-flag=";
+} // namespace custom_flag
+
/// See also MultilibSetBuilder for combining multilibs into a set.
class MultilibSet {
public:
@@ -120,15 +144,18 @@ class MultilibSet {
private:
multilib_list Multilibs;
- std::vector<FlagMatcher> FlagMatchers;
+ SmallVector<FlagMatcher> FlagMatchers;
+ SmallVector<custom_flag::Declaration> CustomFlagDecls;
IncludeDirsFunc IncludeCallback;
IncludeDirsFunc FilePathsCallback;
public:
MultilibSet() = default;
MultilibSet(multilib_list &&Multilibs,
- std::vector<FlagMatcher> &&FlagMatchers = {})
- : Multilibs(Multilibs), FlagMatchers(FlagMatchers) {}
+ SmallVector<FlagMatcher> &&FlagMatchers = {},
+ SmallVector<custom_flag::Declaration> &&CustomFlagDecls = {})
+ : Multilibs(std::move(Multilibs)), FlagMatchers(std::move(FlagMatchers)),
+ CustomFlagDecls(std::move(CustomFlagDecls)) {}
const multilib_list &getMultilibs() { return Multilibs; }
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 0207e0f2eb2ded..ccf747e90cb2ca 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -10,6 +10,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Driver/Driver.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
@@ -201,13 +202,20 @@ struct MultilibGroupSerialization {
struct MultilibSetSerialization {
llvm::VersionTuple MultilibVersion;
- std::vector<MultilibGroupSerialization> Groups;
- std::vector<MultilibSerialization> Multilibs;
- std::vector<MultilibSet::FlagMatcher> FlagMatchers;
+ SmallVector<MultilibGroupSerialization> Groups;
+ SmallVector<MultilibSerialization> Multilibs;
+ SmallVector<MultilibSet::FlagMatcher> FlagMatchers;
+ SmallVector<custom_flag::Declaration> CustomFlagDeclarations;
};
} // end anonymous namespace
+LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibSerialization)
+LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibGroupSerialization)
+LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibSet::FlagMatcher)
+LLVM_YAML_IS_SEQUENCE_VECTOR(custom_flag::ValueDetail)
+LLVM_YAML_IS_SEQUENCE_VECTOR(custom_flag::Declaration)
+
template <> struct llvm::yaml::MappingTraits<MultilibSerialization> {
static void mapping(llvm::yaml::IO &io, MultilibSerialization &V) {
io.mapOptional("Dir", V.Dir);
@@ -255,11 +263,61 @@ template <> struct llvm::yaml::MappingTraits<MultilibSet::FlagMatcher> {
}
};
+template <>
+struct llvm::yaml::MappingContextTraits<custom_flag::ValueDetail,
+ llvm::SmallSet<std::string, 32>> {
+ static void mapping(llvm::yaml::IO &io, custom_flag::ValueDetail &V,
+ llvm::SmallSet<std::string, 32> &) {
+ io.mapRequired("Name", V.Name);
+ io.mapOptional("MacroDefines", V.MacroDefines);
+ }
+ static std::string validate(IO &io, custom_flag::ValueDetail &V,
+ llvm::SmallSet<std::string, 32> &NameSet) {
+ if (V.Name.empty())
+ return "custom flag value requires a name";
+ if (!NameSet.insert(V.Name).second)
+ return "duplicate custom flag value name: \"" + V.Name + "\"";
+ return {};
+ }
+};
+
+template <>
+struct llvm::yaml::MappingContextTraits<custom_flag::Declaration,
+ llvm::SmallSet<std::string, 32>> {
+ static void mapping(llvm::yaml::IO &io, custom_flag::Declaration &V,
+ llvm::SmallSet<std::string, 32> &NameSet) {
+ io.mapRequired("Name", V.Name);
+ io.mapRequired("Values", V.ValueList, NameSet);
+ std::string DefaultValueName;
+ io.mapRequired("Default", DefaultValueName);
+
+ for (auto [Idx, Value] : llvm::enumerate(V.ValueList)) {
+ Value.Decl = &V;
+ if (Value.Name == DefaultValueName) {
+ assert(!V.DefaultValueIdx);
+ V.DefaultValueIdx = Idx;
+ }
+ }
+ }
+ static std::string validate(IO &io, custom_flag::Declaration &V,
+ llvm::SmallSet<std::string, 32> &) {
+ if (V.Name.empty())
+ return "custom flag requires a name";
+ if (V.ValueList.empty())
+ return "custom flag must have at least one value";
+ if (!V.DefaultValueIdx)
+ return "custom flag must have a default value";
+ return {};
+ }
+};
+
template <> struct llvm::yaml::MappingTraits<MultilibSetSerialization> {
static void mapping(llvm::yaml::IO &io, MultilibSetSerialization &M) {
io.mapRequired("MultilibVersion", M.MultilibVersion);
io.mapRequired("Variants", M.Multilibs);
io.mapOptional("Groups", M.Groups);
+ llvm::SmallSet<std::string, 32> NameSet;
+ io.mapOptionalWithContext("Flags", M.CustomFlagDeclarations, NameSet);
io.mapOptional("Mappings", M.FlagMatchers);
}
static std::string validate(IO &io, MultilibSetSerialization &M) {
@@ -288,10 +346,6 @@ template <> struct llvm::yaml::MappingTraits<MultilibSetSerialization> {
}
};
-LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibSerialization)
-LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibGroupSerialization)
-LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibSet::FlagMatcher)
-
llvm::ErrorOr<MultilibSet>
MultilibSet::parseYaml(llvm::MemoryBufferRef Input,
llvm::SourceMgr::DiagHandlerTy DiagHandler,
@@ -319,7 +373,8 @@ MultilibSet::parseYaml(llvm::MemoryBufferRef Input,
}
}
- return MultilibSet(std::move(Multilibs), std::move(MS.FlagMatchers));
+ return MultilibSet(std::move(Multilibs), std::move(MS.FlagMatchers),
+ std::move(MS.CustomFlagDeclarations));
}
LLVM_DUMP_METHOD void MultilibSet::dump() const {
@@ -335,3 +390,41 @@ raw_ostream &clang::driver::operator<<(raw_ostream &OS, const MultilibSet &MS) {
MS.print(OS);
return OS;
}
+
+namespace clang::driver::custom_flag {
+Declaration::Declaration(const Declaration &Other)
+ : Name(Other.Name), ValueList(Other.ValueList),
+ DefaultValueIdx(Other.DefaultValueIdx) {
+ for (ValueDetail &Detail : ValueList)
+ Detail.Decl = this;
+}
+
+Declaration::Declaration(Declaration &&Other)
+ : Name(std::move(Other.Name)), ValueList(std::move(Other.ValueList)),
+ DefaultValueIdx(std::move(Other.DefaultValueIdx)) {
+ for (ValueDetail &Detail : ValueList)
+ Detail.Decl = this;
+}
+
+Declaration &Declaration::operator=(const Declaration &Other) {
+ if (this == &Other)
+ return *this;
+ Name = Other.Name;
+ ValueList = Other.ValueList;
+ DefaultValueIdx = Other.DefaultValueIdx;
+ for (ValueDetail &Detail : ValueList)
+ Detail.Decl = this;
+ return *this;
+}
+
+Declaration &Declaration::operator=(Declaration &&Other) {
+ if (this == &Other)
+ return *this;
+ Name = std::move(Other.Name);
+ ValueList = std::move(Other.ValueList);
+ DefaultValueIdx = std::move(Other.DefaultValueIdx);
+ for (ValueDetail &Detail : ValueList)
+ Detail.Decl = this;
+ return *this;
+}
+} // namespace clang::driver::custom_flag
diff --git a/clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml b/clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml
new file mode 100644
index 00000000000000..fe6a9a8d7f1ee7
--- /dev/null
+++ b/clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml
@@ -0,0 +1,133 @@
+# RUN: split-file %s %t
+
+# 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-macro-defines.yaml %s -### -o /dev/null 2>&1 \
+# RUN: | FileCheck %s
+# CHECK-NOT: error:
+
+# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/missing-flag-name.yaml %s -### -o /dev/null 2>&1 \
+# RUN: | FileCheck %s --check-prefix=CHECK-MISSING-FLAG-NAME
+# CHECK-MISSING-FLAG-NAME: error: custom flag requires a name
+
+# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/missing-flag-values.yaml %s -### -o /dev/null 2>&1 \
+# RUN: | FileCheck %s --check-prefix=CHECK-MISSING-FLAG-VALUES
+# CHECK-MISSING-FLAG-VALUES: error: custom flag must have at least one value
+
+# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/missing-flag-value-default.yaml %s -### -o /dev/null 2>&1 \
+# RUN: | FileCheck %s --check-prefix=CHECK-MISSING-FLAG-VALUE-DEFAULT
+# CHECK-MISSING-FLAG-VALUE-DEFAULT: error: custom flag must have a default value
+
+# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/missing-flag-value-name.yaml %s -### -o /dev/null 2>&1 \
+# RUN: | FileCheck %s --check-prefix=CHECK-MISSING-FLAG-VALUE-NAME
+# CHECK-MISSING-FLAG-VALUE-NAME: error: custom flag value requires a name
+
+# RUN: %clang --target=arm-none-eabi --multi-lib-config=%t/duplicate-flag-value-name.yaml %s -### -o /dev/null 2>&1 \
+# RUN: | FileCheck %s --check-prefix=CHECK-DUPLICATE-FLAG-VALUE-NAME
+# CHECK-DUPLICATE-FLAG-VALUE-NAME: error: duplicate custom flag value name: "value-name"
+# CHECK-DUPLICATE-FLAG-VALUE-NAME-NEXT: - Name: value-name
+
+#--- multilib-without-macro-defines.yaml
+---
+MultilibVersion: 1.0
+
+Variants:
+- Dir: libc
+ Flags: [-fmultilib-flag=a]
+
+Flags:
+ - Name: flag
+ Values:
+ - Name: a
+ - Name: b
+ Default: a
+
+#--- multilib-with-macro-defines.yaml
+---
+MultilibVersion: 1.0
+
+Variants:
+- Dir: libc
+ Flags: [-fmultilib-flag=a]
+
+Flags:
+ - Name: flag
+ Values:
+ - Name: a
+ MacroDefines: [FEATURE_A]
+ - Name: b
+ MacroDefines: [FEATURE_B]
+ Default: a
+
+#--- missing-flag-name.yaml
+---
+MultilibVersion: 1.0
+
+Variants:
+- Dir: libc
+ Flags: [-fmultilib-flag=a]
+
+Flags:
+ - Values:
+ - Name: a
+ Default: a
+
+#--- missing-flag-values.yaml
+---
+MultilibVersion: 1.0
+
+Variants:
+- Dir: libc
+ Flags: [-fmultilib-flag=a]
+
+Flags:
+ - Name: flag
+ Values:
+ Default: a
+
+#--- missing-flag-value-default.yaml
+---
+MultilibVersion: 1.0
+
+Variants:
+- Dir: libc
+ Flags: [-fmultilib-flag=a]
+
+Flags:
+ - Name: flag
+ Values:
+ - Name: a
+ Default:
+
+#--- missing-flag-value-name.yaml
+---
+MultilibVersion: 1.0
+
+Variants:
+- Dir: libc
+ Flags: [-fmultilib-flag=a]
+
+Flags:
+ - Name: flag
+ Values:
+ - Name:
+ Default: a
+
+#--- duplicate-flag-value-name.yaml
+---
+MultilibVersion: 1.0
+
+Variants:
+- Dir: libc
+ Flags: [-fmultilib-flag=value-name]
+
+Flags:
+ - Name: a
+ Values:
+ - Name: value-name
+ - Name: value-a
+ Default: value-name
+ - Name: b
+ Values:
+ - Name: value-name
+ Default: value-name
>From 7d36f0fd176c85bfeee7a890ab638a16ca43c44d 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 2/8] [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 | 141 ++++++++++--------
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, 328 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 80bce574a3b647..3f29bdf2ff23f4 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -466,7 +466,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 0a533ed2804e25..a8cba32de84e7a 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -168,9 +168,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 701a1d25ca4c8d..17bddf0120215b 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 9a947f32283c3a..4463f01ee052ff 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -264,7 +264,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;
@@ -1397,8 +1397,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
bool HasConfigFileTail = !ContainsError && CfgOptionsTail;
// All arguments, from both config file and command line.
- InputArgList Args =
- HasConfigFileHead ? std::move(*CfgOptionsHead) : std::move(*CLOptions);
+ auto UArgs = std::make_unique<InputArgList>(HasConfigFileHead ? std::move(*CfgOptionsHead) : std::move(*CLOptions));
+ InputArgList &Args = *UArgs;
if (HasConfigFileHead)
for (auto *Opt : *CLOptions)
@@ -1426,52 +1426,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()) {
@@ -1529,6 +1483,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));
@@ -1543,13 +1570,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())
@@ -1569,8 +1589,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();
@@ -1624,16 +1642,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 ccf747e90cb2ca..d33302850b3235 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 eecaaa9a42930d..11282bf796e3af 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -162,9 +162,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)
@@ -175,7 +177,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;
@@ -234,9 +237,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;
@@ -551,3 +558,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 483b5efab5e6e2..dc61006f63c9d0 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.h
+++ b/clang/lib/Driver/ToolChains/BareMetal.h
@@ -70,12 +70,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 131a8cac8910c78df9091f8a5c5144ace013e012 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 3/8] Fix clang-format errors
---
clang/lib/Driver/Driver.cpp | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 4463f01ee052ff..c9a0f058ed9691 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -264,7 +264,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;
@@ -1397,7 +1398,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
bool HasConfigFileTail = !ContainsError && CfgOptionsTail;
// All arguments, from both config file and command line.
- auto UArgs = std::make_unique<InputArgList>(HasConfigFileHead ? std::move(*CfgOptionsHead) : std::move(*CLOptions));
+ auto UArgs = std::make_unique<InputArgList>(
+ HasConfigFileHead ? std::move(*CfgOptionsHead) : std::move(*CLOptions));
InputArgList &Args = *UArgs;
if (HasConfigFileHead)
>From 403ee8c40fa4e0cda2b2edc5b4fd688ae3f7ab5f 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 4/8] 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 aa46b7b15d63f2a83dc45ccea1deb9204c94449e 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 5/8] 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 a8cba32de84e7a..fc071ef48ca0f9 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -169,10 +169,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 17bddf0120215b..7d1d8feebf35e3 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 c9a0f058ed9691..24bc0e41f8f71c 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1398,9 +1398,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
bool HasConfigFileTail = !ContainsError && CfgOptionsTail;
// All arguments, from both config file and command line.
- auto UArgs = std::make_unique<InputArgList>(
- HasConfigFileHead ? std::move(*CfgOptionsHead) : std::move(*CLOptions));
- InputArgList &Args = *UArgs;
+ InputArgList Args = HasConfigFileHead ? std::move(*CfgOptionsHead) : std::move(*CLOptions);
if (HasConfigFileHead)
for (auto *Opt : *CLOptions)
@@ -1428,6 +1426,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()) {
@@ -1485,79 +1529,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));
@@ -1572,6 +1543,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())
@@ -1591,6 +1569,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();
@@ -1644,6 +1624,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);
+ }
+ }
+ }
+
// Perform the default argument translations.
DerivedArgList *TranslatedArgs = TranslateInputArgs(*UArgs);
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index d33302850b3235..53816aa46b4fb7 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 11282bf796e3af..ffb1c6e34d6039 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -166,7 +166,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)
@@ -178,7 +178,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;
@@ -237,13 +237,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;
@@ -560,6 +560,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 dc61006f63c9d0..f6295bda0a6a2e 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.h
+++ b/clang/lib/Driver/ToolChains/BareMetal.h
@@ -71,7 +71,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 =
@@ -80,7 +80,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
>From 46b830b732793f7b6129bec2f2612b54c66f9826 Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Thu, 9 Jan 2025 11:21:39 +0000
Subject: [PATCH 6/8] Add clarifying comment
---
clang/lib/Driver/Multilib.cpp | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 53816aa46b4fb7..591547832112a8 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -225,6 +225,10 @@ bool MultilibSet::select(
Selected.clear();
bool AnyErrors = false;
+ // Determining the list of macro defines depends only on the custom flags
+ // passed in. The library variants actually selected are not relevant in
+ // this. Therefore this assignment can take place before the selection
+ // happens.
if (CustomFlagMacroDefines)
*CustomFlagMacroDefines = std::move(CFMacroDefines);
>From a92176634a398c667fcc515d546af86edc5ba14c Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Thu, 9 Jan 2025 11:52:52 +0000
Subject: [PATCH 7/8] Fix clang-format error
---
clang/lib/Driver/Driver.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 24bc0e41f8f71c..06eb6b945827ac 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1398,7 +1398,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
bool HasConfigFileTail = !ContainsError && CfgOptionsTail;
// All arguments, from both config file and command line.
- InputArgList Args = HasConfigFileHead ? std::move(*CfgOptionsHead) : std::move(*CLOptions);
+ InputArgList Args =
+ HasConfigFileHead ? std::move(*CfgOptionsHead) : std::move(*CLOptions);
if (HasConfigFileHead)
for (auto *Opt : *CLOptions)
>From 71dd4c28c6ab995eb1458a5782c774d0e22e0fa9 Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Tue, 14 Jan 2025 14:00:02 +0000
Subject: [PATCH 8/8] Rewrite code for the removal of shared_ptr use
---
clang/lib/Driver/Multilib.cpp | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 591547832112a8..ad1cc48ffc96ba 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -95,7 +95,7 @@ void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
static void DiagnoseUnclaimedMultilibCustomFlags(
const Driver &D, const SmallVector<StringRef> &UnclaimedCustomFlagValues,
- const SmallVector<custom_flag::DeclarationPtr> &CustomFlagDecls) {
+ const SmallVector<custom_flag::Declaration> &CustomFlagDecls) {
struct EditDistanceInfo {
StringRef FlagValue;
unsigned EditDistance;
@@ -105,7 +105,7 @@ static void DiagnoseUnclaimedMultilibCustomFlags(
for (StringRef Unclaimed : UnclaimedCustomFlagValues) {
std::optional<EditDistanceInfo> BestCandidate;
for (const auto &Decl : CustomFlagDecls) {
- for (const auto &Value : Decl->ValueList) {
+ for (const auto &Value : Decl.ValueList) {
const std::string &FlagValueName = Value.Name;
unsigned EditDistance =
Unclaimed.edit_distance(FlagValueName, /*AllowReplacements=*/true,
@@ -136,8 +136,8 @@ class ValueNameToDetailMap {
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)
+ const Declaration &Decl = *DeclIt;
+ for (const auto &Value : Decl.ValueList)
Mapping.emplace_back(Value.Name, &Value);
}
}
@@ -186,7 +186,7 @@ MultilibSet::processCustomFlags(const Driver &D,
// 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;
+ llvm::SmallPtrSet<custom_flag::Declaration *, 32> TriggeredCustomFlagDecls;
// Detect multiple values for the same flag declaration. Last one wins.
for (auto *CustomFlagValue : llvm::reverse(ClaimedCustomFlagValues)) {
@@ -200,10 +200,10 @@ MultilibSet::processCustomFlags(const Driver &D,
// Detect flag declarations with no value passed in. Select default value.
for (const auto &Decl : CustomFlagDecls) {
- if (TriggeredCustomFlagDecls.contains(Decl))
+ if (TriggeredCustomFlagDecls.contains(&Decl))
continue;
- custom_flag::ValueDetail &CustomFlagValue =
- Decl->ValueList[*Decl->DefaultValueIdx];
+ const custom_flag::ValueDetail &CustomFlagValue =
+ Decl.ValueList[*Decl.DefaultValueIdx];
Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue.Name);
if (CustomFlagValue.MacroDefines)
MacroDefines.append(CustomFlagValue.MacroDefines->begin(),
More information about the cfe-commits
mailing list