Clang Project

clang_source_code/lib/Basic/Targets/PPC.cpp
1//===--- PPC.cpp - Implement PPC target feature support -------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements PPC TargetInfo objects.
10//
11//===----------------------------------------------------------------------===//
12
13#include "PPC.h"
14#include "clang/Basic/Diagnostic.h"
15#include "clang/Basic/MacroBuilder.h"
16#include "clang/Basic/TargetBuiltins.h"
17
18using namespace clang;
19using namespace clang::targets;
20
21const Builtin::Info PPCTargetInfo::BuiltinInfo[] = {
22#define BUILTIN(ID, TYPE, ATTRS)                                               \
23  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
24#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
25  {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
26#include "clang/Basic/BuiltinsPPC.def"
27};
28
29/// handleTargetFeatures - Perform initialization based on the user
30/// configured set of features.
31bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
32                                         DiagnosticsEngine &Diags) {
33  for (const auto &Feature : Features) {
34    if (Feature == "+altivec") {
35      HasAltivec = true;
36    } else if (Feature == "+vsx") {
37      HasVSX = true;
38    } else if (Feature == "+bpermd") {
39      HasBPERMD = true;
40    } else if (Feature == "+extdiv") {
41      HasExtDiv = true;
42    } else if (Feature == "+power8-vector") {
43      HasP8Vector = true;
44    } else if (Feature == "+crypto") {
45      HasP8Crypto = true;
46    } else if (Feature == "+direct-move") {
47      HasDirectMove = true;
48    } else if (Feature == "+qpx") {
49      HasQPX = true;
50    } else if (Feature == "+htm") {
51      HasHTM = true;
52    } else if (Feature == "+float128") {
53      HasFloat128 = true;
54    } else if (Feature == "+power9-vector") {
55      HasP9Vector = true;
56    }
57    // TODO: Finish this list and add an assert that we've handled them
58    // all.
59  }
60
61  return true;
62}
63
64/// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific
65/// #defines that are not tied to a specific subtarget.
66void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
67                                     MacroBuilder &Builder) const {
68  // Target identification.
69  Builder.defineMacro("__ppc__");
70  Builder.defineMacro("__PPC__");
71  Builder.defineMacro("_ARCH_PPC");
72  Builder.defineMacro("__powerpc__");
73  Builder.defineMacro("__POWERPC__");
74  if (PointerWidth == 64) {
75    Builder.defineMacro("_ARCH_PPC64");
76    Builder.defineMacro("__powerpc64__");
77    Builder.defineMacro("__ppc64__");
78    Builder.defineMacro("__PPC64__");
79  }
80
81  // Target properties.
82  if (getTriple().getArch() == llvm::Triple::ppc64le) {
83    Builder.defineMacro("_LITTLE_ENDIAN");
84  } else {
85    if (!getTriple().isOSNetBSD() &&
86        !getTriple().isOSOpenBSD())
87      Builder.defineMacro("_BIG_ENDIAN");
88  }
89
90  // ABI options.
91  if (ABI == "elfv1" || ABI == "elfv1-qpx")
92    Builder.defineMacro("_CALL_ELF""1");
93  if (ABI == "elfv2")
94    Builder.defineMacro("_CALL_ELF""2");
95
96  // This typically is only for a new enough linker (bfd >= 2.16.2 or gold), but
97  // our support post-dates this and it should work on all 64-bit ppc linux
98  // platforms. It is guaranteed to work on all elfv2 platforms.
99  if (getTriple().getOS() == llvm::Triple::Linux && PointerWidth == 64)
100    Builder.defineMacro("_CALL_LINUX""1");
101
102  // Subtarget options.
103  if (!getTriple().isOSAIX()){
104    Builder.defineMacro("__NATURAL_ALIGNMENT__");
105  }
106  Builder.defineMacro("__REGISTER_PREFIX__""");
107
108  // FIXME: Should be controlled by command line option.
109  if (LongDoubleWidth == 128) {
110    Builder.defineMacro("__LONG_DOUBLE_128__");
111    Builder.defineMacro("__LONGDOUBLE128");
112  }
113
114  // Define this for elfv2 (64-bit only) or 64-bit darwin.
115  if (ABI == "elfv2" ||
116      (getTriple().getOS() == llvm::Triple::Darwin && PointerWidth == 64))
117    Builder.defineMacro("__STRUCT_PARM_ALIGN__""16");
118
119  if (ArchDefs & ArchDefineName)
120    Builder.defineMacro(Twine("_ARCH_", StringRef(CPU).upper()));
121  if (ArchDefs & ArchDefinePpcgr)
122    Builder.defineMacro("_ARCH_PPCGR");
123  if (ArchDefs & ArchDefinePpcsq)
124    Builder.defineMacro("_ARCH_PPCSQ");
125  if (ArchDefs & ArchDefine440)
126    Builder.defineMacro("_ARCH_440");
127  if (ArchDefs & ArchDefine603)
128    Builder.defineMacro("_ARCH_603");
129  if (ArchDefs & ArchDefine604)
130    Builder.defineMacro("_ARCH_604");
131  if (ArchDefs & ArchDefinePwr4)
132    Builder.defineMacro("_ARCH_PWR4");
133  if (ArchDefs & ArchDefinePwr5)
134    Builder.defineMacro("_ARCH_PWR5");
135  if (ArchDefs & ArchDefinePwr5x)
136    Builder.defineMacro("_ARCH_PWR5X");
137  if (ArchDefs & ArchDefinePwr6)
138    Builder.defineMacro("_ARCH_PWR6");
139  if (ArchDefs & ArchDefinePwr6x)
140    Builder.defineMacro("_ARCH_PWR6X");
141  if (ArchDefs & ArchDefinePwr7)
142    Builder.defineMacro("_ARCH_PWR7");
143  if (ArchDefs & ArchDefinePwr8)
144    Builder.defineMacro("_ARCH_PWR8");
145  if (ArchDefs & ArchDefinePwr9)
146    Builder.defineMacro("_ARCH_PWR9");
147  if (ArchDefs & ArchDefineA2)
148    Builder.defineMacro("_ARCH_A2");
149  if (ArchDefs & ArchDefineA2q) {
150    Builder.defineMacro("_ARCH_A2Q");
151    Builder.defineMacro("_ARCH_QP");
152  }
153
154  if (getTriple().getVendor() == llvm::Triple::BGQ) {
155    Builder.defineMacro("__bg__");
156    Builder.defineMacro("__THW_BLUEGENE__");
157    Builder.defineMacro("__bgq__");
158    Builder.defineMacro("__TOS_BGQ__");
159  }
160
161  if (HasAltivec) {
162    Builder.defineMacro("__VEC__""10206");
163    Builder.defineMacro("__ALTIVEC__");
164  }
165  if (HasVSX)
166    Builder.defineMacro("__VSX__");
167  if (HasP8Vector)
168    Builder.defineMacro("__POWER8_VECTOR__");
169  if (HasP8Crypto)
170    Builder.defineMacro("__CRYPTO__");
171  if (HasHTM)
172    Builder.defineMacro("__HTM__");
173  if (HasFloat128)
174    Builder.defineMacro("__FLOAT128__");
175  if (HasP9Vector)
176    Builder.defineMacro("__POWER9_VECTOR__");
177
178  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
179  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
180  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
181  if (PointerWidth == 64)
182    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
183
184  // We have support for the bswap intrinsics so we can define this.
185  Builder.defineMacro("__HAVE_BSWAP__""1");
186
187  // FIXME: The following are not yet generated here by Clang, but are
188  //        generated by GCC:
189  //
190  //   _SOFT_FLOAT_
191  //   __RECIP_PRECISION__
192  //   __APPLE_ALTIVEC__
193  //   __RECIP__
194  //   __RECIPF__
195  //   __RSQRTE__
196  //   __RSQRTEF__
197  //   _SOFT_DOUBLE_
198  //   __NO_LWSYNC__
199  //   __CMODEL_MEDIUM__
200  //   __CMODEL_LARGE__
201  //   _CALL_SYSV
202  //   _CALL_DARWIN
203  //   __NO_FPRS__
204}
205
206// Handle explicit options being passed to the compiler here: if we've
207// explicitly turned off vsx and turned on any of:
208// - power8-vector
209// - direct-move
210// - float128
211// - power9-vector
212// then go ahead and error since the customer has expressed an incompatible
213// set of options.
214static bool ppcUserFeaturesCheck(DiagnosticsEngine &Diags,
215                                 const std::vector<std::string> &FeaturesVec) {
216
217  if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "-vsx") !=
218      FeaturesVec.end()) {
219    if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+power8-vector") !=
220        FeaturesVec.end()) {
221      Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower8-vector"
222                                                     << "-mno-vsx";
223      return false;
224    }
225
226    if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+direct-move") !=
227        FeaturesVec.end()) {
228      Diags.Report(diag::err_opt_not_valid_with_opt) << "-mdirect-move"
229                                                     << "-mno-vsx";
230      return false;
231    }
232
233    if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+float128") !=
234        FeaturesVec.end()) {
235      Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfloat128"
236                                                     << "-mno-vsx";
237      return false;
238    }
239
240    if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+power9-vector") !=
241        FeaturesVec.end()) {
242      Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower9-vector"
243                                                     << "-mno-vsx";
244      return false;
245    }
246  }
247
248  return true;
249}
250
251bool PPCTargetInfo::initFeatureMap(
252    llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
253    const std::vector<std::string> &FeaturesVec) const {
254  Features["altivec"] = llvm::StringSwitch<bool>(CPU)
255                            .Case("7400"true)
256                            .Case("g4"true)
257                            .Case("7450"true)
258                            .Case("g4+"true)
259                            .Case("970"true)
260                            .Case("g5"true)
261                            .Case("pwr6"true)
262                            .Case("pwr7"true)
263                            .Case("pwr8"true)
264                            .Case("pwr9"true)
265                            .Case("ppc64"true)
266                            .Case("ppc64le"true)
267                            .Default(false);
268
269  Features["qpx"] = (CPU == "a2q");
270  Features["power9-vector"] = (CPU == "pwr9");
271  Features["crypto"] = llvm::StringSwitch<bool>(CPU)
272                           .Case("ppc64le"true)
273                           .Case("pwr9"true)
274                           .Case("pwr8"true)
275                           .Default(false);
276  Features["power8-vector"] = llvm::StringSwitch<bool>(CPU)
277                                  .Case("ppc64le"true)
278                                  .Case("pwr9"true)
279                                  .Case("pwr8"true)
280                                  .Default(false);
281  Features["bpermd"] = llvm::StringSwitch<bool>(CPU)
282                           .Case("ppc64le"true)
283                           .Case("pwr9"true)
284                           .Case("pwr8"true)
285                           .Case("pwr7"true)
286                           .Default(false);
287  Features["extdiv"] = llvm::StringSwitch<bool>(CPU)
288                           .Case("ppc64le"true)
289                           .Case("pwr9"true)
290                           .Case("pwr8"true)
291                           .Case("pwr7"true)
292                           .Default(false);
293  Features["direct-move"] = llvm::StringSwitch<bool>(CPU)
294                                .Case("ppc64le"true)
295                                .Case("pwr9"true)
296                                .Case("pwr8"true)
297                                .Default(false);
298  Features["vsx"] = llvm::StringSwitch<bool>(CPU)
299                        .Case("ppc64le"true)
300                        .Case("pwr9"true)
301                        .Case("pwr8"true)
302                        .Case("pwr7"true)
303                        .Default(false);
304  Features["htm"] = llvm::StringSwitch<bool>(CPU)
305                        .Case("ppc64le"true)
306                        .Case("pwr9"true)
307                        .Case("pwr8"true)
308                        .Default(false);
309
310  if (!ppcUserFeaturesCheck(Diags, FeaturesVec))
311    return false;
312
313  if (!(ArchDefs & ArchDefinePwr9) && (ArchDefs & ArchDefinePpcgr) &&
314      std::find(FeaturesVec.begin(), FeaturesVec.end(), "+float128") !=
315          FeaturesVec.end()) {
316    // We have __float128 on PPC but not power 9 and above.
317    Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfloat128" << CPU;
318    return false;
319  }
320
321  return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
322}
323
324bool PPCTargetInfo::hasFeature(StringRef Feature) const {
325  return llvm::StringSwitch<bool>(Feature)
326      .Case("powerpc"true)
327      .Case("altivec", HasAltivec)
328      .Case("vsx", HasVSX)
329      .Case("power8-vector", HasP8Vector)
330      .Case("crypto", HasP8Crypto)
331      .Case("direct-move", HasDirectMove)
332      .Case("qpx", HasQPX)
333      .Case("htm", HasHTM)
334      .Case("bpermd", HasBPERMD)
335      .Case("extdiv", HasExtDiv)
336      .Case("float128", HasFloat128)
337      .Case("power9-vector", HasP9Vector)
338      .Default(false);
339}
340
341void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
342                                      StringRef Name, bool Enabled) const {
343  if (Enabled) {
344    // If we're enabling any of the vsx based features then enable vsx and
345    // altivec. We'll diagnose any problems later.
346    bool FeatureHasVSX = llvm::StringSwitch<bool>(Name)
347                             .Case("vsx"true)
348                             .Case("direct-move"true)
349                             .Case("power8-vector"true)
350                             .Case("power9-vector"true)
351                             .Case("float128"true)
352                             .Default(false);
353    if (FeatureHasVSX)
354      Features["vsx"] = Features["altivec"] = true;
355    if (Name == "power9-vector")
356      Features["power8-vector"] = true;
357    Features[Name] = true;
358  } else {
359    // If we're disabling altivec or vsx go ahead and disable all of the vsx
360    // features.
361    if ((Name == "altivec") || (Name == "vsx"))
362      Features["vsx"] = Features["direct-move"] = Features["power8-vector"] =
363          Features["float128"] = Features["power9-vector"] = false;
364    if (Name == "power8-vector")
365      Features["power9-vector"] = false;
366    Features[Name] = false;
367  }
368}
369
370const char *const PPCTargetInfo::GCCRegNames[] = {
371    "r0",  "r1",     "r2",   "r3",      "r4",      "r5",  "r6",  "r7",  "r8",
372    "r9",  "r10",    "r11",  "r12",     "r13",     "r14""r15""r16""r17",
373    "r18""r19",    "r20",  "r21",     "r22",     "r23""r24""r25""r26",
374    "r27""r28",    "r29",  "r30",     "r31",     "f0",  "f1",  "f2",  "f3",
375    "f4",  "f5",     "f6",   "f7",      "f8",      "f9",  "f10""f11""f12",
376    "f13""f14",    "f15",  "f16",     "f17",     "f18""f19""f20""f21",
377    "f22""f23",    "f24",  "f25",     "f26",     "f27""f28""f29""f30",
378    "f31""mq",     "lr",   "ctr",     "ap",      "cr0""cr1""cr2""cr3",
379    "cr4""cr5",    "cr6",  "cr7",     "xer",     "v0",  "v1",  "v2",  "v3",
380    "v4",  "v5",     "v6",   "v7",      "v8",      "v9",  "v10""v11""v12",
381    "v13""v14",    "v15",  "v16",     "v17",     "v18""v19""v20""v21",
382    "v22""v23",    "v24",  "v25",     "v26",     "v27""v28""v29""v30",
383    "v31""vrsave""vscr""spe_acc""spefscr""sfp"
384};
385
386ArrayRef<const char *> PPCTargetInfo::getGCCRegNames() const {
387  return llvm::makeArrayRef(GCCRegNames);
388}
389
390const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = {
391    // While some of these aliases do map to different registers
392    // they still share the same register name.
393    {{"0"}, "r0"},     {{"1"}, "r1"},     {{"2"}, "r2"},     {{"3"}, "r3"},
394    {{"4"}, "r4"},     {{"5"}, "r5"},     {{"6"}, "r6"},     {{"7"}, "r7"},
395    {{"8"}, "r8"},     {{"9"}, "r9"},     {{"10"}, "r10"},   {{"11"}, "r11"},
396    {{"12"}, "r12"},   {{"13"}, "r13"},   {{"14"}, "r14"},   {{"15"}, "r15"},
397    {{"16"}, "r16"},   {{"17"}, "r17"},   {{"18"}, "r18"},   {{"19"}, "r19"},
398    {{"20"}, "r20"},   {{"21"}, "r21"},   {{"22"}, "r22"},   {{"23"}, "r23"},
399    {{"24"}, "r24"},   {{"25"}, "r25"},   {{"26"}, "r26"},   {{"27"}, "r27"},
400    {{"28"}, "r28"},   {{"29"}, "r29"},   {{"30"}, "r30"},   {{"31"}, "r31"},
401    {{"fr0"}, "f0"},   {{"fr1"}, "f1"},   {{"fr2"}, "f2"},   {{"fr3"}, "f3"},
402    {{"fr4"}, "f4"},   {{"fr5"}, "f5"},   {{"fr6"}, "f6"},   {{"fr7"}, "f7"},
403    {{"fr8"}, "f8"},   {{"fr9"}, "f9"},   {{"fr10"}, "f10"}, {{"fr11"}, "f11"},
404    {{"fr12"}, "f12"}, {{"fr13"}, "f13"}, {{"fr14"}, "f14"}, {{"fr15"}, "f15"},
405    {{"fr16"}, "f16"}, {{"fr17"}, "f17"}, {{"fr18"}, "f18"}, {{"fr19"}, "f19"},
406    {{"fr20"}, "f20"}, {{"fr21"}, "f21"}, {{"fr22"}, "f22"}, {{"fr23"}, "f23"},
407    {{"fr24"}, "f24"}, {{"fr25"}, "f25"}, {{"fr26"}, "f26"}, {{"fr27"}, "f27"},
408    {{"fr28"}, "f28"}, {{"fr29"}, "f29"}, {{"fr30"}, "f30"}, {{"fr31"}, "f31"},
409    {{"cc"}, "cr0"},
410};
411
412ArrayRef<TargetInfo::GCCRegAlias> PPCTargetInfo::getGCCRegAliases() const {
413  return llvm::makeArrayRef(GCCRegAliases);
414}
415
416// PPC ELFABIv2 DWARF Definitoin "Table 2.26. Mappings of Common Registers".
417// vs0 ~ vs31 is mapping to 32 - 63,
418// vs32 ~ vs63 is mapping to 77 - 108. 
419const TargetInfo::AddlRegName GCCAddlRegNames[] = {
420    // Table of additional register names to use in user input.
421    {{"vs0"}, 32},   {{"vs1"}, 33},   {{"vs2"}, 34},   {{"vs3"}, 35}, 
422    {{"vs4"}, 36},   {{"vs5"}, 37},   {{"vs6"}, 38},   {{"vs7"}, 39},
423    {{"vs8"}, 40},   {{"vs9"}, 41},   {{"vs10"}, 42},  {{"vs11"}, 43},
424    {{"vs12"}, 44},  {{"vs13"}, 45},  {{"vs14"}, 46},  {{"vs15"}, 47},
425    {{"vs16"}, 48},  {{"vs17"}, 49},  {{"vs18"}, 50},  {{"vs19"}, 51},
426    {{"vs20"}, 52},  {{"vs21"}, 53},  {{"vs22"}, 54},  {{"vs23"}, 55},
427    {{"vs24"}, 56},  {{"vs25"}, 57},  {{"vs26"}, 58},  {{"vs27"}, 59},
428    {{"vs28"}, 60},  {{"vs29"}, 61},  {{"vs30"}, 62},  {{"vs31"}, 63},
429    {{"vs32"}, 77},  {{"vs33"}, 78},  {{"vs34"}, 79},  {{"vs35"}, 80},
430    {{"vs36"}, 81},  {{"vs37"}, 82},  {{"vs38"}, 83},  {{"vs39"}, 84},
431    {{"vs40"}, 85},  {{"vs41"}, 86},  {{"vs42"}, 87},  {{"vs43"}, 88},
432    {{"vs44"}, 89},  {{"vs45"}, 90},  {{"vs46"}, 91},  {{"vs47"}, 92},
433    {{"vs48"}, 93},  {{"vs49"}, 94},  {{"vs50"}, 95},  {{"vs51"}, 96},
434    {{"vs52"}, 97},  {{"vs53"}, 98},  {{"vs54"}, 99},  {{"vs55"}, 100},
435    {{"vs56"}, 101}, {{"vs57"}, 102}, {{"vs58"}, 103}, {{"vs59"}, 104},
436    {{"vs60"}, 105}, {{"vs61"}, 106}, {{"vs62"}, 107}, {{"vs63"}, 108},
437};
438
439ArrayRef<TargetInfo::AddlRegName> PPCTargetInfo::getGCCAddlRegNames() const {
440  if (ABI == "elfv2")
441    return llvm::makeArrayRef(GCCAddlRegNames);
442  else 
443    return TargetInfo::getGCCAddlRegNames(); 
444}
445
446static constexpr llvm::StringLiteral ValidCPUNames[] = {
447    {"generic"}, {"440"},         {"450"},     {"601"},    {"602"},
448    {"603"},     {"603e"},        {"603ev"},   {"604"},    {"604e"},
449    {"620"},     {"630"},         {"g3"},      {"7400"},   {"g4"},
450    {"7450"},    {"g4+"},         {"750"},     {"970"},    {"g5"},
451    {"a2"},      {"a2q"},         {"e500mc"},  {"e5500"},  {"power3"},
452    {"pwr3"},    {"power4"},      {"pwr4"},    {"power5"}, {"pwr5"},
453    {"power5x"}, {"pwr5x"},       {"power6"},  {"pwr6"},   {"power6x"},
454    {"pwr6x"},   {"power7"},      {"pwr7"},    {"power8"}, {"pwr8"},
455    {"power9"},  {"pwr9"},        {"powerpc"}, {"ppc"},    {"powerpc64"},
456    {"ppc64"},   {"powerpc64le"}, {"ppc64le"},
457};
458
459bool PPCTargetInfo::isValidCPUName(StringRef Name) const {
460  return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames);
461}
462
463void PPCTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
464  Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
465}
466
467void PPCTargetInfo::adjust(LangOptions &Opts) {
468  if (HasAltivec)
469    Opts.AltiVec = 1;
470  TargetInfo::adjust(Opts);
471}
472
473ArrayRef<Builtin::Info> PPCTargetInfo::getTargetBuiltins() const {
474  return llvm::makeArrayRef(BuiltinInfo, clang::PPC::LastTSBuiltin -
475                                             Builtin::FirstTSBuiltin);
476}
477