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