Skip to content

Commit 110fa85

Browse files
committed
[Xtensa] Add support of "-mcpu" option.
Implement support of the "-mcpu" option. Support Xtensa features in clang. Add macros definintion in XtensaTargetInfo based on Xtensa features.
1 parent b24636f commit 110fa85

File tree

16 files changed

+394
-37
lines changed

16 files changed

+394
-37
lines changed

clang/lib/Basic/Targets/Xtensa.cpp

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,65 @@ const Builtin::Info XtensaTargetInfo::BuiltinInfo[] = {
2828

2929
void XtensaTargetInfo::getTargetDefines(const LangOptions &Opts,
3030
MacroBuilder &Builder) const {
31-
Builder.defineMacro("__Xtensa__");
31+
Builder.defineMacro("__ELF__");
3232
Builder.defineMacro("__xtensa__");
3333
Builder.defineMacro("__XTENSA__");
3434
Builder.defineMacro("__XTENSA_EL__");
35+
if (HasWindowed)
36+
Builder.defineMacro("__XTENSA_WINDOWED_ABI__");
37+
else
38+
Builder.defineMacro("__XTENSA_CALL0_ABI__");
39+
if (!HasFP)
40+
Builder.defineMacro("__XTENSA_SOFT_FLOAT__");
3541
}
3642

3743
ArrayRef<Builtin::Info> XtensaTargetInfo::getTargetBuiltins() const {
3844
return llvm::makeArrayRef(BuiltinInfo, clang::Xtensa::LastTSBuiltin -
3945
Builtin::FirstTSBuiltin);
4046
}
47+
48+
void XtensaTargetInfo::fillValidCPUList(
49+
SmallVectorImpl<StringRef> &Values) const {
50+
llvm::Xtensa::fillValidCPUList(Values);
51+
}
52+
53+
bool XtensaTargetInfo::initFeatureMap(
54+
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
55+
const std::vector<std::string> &FeaturesVec) const {
56+
57+
// Assume that by default cpu is esp32
58+
if (CPU.empty())
59+
CPU = "esp32";
60+
61+
CPU = llvm::Xtensa::getBaseName(CPU);
62+
63+
SmallVector<StringRef, 16> CPUFeatures;
64+
llvm::Xtensa::getCPUFeatures(CPU, CPUFeatures);
65+
66+
for (auto Feature : CPUFeatures)
67+
if (Feature[0] == '+')
68+
Features[Feature.drop_front(1)] = true;
69+
70+
return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
71+
}
72+
73+
/// Return true if has this feature, need to sync with handleTargetFeatures.
74+
bool XtensaTargetInfo::hasFeature(StringRef Feature) const {
75+
return llvm::StringSwitch<bool>(Feature)
76+
.Case("fp", HasFP)
77+
.Case("windowed", HasWindowed)
78+
.Default(false);
79+
}
80+
81+
/// Perform initialization based on the user configured set of features.
82+
bool XtensaTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
83+
DiagnosticsEngine &Diags) {
84+
for (const auto &Feature : Features) {
85+
if (Feature == "+fp")
86+
HasFP = true;
87+
else if (Feature == "+windowed")
88+
HasWindowed = true;
89+
}
90+
91+
return true;
92+
}

clang/lib/Basic/Targets/Xtensa.h

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "llvm/ADT/StringSwitch.h"
2121
#include "llvm/ADT/Triple.h"
2222
#include "llvm/Support/Compiler.h"
23+
#include "llvm/Support/TargetParser.h"
2324

2425
#include "clang/Basic/Builtins.h"
2526
#include "clang/Basic/MacroBuilder.h"
@@ -31,6 +32,8 @@ namespace targets {
3132
class LLVM_LIBRARY_VISIBILITY XtensaTargetInfo : public TargetInfo {
3233
static const Builtin::Info BuiltinInfo[];
3334
std::string CPU;
35+
bool HasFP = false;
36+
bool HasWindowed = false;
3437

3538
public:
3639
XtensaTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
@@ -94,19 +97,25 @@ class LLVM_LIBRARY_VISIBILITY XtensaTargetInfo : public TargetInfo {
9497
}
9598

9699
bool isValidCPUName(StringRef Name) const override {
97-
return llvm::StringSwitch<bool>(Name)
98-
.Case("esp32", true)
99-
.Case("esp8266", true)
100-
.Case("esp32-s2", true)
101-
.Case("esp32-s3", true)
102-
.Case("generic", true)
103-
.Default(false);
100+
return llvm::Xtensa::parseCPUKind(Name) != llvm::Xtensa::CK_INVALID;
104101
}
105102

106103
bool setCPU(const std::string &Name) override {
107104
CPU = Name;
108105
return isValidCPUName(Name);
109106
}
107+
108+
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
109+
110+
bool
111+
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
112+
StringRef CPU,
113+
const std::vector<std::string> &FeaturesVec) const override;
114+
115+
bool hasFeature(StringRef Feature) const override;
116+
117+
bool handleTargetFeatures(std::vector<std::string> &Features,
118+
DiagnosticsEngine &Diags) override;
110119
};
111120
} // namespace targets
112121
} // namespace clang

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "Hexagon.h"
2323
#include "MSP430.h"
2424
#include "PS4CPU.h"
25+
#include "Xtensa.h"
2526
#include "clang/Basic/CharInfo.h"
2627
#include "clang/Basic/CodeGenOptions.h"
2728
#include "clang/Basic/LangOptions.h"
@@ -375,6 +376,9 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
375376
case llvm::Triple::ve:
376377
ve::getVETargetFeatures(D, Args, Features);
377378
break;
379+
case llvm::Triple::xtensa:
380+
xtensa::getXtensaTargetFeatures(D, Args, Features);
381+
break;
378382
}
379383

