//===--- SystemZ.h - Declare SystemZ target feature support -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares SystemZ TargetInfo objects.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H
#define LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Compiler.h"
namespace clang {
namespace targets {
class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
static const char *const GCCRegNames[];
std::string CPU;
int ISARevision;
bool HasTransactionalExecution;
bool HasVector;
bool SoftFloat;
public:
SystemZTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple), CPU("z10"), ISARevision(8),
HasTransactionalExecution(false), HasVector(false), SoftFloat(false) {
IntMaxType = SignedLong;
Int64Type = SignedLong;
TLSSupported = true;
IntWidth = IntAlign = 32;
LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64;
PointerWidth = PointerAlign = 64;
LongDoubleWidth = 128;
LongDoubleAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEquad();
DefaultAlignForAttributeAligned = 64;
MinGlobalAlign = 16;
if (Triple.isOSzOS()) {
// All vector types are default aligned on an 8-byte boundary, even if the
// vector facility is not available. That is different from Linux.
MaxVectorAlign = 64;
// Compared to Linux/ELF, the data layout differs only in some details:
// - name mangling is GOFF
// - 128 bit vector types are 64 bit aligned
resetDataLayout(
"E-m:l-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64");
} else
resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64");
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
HasStrictFP = true;
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
ArrayRef<Builtin::Info> getTargetBuiltins() const override;
ArrayRef<const char *> getGCCRegNames() const override;
ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
// No aliases.
return None;
}
ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override;
bool isSPRegName(StringRef RegName) const override {
return RegName.equals("r15");
}
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override;
std::string convertConstraint(const char *&Constraint) const override {
switch (Constraint[0]) {
case 'p': // Keep 'p' constraint.
return std::string("p");
case 'Z':
switch (Constraint[1]) {
case 'Q': // Address with base and unsigned 12-bit displacement
case 'R': // Likewise, plus an index
case 'S': // Address with base and signed 20-bit displacement
case 'T': // Likewise, plus an index
// "^" hints llvm that this is a 2 letter constraint.
// "Constraint++" is used to promote the string iterator
// to the next constraint.
return std::string("^") + std::string(Constraint++, 2);
default:
break;
}
break;
default:
break;
}
return TargetInfo::convertConstraint(Constraint);
}
const char *getClobbers() const override {
// FIXME: Is this really right?
return "";
}
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::SystemZBuiltinVaList;
}
int getISARevision(StringRef Name) const;
bool isValidCPUName(StringRef Name) const override {
return getISARevision(Name) != -1;
}
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
bool isValidTuneCPUName(StringRef Name) const override {
return isValidCPUName(Name);
}
void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override {
fillValidCPUList(Values);
}
bool setCPU(const std::string &Name) override {
CPU = Name;
ISARevision = getISARevision(CPU);
return ISARevision != -1;
}
bool
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
const std::vector<std::string> &FeaturesVec) const override {
int ISARevision = getISARevision(CPU);
if (ISARevision >= 10)
Features["transactional-execution"] = true;
if (ISARevision >= 11)
Features["vector"] = true;
if (ISARevision >= 12)
Features["vector-enhancements-1"] = true;
if (ISARevision >= 13)
Features["vector-enhancements-2"] = true;
if (ISARevision >= 14)
Features["nnp-assist"] = true;
return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}
bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override {
HasTransactionalExecution = false;
HasVector = false;
SoftFloat = false;
for (const auto &Feature : Features) {
if (Feature == "+transactional-execution")
HasTransactionalExecution = true;
else if (Feature == "+vector")
HasVector = true;
else if (Feature == "+soft-float")
SoftFloat = true;
}
HasVector &= !SoftFloat;
// If we use the vector ABI, vector types are 64-bit aligned.
if (HasVector && !getTriple().isOSzOS()) {
MaxVectorAlign = 64;
resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64"
"-v128:64-a:8:16-n32:64");
}
return true;
}
bool hasFeature(StringRef Feature) const override;
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
switch (CC) {
case CC_C:
case CC_Swift:
case CC_OpenCLKernel:
return CCCR_OK;
case CC_SwiftAsync:
return CCCR_Error;
default:
return CCCR_Warning;
}
}
StringRef getABI() const override {
if (HasVector)
return "vector";
return "";
}
const char *getLongDoubleMangling() const override { return "g"; }
bool hasBitIntType() const override { return true; }
int getEHDataRegisterNumber(unsigned RegNo) const override {
return RegNo < 4 ? 6 + RegNo : -1;
}
};
} // namespace targets
} // namespace clang
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H