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