380384
for (auto Feature : unifyTargetFeatures(Features)) {

clang/lib/Driver/ToolChains/Xtensa.cpp

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "clang/Driver/Options.h"
2121
#include "llvm/Option/ArgList.h"
2222
#include "llvm/Support/Path.h"
23+
#include "llvm/Support/TargetParser.h"
2324
#include "llvm/Support/VirtualFileSystem.h"
2425
#include <system_error>
2526

@@ -43,9 +44,9 @@ XtensaGCCToolchainDetector::XtensaGCCToolchainDetector(
4344

4445
if (CPUName.equals("esp32"))
4546
ToolchainName = "xtensa-esp32-elf";
46-
else if (CPUName.equals("esp32-s2"))
47+
else if (CPUName.equals("esp32-s2") || CPUName.equals("esp32s2"))
4748
ToolchainName = "xtensa-esp32s2-elf";
48-
else if (CPUName.equals("esp32-s3"))
49+
else if (CPUName.equals("esp32-s3") || CPUName.equals("esp32s3"))
4950
ToolchainName = "xtensa-esp32s3-elf";
5051
else if (CPUName.equals("esp8266"))
5152
ToolchainName = "xtensa-lx106-elf";
@@ -151,11 +152,11 @@ XtensaToolChain::XtensaToolChain(const Driver &D, const llvm::Triple &Triple,
151152
}
152153

153154
Tool *XtensaToolChain::buildLinker() const {
154-
return new tools::Xtensa::Linker(*this);
155+
return new tools::xtensa::Linker(*this);
155156
}
156157

157158
Tool *XtensaToolChain::buildAssembler() const {
158-
return new tools::Xtensa::Assembler(*this);
159+
return new tools::xtensa::Assembler(*this);
159160
}
160161

161162
void XtensaToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
@@ -220,7 +221,7 @@ const StringRef XtensaToolChain::GetTargetCPUVersion(const ArgList &Args) {
220221
return "esp32";
221222
}
222223

223-
void tools::Xtensa::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
224+
void tools::xtensa::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
224225
const InputInfo &Output,
225226
const InputInfoList &Inputs,
226227
const ArgList &Args,
@@ -264,7 +265,7 @@ void tools::Xtensa::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
264265
JA, *this, ResponseFileSupport::AtFileCurCP(), Asm, CmdArgs, Inputs));
265266
}
266267

267-
void Xtensa::Linker::ConstructJob(Compilation &C, const JobAction &JA,
268+
void xtensa::Linker::ConstructJob(Compilation &C, const JobAction &JA,
268269
const InputInfo &Output,
269270
const InputInfoList &Inputs,
270271
const ArgList &Args,
@@ -297,3 +298,31 @@ void Xtensa::Linker::ConstructJob(Compilation &C, const JobAction &JA,
297298
std::make_unique<Command>(JA, *this, ResponseFileSupport::AtFileCurCP(),
298299
Args.MakeArgString(Linker), CmdArgs, Inputs));
299300
}
301+
302+
// Get features by CPU name
303+
static void getXtensaFeaturesFromMcpu(const Driver &D,
304+
const llvm::opt::ArgList &Args,
305+
const llvm::opt::Arg *A, StringRef Mcpu,
306+
std::vector<StringRef> &Features) {
307+
if (llvm::Xtensa::parseCPUKind(Mcpu) == llvm::Xtensa::CK_INVALID) {
308+
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
309+
} else {
310+
SmallVector<StringRef, 16> CPUFeatures;
311+
llvm::Xtensa::getCPUFeatures(Mcpu, CPUFeatures);
312+
for (auto &F : CPUFeatures) {
313+
Features.push_back(F);
314+
}
315+
}
316+
}
317+
318+
// Xtensa target features.
319+
void xtensa::getXtensaTargetFeatures(const Driver &D, const ArgList &Args,
320+
std::vector<StringRef> &Features) {
321+
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
322+
getXtensaFeaturesFromMcpu(D, Args, A, A->getValue(), Features);
323+
324+
// Now add any that the user explicitly requested on the command line,
325+
// which may override the defaults.
326+
handleTargetFeaturesGroup(Args, Features,
327+
options::OPT_m_xtensa_Features_Group);
328+
}

clang/lib/Driver/ToolChains/Xtensa.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class LLVM_LIBRARY_VISIBILITY XtensaToolChain : public Generic_ELF {
6161
} // end namespace toolchains
6262

6363
namespace tools {
64-
namespace Xtensa {
64+
namespace xtensa {
6565
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
6666
public:
6767
Linker(const ToolChain &TC)
@@ -86,7 +86,9 @@ class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
8686
const char *LinkingOutput) const override;
8787
};
8888

89-
} // end namespace Xtensa
89+
void getXtensaTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
90+
std::vector<llvm::StringRef> &Features);
91+
} // end namespace xtensa
9092
} // end namespace tools
9193
} // end namespace driver
9294
} // end namespace clang

