1*06c3fb27SDimitry Andric //===- SystemZ.cpp --------------------------------------------------------===//
2*06c3fb27SDimitry Andric //
3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*06c3fb27SDimitry Andric //
7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
8*06c3fb27SDimitry Andric 
9*06c3fb27SDimitry Andric #include "ABIInfoImpl.h"
10*06c3fb27SDimitry Andric #include "TargetInfo.h"
11*06c3fb27SDimitry Andric #include "clang/Basic/Builtins.h"
12*06c3fb27SDimitry Andric #include "llvm/IR/IntrinsicsS390.h"
13*06c3fb27SDimitry Andric 
14*06c3fb27SDimitry Andric using namespace clang;
15*06c3fb27SDimitry Andric using namespace clang::CodeGen;
16*06c3fb27SDimitry Andric 
17*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
18*06c3fb27SDimitry Andric // SystemZ ABI Implementation
19*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
20*06c3fb27SDimitry Andric 
21*06c3fb27SDimitry Andric namespace {
22*06c3fb27SDimitry Andric 
23*06c3fb27SDimitry Andric class SystemZABIInfo : public ABIInfo {
24*06c3fb27SDimitry Andric   bool HasVector;
25*06c3fb27SDimitry Andric   bool IsSoftFloatABI;
26*06c3fb27SDimitry Andric 
27*06c3fb27SDimitry Andric public:
SystemZABIInfo(CodeGenTypes & CGT,bool HV,bool SF)28*06c3fb27SDimitry Andric   SystemZABIInfo(CodeGenTypes &CGT, bool HV, bool SF)
29*06c3fb27SDimitry Andric       : ABIInfo(CGT), HasVector(HV), IsSoftFloatABI(SF) {}
30*06c3fb27SDimitry Andric 
31*06c3fb27SDimitry Andric   bool isPromotableIntegerTypeForABI(QualType Ty) const;
32*06c3fb27SDimitry Andric   bool isCompoundType(QualType Ty) const;
33*06c3fb27SDimitry Andric   bool isVectorArgumentType(QualType Ty) const;
34*06c3fb27SDimitry Andric   bool isFPArgumentType(QualType Ty) const;
35*06c3fb27SDimitry Andric   QualType GetSingleElementType(QualType Ty) const;
36*06c3fb27SDimitry Andric 
37*06c3fb27SDimitry Andric   ABIArgInfo classifyReturnType(QualType RetTy) const;
38*06c3fb27SDimitry Andric   ABIArgInfo classifyArgumentType(QualType ArgTy) const;
39*06c3fb27SDimitry Andric 
40*06c3fb27SDimitry Andric   void computeInfo(CGFunctionInfo &FI) const override;
41*06c3fb27SDimitry Andric   Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
42*06c3fb27SDimitry Andric                     QualType Ty) const override;
43*06c3fb27SDimitry Andric };
44*06c3fb27SDimitry Andric 
45*06c3fb27SDimitry Andric class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
46*06c3fb27SDimitry Andric   ASTContext &Ctx;
47*06c3fb27SDimitry Andric 
48*06c3fb27SDimitry Andric   // These are used for speeding up the search for a visible vector ABI.
49*06c3fb27SDimitry Andric   mutable bool HasVisibleVecABIFlag = false;
50*06c3fb27SDimitry Andric   mutable std::set<const Type *> SeenTypes;
51*06c3fb27SDimitry Andric 
52*06c3fb27SDimitry Andric   // Returns true (the first time) if Ty is, or is found to include, a vector
53*06c3fb27SDimitry Andric   // type that exposes the vector ABI. This is any vector >=16 bytes which
54*06c3fb27SDimitry Andric   // with vector support are aligned to only 8 bytes. When IsParam is true,
55*06c3fb27SDimitry Andric   // the type belongs to a value as passed between functions. If it is a
56*06c3fb27SDimitry Andric   // vector <=16 bytes it will be passed in a vector register (if supported).
57*06c3fb27SDimitry Andric   bool isVectorTypeBased(const Type *Ty, bool IsParam) const;
58*06c3fb27SDimitry Andric 
59*06c3fb27SDimitry Andric public:
SystemZTargetCodeGenInfo(CodeGenTypes & CGT,bool HasVector,bool SoftFloatABI)60*06c3fb27SDimitry Andric   SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI)
61*06c3fb27SDimitry Andric       : TargetCodeGenInfo(
62*06c3fb27SDimitry Andric             std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)),
63*06c3fb27SDimitry Andric             Ctx(CGT.getContext()) {
64*06c3fb27SDimitry Andric     SwiftInfo =
65*06c3fb27SDimitry Andric         std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false);
66*06c3fb27SDimitry Andric   }
67*06c3fb27SDimitry Andric 
68*06c3fb27SDimitry Andric   // The vector ABI is different when the vector facility is present and when
69*06c3fb27SDimitry Andric   // a module e.g. defines an externally visible vector variable, a flag
70*06c3fb27SDimitry Andric   // indicating a visible vector ABI is added. Eventually this will result in
71*06c3fb27SDimitry Andric   // a GNU attribute indicating the vector ABI of the module.  Ty is the type
72*06c3fb27SDimitry Andric   // of a variable or function parameter that is globally visible.
handleExternallyVisibleObjABI(const Type * Ty,CodeGen::CodeGenModule & M,bool IsParam) const73*06c3fb27SDimitry Andric   void handleExternallyVisibleObjABI(const Type *Ty, CodeGen::CodeGenModule &M,
74*06c3fb27SDimitry Andric                                      bool IsParam) const {
75*06c3fb27SDimitry Andric     if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty, IsParam)) {
76*06c3fb27SDimitry Andric       M.getModule().addModuleFlag(llvm::Module::Warning,
77*06c3fb27SDimitry Andric                                   "s390x-visible-vector-ABI", 1);
78*06c3fb27SDimitry Andric       HasVisibleVecABIFlag = true;
79*06c3fb27SDimitry Andric     }
80*06c3fb27SDimitry Andric   }
81*06c3fb27SDimitry Andric 
setTargetAttributes(const Decl * D,llvm::GlobalValue * GV,CodeGen::CodeGenModule & M) const82*06c3fb27SDimitry Andric   void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
83*06c3fb27SDimitry Andric                            CodeGen::CodeGenModule &M) const override {
84*06c3fb27SDimitry Andric     if (!D)
85*06c3fb27SDimitry Andric       return;
86*06c3fb27SDimitry Andric 
87*06c3fb27SDimitry Andric     // Check if the vector ABI becomes visible by an externally visible
88*06c3fb27SDimitry Andric     // variable or function.
89*06c3fb27SDimitry Andric     if (const auto *VD = dyn_cast<VarDecl>(D)) {
90*06c3fb27SDimitry Andric       if (VD->isExternallyVisible())
91*06c3fb27SDimitry Andric         handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M,
92*06c3fb27SDimitry Andric                                       /*IsParam*/false);
93*06c3fb27SDimitry Andric     }
94*06c3fb27SDimitry Andric     else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
95*06c3fb27SDimitry Andric       if (FD->isExternallyVisible())
96*06c3fb27SDimitry Andric         handleExternallyVisibleObjABI(FD->getType().getTypePtr(), M,
97*06c3fb27SDimitry Andric                                       /*IsParam*/false);
98*06c3fb27SDimitry Andric     }
99*06c3fb27SDimitry Andric   }
100*06c3fb27SDimitry Andric 
testFPKind(llvm::Value * V,unsigned BuiltinID,CGBuilderTy & Builder,CodeGenModule & CGM) const101*06c3fb27SDimitry Andric   llvm::Value *testFPKind(llvm::Value *V, unsigned BuiltinID,
102*06c3fb27SDimitry Andric                           CGBuilderTy &Builder,
103*06c3fb27SDimitry Andric                           CodeGenModule &CGM) const override {
104*06c3fb27SDimitry Andric     assert(V->getType()->isFloatingPointTy() && "V should have an FP type.");
105*06c3fb27SDimitry Andric     // Only use TDC in constrained FP mode.
106*06c3fb27SDimitry Andric     if (!Builder.getIsFPConstrained())
107*06c3fb27SDimitry Andric       return nullptr;
108*06c3fb27SDimitry Andric 
109*06c3fb27SDimitry Andric     llvm::Type *Ty = V->getType();
110*06c3fb27SDimitry Andric     if (Ty->isFloatTy() || Ty->isDoubleTy() || Ty->isFP128Ty()) {
111*06c3fb27SDimitry Andric       llvm::Module &M = CGM.getModule();
112*06c3fb27SDimitry Andric       auto &Ctx = M.getContext();
113*06c3fb27SDimitry Andric       llvm::Function *TDCFunc =
114*06c3fb27SDimitry Andric           llvm::Intrinsic::getDeclaration(&M, llvm::Intrinsic::s390_tdc, Ty);
115*06c3fb27SDimitry Andric       unsigned TDCBits = 0;
116*06c3fb27SDimitry Andric       switch (BuiltinID) {
117*06c3fb27SDimitry Andric       case Builtin::BI__builtin_isnan:
118*06c3fb27SDimitry Andric         TDCBits = 0xf;
119*06c3fb27SDimitry Andric         break;
120*06c3fb27SDimitry Andric       case Builtin::BIfinite:
121*06c3fb27SDimitry Andric       case Builtin::BI__finite:
122*06c3fb27SDimitry Andric       case Builtin::BIfinitef:
123*06c3fb27SDimitry Andric       case Builtin::BI__finitef:
124*06c3fb27SDimitry Andric       case Builtin::BIfinitel:
125*06c3fb27SDimitry Andric       case Builtin::BI__finitel:
126*06c3fb27SDimitry Andric       case Builtin::BI__builtin_isfinite:
127*06c3fb27SDimitry Andric         TDCBits = 0xfc0;
128*06c3fb27SDimitry Andric         break;
129*06c3fb27SDimitry Andric       case Builtin::BI__builtin_isinf:
130*06c3fb27SDimitry Andric         TDCBits = 0x30;
131*06c3fb27SDimitry Andric         break;
132*06c3fb27SDimitry Andric       default:
133*06c3fb27SDimitry Andric         break;
134*06c3fb27SDimitry Andric       }
135*06c3fb27SDimitry Andric       if (TDCBits)
136*06c3fb27SDimitry Andric         return Builder.CreateCall(
137*06c3fb27SDimitry Andric             TDCFunc,
138*06c3fb27SDimitry Andric             {V, llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), TDCBits)});
139*06c3fb27SDimitry Andric     }
140*06c3fb27SDimitry Andric     return nullptr;
141*06c3fb27SDimitry Andric   }
142*06c3fb27SDimitry Andric };
143*06c3fb27SDimitry Andric }
144*06c3fb27SDimitry Andric 
isPromotableIntegerTypeForABI(QualType Ty) const145*06c3fb27SDimitry Andric bool SystemZABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const {
146*06c3fb27SDimitry Andric   // Treat an enum type as its underlying type.
147*06c3fb27SDimitry Andric   if (const EnumType *EnumTy = Ty->getAs<EnumType>())
148*06c3fb27SDimitry Andric     Ty = EnumTy->getDecl()->getIntegerType();
149*06c3fb27SDimitry Andric 
150*06c3fb27SDimitry Andric   // Promotable integer types are required to be promoted by the ABI.
151*06c3fb27SDimitry Andric   if (ABIInfo::isPromotableIntegerTypeForABI(Ty))
152*06c3fb27SDimitry Andric     return true;
153*06c3fb27SDimitry Andric 
154*06c3fb27SDimitry Andric   if (const auto *EIT = Ty->getAs<BitIntType>())
155*06c3fb27SDimitry Andric     if (EIT->getNumBits() < 64)
156*06c3fb27SDimitry Andric       return true;
157*06c3fb27SDimitry Andric 
158*06c3fb27SDimitry Andric   // 32-bit values must also be promoted.
159*06c3fb27SDimitry Andric   if (const BuiltinType *BT = Ty->getAs<BuiltinType>())
160*06c3fb27SDimitry Andric     switch (BT->getKind()) {
161*06c3fb27SDimitry Andric     case BuiltinType::Int:
162*06c3fb27SDimitry Andric     case BuiltinType::UInt:
163*06c3fb27SDimitry Andric       return true;
164*06c3fb27SDimitry Andric     default:
165*06c3fb27SDimitry Andric       return false;
166*06c3fb27SDimitry Andric     }
167*06c3fb27SDimitry Andric   return false;
168*06c3fb27SDimitry Andric }
169*06c3fb27SDimitry Andric 
isCompoundType(QualType Ty) const170*06c3fb27SDimitry Andric bool SystemZABIInfo::isCompoundType(QualType Ty) const {
171*06c3fb27SDimitry Andric   return (Ty->isAnyComplexType() ||
172*06c3fb27SDimitry Andric           Ty->isVectorType() ||
173*06c3fb27SDimitry Andric           isAggregateTypeForABI(Ty));
174*06c3fb27SDimitry Andric }
175*06c3fb27SDimitry Andric 
isVectorArgumentType(QualType Ty) const176*06c3fb27SDimitry Andric bool SystemZABIInfo::isVectorArgumentType(QualType Ty) const {
177*06c3fb27SDimitry Andric   return (HasVector &&
178*06c3fb27SDimitry Andric           Ty->isVectorType() &&
179*06c3fb27SDimitry Andric           getContext().getTypeSize(Ty) <= 128);
180*06c3fb27SDimitry Andric }
181*06c3fb27SDimitry Andric 
isFPArgumentType(QualType Ty) const182*06c3fb27SDimitry Andric bool SystemZABIInfo::isFPArgumentType(QualType Ty) const {
183*06c3fb27SDimitry Andric   if (IsSoftFloatABI)
184*06c3fb27SDimitry Andric     return false;
185*06c3fb27SDimitry Andric 
186*06c3fb27SDimitry Andric   if (const BuiltinType *BT = Ty->getAs<BuiltinType>())
187*06c3fb27SDimitry Andric     switch (BT->getKind()) {
188*06c3fb27SDimitry Andric     case BuiltinType::Float:
189*06c3fb27SDimitry Andric     case BuiltinType::Double:
190*06c3fb27SDimitry Andric       return true;
191*06c3fb27SDimitry Andric     default:
192*06c3fb27SDimitry Andric       return false;
193*06c3fb27SDimitry Andric     }
194*06c3fb27SDimitry Andric 
195*06c3fb27SDimitry Andric   return false;
196*06c3fb27SDimitry Andric }
197*06c3fb27SDimitry Andric 
GetSingleElementType(QualType Ty) const198*06c3fb27SDimitry Andric QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const {
199*06c3fb27SDimitry Andric   const RecordType *RT = Ty->getAs<RecordType>();
200*06c3fb27SDimitry Andric 
201*06c3fb27SDimitry Andric   if (RT && RT->isStructureOrClassType()) {
202*06c3fb27SDimitry Andric     const RecordDecl *RD = RT->getDecl();
203*06c3fb27SDimitry Andric     QualType Found;
204*06c3fb27SDimitry Andric 
205*06c3fb27SDimitry Andric     // If this is a C++ record, check the bases first.
206*06c3fb27SDimitry Andric     if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
207*06c3fb27SDimitry Andric       if (CXXRD->hasDefinition())
208*06c3fb27SDimitry Andric         for (const auto &I : CXXRD->bases()) {
209*06c3fb27SDimitry Andric           QualType Base = I.getType();
210*06c3fb27SDimitry Andric 
211*06c3fb27SDimitry Andric           // Empty bases don't affect things either way.
212*06c3fb27SDimitry Andric           if (isEmptyRecord(getContext(), Base, true))
213*06c3fb27SDimitry Andric             continue;
214*06c3fb27SDimitry Andric 
215*06c3fb27SDimitry Andric           if (!Found.isNull())
216*06c3fb27SDimitry Andric             return Ty;
217*06c3fb27SDimitry Andric           Found = GetSingleElementType(Base);
218*06c3fb27SDimitry Andric         }
219*06c3fb27SDimitry Andric 
220*06c3fb27SDimitry Andric     // Check the fields.
221*06c3fb27SDimitry Andric     for (const auto *FD : RD->fields()) {
222*06c3fb27SDimitry Andric       // Unlike isSingleElementStruct(), empty structure and array fields
223*06c3fb27SDimitry Andric       // do count.  So do anonymous bitfields that aren't zero-sized.
224*06c3fb27SDimitry Andric 
225*06c3fb27SDimitry Andric       // Like isSingleElementStruct(), ignore C++20 empty data members.
226*06c3fb27SDimitry Andric       if (FD->hasAttr<NoUniqueAddressAttr>() &&
227*06c3fb27SDimitry Andric           isEmptyRecord(getContext(), FD->getType(), true))
228*06c3fb27SDimitry Andric         continue;
229*06c3fb27SDimitry Andric 
230*06c3fb27SDimitry Andric       // Unlike isSingleElementStruct(), arrays do not count.
231*06c3fb27SDimitry Andric       // Nested structures still do though.
232*06c3fb27SDimitry Andric       if (!Found.isNull())
233*06c3fb27SDimitry Andric         return Ty;
234*06c3fb27SDimitry Andric       Found = GetSingleElementType(FD->getType());
235*06c3fb27SDimitry Andric     }
236*06c3fb27SDimitry Andric 
237*06c3fb27SDimitry Andric     // Unlike isSingleElementStruct(), trailing padding is allowed.
238*06c3fb27SDimitry Andric     // An 8-byte aligned struct s { float f; } is passed as a double.
239*06c3fb27SDimitry Andric     if (!Found.isNull())
240*06c3fb27SDimitry Andric       return Found;
241*06c3fb27SDimitry Andric   }
242*06c3fb27SDimitry Andric 
243*06c3fb27SDimitry Andric   return Ty;
244*06c3fb27SDimitry Andric }
245*06c3fb27SDimitry Andric 
EmitVAArg(CodeGenFunction & CGF,Address VAListAddr,QualType Ty) const246*06c3fb27SDimitry Andric Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
247*06c3fb27SDimitry Andric                                   QualType Ty) const {
248*06c3fb27SDimitry Andric   // Assume that va_list type is correct; should be pointer to LLVM type:
249*06c3fb27SDimitry Andric   // struct {
250*06c3fb27SDimitry Andric   //   i64 __gpr;
251*06c3fb27SDimitry Andric   //   i64 __fpr;
252*06c3fb27SDimitry Andric   //   i8 *__overflow_arg_area;
253*06c3fb27SDimitry Andric   //   i8 *__reg_save_area;
254*06c3fb27SDimitry Andric   // };
255*06c3fb27SDimitry Andric 
256*06c3fb27SDimitry Andric   // Every non-vector argument occupies 8 bytes and is passed by preference
257*06c3fb27SDimitry Andric   // in either GPRs or FPRs.  Vector arguments occupy 8 or 16 bytes and are
258*06c3fb27SDimitry Andric   // always passed on the stack.
259*06c3fb27SDimitry Andric   const SystemZTargetCodeGenInfo &SZCGI =
260*06c3fb27SDimitry Andric       static_cast<const SystemZTargetCodeGenInfo &>(
261*06c3fb27SDimitry Andric           CGT.getCGM().getTargetCodeGenInfo());
262*06c3fb27SDimitry Andric   Ty = getContext().getCanonicalType(Ty);
263*06c3fb27SDimitry Andric   auto TyInfo = getContext().getTypeInfoInChars(Ty);
264*06c3fb27SDimitry Andric   llvm::Type *ArgTy = CGF.ConvertTypeForMem(Ty);
265*06c3fb27SDimitry Andric   llvm::Type *DirectTy = ArgTy;
266*06c3fb27SDimitry Andric   ABIArgInfo AI = classifyArgumentType(Ty);
267*06c3fb27SDimitry Andric   bool IsIndirect = AI.isIndirect();
268*06c3fb27SDimitry Andric   bool InFPRs = false;
269*06c3fb27SDimitry Andric   bool IsVector = false;
270*06c3fb27SDimitry Andric   CharUnits UnpaddedSize;
271*06c3fb27SDimitry Andric   CharUnits DirectAlign;
272*06c3fb27SDimitry Andric   SZCGI.handleExternallyVisibleObjABI(Ty.getTypePtr(), CGT.getCGM(),
273*06c3fb27SDimitry Andric                                       /*IsParam*/true);
274*06c3fb27SDimitry Andric   if (IsIndirect) {
275*06c3fb27SDimitry Andric     DirectTy = llvm::PointerType::getUnqual(DirectTy);
276*06c3fb27SDimitry Andric     UnpaddedSize = DirectAlign = CharUnits::fromQuantity(8);
277*06c3fb27SDimitry Andric   } else {
278*06c3fb27SDimitry Andric     if (AI.getCoerceToType())
279*06c3fb27SDimitry Andric       ArgTy = AI.getCoerceToType();
280*06c3fb27SDimitry Andric     InFPRs = (!IsSoftFloatABI && (ArgTy->isFloatTy() || ArgTy->isDoubleTy()));
281*06c3fb27SDimitry Andric     IsVector = ArgTy->isVectorTy();
282*06c3fb27SDimitry Andric     UnpaddedSize = TyInfo.Width;
283*06c3fb27SDimitry Andric     DirectAlign = TyInfo.Align;
284*06c3fb27SDimitry Andric   }
285*06c3fb27SDimitry Andric   CharUnits PaddedSize = CharUnits::fromQuantity(8);
286*06c3fb27SDimitry Andric   if (IsVector && UnpaddedSize > PaddedSize)
287*06c3fb27SDimitry Andric     PaddedSize = CharUnits::fromQuantity(16);
288*06c3fb27SDimitry Andric   assert((UnpaddedSize <= PaddedSize) && "Invalid argument size.");
289*06c3fb27SDimitry Andric 
290*06c3fb27SDimitry Andric   CharUnits Padding = (PaddedSize - UnpaddedSize);
291*06c3fb27SDimitry Andric 
292*06c3fb27SDimitry Andric   llvm::Type *IndexTy = CGF.Int64Ty;
293*06c3fb27SDimitry Andric   llvm::Value *PaddedSizeV =
294*06c3fb27SDimitry Andric     llvm::ConstantInt::get(IndexTy, PaddedSize.getQuantity());
295*06c3fb27SDimitry Andric 
296*06c3fb27SDimitry Andric   if (IsVector) {
297*06c3fb27SDimitry Andric     // Work out the address of a vector argument on the stack.
298*06c3fb27SDimitry Andric     // Vector arguments are always passed in the high bits of a
299*06c3fb27SDimitry Andric     // single (8 byte) or double (16 byte) stack slot.
300*06c3fb27SDimitry Andric     Address OverflowArgAreaPtr =
301*06c3fb27SDimitry Andric         CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_ptr");
302*06c3fb27SDimitry Andric     Address OverflowArgArea =
303*06c3fb27SDimitry Andric         Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"),
304*06c3fb27SDimitry Andric                 CGF.Int8Ty, TyInfo.Align);
305*06c3fb27SDimitry Andric     Address MemAddr = OverflowArgArea.withElementType(DirectTy);
306*06c3fb27SDimitry Andric 
307*06c3fb27SDimitry Andric     // Update overflow_arg_area_ptr pointer
308*06c3fb27SDimitry Andric     llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP(
309*06c3fb27SDimitry Andric         OverflowArgArea.getElementType(), OverflowArgArea.getPointer(),
310*06c3fb27SDimitry Andric         PaddedSizeV, "overflow_arg_area");
311*06c3fb27SDimitry Andric     CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr);
312*06c3fb27SDimitry Andric 
313*06c3fb27SDimitry Andric     return MemAddr;
314*06c3fb27SDimitry Andric   }
315*06c3fb27SDimitry Andric 
316*06c3fb27SDimitry Andric   assert(PaddedSize.getQuantity() == 8);
317*06c3fb27SDimitry Andric 
318*06c3fb27SDimitry Andric   unsigned MaxRegs, RegCountField, RegSaveIndex;
319*06c3fb27SDimitry Andric   CharUnits RegPadding;
320*06c3fb27SDimitry Andric   if (InFPRs) {
321*06c3fb27SDimitry Andric     MaxRegs = 4; // Maximum of 4 FPR arguments
322*06c3fb27SDimitry Andric     RegCountField = 1; // __fpr
323*06c3fb27SDimitry Andric     RegSaveIndex = 16; // save offset for f0
324*06c3fb27SDimitry Andric     RegPadding = CharUnits(); // floats are passed in the high bits of an FPR
325*06c3fb27SDimitry Andric   } else {
326*06c3fb27SDimitry Andric     MaxRegs = 5; // Maximum of 5 GPR arguments
327*06c3fb27SDimitry Andric     RegCountField = 0; // __gpr
328*06c3fb27SDimitry Andric     RegSaveIndex = 2; // save offset for r2
329*06c3fb27SDimitry Andric     RegPadding = Padding; // values are passed in the low bits of a GPR
330*06c3fb27SDimitry Andric   }
331*06c3fb27SDimitry Andric 
332*06c3fb27SDimitry Andric   Address RegCountPtr =
333*06c3fb27SDimitry Andric       CGF.Builder.CreateStructGEP(VAListAddr, RegCountField, "reg_count_ptr");
334*06c3fb27SDimitry Andric   llvm::Value *RegCount = CGF.Builder.CreateLoad(RegCountPtr, "reg_count");
335*06c3fb27SDimitry Andric   llvm::Value *MaxRegsV = llvm::ConstantInt::get(IndexTy, MaxRegs);
336*06c3fb27SDimitry Andric   llvm::Value *InRegs = CGF.Builder.CreateICmpULT(RegCount, MaxRegsV,
337*06c3fb27SDimitry Andric                                                  "fits_in_regs");
338*06c3fb27SDimitry Andric 
339*06c3fb27SDimitry Andric   llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg");
340*06c3fb27SDimitry Andric   llvm::BasicBlock *InMemBlock = CGF.createBasicBlock("vaarg.in_mem");
341*06c3fb27SDimitry Andric   llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end");
342*06c3fb27SDimitry Andric   CGF.Builder.CreateCondBr(InRegs, InRegBlock, InMemBlock);
343*06c3fb27SDimitry Andric 
344*06c3fb27SDimitry Andric   // Emit code to load the value if it was passed in registers.
345*06c3fb27SDimitry Andric   CGF.EmitBlock(InRegBlock);
346*06c3fb27SDimitry Andric 
347*06c3fb27SDimitry Andric   // Work out the address of an argument register.
348*06c3fb27SDimitry Andric   llvm::Value *ScaledRegCount =
349*06c3fb27SDimitry Andric     CGF.Builder.CreateMul(RegCount, PaddedSizeV, "scaled_reg_count");
350*06c3fb27SDimitry Andric   llvm::Value *RegBase =
351*06c3fb27SDimitry Andric     llvm::ConstantInt::get(IndexTy, RegSaveIndex * PaddedSize.getQuantity()
352*06c3fb27SDimitry Andric                                       + RegPadding.getQuantity());
353*06c3fb27SDimitry Andric   llvm::Value *RegOffset =
354*06c3fb27SDimitry Andric     CGF.Builder.CreateAdd(ScaledRegCount, RegBase, "reg_offset");
355*06c3fb27SDimitry Andric   Address RegSaveAreaPtr =
356*06c3fb27SDimitry Andric       CGF.Builder.CreateStructGEP(VAListAddr, 3, "reg_save_area_ptr");
357*06c3fb27SDimitry Andric   llvm::Value *RegSaveArea =
358*06c3fb27SDimitry Andric       CGF.Builder.CreateLoad(RegSaveAreaPtr, "reg_save_area");
359*06c3fb27SDimitry Andric   Address RawRegAddr(
360*06c3fb27SDimitry Andric       CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, RegOffset, "raw_reg_addr"),
361*06c3fb27SDimitry Andric       CGF.Int8Ty, PaddedSize);
362*06c3fb27SDimitry Andric   Address RegAddr = RawRegAddr.withElementType(DirectTy);
363*06c3fb27SDimitry Andric 
364*06c3fb27SDimitry Andric   // Update the register count
365*06c3fb27SDimitry Andric   llvm::Value *One = llvm::ConstantInt::get(IndexTy, 1);
366*06c3fb27SDimitry Andric   llvm::Value *NewRegCount =
367*06c3fb27SDimitry Andric     CGF.Builder.CreateAdd(RegCount, One, "reg_count");
368*06c3fb27SDimitry Andric   CGF.Builder.CreateStore(NewRegCount, RegCountPtr);
369*06c3fb27SDimitry Andric   CGF.EmitBranch(ContBlock);
370*06c3fb27SDimitry Andric 
371*06c3fb27SDimitry Andric   // Emit code to load the value if it was passed in memory.
372*06c3fb27SDimitry Andric   CGF.EmitBlock(InMemBlock);
373*06c3fb27SDimitry Andric 
374*06c3fb27SDimitry Andric   // Work out the address of a stack argument.
375*06c3fb27SDimitry Andric   Address OverflowArgAreaPtr =
376*06c3fb27SDimitry Andric       CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_ptr");
377*06c3fb27SDimitry Andric   Address OverflowArgArea =
378*06c3fb27SDimitry Andric       Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"),
379*06c3fb27SDimitry Andric               CGF.Int8Ty, PaddedSize);
380*06c3fb27SDimitry Andric   Address RawMemAddr =
381*06c3fb27SDimitry Andric       CGF.Builder.CreateConstByteGEP(OverflowArgArea, Padding, "raw_mem_addr");
382*06c3fb27SDimitry Andric   Address MemAddr = RawMemAddr.withElementType(DirectTy);
383*06c3fb27SDimitry Andric 
384*06c3fb27SDimitry Andric   // Update overflow_arg_area_ptr pointer
385*06c3fb27SDimitry Andric   llvm::Value *NewOverflowArgArea =
386*06c3fb27SDimitry Andric     CGF.Builder.CreateGEP(OverflowArgArea.getElementType(),
387*06c3fb27SDimitry Andric                           OverflowArgArea.getPointer(), PaddedSizeV,
388*06c3fb27SDimitry Andric                           "overflow_arg_area");
389*06c3fb27SDimitry Andric   CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr);
390*06c3fb27SDimitry Andric   CGF.EmitBranch(ContBlock);
391*06c3fb27SDimitry Andric 
392*06c3fb27SDimitry Andric   // Return the appropriate result.
393*06c3fb27SDimitry Andric   CGF.EmitBlock(ContBlock);
394*06c3fb27SDimitry Andric   Address ResAddr = emitMergePHI(CGF, RegAddr, InRegBlock, MemAddr, InMemBlock,
395*06c3fb27SDimitry Andric                                  "va_arg.addr");
396*06c3fb27SDimitry Andric 
397*06c3fb27SDimitry Andric   if (IsIndirect)
398*06c3fb27SDimitry Andric     ResAddr = Address(CGF.Builder.CreateLoad(ResAddr, "indirect_arg"), ArgTy,
399*06c3fb27SDimitry Andric                       TyInfo.Align);
400*06c3fb27SDimitry Andric 
401*06c3fb27SDimitry Andric   return ResAddr;
402*06c3fb27SDimitry Andric }
403*06c3fb27SDimitry Andric 
classifyReturnType(QualType RetTy) const404*06c3fb27SDimitry Andric ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const {
405*06c3fb27SDimitry Andric   if (RetTy->isVoidType())
406*06c3fb27SDimitry Andric     return ABIArgInfo::getIgnore();
407*06c3fb27SDimitry Andric   if (isVectorArgumentType(RetTy))
408*06c3fb27SDimitry Andric     return ABIArgInfo::getDirect();
409*06c3fb27SDimitry Andric   if (isCompoundType(RetTy) || getContext().getTypeSize(RetTy) > 64)
410*06c3fb27SDimitry Andric     return getNaturalAlignIndirect(RetTy);
411*06c3fb27SDimitry Andric   return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)
412*06c3fb27SDimitry Andric                                                : ABIArgInfo::getDirect());
413*06c3fb27SDimitry Andric }
414*06c3fb27SDimitry Andric 
classifyArgumentType(QualType Ty) const415*06c3fb27SDimitry Andric ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
416*06c3fb27SDimitry Andric   // Handle the generic C++ ABI.
417*06c3fb27SDimitry Andric   if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
418*06c3fb27SDimitry Andric     return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
419*06c3fb27SDimitry Andric 
420*06c3fb27SDimitry Andric   // Integers and enums are extended to full register width.
421*06c3fb27SDimitry Andric   if (isPromotableIntegerTypeForABI(Ty))
422*06c3fb27SDimitry Andric     return ABIArgInfo::getExtend(Ty);
423*06c3fb27SDimitry Andric 
424*06c3fb27SDimitry Andric   // Handle vector types and vector-like structure types.  Note that
425*06c3fb27SDimitry Andric   // as opposed to float-like structure types, we do not allow any
426*06c3fb27SDimitry Andric   // padding for vector-like structures, so verify the sizes match.
427*06c3fb27SDimitry Andric   uint64_t Size = getContext().getTypeSize(Ty);
428*06c3fb27SDimitry Andric   QualType SingleElementTy = GetSingleElementType(Ty);
429*06c3fb27SDimitry Andric   if (isVectorArgumentType(SingleElementTy) &&
430*06c3fb27SDimitry Andric       getContext().getTypeSize(SingleElementTy) == Size)
431*06c3fb27SDimitry Andric     return ABIArgInfo::getDirect(CGT.ConvertType(SingleElementTy));
432*06c3fb27SDimitry Andric 
433*06c3fb27SDimitry Andric   // Values that are not 1, 2, 4 or 8 bytes in size are passed indirectly.
434*06c3fb27SDimitry Andric   if (Size != 8 && Size != 16 && Size != 32 && Size != 64)
435*06c3fb27SDimitry Andric     return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
436*06c3fb27SDimitry Andric 
437*06c3fb27SDimitry Andric   // Handle small structures.
438*06c3fb27SDimitry Andric   if (const RecordType *RT = Ty->getAs<RecordType>()) {
439*06c3fb27SDimitry Andric     // Structures with flexible arrays have variable length, so really
440*06c3fb27SDimitry Andric     // fail the size test above.
441*06c3fb27SDimitry Andric     const RecordDecl *RD = RT->getDecl();
442*06c3fb27SDimitry Andric     if (RD->hasFlexibleArrayMember())
443*06c3fb27SDimitry Andric       return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
444*06c3fb27SDimitry Andric 
445*06c3fb27SDimitry Andric     // The structure is passed as an unextended integer, a float, or a double.
446*06c3fb27SDimitry Andric     llvm::Type *PassTy;
447*06c3fb27SDimitry Andric     if (isFPArgumentType(SingleElementTy)) {
448*06c3fb27SDimitry Andric       assert(Size == 32 || Size == 64);
449*06c3fb27SDimitry Andric       if (Size == 32)
450*06c3fb27SDimitry Andric         PassTy = llvm::Type::getFloatTy(getVMContext());
451*06c3fb27SDimitry Andric       else
452*06c3fb27SDimitry Andric         PassTy = llvm::Type::getDoubleTy(getVMContext());
453*06c3fb27SDimitry Andric     } else
454*06c3fb27SDimitry Andric       PassTy = llvm::IntegerType::get(getVMContext(), Size);
455*06c3fb27SDimitry Andric     return ABIArgInfo::getDirect(PassTy);
456*06c3fb27SDimitry Andric   }
457*06c3fb27SDimitry Andric 
458*06c3fb27SDimitry Andric   // Non-structure compounds are passed indirectly.
459*06c3fb27SDimitry Andric   if (isCompoundType(Ty))
460*06c3fb27SDimitry Andric     return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
461*06c3fb27SDimitry Andric 
462*06c3fb27SDimitry Andric   return ABIArgInfo::getDirect(nullptr);
463*06c3fb27SDimitry Andric }
464*06c3fb27SDimitry Andric 
computeInfo(CGFunctionInfo & FI) const465*06c3fb27SDimitry Andric void SystemZABIInfo::computeInfo(CGFunctionInfo &FI) const {
466*06c3fb27SDimitry Andric   const SystemZTargetCodeGenInfo &SZCGI =
467*06c3fb27SDimitry Andric       static_cast<const SystemZTargetCodeGenInfo &>(
468*06c3fb27SDimitry Andric           CGT.getCGM().getTargetCodeGenInfo());
469*06c3fb27SDimitry Andric   if (!getCXXABI().classifyReturnType(FI))
470*06c3fb27SDimitry Andric     FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
471*06c3fb27SDimitry Andric   unsigned Idx = 0;
472*06c3fb27SDimitry Andric   for (auto &I : FI.arguments()) {
473*06c3fb27SDimitry Andric     I.info = classifyArgumentType(I.type);
474*06c3fb27SDimitry Andric     if (FI.isVariadic() && Idx++ >= FI.getNumRequiredArgs())
475*06c3fb27SDimitry Andric       // Check if a vararg vector argument is passed, in which case the
476*06c3fb27SDimitry Andric       // vector ABI becomes visible as the va_list could be passed on to
477*06c3fb27SDimitry Andric       // other functions.
478*06c3fb27SDimitry Andric       SZCGI.handleExternallyVisibleObjABI(I.type.getTypePtr(), CGT.getCGM(),
479*06c3fb27SDimitry Andric                                           /*IsParam*/true);
480*06c3fb27SDimitry Andric   }
481*06c3fb27SDimitry Andric }
482*06c3fb27SDimitry Andric 
isVectorTypeBased(const Type * Ty,bool IsParam) const483*06c3fb27SDimitry Andric bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty,
484*06c3fb27SDimitry Andric                                                  bool IsParam) const {
485*06c3fb27SDimitry Andric   if (!SeenTypes.insert(Ty).second)
486*06c3fb27SDimitry Andric     return false;
487*06c3fb27SDimitry Andric 
488*06c3fb27SDimitry Andric   if (IsParam) {
489*06c3fb27SDimitry Andric     // A narrow (<16 bytes) vector will as a parameter also expose the ABI as
490*06c3fb27SDimitry Andric     // it will be passed in a vector register. A wide (>16 bytes) vector will
491*06c3fb27SDimitry Andric     // be passed via "hidden" pointer where any extra alignment is not
492*06c3fb27SDimitry Andric     // required (per GCC).
493*06c3fb27SDimitry Andric     const Type *SingleEltTy = getABIInfo<SystemZABIInfo>()
494*06c3fb27SDimitry Andric                                   .GetSingleElementType(QualType(Ty, 0))
495*06c3fb27SDimitry Andric                                   .getTypePtr();
496*06c3fb27SDimitry Andric     bool SingleVecEltStruct = SingleEltTy != Ty && SingleEltTy->isVectorType() &&
497*06c3fb27SDimitry Andric       Ctx.getTypeSize(SingleEltTy) == Ctx.getTypeSize(Ty);
498*06c3fb27SDimitry Andric     if (Ty->isVectorType() || SingleVecEltStruct)
499*06c3fb27SDimitry Andric       return Ctx.getTypeSize(Ty) / 8 <= 16;
500*06c3fb27SDimitry Andric   }
501*06c3fb27SDimitry Andric 
502*06c3fb27SDimitry Andric   // Assume pointers are dereferenced.
503*06c3fb27SDimitry Andric   while (Ty->isPointerType() || Ty->isArrayType())
504*06c3fb27SDimitry Andric     Ty = Ty->getPointeeOrArrayElementType();
505*06c3fb27SDimitry Andric 
506*06c3fb27SDimitry Andric   // Vectors >= 16 bytes expose the ABI through alignment requirements.
507*06c3fb27SDimitry Andric   if (Ty->isVectorType() && Ctx.getTypeSize(Ty) / 8 >= 16)
508*06c3fb27SDimitry Andric       return true;
509*06c3fb27SDimitry Andric 
510*06c3fb27SDimitry Andric   if (const auto *RecordTy = Ty->getAs<RecordType>()) {
511*06c3fb27SDimitry Andric     const RecordDecl *RD = RecordTy->getDecl();
512*06c3fb27SDimitry Andric     if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
513*06c3fb27SDimitry Andric       if (CXXRD->hasDefinition())
514*06c3fb27SDimitry Andric         for (const auto &I : CXXRD->bases())
515*06c3fb27SDimitry Andric           if (isVectorTypeBased(I.getType().getTypePtr(), /*IsParam*/false))
516*06c3fb27SDimitry Andric             return true;
517*06c3fb27SDimitry Andric     for (const auto *FD : RD->fields())
518*06c3fb27SDimitry Andric       if (isVectorTypeBased(FD->getType().getTypePtr(), /*IsParam*/false))
519*06c3fb27SDimitry Andric         return true;
520*06c3fb27SDimitry Andric   }
521*06c3fb27SDimitry Andric 
522*06c3fb27SDimitry Andric   if (const auto *FT = Ty->getAs<FunctionType>())
523*06c3fb27SDimitry Andric     if (isVectorTypeBased(FT->getReturnType().getTypePtr(), /*IsParam*/true))
524*06c3fb27SDimitry Andric       return true;
525*06c3fb27SDimitry Andric   if (const FunctionProtoType *Proto = Ty->getAs<FunctionProtoType>())
526*06c3fb27SDimitry Andric     for (const auto &ParamType : Proto->getParamTypes())
527*06c3fb27SDimitry Andric       if (isVectorTypeBased(ParamType.getTypePtr(), /*IsParam*/true))
528*06c3fb27SDimitry Andric         return true;
529*06c3fb27SDimitry Andric 
530*06c3fb27SDimitry Andric   return false;
531*06c3fb27SDimitry Andric }
532*06c3fb27SDimitry Andric 
533*06c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo>
createSystemZTargetCodeGenInfo(CodeGenModule & CGM,bool HasVector,bool SoftFloatABI)534*06c3fb27SDimitry Andric CodeGen::createSystemZTargetCodeGenInfo(CodeGenModule &CGM, bool HasVector,
535*06c3fb27SDimitry Andric                                         bool SoftFloatABI) {
536*06c3fb27SDimitry Andric   return std::make_unique<SystemZTargetCodeGenInfo>(CGM.getTypes(), HasVector,
537*06c3fb27SDimitry Andric                                                     SoftFloatABI);
538*06c3fb27SDimitry Andric }
539