[clang] b4eebc8 - [Driver] Enable multilib.yaml in the BareMetal ToolChain

Michael Platings via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 13 22:47:22 PDT 2023


Author: Michael Platings
Date: 2023-06-14T06:46:41+01:00
New Revision: b4eebc8674e1f1dc1ef08fa7648ca494a119449d

URL: https://github.com/llvm/llvm-project/commit/b4eebc8674e1f1dc1ef08fa7648ca494a119449d
DIFF: https://github.com/llvm/llvm-project/commit/b4eebc8674e1f1dc1ef08fa7648ca494a119449d.diff

LOG: [Driver] Enable multilib.yaml in the BareMetal ToolChain

The default location for multilib.yaml is lib/clang-runtimes, without
any target-specific suffix. This will allow multilibs for different
architectures to share a common include directory.

To avoid breaking the arm-execute-only.c CHECK-NO-EXECUTE-ONLY-ASM
test, add a ForMultilib argument to getARMTargetFeatures.

Since the presence of multilib.yaml can change the exact location of a
library, relax the baremetal.cpp test.

Differential Revision: https://reviews.llvm.org/D142986

Added: 
    clang/test/Driver/baremetal-multilib.yaml

Modified: 
    clang/lib/Driver/ToolChain.cpp
    clang/lib/Driver/ToolChains/Arch/ARM.cpp
    clang/lib/Driver/ToolChains/Arch/ARM.h
    clang/lib/Driver/ToolChains/BareMetal.cpp
    clang/test/Driver/baremetal.cpp
    clang/test/Driver/lit.local.cfg

Removed: 
    


################################################################################
diff  --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 9276b9a2ab85b..44b2a3d8f9d0b 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -199,8 +199,8 @@ static void getARMMultilibFlags(const Driver &D,
                                       const llvm::opt::ArgList &Args,
                                       Multilib::flags_list &Result) {
   std::vector<StringRef> Features;
-  llvm::ARM::FPUKind FPUKind =
-      tools::arm::getARMTargetFeatures(D, Triple, Args, Features, false);
+  llvm::ARM::FPUKind FPUKind = tools::arm::getARMTargetFeatures(
+      D, Triple, Args, Features, false /*ForAs*/, true /*ForMultilib*/);
   const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);
   llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),
                                        UnifiedFeatures.end());

diff  --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index 62eee13664523..2ff18a47ef77a 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -467,7 +467,7 @@ llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver &D,
                                              const llvm::Triple &Triple,
                                              const ArgList &Args,
                                              std::vector<StringRef> &Features,