clang/test/Driver/xtensa-cpus.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Check target CPUs are correctly passed.
2+
3+
// RUN: %clang -target xtensa -### -c %s 2>&1 -mcpu=esp8266 | FileCheck -check-prefix=MCPU-ESP8266 %s
4+
// MCPU-ESP8266: "-target-cpu" "esp8266"
5+
// MCPU-ESP8266: "-target-feature" "+density" "-target-feature" "+nsa" "-target-feature" "+mul32" "-target-feature" "+extendedl32r"
6+
// MCPU-ESP8266: "-target-feature" "+debug" "-target-feature" "+exception" "-target-feature" "+highpriinterrupts"
7+
// MCPU-ESP8266: "-target-feature" "+interrupt" "-target-feature" "+rvector" "-target-feature" "+timerint" "-target-feature" "+prid"
8+
// MCPU-ESP8266: "-target-feature" "+regprotect"
9+
10+
// RUN: %clang -target xtensa -### -c %s 2>&1 -mcpu=esp32 | FileCheck -check-prefix=MCPU-ESP32 %s
11+
// MCPU-ESP32: "-target-cpu" "esp32"
12+
// MCPU-ESP32: "-target-feature" "+density" "-target-feature" "+fp" "-target-feature" "+windowed" "-target-feature" "+bool"
13+
// MCPU-ESP32: "-target-feature" "+loop" "-target-feature" "+sext" "-target-feature" "+nsa" "-target-feature" "+mul32"
14+
// MCPU-ESP32: "-target-feature" "+mul32high" "-target-feature" "+div32" "-target-feature" "+mac16" "-target-feature" "+dfpaccel"
15+
// MCPU-ESP32: "-target-feature" "+s32c1i" "-target-feature" "+threadptr" "-target-feature" "+atomctl" "-target-feature" "+memctl"
16+
// MCPU-ESP32: "-target-feature" "+debug" "-target-feature" "+exception" "-target-feature" "+highpriinterrupts"
17+
// MCPU-ESP32: "-target-feature" "+coprocessor" "-target-feature" "+interrupt" "-target-feature" "+rvector" "-target-feature" "+timerint"
18+
// MCPU-ESP32: "-target-feature" "+prid" "-target-feature" "+regprotect" "-target-feature" "+miscsr"
19+
20+
// RUN: %clang -target xtensa -### -c %s 2>&1 -mcpu=esp32s2 | FileCheck -check-prefix=MCPU-ESP32S2 %s
21+
// MCPU-ESP32S2: "-target-cpu" "esp32s2"
22+
// MCPU-ESP32S2: "-target-feature" "+density" "-target-feature" "+windowed" "-target-feature" "+sext" "-target-feature" "+nsa"
23+
// MCPU-ESP32S2: "-target-feature" "+mul32" "-target-feature" "+mul32high" "-target-feature" "+div32" "-target-feature" "+threadptr"
24+
// MCPU-ESP32S2: "-target-feature" "+memctl" "-target-feature" "+debug" "-target-feature" "+exception" "-target-feature" "+highpriinterrupts"
25+
// MCPU-ESP32S2: "-target-feature" "+coprocessor" "-target-feature" "+interrupt" "-target-feature" "+rvector" "-target-feature" "+timerint"
26+
// MCPU-ESP32S2: "-target-feature" "+prid" "-target-feature" "+regprotect" "-target-feature" "+miscsr" "-target-feature" "+esp32s2"
27+
28+
// RUN: %clang -target xtensa -### -c %s 2>&1 -mcpu=esp32s3 | FileCheck -check-prefix=MCPU-ESP32S3 %s
29+
// MCPU-ESP32S3: "-target-cpu" "esp32s3"
30+
// MCPU-ESP32S3: "-target-feature" "+density" "-target-feature" "+fp" "-target-feature" "+windowed" "-target-feature" "+bool"
31+
// MCPU-ESP32S3: "-target-feature" "+loop" "-target-feature" "+sext" "-target-feature" "+nsa" "-target-feature" "+mul32"
32+
// MCPU-ESP32S3: "-target-feature" "+mul32high" "-target-feature" "+div32" "-target-feature" "+mac16" "-target-feature" "+dfpaccel"
33+
// MCPU-ESP32S3: "-target-feature" "+s32c1i" "-target-feature" "+threadptr" "-target-feature" "+atomctl" "-target-feature" "+memctl"
34+
// MCPU-ESP32S3: "-target-feature" "+debug" "-target-feature" "+exception" "-target-feature" "+highpriinterrupts"
35+
// MCPU-ESP32S3: "-target-feature" "+coprocessor" "-target-feature" "+interrupt" "-target-feature" "+rvector" "-target-feature" "+timerint"
36+
// MCPU-ESP32S3: "-target-feature" "+prid" "-target-feature" "+regprotect" "-target-feature" "+miscsr" "-target-feature" "+esp32s3"

