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
getGCCRegNames() const480b57cec5SDimitry Andric ArrayRef<const char *> SystemZTargetInfo::getGCCRegNames() const {
49bdd1243dSDimitry Andric return llvm::ArrayRef(GCCRegNames);
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric
getGCCAddlRegNames() const520b57cec5SDimitry Andric ArrayRef<TargetInfo::AddlRegName> SystemZTargetInfo::getGCCAddlRegNames() const {
53bdd1243dSDimitry Andric return llvm::ArrayRef(GCCAddlRegNames);
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric
validateAsmConstraint(const char * & Name,TargetInfo::ConstraintInfo & Info) const560b57cec5SDimitry 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
getISARevision(StringRef Name) const1100b57cec5SDimitry 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
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const1200b57cec5SDimitry 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
hasFeature(StringRef Feature) const1260b57cec5SDimitry 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
getMinGlobalAlign(uint64_t Size,bool HasNonWeakDef) const141*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
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const1510b57cec5SDimitry 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
getTargetBuiltins() const1730b57cec5SDimitry Andric ArrayRef<Builtin::Info> SystemZTargetInfo::getTargetBuiltins() const {
174bdd1243dSDimitry Andric return llvm::ArrayRef(BuiltinInfo, clang::SystemZ::LastTSBuiltin -
1750b57cec5SDimitry Andric Builtin::FirstTSBuiltin);
1760b57cec5SDimitry Andric }
177