-                                             bool ForAS) {
+                                             bool ForAS, bool ForMultilib) {
   bool KernelOrKext =
       Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
   arm::FloatABI ABI = arm::getARMFloatABI(D, Triple, Args);
@@ -807,7 +807,9 @@ llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver &D,
 
   // Generate execute-only output (no data access to code sections).
   // This only makes sense for the compiler, not for the assembler.
-  if (!ForAS) {
+  // It's not needed for multilib selection and may hide an unused
+  // argument diagnostic if the code is always run.
+  if (!ForAS && !ForMultilib) {
     // Supported only on ARMv6T2 and ARMv7 and above.
     // Cannot be combined with -mno-movt.
     if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) {

diff  --git a/clang/lib/Driver/ToolChains/Arch/ARM.h b/clang/lib/Driver/ToolChains/Arch/ARM.h
index 0f18305579a2a..08696ad28931f 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.h
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -67,7 +67,7 @@ llvm::ARM::FPUKind getARMTargetFeatures(const Driver &D,
                                         const llvm::Triple &Triple,
                                         const llvm::opt::ArgList &Args,
                                         std::vector<llvm::StringRef> &Features,
-                                        bool ForAS);
+                                        bool ForAS, bool ForMultilib = false);
 int getARMSubArchVersionNumber(const llvm::Triple &Triple);
 bool isARMMProfile(const llvm::Triple &Triple);
 bool isARMAProfile(const llvm::Triple &Triple);

diff  --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index ec3571bb60ee8..c167f8608945e 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -155,6 +155,46 @@ static bool isRISCVBareMetal(const llvm::Triple &Triple) {
   return Triple.getEnvironmentName() == "elf";
 }
 
+static bool findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
+                                  StringRef MultilibPath, const ArgList &Args,
+                                  DetectedMultilibs &Result) {
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MB =
+      D.getVFS().getBufferForFile(MultilibPath);
+  if (!MB)
+    return false;
+  Multilib::flags_list Flags = TC.getMultilibFlags(Args);
+  llvm::ErrorOr<MultilibSet> ErrorOrMultilibSet =
+      MultilibSet::parseYaml(*MB.get());
+  if (ErrorOrMultilibSet.getError())
+    return false;
+  Result.Multilibs = ErrorOrMultilibSet.get();
+  return Result.Multilibs.select(Flags, Result.SelectedMultilib);
+}
+
+static constexpr llvm::StringLiteral MultilibFilename = "multilib.yaml";
+
+// Get the sysroot, before multilib takes effect.
+static std::string computeBaseSysRoot(const Driver &D,
+                                      const llvm::Triple &Triple) {
+  if (!D.SysRoot.empty())
+    return D.SysRoot;
+
+  SmallString<128> SysRootDir(D.Dir);
+  llvm::sys::path::append(SysRootDir, "..", "lib", "clang-runtimes");
+
+  SmallString<128> MultilibPath(SysRootDir);
+  llvm::sys::path::append(MultilibPath, MultilibFilename);
+
+  // New behaviour: if multilib.yaml is found then use clang-runtimes as the
+  // sysroot.
+  if (D.getVFS().exists(MultilibPath))
+    return std::string(SysRootDir);
+
+  // Otherwise fall back to the old behaviour of appending the target triple.
+  llvm::sys::path::append(SysRootDir, D.getTargetTriple());
+  return std::string(SysRootDir);
+}
+
 void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
                               const ArgList &Args) {
   DetectedMultilibs Result;
@@ -163,6 +203,12 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
       SelectedMultilib = Result.SelectedMultilib;
       Multilibs = Result.Multilibs;
     }
+  } else {
+    llvm::SmallString<128> MultilibPath(computeBaseSysRoot(D, Triple));
+    llvm::sys::path::append(MultilibPath, MultilibFilename);
+    findMultilibsFromYAML(*this, D, MultilibPath, Args, Result);
+    SelectedMultilib = Result.SelectedMultilib;
+    Multilibs = Result.Multilibs;
   }
 }
 
@@ -176,15 +222,8 @@ Tool *BareMetal::buildLinker() const {
 }
 
 std::string BareMetal::computeSysRoot() const {
-  if (!getDriver().SysRoot.empty())
-    return getDriver().SysRoot + SelectedMultilib.osSuffix();
-
-  SmallString<128> SysRootDir;
-  llvm::sys::path::append(SysRootDir, getDriver().Dir, "../lib/clang-runtimes",
-                          getDriver().getTargetTriple());
-
-  SysRootDir += SelectedMultilib.osSuffix();
-  return std::string(SysRootDir);
+  return computeBaseSysRoot(getDriver(), getTriple()) +
+         SelectedMultilib.osSuffix();
 }
 
 void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,

