Skip to content

Commit 55a9b82

Browse files
andreisfrantmak
authored andcommitted
[Xtensa] Implement Xtensa toolchain.
1 parent d436779 commit 55a9b82

File tree

4 files changed

+371
-0
lines changed

4 files changed

+371
-0
lines changed

clang/lib/Driver/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ add_clang_library(clangDriver
7070
ToolChains/WebAssembly.cpp
7171
ToolChains/XCore.cpp
7272
ToolChains/PPCLinux.cpp
73+
ToolChains/Xtensa.cpp
7374
ToolChains/InterfaceStubs.cpp
7475
Types.cpp
7576
XRayArgs.cpp

clang/lib/Driver/Driver.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "ToolChains/TCE.h"
4646
#include "ToolChains/WebAssembly.h"
4747
#include "ToolChains/XCore.h"
48+
#include "ToolChains/Xtensa.h"
4849
#include "clang/Basic/Version.h"
4950
#include "clang/Config/config.h"
5051
#include "clang/Driver/Action.h"
@@ -4934,6 +4935,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
49344935
case llvm::Triple::riscv64:
49354936
TC = std::make_unique<toolchains::RISCVToolChain>(*this, Target, Args);
49364937
break;
4938+
case llvm::Triple::xtensa:
4939+
TC = std::make_unique<toolchains::XtensaToolChain>(*this, Target, Args);
4940+
break;
49374941
default:
49384942
if (Target.getVendor() == llvm::Triple::Myriad)
49394943
TC = std::make_unique<toolchains::MyriadToolChain>(*this, Target,
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
//===--- Xtensa.cpp - Xtensa ToolChain Implementations ----------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6+
// See https://llvm.org/LICENSE.txt for license information.
7+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8+
//
9+
//===----------------------------------------------------------------------===//
10+
11+
#include "Xtensa.h"
12+
#include "CommonArgs.h"
13+
#include "InputInfo.h"
14+
#include "clang/Basic/Cuda.h"
15+
#include "clang/Config/config.h"
16+
#include "clang/Driver/Compilation.h"
17+
#include "clang/Driver/Distro.h"
18+
#include "clang/Driver/Driver.h"
19+
#include "clang/Driver/DriverDiagnostic.h"
20+
#include "clang/Driver/Options.h"
21+
#include "llvm/Option/ArgList.h"
22+
#include "llvm/Support/Path.h"
23+
#include "llvm/Support/VirtualFileSystem.h"
24+
#include <system_error>
25+
26+
using namespace clang::driver;
27+
using namespace clang::driver::tools;
28+
using namespace clang::driver::toolchains;
29+
using namespace clang;
30+
using namespace llvm::opt;
31+
32+
XtensaGCCToolchainDetector::XtensaGCCToolchainDetector(
33+
const Driver &D, const llvm::Triple &HostTriple,
34+
const llvm::opt::ArgList &Args) {
35+
std::string InstalledDir;
36+
InstalledDir = D.getInstalledDir();
37+
StringRef CPUName = XtensaToolChain::GetTargetCPUVersion(Args);
38+
std::string Dir;
39+
std::string ToolchainName;
40+
std::string ToolchainDir;
41+
42+
if (CPUName.equals("esp32"))
43+
ToolchainName = "xtensa-esp32-elf";
44+
else if (CPUName.equals("esp32-s2"))
45+
ToolchainName = "xtensa-esp32s2-elf";
46+
else if (CPUName.equals("esp8266"))
47+
ToolchainName = "xtensa-lx106-elf";
48+
49+
Slash = llvm::sys::path::get_separator().str();
50+
51+
ToolchainDir = InstalledDir + Slash + "..";
52+
Dir = ToolchainDir + Slash + "lib" + Slash + "gcc" + Slash + ToolchainName +
53+
Slash;
54+
GCCLibAndIncVersion = "";
55+
56+
if (D.getVFS().exists(Dir)) {
57+
std::error_code EC;
58+
for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(Dir, EC), LE;
59+
!EC && LI != LE; LI = LI.increment(EC)) {
60+
StringRef VersionText = llvm::sys::path::filename(LI->path());
61+
auto GCCVersion = Generic_GCC::GCCVersion::Parse(VersionText);
62+
if (GCCVersion.Major == -1)
63+
continue;
64+
GCCLibAndIncVersion = GCCVersion.Text;
65+
}
66+
if (GCCLibAndIncVersion == "")
67+
llvm_unreachable("Unexpected Xtensa GCC toolchain version");
68+
69+
} else {
70+
// Unable to find Xtensa GCC toolchain;
71+
GCCToolchainName = "";
72+
return;
73+
}
74+
GCCToolchainDir = ToolchainDir;
75+
GCCToolchainName = ToolchainName;
76+
}
77+
78+
/// Xtensa Toolchain
79+
XtensaToolChain::XtensaToolChain(const Driver &D, const llvm::Triple &Triple,
80+
const ArgList &Args)
81+
: Generic_ELF(D, Triple, Args), XtensaGCCToolchain(D, getTriple(), Args) {
82+
for (auto *A : Args) {
83+
std::string Str = A->getAsString(Args);
84+
if (!Str.compare("-mlongcalls"))
85+
A->claim();
86+
if (!Str.compare("-fno-tree-switch-conversion"))
87+
A->claim();
88+
89+
// Currently don't use integrated assembler for assembler input files
90+
if ((IsIntegratedAsm) && (Str.length() > 2)) {
91+
std::string ExtSubStr = Str.substr(Str.length() - 2);
92+
if (!ExtSubStr.compare(".s"))
93+
IsIntegratedAsm = false;
94+
if (!ExtSubStr.compare(".S"))
95+
IsIntegratedAsm = false;
96+
}
97+
}
98+
99+
// Currently don't use integrated assembler for assembler input files
100+
if (IsIntegratedAsm) {
101+
if (Args.getLastArgValue(options::OPT_x).equals("assembler"))
102+
IsIntegratedAsm = false;
103+
104+
if (Args.getLastArgValue(options::OPT_x).equals("assembler-with-cpp"))
105+
IsIntegratedAsm = false;
106+
}
107+
}
108+
109+
Tool *XtensaToolChain::buildLinker() const {
110+
return new tools::Xtensa::Linker(*this);
111+
}
112+
113+
Tool *XtensaToolChain::buildAssembler() const {
114+
return new tools::Xtensa::Assembler(*this);
115+
}
116+
117+
void XtensaToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
118+
ArgStringList &CC1Args) const {
119+
if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc) ||
120+
DriverArgs.hasArg(options::OPT_nostdlibinc))
121+
return;
122+
123+
if (!XtensaGCCToolchain.IsValid())
124+
return;
125+
126+
std::string Slash = XtensaGCCToolchain.Slash;
127+
128+
std::string Path1 = getDriver().ResourceDir.c_str() + Slash + "include";
129+
std::string Path2 =
130+
XtensaGCCToolchain.GCCToolchainDir + Slash + "lib" + Slash + "gcc" +
131+
Slash + XtensaGCCToolchain.GCCToolchainName + Slash +
132+
XtensaGCCToolchain.GCCLibAndIncVersion + Slash + "include";
133+
std::string Path3 =
134+
XtensaGCCToolchain.GCCToolchainDir + Slash + "lib" + Slash + "gcc" +
135+
Slash + XtensaGCCToolchain.GCCToolchainName + Slash +
136+
XtensaGCCToolchain.GCCLibAndIncVersion + Slash + "include-fixed";
137+
std::string Path4 = XtensaGCCToolchain.GCCToolchainDir + Slash +
138+
XtensaGCCToolchain.GCCToolchainName + Slash +
139+
"sys-include";
140+
std::string Path5 = XtensaGCCToolchain.GCCToolchainDir + Slash +
141+
XtensaGCCToolchain.GCCToolchainName + Slash + "include";
142+
143+
const StringRef Paths[] = {Path1, Path2, Path3, Path4, Path5};
144+
addSystemIncludes(DriverArgs, CC1Args, Paths);
145+
}
146+
147+
void XtensaToolChain::addLibStdCxxIncludePaths(
148+
const llvm::opt::ArgList &DriverArgs,
149+
llvm::opt::ArgStringList &CC1Args) const {
150+
if (!XtensaGCCToolchain.IsValid())
151+
return;
152+
153+
std::string Slash = XtensaGCCToolchain.Slash;
154+
155+
std::string BaseDir = XtensaGCCToolchain.GCCToolchainDir + Slash +
156+
XtensaGCCToolchain.GCCToolchainName + Slash +
157+
"include" + Slash + "c++" + Slash +
158+
XtensaGCCToolchain.GCCLibAndIncVersion;
159+
std::string TargetDir = BaseDir + Slash + XtensaGCCToolchain.GCCToolchainName;
160+
addLibStdCXXIncludePaths(BaseDir, "", "", "", "", "", DriverArgs, CC1Args);
161+
addLibStdCXXIncludePaths(TargetDir, "", "", "", "", "", DriverArgs, CC1Args);
162+
TargetDir = BaseDir + Slash + "backward";
163+
addLibStdCXXIncludePaths(TargetDir, "", "", "", "", "", DriverArgs, CC1Args);
164+
}
165+
166+
ToolChain::CXXStdlibType
167+
XtensaToolChain::GetCXXStdlibType(const ArgList &Args) const {
168+
Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
169+
if (!A)
170+
return ToolChain::CST_Libstdcxx;
171+
172+
StringRef Value = A->getValue();
173+
if (Value != "libstdc++")
174+
getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
175+
176+
return ToolChain::CST_Libstdcxx;
177+
}
178+
179+
const StringRef XtensaToolChain::GetTargetCPUVersion(const ArgList &Args) {
180+
if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
181+
StringRef CPUName = A->getValue();
182+
return CPUName;
183+
}
184+
return "esp32";
185+
}
186+
187+
void tools::Xtensa::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
188+
const InputInfo &Output,
189+
const InputInfoList &Inputs,
190+
const ArgList &Args,
191+
const char *LinkingOutput) const {
192+
const auto &TC =
193+
static_cast<const toolchains::XtensaToolChain &>(getToolChain());
194+
195+
if (!TC.XtensaGCCToolchain.IsValid())
196+
llvm_unreachable("Unable to find Xtensa GCC assembler");
197+
198+
claimNoWarnArgs(Args);
199+
ArgStringList CmdArgs;
200+
201+
CmdArgs.push_back("-o");
202+
CmdArgs.push_back(Output.getFilename());
203+
204+
CmdArgs.push_back("-c");
205+
206+
if (Args.hasArg(options::OPT_v))
207+
CmdArgs.push_back("-v");
208+
209+
if (Arg *A = Args.getLastArg(options::OPT_g_Group))
210+
if (!A->getOption().matches(options::OPT_g0))
211+
CmdArgs.push_back("-g");
212+
213+
if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
214+
false))
215+
CmdArgs.push_back("-fverbose-asm");
216+
217+
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
218+
219+
for (const auto &II : Inputs)
220+
CmdArgs.push_back(II.getFilename());
221+
222+
std::string Slash = TC.XtensaGCCToolchain.Slash;
223+
224+
const char *Asm =
225+
Args.MakeArgString(getToolChain().getDriver().Dir + Slash +
226+
TC.XtensaGCCToolchain.GCCToolchainName + "-as");
227+
C.addCommand(std::make_unique<Command>(JA, *this, Asm, CmdArgs, Inputs));
228+
}
229+
230+
void Xtensa::Linker::ConstructJob(Compilation &C, const JobAction &JA,
231+
const InputInfo &Output,
232+
const InputInfoList &Inputs,
233+
const ArgList &Args,
234+
const char *LinkingOutput) const {
235+
const auto &TC =
236+
static_cast<const toolchains::XtensaToolChain &>(getToolChain());
237+
238+
if (!TC.XtensaGCCToolchain.IsValid())
239+
llvm_unreachable("Unable to find Xtensa GCC linker");
240+
241+
std::string Slash = TC.XtensaGCCToolchain.Slash;
242+
243+
std::string Linker = getToolChain().getDriver().Dir + Slash +
244+
TC.XtensaGCCToolchain.GCCToolchainName + "-ld";
245+
ArgStringList CmdArgs;
246+
247+
Args.AddAllArgs(CmdArgs,
248+
{options::OPT_T_Group, options::OPT_e, options::OPT_s,
249+
options::OPT_L, options::OPT_t, options::OPT_u_Group});
250+
251+
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
252+
253+
std::string Libs = TC.XtensaGCCToolchain.GCCToolchainDir + Slash + "lib" +
254+
Slash + "gcc" + Slash +
255+
TC.XtensaGCCToolchain.GCCToolchainName + Slash +
256+
TC.XtensaGCCToolchain.GCCLibAndIncVersion + Slash;
257+
CmdArgs.push_back("-L");
258+
CmdArgs.push_back(Args.MakeArgString(Libs));
259+
260+
Libs = TC.XtensaGCCToolchain.GCCToolchainDir + Slash +
261+
TC.XtensaGCCToolchain.GCCToolchainName + Slash + "lib" + Slash;
262+
CmdArgs.push_back("-L");
263+
CmdArgs.push_back(Args.MakeArgString(Libs));
264+
265+
CmdArgs.push_back("-v");
266+
267+
CmdArgs.push_back("-o");
268+
CmdArgs.push_back(Output.getFilename());
269+
C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
270+
CmdArgs, Inputs));
271+
}
272+

