Skip to content

Xtensa lld update #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: xtensa-lld
Choose a base branch
from
Open
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
42 changes: 41 additions & 1 deletion clang/lib/Driver/ToolChains/Gnu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1676,6 +1676,42 @@ static void findRISCVMultilibs(const Driver &D,
Result.Multilibs = RISCVMultilibs;
}

static void findXtensaMultilibs(const Driver &D,
const llvm::Triple &TargetTriple, StringRef Path,
const ArgList &Args, DetectedMultilibs &Result) {

MultilibSet XtensaMultilibs = MultilibSet();
bool IsESP32 = Args.getLastArgValue(options::OPT_mcpu_EQ, "esp32").equals("esp32");

XtensaMultilibs.push_back(Multilib());
if (IsESP32)
XtensaMultilibs.push_back(Multilib("esp32-psram", {}, {}, 2)
.flag("+mfix-esp32-psram-cache-issue"));

XtensaMultilibs.push_back(
Multilib("no-rtti", {}, {}, 1).flag("+fno-rtti").flag("-frtti"));

if (IsESP32)
XtensaMultilibs.push_back(Multilib("esp32-psram/no-rtti", {}, {}, 3)
.flag("+fno-rtti")
.flag("-frtti")
.flag("+mfix-esp32-psram-cache-issue"));

Multilib::flags_list Flags;
addMultilibFlag(
Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti, false), "frtti",
Flags);

if (IsESP32)
addMultilibFlag(Args.hasFlag(options::OPT_mfix_esp32_psram_cache_issue,
options::OPT_mfix_esp32_psram_cache_issue,
false),
"mfix-esp32-psram-cache-issue", Flags);

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

static bool findBiarchMultilibs(const Driver &D,
const llvm::Triple &TargetTriple,
StringRef Path, const ArgList &Args,
Expand Down Expand Up @@ -2198,7 +2234,9 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
"s390x-suse-linux", "s390x-redhat-linux"};

static const char *const XtensaLibDirs[] = {"/lib"};
static const char *const XtensaTriples[] = {"xtensa-unknown-elf"};
static const char *const XtensaTriples[] = {
"xtensa-unknown-elf", "xtensa-esp32-elf", "xtensa-esp32s2-elf",
"xtensa-esp32s3-elf"};

using std::begin;
using std::end;
Expand Down Expand Up @@ -2502,6 +2540,8 @@ bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
findMSP430Multilibs(D, TargetTriple, Path, Args, Detected);
} else if (TargetArch == llvm::Triple::avr) {
// AVR has no multilibs.
} else if (TargetArch == llvm::Triple::xtensa) {
findXtensaMultilibs(D, TargetTriple, Path, Args, Detected);
} else if (!findBiarchMultilibs(D, TargetTriple, Path, Args,
NeedsBiarchSuffix, Detected)) {
return false;
Expand Down
230 changes: 101 additions & 129 deletions clang/lib/Driver/ToolChains/Xtensa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

#include "Xtensa.h"
#include "CommonArgs.h"
#include "clang/Driver/InputInfo.h"
#include "clang/Basic/Cuda.h"
#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
Expand All @@ -31,58 +30,23 @@ using namespace llvm::opt;

using tools::addMultilibFlag;

XtensaGCCToolchainDetector::XtensaGCCToolchainDetector(
const Driver &D, const llvm::Triple &HostTriple,
const llvm::opt::ArgList &Args) {
std::string InstalledDir;
InstalledDir = D.getInstalledDir();
StringRef CPUName = XtensaToolChain::GetTargetCPUVersion(Args);
std::string Dir;
std::string ToolchainName;
std::string ToolchainDir;

if (CPUName.equals("esp32"))
ToolchainName = "xtensa-esp32-elf";
else if (CPUName.equals("esp32-s2"))
ToolchainName = "xtensa-esp32s2-elf";
else if (CPUName.equals("esp32-s3"))
ToolchainName = "xtensa-esp32s3-elf";
else if (CPUName.equals("esp8266"))
ToolchainName = "xtensa-lx106-elf";

Slash = llvm::sys::path::get_separator().str();

ToolchainDir = InstalledDir + Slash + "..";
Dir = ToolchainDir + Slash + "lib" + Slash + "gcc" + Slash + ToolchainName +
Slash;
GCCLibAndIncVersion = "";

if (D.getVFS().exists(Dir)) {
std::error_code EC;
for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(Dir, EC), LE;
!EC && LI != LE; LI = LI.increment(EC)) {
StringRef VersionText = llvm::sys::path::filename(LI->path());
auto GCCVersion = Generic_GCC::GCCVersion::Parse(VersionText);
if (GCCVersion.Major == -1)
continue;
GCCLibAndIncVersion = GCCVersion.Text;
}
if (GCCLibAndIncVersion == "")
llvm_unreachable("Unexpected Xtensa GCC toolchain version");

} else {
// Unable to find Xtensa GCC toolchain;
GCCToolchainName = "";
return;
}
GCCToolchainDir = ToolchainDir;
GCCToolchainName = ToolchainName;
}