diff  --git a/clang/test/Driver/baremetal-multilib.yaml b/clang/test/Driver/baremetal-multilib.yaml
new file mode 100644
index 0000000000000..93fa61ce6adf0
--- /dev/null
+++ b/clang/test/Driver/baremetal-multilib.yaml
@@ -0,0 +1,145 @@
+# REQUIRES: shell
+# UNSUPPORTED: system-windows
+
+# RUN: rm -rf %T/baremetal_multilib
+# RUN: mkdir -p %T/baremetal_multilib/bin
+# RUN: mkdir -p %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib
+# RUN: touch %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib/libclang_rt.builtins.a
+# RUN: ln -s %clang %T/baremetal_multilib/bin/clang
+# RUN: ln -s %s %T/baremetal_multilib/lib/clang-runtimes/multilib.yaml
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x c++ %s -### -o %t.out 2>&1 \
+# RUN:     --target=thumbv8m.main-none-eabihf --sysroot= \
+# RUN:   | FileCheck -DSYSROOT=%T/baremetal_multilib %s
+# CHECK:      "-cc1" "-triple" "thumbv8m.main-none-unknown-eabihf"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include/c++/v1"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include"
+# CHECK-SAME: "-x" "c++" "{{.*}}baremetal-multilib.yaml"
+# CHECK-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic"
+# CHECK-SAME: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib"
+# CHECK-SAME: "-lc" "-lm" "-lclang_rt.builtins"
+# CHECK-SAME: "-o" "{{.*}}.tmp.out"
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN:     --target=thumbv8m.main-none-eabihf --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY %s
+# CHECK-PRINT-MULTI-DIRECTORY: arm-none-eabi/thumb/v8-m.main/fp
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-lib 2>&1 \
+# RUN:     --target=arm-none-eabi --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v6-m/nofp;@-target=thumbv6m-none-unknown-eabi at mfpu=none
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7-m/nofp;@-target=thumbv7m-none-unknown-eabi at mfpu=none
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7e-m/nofp;@-target=thumbv7em-none-unknown-eabi at mfpu=none
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/nofp;@-target=thumbv8m.main-none-unknown-eabi at mfpu=none
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/nofp/nomve;@-target=thumbv8.1m.main-none-unknown-eabi at mfpu=none
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7e-m/fpv4_sp_d16;@-target=thumbv7em-none-unknown-eabihf at mfpu=fpv4-sp-d16
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7e-m/fpv5_d16;@-target=thumbv7em-none-unknown-eabihf at mfpu=fpv5-d16
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/fp;@-target=thumbv8m.main-none-unknown-eabihf at mfpu=fpv5-d16
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/fp;@-target=thumbv8.1m.main-none-unknown-eabihf at mfpu=fp-armv8-fullfp16-sp-d16
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/nofp/mve;@-target=thumbv8.1m.main-none-unknown-eabihf at march=thumbv8.1m.main+mve at mfpu=none
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x assembler -mexecute-only \
+# RUN:     --target=arm-none-eabi --sysroot= %s -c -### 2>&1 \
+# RUN:    | FileCheck %s --check-prefix=CHECK-NO-EXECUTE-ONLY-ASM
+# CHECK-NO-EXECUTE-ONLY-ASM: warning: argument unused during compilation: '-mexecute-only'
+
+---
+# This file is in two parts:
+# 1. A list of library variants.
+# 2. A mapping from flags generated from command line arguments to further
+#    flags.
+
+# How does clang use this file?
+# 1. If the ToolChain class for the architecture supports this form of
+#    multilib it then it loads the file if present in sysroot.
+# 2. Generate flags from the user provided arguments.
+#    (Use `clang -print-multi-flags-experimental` to see which flags are
+#    generated).
+# 3. Compare the arguments against each regular expression and store
+#    associated flags if there's a match.
+# 4. Find the last library variant whose flags are a subset of the
+#    flags derived from the user provided arguments.
+# 5. Use the directory for the library variant as the sysroot.
+
+# Clang will emit an error if this number is greater than its current multilib
+# version or if its major version 
diff ers, but will accept lesser minor
+# versions.
+MultilibVersion: 1.0
+
+# The first section of the file is the list of library variants.
+# A library is considered compatible if the are a subset of the flags derived
+# from the arguments provided by the user.
+# If multiple libraries are deemed compatible then the one that appears
+# last in the list wins. A ToolChain may instead opt to use more than one
+# multilib, layered on top of each other.
+
+Variants:
+- Dir: arm-none-eabi/thumb/v6-m/nofp
+  Flags: [--target=thumbv6m-none-unknown-eabi, -mfpu=none]
+
+- Dir: arm-none-eabi/thumb/v7-m/nofp
+  Flags: [--target=thumbv7m-none-unknown-eabi, -mfpu=none]
+
+- Dir: arm-none-eabi/thumb/v7e-m/nofp
+  Flags: [--target=thumbv7em-none-unknown-eabi, -mfpu=none]
+
+- Dir: arm-none-eabi/thumb/v8-m.main/nofp
+  Flags: [--target=thumbv8m.main-none-unknown-eabi, -mfpu=none]
+
+- Dir: arm-none-eabi/thumb/v8.1-m.main/nofp/nomve
+  Flags: [--target=thumbv8.1m.main-none-unknown-eabi, -mfpu=none]
+
+- Dir: arm-none-eabi/thumb/v7e-m/fpv4_sp_d16
+  Flags: [--target=thumbv7em-none-unknown-eabihf, -mfpu=fpv4-sp-d16]
+
+- Dir: arm-none-eabi/thumb/v7e-m/fpv5_d16
+  Flags: [--target=thumbv7em-none-unknown-eabihf, -mfpu=fpv5-d16]
+
+- Dir: arm-none-eabi/thumb/v8-m.main/fp
+  Flags: [--target=thumbv8m.main-none-unknown-eabihf, -mfpu=fpv5-d16]
+
+- Dir: arm-none-eabi/thumb/v8.1-m.main/fp
+  Flags: [--target=thumbv8.1m.main-none-unknown-eabihf, -mfpu=fp-armv8-fullfp16-sp-d16]
+
+- Dir: arm-none-eabi/thumb/v8.1-m.main/nofp/mve
+  Flags: [--target=thumbv8.1m.main-none-unknown-eabihf, -march=thumbv8.1m.main+mve, -mfpu=none]
+
+
+# The second section of the file is a map from auto-detected flags
+# to custom flags. The auto-detected flags can be printed out
+# by running clang with `-print-multi-flags-experimental`.
+# The regex must match a whole flag string.
+# All flags in the "Flags" list will be added if an argument matches.
+Mappings:
+# For v8m.base (and potential later v8m baseline versions) use v6m
+- Match: --target=thumbv8(\.[0-9]+)?m\.base-none-unknown-eabi
+  Flags: [--target=thumbv6m-none-unknown-eabi]
+# Match versions after v8.1m.main. We assume that v8.2m (if/when it exists) will
+# be backwards compatible with v8.1m.
+# The alternative is to not recognise later versions, and require that
+# this multilib spec is updated before it can be used with newer
+# architecture versions.
+- Match: --target=thumbv8\.[1-9]m\.main-none-unknown-eabi
+  Flags: [--target=thumbv8.1m.main-none-unknown-eabi]
+- Match: --target=thumbv8\.[1-9]m\.main-none-unknown-eabihf
+  Flags: [--target=thumbv8.1m.main-none-unknown-eabihf]
+
+- Match: -march=thumbv8\.[1-9]m\.main.*\+mve($|\+).*
+  Flags: [-march=thumbv8.1m.main+mve]
+
+# Hierarchy among FPUs: fpvN-d16 is a superset of fpvN-sp-d16, and
+# fpvN-d16 is a superset of fpv[N-1]-d16, for all N.
+- Match: -mfpu=fpv5-d16
+  Flags:
+  - -mfpu=fpv4-d16
+  - -mfpu=fpv5-sp-d16
+  - -mfpu=fpv4-sp-d16
+- Match: -mfpu=fpv5-sp-d16
+  Flags:
+  - -mfpu=fpv4-sp-d16
+- Match: -mfpu=fpv4-d16
+  Flags:
+  - -mfpu=fpv4-sp-d16
+
+...

