diff --git a/clang/lib/Driver/ToolChains/BareMetal.h b/clang/lib/Driver/ToolChains/BareMetal.h --- a/clang/lib/Driver/ToolChains/BareMetal.h +++ b/clang/lib/Driver/ToolChains/BareMetal.h @@ -70,6 +70,9 @@ void AddLinkRuntimeLib(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; std::string computeSysRoot() const override; + +private: + llvm::SmallVector getOrderedMultilibs() const; }; } // namespace toolchains diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp --- a/clang/lib/Driver/ToolChains/BareMetal.cpp +++ b/clang/lib/Driver/ToolChains/BareMetal.cpp @@ -102,9 +102,12 @@ findMultilibs(D, Triple, Args); SmallString<128> SysRoot(computeSysRoot()); if (!SysRoot.empty()) { - llvm::sys::path::append(SysRoot, "lib"); - getFilePaths().push_back(std::string(SysRoot)); - getLibraryPaths().push_back(std::string(SysRoot)); + for (const Multilib &M : getOrderedMultilibs()) { + SmallString<128> Dir(SysRoot); + llvm::sys::path::append(Dir, M.osSuffix(), "lib"); + getFilePaths().push_back(std::string(Dir)); + getLibraryPaths().push_back(std::string(Dir)); + } } } @@ -226,9 +229,18 @@ } std::string BareMetal::computeSysRoot() const { - std::string Result = computeBaseSysRoot(getDriver(), getTriple()); - if (!SelectedMultilibs.empty()) { - Result += SelectedMultilibs.back().osSuffix(); + return computeBaseSysRoot(getDriver(), getTriple()); +} + +llvm::SmallVector BareMetal::getOrderedMultilibs() const { + llvm::SmallVector Result; + // Get multilibs in reverse order because they're ordered most-specific last. + for (auto It = SelectedMultilibs.rbegin(), End = SelectedMultilibs.rend(); + It != End; ++It) { + Result.push_back(*It); + } + if (Result.empty()) { + Result.push_back(Multilib()); } return Result; } @@ -245,10 +257,14 @@ } if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) { - SmallString<128> Dir(computeSysRoot()); - if (!Dir.empty()) { - llvm::sys::path::append(Dir, "include"); - addSystemInclude(DriverArgs, CC1Args, Dir.str()); + const SmallString<128> SysRoot(computeSysRoot()); + if (!SysRoot.empty()) { + for (const Multilib &M : getOrderedMultilibs()) { + SmallString<128> Dir(SysRoot); + llvm::sys::path::append(Dir, M.includeSuffix()); + llvm::sys::path::append(Dir, "include"); + addSystemInclude(DriverArgs, CC1Args, Dir.str()); + } } } } @@ -271,44 +287,47 @@ if (SysRoot.empty()) return; - switch (GetCXXStdlibType(DriverArgs)) { - case ToolChain::CST_Libcxx: { - // First check sysroot/usr/include/c++/v1 if it exists. - SmallString<128> TargetDir(SysRoot); - llvm::sys::path::append(TargetDir, "usr", "include", "c++", "v1"); - if (D.getVFS().exists(TargetDir)) { - addSystemInclude(DriverArgs, CC1Args, TargetDir.str()); + for (const Multilib &M : getOrderedMultilibs()) { + SmallString<128> Dir(SysRoot); + llvm::sys::path::append(Dir, M.gccSuffix()); + switch (GetCXXStdlibType(DriverArgs)) { + case ToolChain::CST_Libcxx: { + // First check sysroot/usr/include/c++/v1 if it exists. + SmallString<128> TargetDir(Dir); + llvm::sys::path::append(TargetDir, "usr", "include", "c++", "v1"); + if (D.getVFS().exists(TargetDir)) { + addSystemInclude(DriverArgs, CC1Args, TargetDir.str()); + break; + } + // Add generic path if nothing else succeeded so far. + llvm::sys::path::append(Dir, "include", "c++", "v1"); + addSystemInclude(DriverArgs, CC1Args, Dir.str()); + break; + } + case ToolChain::CST_Libstdcxx: { + llvm::sys::path::append(Dir, "include", "c++"); + std::error_code EC; + Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""}; + // Walk the subdirs, and find the one with the newest gcc version: + for (llvm::vfs::directory_iterator + LI = D.getVFS().dir_begin(Dir.str(), EC), + LE; + !EC && LI != LE; LI = LI.increment(EC)) { + StringRef VersionText = llvm::sys::path::filename(LI->path()); + auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText); + if (CandidateVersion.Major == -1) + continue; + if (CandidateVersion <= Version) + continue; + Version = CandidateVersion; + } + if (Version.Major != -1) { + llvm::sys::path::append(Dir, Version.Text); + addSystemInclude(DriverArgs, CC1Args, Dir.str()); + } break; } - // Add generic path if nothing else succeeded so far. - SmallString<128> Dir(SysRoot); - llvm::sys::path::append(Dir, "include", "c++", "v1"); - addSystemInclude(DriverArgs, CC1Args, Dir.str()); - break; - } - case ToolChain::CST_Libstdcxx: { - SmallString<128> Dir(SysRoot); - llvm::sys::path::append(Dir, "include", "c++"); - std::error_code EC; - Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""}; - // Walk the subdirs, and find the one with the newest gcc version: - for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(Dir.str(), EC), - LE; - !EC && LI != LE; LI = LI.increment(EC)) { - StringRef VersionText = llvm::sys::path::filename(LI->path()); - auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText); - if (CandidateVersion.Major == -1) - continue; - if (CandidateVersion <= Version) - continue; - Version = CandidateVersion; } - if (Version.Major == -1) - return; - llvm::sys::path::append(Dir, Version.Text); - addSystemInclude(DriverArgs, CC1Args, Dir.str()); - break; - } } } diff --git a/clang/test/Driver/Inputs/baremetal_multilib/multilib.yaml b/clang/test/Driver/Inputs/baremetal_multilib/multilib.yaml --- a/clang/test/Driver/Inputs/baremetal_multilib/multilib.yaml +++ b/clang/test/Driver/Inputs/baremetal_multilib/multilib.yaml @@ -65,6 +65,14 @@ flags: [target=thumbv8.1m.main-none-unknown-eabihf, march=+mve] printArgs: [--target=arm-none-eabihf, -march=armv8.1m.main+nofp+mve] +# A specialisation of v8.1-m.main/fp without exceptions. +# This layers over the top of the regular v8.1-m.main/fp so it doesn't +# need to have its own include directory or C library, thereby saving +# disk space. +- dir: arm-none-eabi/thumb/v8.1-m.main/fp/noexcept + flags: [target=thumbv8.1m.main-none-unknown-eabihf, hasfpu, fno-exceptions] + printArgs: [--target=thumbv8.1m.main-none-eabihf, -fno-exceptions] + # The second section of the file is a map from auto-detected flags # to custom flags. The auto-detected flags can be printed out diff --git a/clang/test/Driver/baremetal-multilib.cpp b/clang/test/Driver/baremetal-multilib.cpp --- a/clang/test/Driver/baremetal-multilib.cpp +++ b/clang/test/Driver/baremetal-multilib.cpp @@ -25,6 +25,23 @@ // 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 %s -### -o %t.o 2>&1 \ +// RUN: --target=thumbv8.1m.main-none-eabihf -fno-exceptions --sysroot= \ +// RUN: | FileCheck --check-prefix=CHECK-LAYERED-MULTILIB %s +// CHECK-LAYERED-MULTILIB: "{{.*}}clang{{.*}}" "-cc1" "-triple" "thumbv8.1m.main-none-unknown-eabihf" +// CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "{{.*}}/baremetal_multilib/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/include/c++/v1" +// CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "{{.*}}/baremetal_multilib/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/include/c++/v1" +// CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "{{.*}}/baremetal_multilib/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/include" +// CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "{{.*}}/baremetal_multilib/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/include" +// CHECK-LAYERED-MULTILIB-NEXT: "-L{{.*}}/baremetal_multilib/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/lib" +// CHECK-LAYERED-MULTILIB-SAME: "-L{{.*}}/baremetal_multilib/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/lib" + +// RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \ +// RUN: --target=thumbv8.1m.main-none-eabihf -fno-exceptions --sysroot= \ +// RUN: | FileCheck --check-prefix=CHECK-LAYERED-PRINT-MULTI-DIRECTORY %s +// CHECK-LAYERED-PRINT-MULTI-DIRECTORY: arm-none-eabi/thumb/v8.1-m.main/fp +// CHECK-LAYERED-PRINT-MULTI-DIRECTORY-NEXT: arm-none-eabi/thumb/v8.1-m.main/fp/noexcept + // 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 @@ -38,6 +55,7 @@ // CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/fp;@-target=thumbv8m.main-none-eabihf // CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/fp;@-target=thumbv8.1m.main-none-eabihf // CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/nofp/mve;@-target=arm-none-eabihf@march=armv8.1m.main+nofp+mve +// CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/fp/noexcept;@-target=thumbv8.1m.main-none-eabihf@fno-exceptions // RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x assembler -mexecute-only \ // RUN: --target=arm-none-eabi --sysroot= %s -c -### 2>&1 \