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