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 @@ -103,9 +103,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)); + } } } @@ -220,10 +223,15 @@ } 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 { + // Get multilibs in reverse order because they're ordered most-specific last. + llvm::SmallVector Result(SelectedMultilibs.rbegin(), + SelectedMultilibs.rend()); + if (Result.empty()) + Result.push_back(Multilib()); return Result; } @@ -239,10 +247,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()); + } } } } @@ -265,44 +277,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/baremetal-multilib.yaml b/clang/test/Driver/baremetal-multilib.yaml --- a/clang/test/Driver/baremetal-multilib.yaml +++ b/clang/test/Driver/baremetal-multilib.yaml @@ -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 -x c++ %s -### -o %t.out 2>&1 \ +# RUN: --target=thumbv8.1m.main-none-eabihf -fno-exceptions --sysroot= \ +# RUN: | FileCheck -DSYSROOT=%T/baremetal_multilib --check-prefix=CHECK-LAYERED-MULTILIB %s +# CHECK-LAYERED-MULTILIB: "-cc1" "-triple" "thumbv8.1m.main-none-unknown-eabihf" +# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/include/c++/v1" +# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/include/c++/v1" +# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/include" +# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/include" +# CHECK-LAYERED-MULTILIB-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/lib" +# CHECK-LAYERED-MULTILIB-SAME: "-L[[SYSROOT]]/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 \ @@ -118,6 +136,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