clang/lib/Driver/ToolChains/Xtensa.h

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//===--- Xtensa.h - Xtensa Tool and ToolChain Implementations ---*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6+
// See https://llvm.org/LICENSE.txt for license information.
7+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8+
//
9+
//===----------------------------------------------------------------------===//
10+
11+
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Xtensa_H
12+
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Xtensa_H
13+
14+
#include "Gnu.h"
15+
#include "InputInfo.h"
16+
#include "clang/Driver/Tool.h"
17+
#include "clang/Driver/ToolChain.h"
18+
19+
namespace clang {
20+
namespace driver {
21+
namespace toolchains {
22+
23+
class XtensaGCCToolchainDetector {
24+
public:
25+
std::string GCCLibAndIncVersion;
26+
std::string GCCToolchainName;
27+
std::string GCCToolchainDir;
28+
std::string Slash;
29+
30+
XtensaGCCToolchainDetector(const Driver &D, const llvm::Triple &HostTriple,
31+
const llvm::opt::ArgList &Args);
32+
33+
bool IsValid() const { return GCCToolchainName != ""; }
34+
};
35+
36+
class LLVM_LIBRARY_VISIBILITY XtensaToolChain : public Generic_ELF {
37+
protected:
38+
Tool *buildLinker() const override;
39+
Tool *buildAssembler() const override;
40+
41+
public:
42+
XtensaToolChain(const Driver &D, const llvm::Triple &Triple,
43+
const llvm::opt::ArgList &Args);
44+
void
45+
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
46+
llvm::opt::ArgStringList &CC1Args) const override;
47+
void
48+
addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
49+
llvm::opt::ArgStringList &CC1Args) const override;
50+
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
51+
bool IsIntegratedAssemblerDefault() const override {
52+
return (IsIntegratedAsm || (XtensaGCCToolchain.GCCToolchainName == ""));
53+
}
54+
55+
static const StringRef GetTargetCPUVersion(const llvm::opt::ArgList &Args);
56+
57+
XtensaGCCToolchainDetector XtensaGCCToolchain;
58+
bool IsIntegratedAsm = true;
59+
};
60+
61+
} // end namespace toolchains
62+
63+
namespace tools {
64+
namespace Xtensa {
65+
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
66+
public:
67+
Linker(const ToolChain &TC)
68+
: GnuTool("Xtensa::Linker", "xtensa-esp32-elf-ld", TC) {}
69+
bool hasIntegratedCPP() const override { return false; }
70+
bool isLinkJob() const override { return true; }
71+
void ConstructJob(Compilation &C, const JobAction &JA,
72+
const InputInfo &Output, const InputInfoList &Inputs,
73+
const llvm::opt::ArgList &TCArgs,
74+
const char *LinkingOutput) const override;
75+
};
76+
77+
class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
78+
public:
79+
Assembler(const ToolChain &TC)
80+
: Tool("Xtensa::Assembler", "xtensa-esp32-elf-as", TC) {}
81+
82+
bool hasIntegratedCPP() const override { return false; }
83+
void ConstructJob(Compilation &C, const JobAction &JA,
84+
const InputInfo &Output, const InputInfoList &Inputs,
85+
const llvm::opt::ArgList &TCArgs,
86+
const char *LinkingOutput) const override;
87+
};
88+
89+
} // end namespace Xtensa
90+
} // end namespace tools
91+
} // end namespace driver
92+
} // end namespace clang
93+
94+
#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Xtensa_H

0 commit comments

Comments
 (0)