Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 103 additions & 18 deletions clang/lib/Driver/ToolChains/BareMetal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ static bool findRISCVMultilibs(const Driver &D,
return false;
}

static std::string computeBaseSysRoot(const Driver &D, bool IncludeTriple) {
static std::string computeInstalledToolchainSysRoot(const Driver &D,
bool IncludeTriple) {
if (!D.SysRoot.empty())
return D.SysRoot;

Expand All @@ -110,20 +111,93 @@ static std::string computeBaseSysRoot(const Driver &D, bool IncludeTriple) {
return std::string(SysRootDir);
}

// GCC sysroot here means form sysroot from either --gcc-install-dir, or from
// --gcc-toolchain or if the toolchain is installed alongside clang in
// bin/../<TargetTriple> directory if it is not explicitly specified on the
// command line through `--sysroot` option. libc here will be newlib.
std::string BareMetal::computeGCCSysRoot() const {
if (!getDriver().SysRoot.empty())
return getDriver().SysRoot;

SmallString<128> SysRootDir;
if (GCCInstallation.isValid()) {
StringRef LibDir = GCCInstallation.getParentLibPath();
StringRef TripleStr = GCCInstallation.getTriple().str();
llvm::sys::path::append(SysRootDir, LibDir, "..", TripleStr);
} else {
// Use the triple as provided to the driver. Unlike the parsed triple
// this has not been normalized to always contain every field.
llvm::sys::path::append(SysRootDir, getDriver().Dir, "..",
getDriver().getTargetTriple());
}

if (!llvm::sys::fs::exists(SysRootDir))
return std::string();

return std::string(SysRootDir);
}

std::string BareMetal::computeSysRoot() const {
if (!SysRoot.empty())
return SysRoot;

std::string SysRoot = getDriver().SysRoot;
if (!SysRoot.empty() && llvm::sys::fs::exists(SysRoot))
return SysRoot;

// Verify the GCC installation from -gcc-install-dir, --gcc-toolchain, or
// alongside clang. If valid, form the sysroot. Otherwise, check
// lib/clang-runtimes above the driver.
SysRoot = computeGCCSysRoot();
if (!SysRoot.empty())
return SysRoot;

SysRoot =
computeInstalledToolchainSysRoot(getDriver(), /*IncludeTriple*/ true);

return SysRoot;
}

static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs,
const Multilib &Multilib,
StringRef InstallPath,
ToolChain::path_list &Paths) {
if (const auto &PathsCallback = Multilibs.filePathsCallback())
for (const auto &Path : PathsCallback(Multilib))
addPathIfExists(D, InstallPath + Path, Paths);
}

BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args),
SysRoot(computeBaseSysRoot(D, /*IncludeTriple=*/true)) {
getProgramPaths().push_back(getDriver().Dir);

findMultilibs(D, Triple, Args);
SmallString<128> SysRoot(computeSysRoot());
if (!SysRoot.empty()) {
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));
: Generic_ELF(D, Triple, Args) {
GCCInstallation.init(Triple, Args);
SysRoot = computeSysRoot();
if (GCCInstallation.isValid()) {
Multilibs = GCCInstallation.getMultilibs();
SelectedMultilibs.assign({GCCInstallation.getMultilib()});
path_list &Paths = getFilePaths();
// Add toolchain/multilib specific file paths.
addMultilibsFilePaths(D, Multilibs, SelectedMultilibs.back(),
GCCInstallation.getInstallPath(), Paths);
getFilePaths().push_back(GCCInstallation.getInstallPath().str());
ToolChain::path_list &PPaths = getProgramPaths();
// Multilib cross-compiler GCC installations put ld in a triple-prefixed
// directory off of the parent of the GCC installation.
PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
GCCInstallation.getTriple().str() + "/bin")
.str());
PPaths.push_back((GCCInstallation.getParentLibPath() + "/../bin").str());
getFilePaths().push_back(computeSysRoot() + "/lib");
} else {
getProgramPaths().push_back(getDriver().Dir);
findMultilibs(D, Triple, Args);
if (!SysRoot.empty()) {
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));
}
}
}
}
Expand Down Expand Up @@ -215,7 +289,7 @@ getMultilibConfigPath(const Driver &D, const llvm::Triple &Triple,
return {};
}
} else {
MultilibPath = computeBaseSysRoot(D, /*IncludeTriple=*/false);
MultilibPath = computeInstalledToolchainSysRoot(D, /*IncludeTriple=*/false);
llvm::sys::path::append(MultilibPath, MultilibFilename);
}
return MultilibPath;
Expand All @@ -233,7 +307,7 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
if (D.getVFS().exists(*MultilibPath)) {
// If multilib.yaml is found, update sysroot so it doesn't use a target
// specific suffix
SysRoot = computeBaseSysRoot(D, /*IncludeTriple=*/false);
SysRoot = computeInstalledToolchainSysRoot(D, /*IncludeTriple=*/false);
findMultilibsFromYAML(*this, D, *MultilibPath, Args, Result);
SelectedMultilibs = Result.SelectedMultilibs;
Multilibs = Result.Multilibs;
Expand All @@ -258,8 +332,6 @@ Tool *BareMetal::buildStaticLibTool() const {
return new tools::baremetal::StaticLibTool(*this);
}

std::string BareMetal::computeSysRoot() const { return SysRoot; }

BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const {
// Get multilibs in reverse order because they're ordered most-specific last.
if (!SelectedMultilibs.empty())
Expand Down Expand Up @@ -304,6 +376,19 @@ void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
CC1Args.push_back("-nostdsysteminc");
}

void BareMetal::addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
if (!GCCInstallation.isValid())
return;
const GCCVersion &Version = GCCInstallation.getVersion();
StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
addLibStdCXXIncludePaths(computeSysRoot() + "/include/c++/" + Version.Text,
TripleStr, Multilib.includeSuffix(), DriverArgs,
CC1Args);
}

