clang 20.0.0git
SystemZ.cpp
Go to the documentation of this file.
1//===- SystemZ.cpp --------------------------------------------------------===//
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#include "ABIInfoImpl.h"
10#include "TargetInfo.h"
12#include "llvm/IR/IntrinsicsS390.h"
13
14using namespace clang;
15using namespace clang::CodeGen;
16
17//===----------------------------------------------------------------------===//
18// SystemZ ABI Implementation
19//===----------------------------------------------------------------------===//
20
21namespace {
22
23class SystemZABIInfo : public ABIInfo {
24 bool HasVector;
25 bool IsSoftFloatABI;
26
27public:
28 SystemZABIInfo(CodeGenTypes &CGT, bool HV, bool SF)
29 : ABIInfo(CGT), HasVector(HV), IsSoftFloatABI(SF) {}
30
32 bool isCompoundType(QualType Ty) const;
33 bool isVectorArgumentType(QualType Ty) const;
34 bool isFPArgumentType(QualType Ty) const;
35 QualType GetSingleElementType(QualType Ty) const;
36
39
40 void computeInfo(CGFunctionInfo &FI) const override;
41 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
42 AggValueSlot Slot) const override;
43};
44
45class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
46 ASTContext &Ctx;
47
48 // These are used for speeding up the search for a visible vector ABI.
49 mutable bool HasVisibleVecABIFlag = false;
50 mutable std::set<const Type *> SeenTypes;
51
52 // Returns true (the first time) if Ty is, or is found to include, a vector
53 // type that exposes the vector ABI. This is any vector >=16 bytes which
54 // with vector support are aligned to only 8 bytes. When IsParam is true,
55 // the type belongs to a value as passed between functions. If it is a
56 // vector <=16 bytes it will be passed in a vector register (if supported).
57 bool isVectorTypeBased(const Type *Ty, bool IsParam) const;
58
59public:
60 SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI)
62 std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)),
63 Ctx(CGT.getContext()) {
64 SwiftInfo =
65 std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false);
66 }
67
68 // The vector ABI is different when the vector facility is present and when
69 // a module e.g. defines an externally visible vector variable, a flag
70 // indicating a visible vector ABI is added. Eventually this will result in
71 // a GNU attribute indicating the vector ABI of the module. Ty is the type
72 // of a variable or function parameter that is globally visible.
73 void handleExternallyVisibleObjABI(const Type *Ty, CodeGen::CodeGenModule &M,
74 bool IsParam) const {
75 if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty, IsParam)) {
76 M.getModule().addModuleFlag(llvm::Module::Warning,
77 "s390x-visible-vector-ABI", 1);
78 HasVisibleVecABIFlag = true;
79 }
80 }
81
82 void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
83 CodeGen::CodeGenModule &M) const override {
84 if (!D)
85 return;
86
87 // Check if the vector ABI becomes visible by an externally visible
88 // variable or function.
89 if (const auto *VD = dyn_cast<VarDecl>(D)) {
90 if (VD->isExternallyVisible())
91 handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M,
92 /*IsParam*/false);
93 }
94 else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
95 if (FD->isExternallyVisible())
96 handleExternallyVisibleObjABI(FD->getType().getTypePtr(), M,
97 /*IsParam*/false);
98 }
99 }
100
101 llvm::Value *testFPKind(llvm::Value *V, unsigned BuiltinID,
102 CGBuilderTy &Builder,
103 CodeGenModule &CGM) const override {
104 assert(V->getType()->isFloatingPointTy() && "V should have an FP type.");
105 // Only use TDC in constrained FP mode.
106 if (!Builder.getIsFPConstrained())
107 return nullptr;
108
109 llvm::Type *Ty = V->getType();
110 if (Ty->isFloatTy() || Ty->isDoubleTy() || Ty->isFP128Ty()) {
111 llvm::Module &M = CGM.getModule();
112 auto &Ctx = M.getContext();
113 llvm::Function *TDCFunc = llvm::Intrinsic::getOrInsertDeclaration(
114 &M, llvm::Intrinsic::s390_tdc, Ty);
115 unsigned TDCBits = 0;
116 switch (BuiltinID) {
117 case Builtin::BI__builtin_isnan:
118 TDCBits = 0xf;
119 break;
120 case Builtin::BIfinite:
121 case Builtin::BI__finite:
122 case Builtin::BIfinitef:
123 case Builtin::BI__finitef:
124 case Builtin::BIfinitel:
125 case Builtin::BI__finitel:
126 case Builtin::BI__builtin_isfinite:
127 TDCBits = 0xfc0;
128 break;
129 case Builtin::BI__builtin_isinf:
130 TDCBits = 0x30;
131 break;
132 default:
133 break;
134 }
135 if (TDCBits)
136 return Builder.CreateCall(
137 TDCFunc,
138 {V, llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), TDCBits)});
139 }
140 return nullptr;
141 }
142};
143}
144
145bool SystemZABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const {
146 // Treat an enum type as its underlying type.
147 if (const EnumType *EnumTy = Ty->getAs<EnumType>())
148 Ty = EnumTy->getDecl()->getIntegerType();
149
150 // Promotable integer types are required to be promoted by the ABI.
152 return true;
153
154 if (const auto *EIT = Ty->getAs<BitIntType>())
155 if (EIT->getNumBits() < 64)
156 return true;
157
158 // 32-bit values must also be promoted.
159 if (const