Index: clang/lib/Driver/ToolChains/BareMetal.h =================================================================== --- clang/lib/Driver/ToolChains/BareMetal.h +++ clang/lib/Driver/ToolChains/BareMetal.h @@ -26,6 +26,10 @@ ~BareMetal() override = default; static bool handlesTarget(const llvm::Triple &Triple); + + void findMultilibs(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + protected: Tool *buildLinker() const override; Index: clang/lib/Driver/ToolChains/BareMetal.cpp =================================================================== --- clang/lib/Driver/ToolChains/BareMetal.cpp +++ clang/lib/Driver/ToolChains/BareMetal.cpp @@ -12,6 +12,7 @@ #include "InputInfo.h" #include "Gnu.h" +#include "Arch/RISCV.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" @@ -27,12 +28,76 @@ using namespace clang::driver::tools; using namespace clang::driver::toolchains; +static Multilib makeMultilib(StringRef commonSuffix) { + return Multilib(commonSuffix, commonSuffix, commonSuffix); +} + +static bool findRISCVMultilibs(const Driver &D, + const llvm::Triple &TargetTriple, + const ArgList &Args, DetectedMultilibs &Result) { + Multilib::flags_list Flags; + StringRef Arch = riscv::getRISCVArch(Args, TargetTriple); + StringRef Abi = tools::riscv::getRISCVABI(Args, TargetTriple); + + if (TargetTriple.getArch() == llvm::Triple::riscv64) { + Multilib Imac = makeMultilib("").flag("+march=rv64imac").flag("+mabi=lp64"); + Multilib Imafdc = makeMultilib("/rv64imafdc/lp64d") + .flag("+march=rv64imafdc") + .flag("+mabi=lp64d"); + + // Multilib reuse + bool UseImafdc = + (Arch == "rv64imafdc") || (Arch == "rv64gc"); // gc => imafdc + + addMultilibFlag((Arch == "rv64imac"), "march=rv64imac", Flags); + addMultilibFlag(UseImafdc, "march=rv64imafdc", Flags); + addMultilibFlag(Abi == "lp64", "mabi=lp64", Flags); + addMultilibFlag(Abi == "lp64d", "mabi=lp64d", Flags); + + Result.Multilibs = MultilibSet().Either(Imac, Imafdc); + return Result.Multilibs.select(Flags, Result.SelectedMultilib); + } else if (TargetTriple.getArch() == llvm::Triple::riscv32) { + Multilib Imac = + makeMultilib("").flag("+march=rv32imac").flag("+mabi=ilp32"); + Multilib I = + makeMultilib("/rv32i/ilp32").flag("+march=rv32i").flag("+mabi=ilp32"); + Multilib Im = + makeMultilib("/rv32im/ilp32").flag("+march=rv32im").flag("+mabi=ilp32"); + Multilib Iac = makeMultilib("/rv32iac/ilp32") + .flag("+march=rv32iac") + .flag("+mabi=ilp32"); + Multilib Imafc = makeMultilib("/rv32imafc/ilp32f") + .flag("+march=rv32imafc") + .flag("+mabi=ilp32f"); + + // Multilib reuse + bool UseI = (Arch == "rv32i") || (Arch == "rv32ic"); // ic => i + bool UseIm = (Arch == "rv32im") || (Arch == "rv32imc"); // imc => im + bool UseImafc = (Arch == "rv32imafc") || (Arch == "rv32imafdc") || + (Arch == "rv32gc"); // imafdc,gc => imafc + + addMultilibFlag(UseI, "march=rv32i", Flags); + addMultilibFlag(UseIm, "march=rv32im", Flags); + addMultilibFlag((Arch == "rv32iac"), "march=rv32iac", Flags); + addMultilibFlag((Arch == "rv32imac"), "march=rv32imac", Flags); + addMultilibFlag(UseImafc, "march=rv32imafc", Flags); + addMultilibFlag(Abi == "ilp32", "mabi=ilp32", Flags); + addMultilibFlag(Abi == "ilp32f", "mabi=ilp32f", Flags); + + Result.Multilibs = MultilibSet().Either(I, Im, Iac, Imac, Imafc); + return Result.Multilibs.select(Flags, Result.SelectedMultilib); + } + return false; +} + BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : ToolChain(D, Triple, Args) { getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); + + findMultilibs(D, Triple, Args); SmallString<128> SysRoot(computeSysRoot()); if (!SysRoot.empty()) { llvm::sys::path::append(SysRoot, "lib"); @@ -73,6 +138,17 @@ return Triple.getEnvironmentName() == "elf"; } +void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) { + DetectedMultilibs Result; + if (isRISCVBareMetal(Triple)) { + if (findRISCVMultilibs(D, Triple, Args, Result)) { + SelectedMultilib = Result.SelectedMultilib; + Multilibs = Result.Multilibs; + } + } +} + bool BareMetal::handlesTarget(const llvm::Triple &Triple) { return isARMBareMetal(Triple) || isRISCVBareMetal(Triple); } @@ -90,18 +166,20 @@ std::string BareMetal::getRuntimesDir() const { SmallString<128> Dir(getDriver().ResourceDir); + Dir += SelectedMultilib.osSuffix(); llvm::sys::path::append(Dir, "lib", "baremetal"); return std::string(Dir.str()); } std::string BareMetal::computeSysRoot() const { if (!getDriver().SysRoot.empty()) - return getDriver().SysRoot; + 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); } Index: clang/test/Driver/baremetal.cpp =================================================================== --- clang/test/Driver/baremetal.cpp +++ clang/test/Driver/baremetal.cpp @@ -233,3 +233,113 @@ // CHECK-RV64-NDL-SAME: "-L{{[^"]*}}{{[/\\]+}}lib{{(64)?}}{{[/\\]+}}clang{{[/\\]+}}{{.*}}{{[/\\]+}}lib{{[/\\]+}}baremetal" // CHECK-RV64-NDL-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}basic_riscv64_tree{{[/\\]+}}riscv64-unknown-elf{{[/\\]+}}lib" // CHECK-RV64-NDL-SAME: "-o" "{{.*}}.o" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target riscv64-unknown-elf \ +// RUN: -march=rv64imafdc -mabi=lp64d \ +// RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf \ +// RUN: | FileCheck --check-prefix=CHECK-RV64FD %s + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target riscv64-unknown-elf \ +// RUN: -march=rv64gc -mabi=lp64d \ +// RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf \ +// RUN: | FileCheck --check-prefix=CHECK-RV64FD %s + +// CHECK-RV64FD: "[[PREFIX_DIR:.*]]{{[/\\]+}}{{[^/^\\]+}}{{[/\\]+}}clang{{.*}}" "-cc1" "-triple" "riscv64-unknown-unknown-elf" +// CHECK-RV64FD-SAME: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-RV64FD-SAME: "-isysroot" "[[SYSROOT:[^"]*]]" +// CHECK-RV64FD-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}rv64imafdc{{[/\\]+}}lp64d{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" +// CHECk-RV64FD-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}rv64imafdc{{[/\\]+}}lp64d{{[/\\]+}}include" +// CHECK-RV64FD-SAME: "-x" "c++" "{{.*}}baremetal.cpp" +// CHECK-RV64FD-NEXT: "{{[^"]*}}ld{{(\.(lld|bfd|gold))?}}{{(\.exe)?}}" "{{.*}}.o" "-Bstatic" +// CHECK-RV64FD-SAME: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}rv64imafdc{{[/\\]+}}lp64d{{[/\\]+}}lib{{[/\\]+}}baremetal" +// CHECK-RV64FD-SAME: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}rv64imafdc{{[/\\]+}}lp64d{{[/\\]+}}lib" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target riscv32-unknown-elf \ +// RUN: -march=rv32i -mabi=ilp32 \ +// RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ +// RUN: | FileCheck --check-prefix=CHECK-RV32I %s + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target riscv32-unknown-elf \ +// RUN: -march=rv32ic -mabi=ilp32 \ +// RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ +// RUN: | FileCheck --check-prefix=CHECK-RV32I %s + +// CHECK-RV32I: "[[PREFIX_DIR:.*]]{{[/\\]+}}{{[^/^\\]+}}{{[/\\]+}}clang{{.*}}" "-cc1" "-triple" "riscv32-unknown-unknown-elf" +// CHECK-RV32I-SAME: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-RV32I-SAME: "-isysroot" "[[SYSROOT:[^"]*]]" +// CHECK-RV32I-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}rv32i{{[/\\]+}}ilp32{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" +// CHECK-RV32I-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}rv32i{{[/\\]+}}ilp32{{[/\\]+}}include" +// CHECK-RV32I-SAME: "-x" "c++" "{{.*}}baremetal.cpp" +// CHECK-RV32I-NEXT: "{{[^"]*}}ld{{(\.(lld|bfd|gold))?}}{{(\.exe)?}}" "{{.*}}.o" "-Bstatic" +// CHECK-RV32I-SAME: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}rv32i{{[/\\]+}}ilp32{{[/\\]+}}lib{{[/\\]+}}baremetal" +// CHECK-RV32I-SAME: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}rv32i{{[/\\]+}}ilp32{{[/\\]+}}lib" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target riscv32-unknown-elf \ +// RUN: -march=rv32im -mabi=ilp32 \ +// RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ +// RUN: | FileCheck --check-prefix=CHECK-RV32IM %s + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target riscv32-unknown-elf \ +// RUN: -march=rv32imc -mabi=ilp32 \ +// RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ +// RUN: | FileCheck --check-prefix=CHECK-RV32IM %s + +// CHECK-RV32IM: "[[PREFIX_DIR:.*]]{{[/\\]+}}{{[^/^\\]+}}{{[/\\]+}}clang{{.*}}" "-cc1" "-triple" "riscv32-unknown-unknown-elf" +// CHECK-RV32IM-SAME: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-RV32IM-SAME: "-isysroot" "[[SYSROOT:[^"]*]]" +// CHECK-RV32IM-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}rv32im{{[/\\]+}}ilp32{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" +// CHECK-RV32IM-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}rv32im{{[/\\]+}}ilp32{{[/\\]+}}include" +// CHECK-RV32IM-SAME: "-x" "c++" "{{.*}}baremetal.cpp" +// CHECK-RV32IM-NEXT: "{{[^"]*}}ld{{(\.(lld|bfd|gold))?}}{{(\.exe)?}}" "{{.*}}.o" "-Bstatic" +// CHECK-RV32IM-SAME: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}rv32im{{[/\\]+}}ilp32{{[/\\]+}}lib{{[/\\]+}}baremetal" +// CHECK-RV32IM-SAME: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}rv32im{{[/\\]+}}ilp32{{[/\\]+}}lib" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target riscv32-unknown-elf \ +// RUN: -march=rv32iac -mabi=ilp32 \ +// RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ +// RUN: | FileCheck --check-prefix=CHECK-RV32IAC %s + +// CHECK-RV32IAC: "[[PREFIX_DIR:.*]]{{[/\\]+}}{{[^/^\\]+}}{{[/\\]+}}clang{{.*}}" "-cc1" "-triple" "riscv32-unknown-unknown-elf" +// CHECK-RV32IAC-SAME: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-RV32IAC-SAME: "-isysroot" "[[SYSROOT:[^"]*]]" +// CHECK-RV32IAC-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}rv32iac{{[/\\]+}}ilp32{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" +// CHECK-RV32IAC-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}rv32iac{{[/\\]+}}ilp32{{[/\\]+}}include" +// CHECK-RV32IAC-SAME: "-x" "c++" "{{.*}}baremetal.cpp" +// CHECK-RV32IAC-NEXT: "{{[^"]*}}ld{{(\.(lld|bfd|gold))?}}{{(\.exe)?}}" "{{.*}}.o" "-Bstatic" +// CHECK-RV32IAC-SAME: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}rv32iac{{[/\\]+}}ilp32{{[/\\]+}}lib{{[/\\]+}}baremetal" +// CHECK-RV32IAC-SAME: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}rv32iac{{[/\\]+}}ilp32{{[/\\]+}}lib" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target riscv32-unknown-elf \ +// RUN: -march=rv32imafc -mabi=ilp32f \ +// RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ +// RUN: | FileCheck --check-prefix=CHECK-RV32IMAFC %s + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target riscv32-unknown-elf \ +// RUN: -march=rv32imafdc -mabi=ilp32f \ +// RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ +// RUN: | FileCheck --check-prefix=CHECK-RV32IMAFC %s + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target riscv32-unknown-elf \ +// RUN: -march=rv32gc -mabi=ilp32f \ +// RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ +// RUN: | FileCheck --check-prefix=CHECK-RV32IMAFC %s + +// CHECK-RV32IMAFC: "[[PREFIX_DIR:.*]]{{[/\\]+}}{{[^/^\\]+}}{{[/\\]+}}clang{{.*}}" "-cc1" "-triple" "riscv32-unknown-unknown-elf" +// CHECK-RV32IMAFC-SAME: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-RV32IMAFC-SAME: "-isysroot" "[[SYSROOT:[^"]*]]" +// CHECK-RV32IMAFC-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}rv32imafc{{[/\\]+}}ilp32f{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" +// CHECK-RV32IMAFC-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}rv32imafc{{[/\\]+}}ilp32f{{[/\\]+}}include" +// CHECK-RV32IMAFC-SAME: "-x" "c++" "{{.*}}baremetal.cpp" +// CHECK-RV32IMAFC-NEXT: "{{[^"]*}}ld{{(\.(lld|bfd|gold))?}}{{(\.exe)?}}" "{{.*}}.o" "-Bstatic" +// CHECK-RV32IMAFC-SAME: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}rv32imafc{{[/\\]+}}ilp32f{{[/\\]+}}lib{{[/\\]+}}baremetal" +// CHECK-RV32IMAFC-SAME: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}rv32imafc{{[/\\]+}}ilp32f{{[/\\]+}}lib"