xref: /freebsd-src/contrib/llvm-project/clang/lib/Basic/Targets/SystemZ.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- SystemZ.cpp - Implement SystemZ target feature support -----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements SystemZ TargetInfo objects.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "SystemZ.h"
140b57cec5SDimitry Andric #include "clang/Basic/Builtins.h"
150b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h"
160b57cec5SDimitry Andric #include "clang/Basic/MacroBuilder.h"
170b57cec5SDimitry Andric #include "clang/Basic/TargetBuiltins.h"
180b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric using namespace clang;
210b57cec5SDimitry Andric using namespace clang::targets;
220b57cec5SDimitry Andric 
23bdd1243dSDimitry Andric static constexpr Builtin::Info BuiltinInfo[] = {
240b57cec5SDimitry Andric #define BUILTIN(ID, TYPE, ATTRS)                                               \
25bdd1243dSDimitry Andric   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
260b57cec5SDimitry Andric #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
27bdd1243dSDimitry Andric   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
280b57cec5SDimitry Andric #include "clang/Basic/BuiltinsSystemZ.def"
290b57cec5SDimitry Andric };
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric const char *const SystemZTargetInfo::GCCRegNames[] = {
320b57cec5SDimitry Andric     "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
330b57cec5SDimitry Andric     "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
340b57cec5SDimitry Andric     "f0",  "f2",  "f4",  "f6",  "f1",  "f3",  "f5",  "f7",
350b57cec5SDimitry Andric     "f8",  "f10", "f12", "f14", "f9",  "f11", "f13", "f15",
360b57cec5SDimitry Andric     /*ap*/"", "cc", /*fp*/"", /*rp*/"", "a0",  "a1",
370b57cec5SDimitry Andric     "v16", "v18", "v20", "v22", "v17", "v19", "v21", "v23",
380b57cec5SDimitry Andric     "v24", "v26", "v28", "v30", "v25", "v27", "v29", "v31"
390b57cec5SDimitry Andric };
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric const TargetInfo::AddlRegName GCCAddlRegNames[] = {
420b57cec5SDimitry Andric     {{"v0"}, 16}, {{"v2"},  17}, {{"v4"},  18}, {{"v6"},  19},
430b57cec5SDimitry Andric     {{"v1"}, 20}, {{"v3"},  21}, {{"v5"},  22}, {{"v7"},  23},
440b57cec5SDimitry Andric     {{"v8"}, 24}, {{"v10"}, 25}, {{"v12"}, 26}, {{"v14"}, 27},
450b57cec5SDimitry Andric     {{"v9"}, 28}, {{"v11"}, 29}, {{"v13"}, 30}, {{"v15"}, 31}
460b57cec5SDimitry Andric };
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric ArrayRef<const char *> SystemZTargetInfo::getGCCRegNames() const {
49bdd1243dSDimitry Andric   return llvm::ArrayRef(GCCRegNames);
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric ArrayRef<TargetInfo::AddlRegName> SystemZTargetInfo::getGCCAddlRegNames() const {
53bdd1243dSDimitry Andric   return llvm::ArrayRef(GCCAddlRegNames);
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric bool SystemZTargetInfo::validateAsmConstraint(
570b57cec5SDimitry Andric     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
580b57cec5SDimitry Andric   switch (*Name) {
590b57cec5SDimitry Andric   default:
600b57cec5SDimitry Andric     return false;
610b57cec5SDimitry Andric 
6281ad6265SDimitry Andric   case 'Z':
6381ad6265SDimitry Andric     switch (Name[1]) {
6481ad6265SDimitry Andric     default:
6581ad6265SDimitry Andric       return false;
6681ad6265SDimitry Andric     case 'Q': // Address with base and unsigned 12-bit displacement
6781ad6265SDimitry Andric     case 'R': // Likewise, plus an index
6881ad6265SDimitry Andric     case 'S': // Address with base and signed 20-bit displacement
6981ad6265SDimitry Andric     case 'T': // Likewise, plus an index
7081ad6265SDimitry Andric       break;
7181ad6265SDimitry Andric     }
72bdd1243dSDimitry Andric     [[fallthrough]];
730b57cec5SDimitry Andric   case 'a': // Address register
740b57cec5SDimitry Andric   case 'd': // Data register (equivalent to 'r')
750b57cec5SDimitry Andric   case 'f': // Floating-point register
760b57cec5SDimitry Andric   case 'v': // Vector register
770b57cec5SDimitry Andric     Info.setAllowsRegister();
780b57cec5SDimitry Andric     return true;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   case 'I': // Unsigned 8-bit constant
810b57cec5SDimitry Andric   case 'J': // Unsigned 12-bit constant
820b57cec5SDimitry Andric   case 'K': // Signed 16-bit constant
830b57cec5SDimitry Andric   case 'L': // Signed 20-bit displacement (on all targets we support)
840b57cec5SDimitry Andric   case 'M': // 0x7fffffff
850b57cec5SDimitry Andric     return true;
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   case 'Q': // Memory with base and unsigned 12-bit displacement
880b57cec5SDimitry Andric   case 'R': // Likewise, plus an index
890b57cec5SDimitry Andric   case 'S': // Memory with base and signed 20-bit displacement
900b57cec5SDimitry Andric   case 'T': // Likewise, plus an index
910b57cec5SDimitry Andric     Info.setAllowsMemory();
920b57cec5SDimitry Andric     return true;
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric struct ISANameRevision {
970b57cec5SDimitry Andric   llvm::StringLiteral Name;
980b57cec5SDimitry Andric   int ISARevisionID;
990b57cec5SDimitry Andric };
1000b57cec5SDimitry Andric static constexpr ISANameRevision ISARevisions[] = {
1010b57cec5SDimitry Andric   {{"arch8"}, 8}, {{"z10"}, 8},
1020b57cec5SDimitry Andric   {{"arch9"}, 9}, {{"z196"}, 9},
1030b57cec5SDimitry Andric   {{"arch10"}, 10}, {{"zEC12"}, 10},
1040b57cec5SDimitry Andric   {{"arch11"}, 11}, {{"z13"}, 11},
1050b57cec5SDimitry Andric   {{"arch12"}, 12}, {{"z14"}, 12},
106fe6060f1SDimitry Andric   {{"arch13"}, 13}, {{"z15"}, 13},
10781ad6265SDimitry Andric   {{"arch14"}, 14}, {{"z16"}, 14},
1080b57cec5SDimitry Andric };
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric int SystemZTargetInfo::getISARevision(StringRef Name) const {
1110b57cec5SDimitry Andric   const auto Rev =
1120b57cec5SDimitry Andric       llvm::find_if(ISARevisions, [Name](const ISANameRevision &CR) {
1130b57cec5SDimitry Andric         return CR.Name == Name;
1140b57cec5SDimitry Andric       });
1150b57cec5SDimitry Andric   if (Rev == std::end(ISARevisions))
1160b57cec5SDimitry Andric     return -1;
1170b57cec5SDimitry Andric   return Rev->ISARevisionID;
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric void SystemZTargetInfo::fillValidCPUList(
1210b57cec5SDimitry Andric     SmallVectorImpl<StringRef> &Values) const {
1220b57cec5SDimitry Andric   for (const ISANameRevision &Rev : ISARevisions)
1230b57cec5SDimitry Andric     Values.push_back(Rev.Name);
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric bool SystemZTargetInfo::hasFeature(StringRef Feature) const {
1270b57cec5SDimitry Andric   return llvm::StringSwitch<bool>(Feature)
1280b57cec5SDimitry Andric       .Case("systemz", true)
1290b57cec5SDimitry Andric       .Case("arch8", ISARevision >= 8)
1300b57cec5SDimitry Andric       .Case("arch9", ISARevision >= 9)
1310b57cec5SDimitry Andric       .Case("arch10", ISARevision >= 10)
1320b57cec5SDimitry Andric       .Case("arch11", ISARevision >= 11)
1330b57cec5SDimitry Andric       .Case("arch12", ISARevision >= 12)
1340b57cec5SDimitry Andric       .Case("arch13", ISARevision >= 13)
135fe6060f1SDimitry Andric       .Case("arch14", ISARevision >= 14)
1360b57cec5SDimitry Andric       .Case("htm", HasTransactionalExecution)
1370b57cec5SDimitry Andric       .Case("vx", HasVector)
1380b57cec5SDimitry Andric       .Default(false);
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric 
141*0fca6ea1SDimitry Andric unsigned SystemZTargetInfo::getMinGlobalAlign(uint64_t Size,
142*0fca6ea1SDimitry Andric                                               bool HasNonWeakDef) const {
143*0fca6ea1SDimitry Andric   // Don't enforce the minimum alignment on an external or weak symbol if
144*0fca6ea1SDimitry Andric   // -munaligned-symbols is passed.
145*0fca6ea1SDimitry Andric   if (UnalignedSymbols && !HasNonWeakDef)
146*0fca6ea1SDimitry Andric     return 0;
147*0fca6ea1SDimitry Andric 
148*0fca6ea1SDimitry Andric   return MinGlobalAlign;
149*0fca6ea1SDimitry Andric }
150*0fca6ea1SDimitry Andric 
1510b57cec5SDimitry Andric void SystemZTargetInfo::getTargetDefines(const LangOptions &Opts,
1520b57cec5SDimitry Andric                                          MacroBuilder &Builder) const {
1530b57cec5SDimitry Andric   Builder.defineMacro("__s390__");
1540b57cec5SDimitry Andric   Builder.defineMacro("__s390x__");
1550b57cec5SDimitry Andric   Builder.defineMacro("__zarch__");
1560b57cec5SDimitry Andric   Builder.defineMacro("__LONG_DOUBLE_128__");
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   Builder.defineMacro("__ARCH__", Twine(ISARevision));
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
1610b57cec5SDimitry Andric   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
1620b57cec5SDimitry Andric   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
1630b57cec5SDimitry Andric   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   if (HasTransactionalExecution)
1660b57cec5SDimitry Andric     Builder.defineMacro("__HTM__");
1670b57cec5SDimitry Andric   if (HasVector)
1680b57cec5SDimitry Andric     Builder.defineMacro("__VX__");
1690b57cec5SDimitry Andric   if (Opts.ZVector)
170fe6060f1SDimitry Andric     Builder.defineMacro("__VEC__", "10304");
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric ArrayRef<Builtin::Info> SystemZTargetInfo::getTargetBuiltins() const {
174bdd1243dSDimitry Andric   return llvm::ArrayRef(BuiltinInfo, clang::SystemZ::LastTSBuiltin -
1750b57cec5SDimitry Andric                                          Builtin::FirstTSBuiltin);
1760b57cec5SDimitry Andric }
177