/// Xtensa Toolchain
XtensaToolChain::XtensaToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args), XtensaGCCToolchain(D, getTriple(), Args) {
: Generic_ELF(D, Triple, Args) {

GCCInstallation.init(Triple, Args);

if (!GCCInstallation.isValid()) {
llvm_unreachable("Unexpected Xtensa GCC toolchain version");
}

GCCLibAndIncVersion = GCCInstallation.getVersion().Text;
GCCToolchainName = GCCInstallation.getTriple().str();
SmallString<128> Path(GCCInstallation.getParentLibPath());
llvm::sys::path::append(Path, "..");
GCCToolchainDir = Path.c_str();

for (auto *A : Args) {
std::string Str = A->getAsString(Args);
if (!Str.compare("-mlongcalls"))
Expand All @@ -109,45 +73,18 @@ XtensaToolChain::XtensaToolChain(const Driver &D, const llvm::Triple &Triple,
IsIntegratedAsm = false;
}

bool IsESP32 = XtensaToolChain::GetTargetCPUVersion(Args).equals("esp32");
Multilibs.push_back(Multilib());
if (IsESP32)
Multilibs.push_back(Multilib("esp32-psram", {}, {}, 2)
.flag("+mfix-esp32-psram-cache-issue"));

Multilibs.push_back(
Multilib("no-rtti", {}, {}, 1).flag("+fno-rtti").flag("-frtti"));

if (IsESP32)
Multilibs.push_back(Multilib("esp32-psram/no-rtti", {}, {}, 3)
.flag("+fno-rtti")
.flag("-frtti")
.flag("+mfix-esp32-psram-cache-issue"));

Multilib::flags_list Flags;
addMultilibFlag(
Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti, false), "frtti",
Flags);

if (IsESP32)
addMultilibFlag(Args.hasFlag(options::OPT_mfix_esp32_psram_cache_issue,
options::OPT_mfix_esp32_psram_cache_issue,
false),
"mfix-esp32-psram-cache-issue", Flags);

Multilibs.select(Flags, SelectedMultilib);

const std::string Slash = XtensaGCCToolchain.Slash;
std::string Libs =
XtensaGCCToolchain.GCCToolchainDir + Slash + "lib" + Slash + "gcc" +
Slash + XtensaGCCToolchain.GCCToolchainName + Slash +
XtensaGCCToolchain.GCCLibAndIncVersion + SelectedMultilib.gccSuffix();
getFilePaths().push_back(Libs);

Libs = XtensaGCCToolchain.GCCToolchainDir + Slash +
XtensaGCCToolchain.GCCToolchainName + Slash + "lib" +
SelectedMultilib.gccSuffix();
getFilePaths().push_back(Libs);
SmallString<128> Libs1(GCCToolchainDir);
llvm::sys::path::append(Libs1, "lib", "gcc", GCCToolchainName,
GCCLibAndIncVersion);
if (!SelectedMultilib.gccSuffix().empty())
llvm::sys::path::append(Libs1, SelectedMultilib.gccSuffix());
getFilePaths().push_back(Libs1.c_str());

SmallString<128> Libs2(GCCToolchainDir);
llvm::sys::path::append(Libs2, GCCToolchainName, "lib");
if (!SelectedMultilib.gccSuffix().empty())
llvm::sys::path::append(Libs2, SelectedMultilib.gccSuffix());
getFilePaths().push_back(Libs2.c_str());
}

Tool *XtensaToolChain::buildLinker() const {
Expand All @@ -164,17 +101,15 @@ void XtensaToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
DriverArgs.hasArg(options::OPT_nostdlibinc))
return;

if (!XtensaGCCToolchain.IsValid())
if (!GCCInstallation.isValid())
return;

std::string Slash = XtensaGCCToolchain.Slash;

std::string Path1 = getDriver().ResourceDir.c_str() + Slash + "include";
std::string Path2 = XtensaGCCToolchain.GCCToolchainDir + Slash +
XtensaGCCToolchain.GCCToolchainName + Slash +
"sys-include";
std::string Path3 = XtensaGCCToolchain.GCCToolchainDir + Slash +
XtensaGCCToolchain.GCCToolchainName + Slash + "include";
SmallString<128> Path1(getDriver().ResourceDir);
llvm::sys::path::append(Path1, "include");
SmallString<128> Path2(GCCToolchainDir);
llvm::sys::path::append(Path2, GCCToolchainName, "sys-include");
SmallString<128> Path3(GCCToolchainDir);
llvm::sys::path::append(Path3, GCCToolchainName, "include");

const StringRef Paths[] = {Path1, Path2, Path3};
addSystemIncludes(DriverArgs, CC1Args, Paths);
Expand All @@ -183,20 +118,20 @@ void XtensaToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
void XtensaToolChain::addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
if (!XtensaGCCToolchain.IsValid())
if (!GCCInstallation.isValid())
return;

std::string Slash = XtensaGCCToolchain.Slash;
SmallString<128> BaseDir(GCCToolchainDir);
llvm::sys::path::append(BaseDir, GCCToolchainName, "include", "c++",
GCCLibAndIncVersion);
SmallString<128> TargetDir(BaseDir);
llvm::sys::path::append(TargetDir, GCCToolchainName);
SmallString<128> TargetDirBackward(BaseDir);
llvm::sys::path::append(TargetDirBackward, "backward");

std::string BaseDir = XtensaGCCToolchain.GCCToolchainDir + Slash +
XtensaGCCToolchain.GCCToolchainName + Slash +
"include" + Slash + "c++" + Slash +
XtensaGCCToolchain.GCCLibAndIncVersion;
std::string TargetDir = BaseDir + Slash + XtensaGCCToolchain.GCCToolchainName;
addLibStdCXXIncludePaths(BaseDir, "", "", DriverArgs, CC1Args);
addLibStdCXXIncludePaths(TargetDir, "", "", DriverArgs, CC1Args);
TargetDir = BaseDir + Slash + "backward";
addLibStdCXXIncludePaths(TargetDir, "", "", DriverArgs, CC1Args);
addLibStdCXXIncludePaths(TargetDirBackward, "", "", DriverArgs, CC1Args);
}