diff  --git a/clang/test/Driver/baremetal.cpp b/clang/test/Driver/baremetal.cpp
index c00713a5d30fb..af511b939896a 100644
--- a/clang/test/Driver/baremetal.cpp
+++ b/clang/test/Driver/baremetal.cpp
@@ -118,9 +118,9 @@
 // Verify that the bare metal driver does not include any host system paths:
 // CHECK-AARCH64-NO-HOST-INC: InstalledDir: [[INSTALLEDDIR:.+]]
 // CHECK-AARCH64-NO-HOST-INC: "-resource-dir" "[[RESOURCE:[^"]+]]"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include{{[/\\]+}}c++{{[/\\]+}}v1"
 // CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[RESOURCE]]{{[/\\]+}}include"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include"
 
 // RUN: %clang %s -### --target=riscv64-unknown-elf -o %t.out -L some/directory/user/asked/for \
 // RUN:     --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf 2>&1 \

diff  --git a/clang/test/Driver/lit.local.cfg b/clang/test/Driver/lit.local.cfg
index 0d124704d6ecd..cb788c205b9d7 100644
--- a/clang/test/Driver/lit.local.cfg
+++ b/clang/test/Driver/lit.local.cfg
@@ -19,6 +19,7 @@ config.suffixes = [
     ".hip",
     ".hipi",
     ".hlsl",
+    ".yaml",
 ]
 config.substitutions = list(config.substitutions)
 config.substitutions.insert(


        


More information about the cfe-commits mailing list