Commit 4fccd383 authored by Zakk Chen's avatar Zakk Chen Committed by Zakk Chen
Browse files

[RISCV] Support mutilib in baremetal environment

1. Currently only support the set of multilibs same to riscv-gnu-toolchain.
2. Fix testcase typo causes fail on Windows.
3. Fix testcases to set empty sysroot.

Reviewers: espindola, asb, kito-cheng, lenary

Reviewed By: lenary

Differential Revision: https://reviews.llvm.org/D67508
parent f7170d17
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
@@ -1503,9 +1503,65 @@ static bool findMSP430Multilibs(const Driver &D,
  return false;
}

static void findRISCVBareMetalMultilibs(const Driver &D,
                                        const llvm::Triple &TargetTriple,
                                        StringRef Path, const ArgList &Args,
                                        DetectedMultilibs &Result) {
  FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
  struct RiscvMultilib {
    StringRef march;
    StringRef mabi;
  };
  // currently only support the set of multilibs like riscv-gnu-toolchain does.
  // TODO: support MULTILIB_REUSE
  SmallVector<RiscvMultilib, 8> RISCVMultilibSet = {
      {"rv32i", "ilp32"},     {"rv32im", "ilp32"},     {"rv32iac", "ilp32"},
      {"rv32imac", "ilp32"},  {"rv32imafc", "ilp32f"}, {"rv64imac", "lp64"},
      {"rv64imafdc", "lp64d"}};

  std::vector<Multilib> Ms;
  for (auto Element : RISCVMultilibSet) {
    // multilib path rule is ${march}/${mabi}
    Ms.emplace_back(
        makeMultilib((Twine(Element.march) + "/" + Twine(Element.mabi)).str())
            .flag(Twine("+march=", Element.march).str())
            .flag(Twine("+mabi=", Element.mabi).str()));
  }
  MultilibSet RISCVMultilibs =
      MultilibSet()
          .Either(ArrayRef<Multilib>(Ms))
          .FilterOut(NonExistent)
          .setFilePathsCallback([](const Multilib &M) {
            return std::vector<std::string>(
                {M.gccSuffix(),
                 "/../../../../riscv64-unknown-elf/lib" + M.gccSuffix(),
                 "/../../../../riscv32-unknown-elf/lib" + M.gccSuffix()});
          });


  Multilib::flags_list Flags;
  llvm::StringSet<> Added_ABIs;
  StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);
  StringRef MArch = tools::riscv::getRISCVArch(Args, TargetTriple);
  for (auto Element : RISCVMultilibSet) {
    addMultilibFlag(MArch == Element.march,
                    Twine("march=", Element.march).str().c_str(), Flags);
    if (!Added_ABIs.count(Element.mabi)) {
      Added_ABIs.insert(Element.mabi);
      addMultilibFlag(ABIName == Element.mabi,
                      Twine("mabi=", Element.mabi).str().c_str(), Flags);
    }
  }

  if (RISCVMultilibs.select(Flags, Result.SelectedMultilib))
    Result.Multilibs = RISCVMultilibs;
}

static void findRISCVMultilibs(const Driver &D,
                               const llvm::Triple &TargetTriple, StringRef Path,
                               const ArgList &Args, DetectedMultilibs &Result) {
  if (TargetTriple.getOS() == llvm::Triple::UnknownOS)
    return findRISCVBareMetalMultilibs(D, TargetTriple, Path, Args, Result);

  FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
  Multilib Ilp32 = makeMultilib("lib32/ilp32").flag("+m32").flag("+mabi=ilp32");
+31 −3
Original line number Diff line number Diff line
@@ -22,19 +22,39 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;

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);
}

/// RISCV Toolchain
RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple,
                               const ArgList &Args)
    : Generic_ELF(D, Triple, Args) {
  GCCInstallation.init(Triple, Args);
  getFilePaths().push_back(computeSysRoot() + "/lib");
  if (GCCInstallation.isValid()) {
    Multilibs = GCCInstallation.getMultilibs();
    SelectedMultilib = GCCInstallation.getMultilib();
    path_list &Paths = getFilePaths();
    // Add toolchain/multilib specific file paths.
    addMultilibsFilePaths(D, Multilibs, SelectedMultilib,
                          GCCInstallation.getInstallPath(), Paths);
    getFilePaths().push_back(GCCInstallation.getInstallPath().str());
    getProgramPaths().push_back(
        (GCCInstallation.getParentLibPath() + "/../bin").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());
  } else {
    getProgramPaths().push_back(D.Dir);
  }
  getFilePaths().push_back(computeSysRoot() + "/lib");
}

Tool *RISCVToolChain::buildLinker() const {
@@ -105,6 +125,14 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  bool IsRV64 = ToolChain.getArch() == llvm::Triple::riscv64;
  CmdArgs.push_back("-m");
  if (IsRV64) {
    CmdArgs.push_back("elf64lriscv");
  } else {
    CmdArgs.push_back("elf32lriscv");
  }

  std::string Linker = getToolChain().GetProgramPath(getShortName());

  bool WantCRTs =
Loading