ToolChain::CXXStdlibType
Expand All @@ -212,6 +147,11 @@ XtensaToolChain::GetCXXStdlibType(const ArgList &Args) const {
return ToolChain::CST_Libstdcxx;
}

ToolChain::UnwindLibType
XtensaToolChain::GetUnwindLibType(const llvm::opt::ArgList &Args) const {
return ToolChain::UNW_None;
}

const StringRef XtensaToolChain::GetTargetCPUVersion(const ArgList &Args) {
if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
StringRef CPUName = A->getValue();
Expand All @@ -228,7 +168,7 @@ void tools::Xtensa::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const auto &TC =
static_cast<const toolchains::XtensaToolChain &>(getToolChain());

if (!TC.XtensaGCCToolchain.IsValid())
if (TC.GCCToolchainName == "")
llvm_unreachable("Unable to find Xtensa GCC assembler");

claimNoWarnArgs(Args);
Expand All @@ -255,45 +195,77 @@ void tools::Xtensa::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());

std::string Slash = TC.XtensaGCCToolchain.Slash;
SmallString<128> Asm(TC.GCCToolchainDir);
llvm::sys::path::append(Asm, "bin",
TC.GCCToolchainName + "-" + getShortName());

const char *Asm =
Args.MakeArgString(getToolChain().getDriver().Dir + Slash +
TC.XtensaGCCToolchain.GCCToolchainName + "-as");
C.addCommand(std::make_unique<Command>(
JA, *this, ResponseFileSupport::AtFileCurCP(), Asm, CmdArgs, Inputs));
C.addCommand(
std::make_unique<Command>(JA, *this, ResponseFileSupport::AtFileCurCP(),
Args.MakeArgString(Asm), CmdArgs, Inputs));
}