clang/test/Misc/target-invalid-cpu-note.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,7 @@
205205
// RUN: not %clang_cc1 -triple riscv64 -tune-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix TUNE-RISCV64
206206
// TUNE-RISCV64: error: unknown target CPU 'not-a-cpu'
207207
// TUNE-RISCV64: note: valid target CPU values are: generic-rv64, rocket-rv64, sifive-7-rv64, sifive-u54, sifive-u74, generic, rocket, sifive-7-series
208+
209+
// RUN: not %clang_cc1 -triple xtensa -tune-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix TUNE-XTENSA
210+
// TUNE-XTENSA: error: unknown target CPU 'not-a-cpu'
211+
// TUNE-XTENSA: note: valid target CPU values are: generic, esp8266, esp32, esp32s2, esp32-s2, esp32s3, esp32-s3

llvm/include/llvm/Support/TargetParser.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,54 @@ StringRef resolveTuneCPUAlias(StringRef TuneCPU, bool IsRV64);
177177

178178
} // namespace RISCV
179179

180+
namespace Xtensa {
181+
182+
enum CPUKind : unsigned {
183+
#define XTENSA_CPU(ENUM, NAME, FEATURES) CK_##ENUM,
184+
#include "XtensaTargetParser.def"
185+
};
186+
187+
enum FeatureKind : uint64_t {
188+
FK_INVALID = 0,
189+
FK_NONE = 1,
190+
FK_FP = 1 << 1,
191+
FK_WINDOWED = 1 << 2,
192+
FK_BOOLEAN = 1 << 3,
193+
FK_DENSITY = 1 << 4,
194+
FK_LOOP = 1 << 5,
195+
FK_SEXT = 1 << 6,
196+
FK_NSA = 1 << 7,
197+
FK_MUL32 = 1 << 8,
198+
FK_MUL32HIGH = 1 << 9,
199+
FK_DIV32 = 1 << 10,
200+
FK_MAC16 = 1 << 11,
201+
FK_DFPACCEL = 1 << 12,
202+
FK_S32C1I = 1 << 13,
203+
FK_THREADPTR = 1 << 14,
204+
FK_EXTENDEDL32R = 1 << 15,
205+
FK_ATOMCTL = 1 << 16,
206+
FK_MEMCTL = 1 << 17,
207+
FK_DEBUG = 1 << 18,
208+
FK_EXCEPTION = 1 << 19,
209+
FK_HIGHPRIINTERRUPTS = 1 << 20,
210+
FK_COPROCESSOR = 1 << 21,
211+
FK_INTERRUPT = 1 << 22,
212+
FK_RVECTOR = 1 << 23,
213+
FK_TIMERINT = 1 << 24,
214+
FK_PRID = 1 << 25,
215+
FK_REGPROTECT = 1 << 26,
216+
FK_MISCSR = 1 << 27,
217+
FK_ESP32S2OPS = 1 << 28,
218+
FK_ESP32S3OPS = 1 << 29
219+
};
220+
221+
CPUKind parseCPUKind(StringRef CPU);
222+
StringRef getBaseName(StringRef CPU);
223+
void getCPUFeatures(StringRef CPU, SmallVectorImpl<StringRef> &Features);
224+
void fillValidCPUList(SmallVectorImpl<StringRef> &Values);
225+
226+
} // namespace Xtensa
227+
180228
} // namespace llvm
181229

182230
#endif

0 commit comments

Comments
 (0)