void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
Expand Down Expand Up @@ -341,7 +426,7 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
break;
}
case ToolChain::CST_Libstdcxx:
// We only support libc++ toolchain installation.
addLibStdCxxIncludePaths(DriverArgs, CC1Args);
break;
}

Expand Down
8 changes: 6 additions & 2 deletions clang/lib/Driver/ToolChains/BareMetal.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_BAREMETAL_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_BAREMETAL_H

#include "ToolChains/Gnu.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"

Expand All @@ -19,7 +20,7 @@ namespace driver {

namespace toolchains {

class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain {
class LLVM_LIBRARY_VISIBILITY BareMetal : public Generic_ELF {
public:
BareMetal(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
Expand All @@ -35,7 +36,6 @@ class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain {
Tool *buildStaticLibTool() const override;

public:
bool useIntegratedAs() const override { return true; }
bool isBareMetal() const override { return true; }
bool isCrossCompiling() const override { return true; }
bool HasNativeLLVMSupport() const override { return true; }
Expand Down Expand Up @@ -67,6 +67,9 @@ class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain {
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void
addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
std::string computeSysRoot() const override;
SanitizerMask getSupportedSanitizers() const override;

Expand All @@ -76,6 +79,7 @@ class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain {
OrderedMultilibs getOrderedMultilibs() const;

std::string SysRoot;
std::string computeGCCSysRoot() const;
};

} // namespace toolchains
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Empty file.
28 changes: 28 additions & 0 deletions clang/test/Driver/aarch64-toolchain-extra.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// A basic clang -cc1 command-line, and simple environment check.

// The tests here are similar to those in aarch64-toolchain.c, however
// these tests need to create symlinks to test directory trees in order to
// set up the environment and therefore shell support is required.
// REQUIRES: shell
// UNSUPPORTED: system-windows

// If there is no GCC install detected then the driver searches for executables
// and runtime starting from the directory tree above the driver itself.
// The test below checks that the driver correctly finds the linker and
// runtime if and only if they exist.
//
// RUN: rm -rf %t
// RUN: mkdir -p %t/aarch64-nogcc/bin
// RUN: ln -s %clang %t/aarch64-nogcc/bin/clang
// RUN: ln -s %S/Inputs/basic_aarch64_nogcc_tree/aarch64-none-elf %t/aarch64-nogcc/aarch64-none-elf
// RUN: %t/aarch64-nogcc/bin/clang %s -### -no-canonical-prefixes \
// RUN: --gcc-toolchain=%t/aarch64-nogcc/invalid \
// RUN: --target=aarch64-none-elf --rtlib=libgcc -fuse-ld=ld 2>&1 \
// RUN: | FileCheck -check-prefix=C-ARM-BAREMETAL-NOGCC %s

// RUN: %t/aarch64-nogcc/bin/clang %s -### -no-canonical-prefixes \
// RUN: --sysroot=%t/aarch64-nogcc/bin/../aarch64-none-elf \
// RUN: --target=aarch64-none-elf --rtlib=libgcc -fuse-ld=ld 2>&1 \
// RUN: | FileCheck -check-prefix=C-ARM-BAREMETAL-NOGCC %s

// C-ARM-BAREMETAL-NOGCC: "-internal-isystem" "{{.*}}/aarch64-nogcc/bin/../aarch64-none-elf/include"
61 changes: 61 additions & 0 deletions clang/test/Driver/aarch64-toolchain.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// UNSUPPORTED: system-windows

// RUN: %clang -### %s -fuse-ld= \
// RUN: --target=aarch64-none-elf --rtlib=libgcc \
// RUN: --gcc-toolchain=%S/Inputs/basic_aarch64_gcc_tree \
// RUN: --sysroot=%S/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf 2>&1 \
// RUN: | FileCheck -check-prefix=C-AARCH64-BAREMETAL %s

// C-AARCH64-BAREMETAL: "-cc1" "-triple" "aarch64-unknown-none-elf"
// C-AARCH64-BAREMETAL: "-isysroot" "{{.*}}Inputs/basic_aarch64_gcc_tree/aarch64-none-elf"
// C-AARCH64-BAREMETAL: "-internal-isystem" "{{.*}}Inputs/basic_aarch64_gcc_tree/aarch64-none-elf/include"

// RUN: %clang -### %s -fuse-ld= \
// RUN: --target=aarch64-none-elf --rtlib=libgcc \
// RUN: --gcc-toolchain=%S/Inputs/basic_aarch64_gcc_tree \
// RUN: --sysroot= 2>&1 \
// RUN: | FileCheck -check-prefix=C-AARCH64-BAREMETAL-NOSYSROOT %s

// C-AARCH64-BAREMETAL-NOSYSROOT: "-cc1" "-triple" "aarch64-unknown-none-elf"
// C-AARCH64-BAREMETAL-NOSYSROOT: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../aarch64-none-elf/include"

// RUN: %clangxx -### %s -fuse-ld= \
// RUN: --target=aarch64-none-elf -stdlib=libstdc++ --rtlib=libgcc \
// RUN: --gcc-toolchain=%S/Inputs/basic_aarch64_gcc_tree \
// RUN: --sysroot=%S/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf 2>&1 \
// RUN: | FileCheck -check-prefix=CXX-AARCH64-BAREMETAL %s

// CXX-AARCH64-BAREMETAL: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf/include/c++/8.2.1/aarch64-none-elf"
// CXX-AARCH64-BAREMETAL: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf/include/c++/8.2.1/backward"
// CXX-AARCH64-BAREMETAL: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf/include/c++/8.2.1"
// CXX-AARCH64-BAREMETAL: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf/include"

// RUN: %clangxx -### %s -fuse-ld= \
// RUN: --target=aarch64-none-elf -stdlib=libstdc++ --rtlib=libgcc \
// RUN: --gcc-toolchain=%S/Inputs/basic_aarch64_gcc_tree \
// RUN: --sysroot= 2>&1 \
// RUN: | FileCheck -check-prefix=CXX-AARCH64-BAREMETAL-NOSYSROOT %s

// CXX-AARCH64-BAREMETAL-NOSYSROOT: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../aarch64-none-elf/include/c++/8.2.1/aarch64-none-elf"
// CXX-AARCH64-BAREMETAL-NOSYSROOT: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../aarch64-none-elf/include/c++/8.2.1/backward"
// CXX-AARCH64-BAREMETAL-NOSYSROOT: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../aarch64-none-elf/include/c++/8.2.1"
// CXX-AARCH64-BAREMETAL-NOSYSROOT: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../aarch64-none-elf/include"

// RUN: %clangxx -### %s -fuse-ld= \
// RUN: --target=aarch64-none-elf -stdlib=libc++ --rtlib=libgcc \
// RUN: --gcc-toolchain=%S/Inputs/basic_aarch64_gcc_tree \
// RUN: --sysroot=%S/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf 2>&1 \
// RUN: | FileCheck -check-prefix=CXX-AARCH64-BAREMETAL-LIBCXX %s

// CXX-AARCH64-BAREMETAL-LIBCXX: "-isysroot" "{{.*}}Inputs/basic_aarch64_gcc_tree/aarch64-none-elf"
// CXX-AARCH64-BAREMETAL-LIBCXX: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf/include/c++/v1"
// CXX-AARCH64-BAREMETAL-LIBCXX: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf/include"

// RUN: %clangxx -### %s -fuse-ld= \
// RUN: --target=aarch64-none-elf -stdlib=libc++ --rtlib=libgcc \
// RUN: --gcc-toolchain=%S/Inputs/basic_aarch64_gcc_tree \
// RUN: --sysroot= 2>&1 \
// RUN: | FileCheck -check-prefix=CXX-AARCH64-BAREMETAL-NOSYSROOT-LIBCXX %s

// CXX-AARCH64-BAREMETAL-NOSYSROOT-LIBCXX: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../aarch64-none-elf/include/c++/v1"
// CXX-AARCH64-BAREMETAL-NOSYSROOT-LIBCXX: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../aarch64-none-elf/include"
12 changes: 12 additions & 0 deletions clang/test/Driver/arm-gnutools.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// check that gnu assembler is invoked with arm baremetal as well

// RUN: %clang --target=armv6m-none-eabi --gcc-toolchain=%S/Inputs/basic_riscv32_tree -fno-integrated-as %s -### -c \
// RUN: 2>&1 | FileCheck %s

// RUN: %clang --target=armv7-none-eabi --gcc-toolchain=%S/Inputs/basic_riscv32_tree -fno-integrated-as %s -### -c \
// RUN: 2>&1 | FileCheck %s

// RUN: %clang --target=aarch64-none-elf --gcc-toolchain=%S/Inputs/basic_riscv32_tree -fno-integrated-as %s -### -c \
// RUN: 2>&1 | FileCheck %s

// CHECK: "{{.*}}as{{(.exe)?}}"
28 changes: 28 additions & 0 deletions clang/test/Driver/arm-toolchain-extra.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// A basic clang -cc1 command-line, and simple environment check.

// The tests here are similar to those in arm-toolchain.c, however
// these tests need to create symlinks to test directory trees in order to
// set up the environment and therefore shell support is required.
// REQUIRES: shell
// UNSUPPORTED: system-windows

// If there is no GCC install detected then the driver searches for executables
// and runtime starting from the directory tree above the driver itself.
// The test below checks that the driver correctly finds the linker and
// runtime if and only if they exist.
//
// RUN: rm -rf %t
// RUN: mkdir -p %t/arm-nogcc/bin
// RUN: ln -s %clang %t/arm-nogcc/bin/clang
// RUN: ln -s %S/Inputs/basic_arm_nogcc_tree/armv6m-none-eabi %t/arm-nogcc/armv6m-none-eabi
// RUN: %t/arm-nogcc/bin/clang %s -### -no-canonical-prefixes \
// RUN: --gcc-toolchain=%t/arm-nogcc/invalid \
// RUN: --target=armv6m-none-eabi --rtlib=libgcc -fuse-ld=ld 2>&1 \
// RUN: | FileCheck -check-prefix=C-ARM-BAREMETAL-NOGCC %s

// RUN: %t/arm-nogcc/bin/clang %s -### -no-canonical-prefixes \
// RUN: --sysroot=%t/arm-nogcc/bin/../armv6m-none-eabi \
// RUN: --target=armv6m-none-eabi --rtlib=libgcc -fuse-ld=ld 2>&1 \
// RUN: | FileCheck -check-prefix=C-ARM-BAREMETAL-NOGCC %s

// C-ARM-BAREMETAL-NOGCC: "-internal-isystem" "{{.*}}/arm-nogcc/bin/../armv6m-none-eabi/include"
Loading
Loading