void Xtensa::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
const auto &TC =
static_cast<const toolchains::XtensaToolChain &>(getToolChain());
std::string Slash = TC.XtensaGCCToolchain.Slash;
ArgStringList CmdArgs;
SmallString<128> Linker;
bool WantCRTs =
!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
const auto &ToolChain =
static_cast<const toolchains::XtensaToolChain &>(getToolChain());

if (!TC.XtensaGCCToolchain.IsValid())
if (ToolChain.GCCToolchainName == "")
llvm_unreachable("Unable to find Xtensa GCC linker");

std::string Linker = getToolChain().getDriver().Dir + Slash +
TC.XtensaGCCToolchain.GCCToolchainName + "-ld";
ArgStringList CmdArgs;
if (Args.hasArg(options::OPT_fuse_ld_EQ)) {
Linker.assign(ToolChain.GetLinkerPath());
} else {
Linker.assign(ToolChain.GCCToolchainDir);
llvm::sys::path::append(Linker, "bin",
ToolChain.GCCToolchainName + "-" + getShortName());
}

Args.AddAllArgs(CmdArgs, options::OPT_L);
TC.AddFilePathLibArgs(Args, CmdArgs);
const char *crtbegin, *crtend;
auto RuntimeLib = ToolChain.GetRuntimeLibType(Args);
if (RuntimeLib == ToolChain::RLT_Libgcc) {
crtbegin = "crtbegin.o";
crtend = "crtend.o";
} else {
assert (RuntimeLib == ToolChain::RLT_CompilerRT);
crtbegin = ToolChain.getCompilerRTArgString(Args, "crtbegin",
ToolChain::FT_Object);
crtend = ToolChain.getCompilerRTArgString(Args, "crtend",
ToolChain::FT_Object);
}

if (WantCRTs) {
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
}

AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);

Args.AddAllArgs(CmdArgs, options::OPT_L);
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
Args.AddAllArgs(CmdArgs,
{options::OPT_T_Group, options::OPT_e, options::OPT_s,
options::OPT_t, options::OPT_u_Group});

if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
if (ToolChain.ShouldLinkCXXStdlib(Args))
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
}

AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);

CmdArgs.push_back("-lgcc");
if (WantCRTs)
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));

CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
C.addCommand(
std::make_unique<Command>(JA, *this, ResponseFileSupport::AtFileCurCP(),
Args.MakeArgString(Linker), CmdArgs, Inputs));
C.addCommand(std::make_unique<Command>(
JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker),
CmdArgs, Inputs));
}
Loading