xref: /llvm-project/clang/lib/CodeGen/Targets/SystemZ.cpp (revision fa789dffb1e12c2aece0187aeacc48dfb1768340)
1992cb984SSergei Barannikov //===- SystemZ.cpp --------------------------------------------------------===//
2992cb984SSergei Barannikov //
3992cb984SSergei Barannikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4992cb984SSergei Barannikov // See https://llvm.org/LICENSE.txt for license information.
5992cb984SSergei Barannikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6992cb984SSergei Barannikov //
7992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
8992cb984SSergei Barannikov 
9992cb984SSergei Barannikov #include "ABIInfoImpl.h"
10992cb984SSergei Barannikov #include "TargetInfo.h"
11992cb984SSergei Barannikov #include "clang/Basic/Builtins.h"
12992cb984SSergei Barannikov #include "llvm/IR/IntrinsicsS390.h"
13992cb984SSergei Barannikov 
14992cb984SSergei Barannikov using namespace clang;
15992cb984SSergei Barannikov using namespace clang::CodeGen;
16992cb984SSergei Barannikov 
17992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
18992cb984SSergei Barannikov // SystemZ ABI Implementation
19992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
20992cb984SSergei Barannikov 
21992cb984SSergei Barannikov namespace {
22992cb984SSergei Barannikov 
23992cb984SSergei Barannikov class SystemZABIInfo : public ABIInfo {
24992cb984SSergei Barannikov   bool HasVector;
25992cb984SSergei Barannikov   bool IsSoftFloatABI;
26992cb984SSergei Barannikov 
27992cb984SSergei Barannikov public:
28992cb984SSergei Barannikov   SystemZABIInfo(CodeGenTypes &CGT, bool HV, bool SF)
29992cb984SSergei Barannikov       : ABIInfo(CGT), HasVector(HV), IsSoftFloatABI(SF) {}
30992cb984SSergei Barannikov 
31992cb984SSergei Barannikov   bool isPromotableIntegerTypeForABI(QualType Ty) const;
32992cb984SSergei Barannikov   bool isCompoundType(QualType Ty) const;
33992cb984SSergei Barannikov   bool isVectorArgumentType(QualType Ty) const;
34992cb984SSergei Barannikov   bool isFPArgumentType(QualType Ty) const;
35992cb984SSergei Barannikov   QualType GetSingleElementType(QualType Ty) const;
36992cb984SSergei Barannikov 
37992cb984SSergei Barannikov   ABIArgInfo classifyReturnType(QualType RetTy) const;
38992cb984SSergei Barannikov   ABIArgInfo classifyArgumentType(QualType ArgTy) const;
39992cb984SSergei Barannikov 
40992cb984SSergei Barannikov   void computeInfo(CGFunctionInfo &FI) const override;
416d973b45SMariya Podchishchaeva   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
426d973b45SMariya Podchishchaeva                    AggValueSlot Slot) const override;
43992cb984SSergei Barannikov };
44992cb984SSergei Barannikov 
45992cb984SSergei Barannikov class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
46992cb984SSergei Barannikov   ASTContext &Ctx;
47992cb984SSergei Barannikov 
48992cb984SSergei Barannikov   // These are used for speeding up the search for a visible vector ABI.
49992cb984SSergei Barannikov   mutable bool HasVisibleVecABIFlag = false;
50992cb984SSergei Barannikov   mutable std::set<const Type *> SeenTypes;
51992cb984SSergei Barannikov 
52992cb984SSergei Barannikov   // Returns true (the first time) if Ty is, or is found to include, a vector
53992cb984SSergei Barannikov   // type that exposes the vector ABI. This is any vector >=16 bytes which
54992cb984SSergei Barannikov   // with vector support are aligned to only 8 bytes. When IsParam is true,
55992cb984SSergei Barannikov   // the type belongs to a value as passed between functions. If it is a
56992cb984SSergei Barannikov   // vector <=16 bytes it will be passed in a vector register (if supported).
57992cb984SSergei Barannikov   bool isVectorTypeBased(const Type *Ty, bool IsParam) const;
58992cb984SSergei Barannikov 
59992cb984SSergei Barannikov public:
60992cb984SSergei Barannikov   SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI)
61992cb984SSergei Barannikov       : TargetCodeGenInfo(
62992cb984SSergei Barannikov             std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)),
63992cb984SSergei Barannikov             Ctx(CGT.getContext()) {
64992cb984SSergei Barannikov     SwiftInfo =
65992cb984SSergei Barannikov         std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false);
66992cb984SSergei Barannikov   }
67992cb984SSergei Barannikov 
68992cb984SSergei Barannikov   // The vector ABI is different when the vector facility is present and when
69992cb984SSergei Barannikov   // a module e.g. defines an externally visible vector variable, a flag
70992cb984SSergei Barannikov   // indicating a visible vector ABI is added. Eventually this will result in
71992cb984SSergei Barannikov   // a GNU attribute indicating the vector ABI of the module.  Ty is the type
72992cb984SSergei Barannikov   // of a variable or function parameter that is globally visible.
73992cb984SSergei Barannikov   void handleExternallyVisibleObjABI(const Type *Ty, CodeGen::CodeGenModule &M,
74992cb984SSergei Barannikov                                      bool IsParam) const {
75992cb984SSergei Barannikov     if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty, IsParam)) {
76992cb984SSergei Barannikov       M.getModule().addModuleFlag(llvm::Module::Warning,
77992cb984SSergei Barannikov                                   "s390x-visible-vector-ABI", 1);
78992cb984SSergei Barannikov       HasVisibleVecABIFlag = true;
79992cb984SSergei Barannikov     }
80992cb984SSergei Barannikov   }
81992cb984SSergei Barannikov 
82992cb984SSergei Barannikov   void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
83992cb984SSergei Barannikov                            CodeGen::CodeGenModule &M) const override {
84992cb984SSergei Barannikov     if (!D)
85992cb984SSergei Barannikov       return;
86992cb984SSergei Barannikov 
87992cb984SSergei Barannikov     // Check if the vector ABI becomes visible by an externally visible
88992cb984SSergei Barannikov     // variable or function.
89992cb984SSergei Barannikov     if (const auto *VD = dyn_cast<VarDecl>(D)) {
90992cb984SSergei Barannikov       if (VD->isExternallyVisible())
91992cb984SSergei Barannikov         handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M,
92992cb984SSergei Barannikov                                       /*IsParam*/false);
93992cb984SSergei Barannikov     }
94992cb984SSergei Barannikov     else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
95992cb984SSergei Barannikov       if (FD->isExternallyVisible())
96992cb984SSergei Barannikov         handleExternallyVisibleObjABI(FD->getType().getTypePtr(), M,
97992cb984SSergei Barannikov                                       /*IsParam*/false);
98992cb984SSergei Barannikov     }
99992cb984SSergei Barannikov   }
100992cb984SSergei Barannikov 
101992cb984SSergei Barannikov   llvm::Value *testFPKind(llvm::Value *V, unsigned BuiltinID,
102992cb984SSergei Barannikov                           CGBuilderTy &Builder,
103992cb984SSergei Barannikov                           CodeGenModule &CGM) const override {
104992cb984SSergei Barannikov     assert(V->getType()->isFloatingPointTy() && "V should have an FP type.");
105992cb984SSergei Barannikov     // Only use TDC in constrained FP mode.
106992cb984SSergei Barannikov     if (!Builder.getIsFPConstrained())
107992cb984SSergei Barannikov       return nullptr;
108992cb984SSergei Barannikov 
109992cb984SSergei Barannikov     llvm::Type *Ty = V->getType();
110992cb984SSergei Barannikov     if (Ty->isFloatTy() || Ty->isDoubleTy() || Ty->isFP128Ty()) {
111992cb984SSergei Barannikov       llvm::Module &M = CGM.getModule();
112992cb984SSergei Barannikov       auto &Ctx = M.getContext();
113*fa789dffSRahul Joshi       llvm::Function *TDCFunc = llvm::Intrinsic::getOrInsertDeclaration(
114*fa789dffSRahul Joshi           &M, llvm::Intrinsic::s390_tdc, Ty);
115992cb984SSergei Barannikov       unsigned TDCBits = 0;
116992cb984SSergei Barannikov       switch (BuiltinID) {
117992cb984SSergei Barannikov       case Builtin::BI__builtin_isnan:
118992cb984SSergei Barannikov         TDCBits = 0xf;
119992cb984SSergei Barannikov         break;
120992cb984SSergei Barannikov       case Builtin::BIfinite:
121992cb984SSergei Barannikov       case Builtin::BI__finite:
122992cb984SSergei Barannikov       case Builtin::BIfinitef:
123992cb984SSergei Barannikov       case Builtin::BI__finitef:
124992cb984SSergei Barannikov       case Builtin::BIfinitel:
125992cb984SSergei Barannikov       case Builtin::BI__finitel:
126992cb984SSergei Barannikov       case Builtin::BI__builtin_isfinite:
127992cb984SSergei Barannikov         TDCBits = 0xfc0;
128992cb984SSergei Barannikov         break;
129992cb984SSergei Barannikov       case Builtin::BI__builtin_isinf:
130992cb984SSergei Barannikov         TDCBits = 0x30;
131992cb984SSergei Barannikov         break;
132992cb984SSergei Barannikov       default:
133992cb984SSergei Barannikov         break;
134992cb984SSergei Barannikov       }
135992cb984SSergei Barannikov       if (TDCBits)
136992cb984SSergei Barannikov         return Builder.CreateCall(
137992cb984SSergei Barannikov             TDCFunc,
138992cb984SSergei Barannikov             {V, llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), TDCBits)});
139992cb984SSergei Barannikov     }
140992cb984SSergei Barannikov     return nullptr;
141992cb984SSergei Barannikov   }
142992cb984SSergei Barannikov };
143992cb984SSergei Barannikov }
144992cb984SSergei Barannikov 
145992cb984SSergei Barannikov bool SystemZABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const {
146992cb984SSergei Barannikov   // Treat an enum type as its underlying type.
147992cb984SSergei Barannikov   if (const EnumType *EnumTy = Ty->getAs<EnumType>())
148992cb984SSergei Barannikov     Ty = EnumTy->getDecl()->getIntegerType();
149992cb984SSergei Barannikov 
150992cb984SSergei Barannikov   // Promotable integer types are required to be promoted by the ABI.
151992cb984SSergei Barannikov   if (ABIInfo::isPromotableIntegerTypeForABI(Ty))
152992cb984SSergei Barannikov     return true;
153992cb984SSergei Barannikov 
154992cb984SSergei Barannikov   if (const auto *EIT = Ty->getAs<BitIntType>())
155992cb984SSergei Barannikov     if (EIT->getNumBits() < 64)
156992cb984SSergei Barannikov       return true;
157992cb984SSergei Barannikov 
158992cb984SSergei Barannikov   // 32-bit values must also be promoted.
159992cb984SSergei Barannikov   if (const BuiltinType *BT = Ty->getAs<BuiltinType>())
160992cb984SSergei Barannikov     switch (BT->getKind()) {
161992cb984SSergei Barannikov     case BuiltinType::Int:
162992cb984SSergei Barannikov     case BuiltinType::UInt:
163992cb984SSergei Barannikov       return true;
164992cb984SSergei Barannikov     default:
165992cb984SSergei Barannikov       return false;
166992cb984SSergei Barannikov     }
167992cb984SSergei Barannikov   return false;
168992cb984SSergei Barannikov }
169992cb984SSergei Barannikov 
170992cb984SSergei Barannikov bool SystemZABIInfo::isCompoundType(QualType Ty) const {
171992cb984SSergei Barannikov   return (Ty->isAnyComplexType() ||
172992cb984SSergei Barannikov           Ty->isVectorType() ||
173992cb984SSergei Barannikov           isAggregateTypeForABI(Ty));
174992cb984SSergei Barannikov }
175992cb984SSergei Barannikov 
176992cb984SSergei Barannikov bool SystemZABIInfo::isVectorArgumentType(QualType Ty) const {
177992cb984SSergei Barannikov   return (HasVector &&
178992cb984SSergei Barannikov           Ty->isVectorType() &&
179992cb984SSergei Barannikov           getContext().getTypeSize(Ty) <= 128);
180992cb984SSergei Barannikov }
181992cb984SSergei Barannikov 
182992cb984SSergei Barannikov bool SystemZABIInfo::isFPArgumentType(QualType Ty) const {
183992cb984SSergei Barannikov   if (IsSoftFloatABI)
184992cb984SSergei Barannikov     return false;
185992cb984SSergei Barannikov 
186992cb984SSergei Barannikov   if (const BuiltinType *BT = Ty->getAs<BuiltinType>())
187992cb984SSergei Barannikov     switch (BT->getKind()) {
188992cb984SSergei Barannikov     case BuiltinType::Float:
189992cb984SSergei Barannikov     case BuiltinType::Double:
190992cb984SSergei Barannikov       return true;
191992cb984SSergei Barannikov     default:
192992cb984SSergei Barannikov       return false;
193992cb984SSergei Barannikov     }
194992cb984SSergei Barannikov 
195992cb984SSergei Barannikov   return false;
196992cb984SSergei Barannikov }
197992cb984SSergei Barannikov 
198992cb984SSergei Barannikov QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const {
199992cb984SSergei Barannikov   const RecordType *RT = Ty->getAs<RecordType>();
200992cb984SSergei Barannikov 
201992cb984SSergei Barannikov   if (RT && RT->isStructureOrClassType()) {
202992cb984SSergei Barannikov     const RecordDecl *RD = RT->getDecl();
203992cb984SSergei Barannikov     QualType Found;
204992cb984SSergei Barannikov 
205992cb984SSergei Barannikov     // If this is a C++ record, check the bases first.
206992cb984SSergei Barannikov     if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
207992cb984SSergei Barannikov       if (CXXRD->hasDefinition())
208992cb984SSergei Barannikov         for (const auto &I : CXXRD->bases()) {
209992cb984SSergei Barannikov           QualType Base = I.getType();
210992cb984SSergei Barannikov 
211992cb984SSergei Barannikov           // Empty bases don't affect things either way.
212992cb984SSergei Barannikov           if (isEmptyRecord(getContext(), Base, true))
213992cb984SSergei Barannikov             continue;
214992cb984SSergei Barannikov 
215992cb984SSergei Barannikov           if (!Found.isNull())
216992cb984SSergei Barannikov             return Ty;
217992cb984SSergei Barannikov           Found = GetSingleElementType(Base);
218992cb984SSergei Barannikov         }
219992cb984SSergei Barannikov 
220992cb984SSergei Barannikov     // Check the fields.
221992cb984SSergei Barannikov     for (const auto *FD : RD->fields()) {
222992cb984SSergei Barannikov       // Unlike isSingleElementStruct(), empty structure and array fields
223992cb984SSergei Barannikov       // do count.  So do anonymous bitfields that aren't zero-sized.
224992cb984SSergei Barannikov 
225992cb984SSergei Barannikov       // Like isSingleElementStruct(), ignore C++20 empty data members.
226992cb984SSergei Barannikov       if (FD->hasAttr<NoUniqueAddressAttr>() &&
227992cb984SSergei Barannikov           isEmptyRecord(getContext(), FD->getType(), true))
228992cb984SSergei Barannikov         continue;
229992cb984SSergei Barannikov 
230992cb984SSergei Barannikov       // Unlike isSingleElementStruct(), arrays do not count.
231992cb984SSergei Barannikov       // Nested structures still do though.
232992cb984SSergei Barannikov       if (!Found.isNull())
233992cb984SSergei Barannikov         return Ty;
234992cb984SSergei Barannikov       Found = GetSingleElementType(FD->getType());
235992cb984SSergei Barannikov     }
236992cb984SSergei Barannikov 
237992cb984SSergei Barannikov     // Unlike isSingleElementStruct(), trailing padding is allowed.
238992cb984SSergei Barannikov     // An 8-byte aligned struct s { float f; } is passed as a double.
239992cb984SSergei Barannikov     if (!Found.isNull())
240992cb984SSergei Barannikov       return Found;
241992cb984SSergei Barannikov   }
242992cb984SSergei Barannikov 
243992cb984SSergei Barannikov   return Ty;
244992cb984SSergei Barannikov }
245992cb984SSergei Barannikov 
2466d973b45SMariya Podchishchaeva RValue SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
2476d973b45SMariya Podchishchaeva                                  QualType Ty, AggValueSlot Slot) const {
248992cb984SSergei Barannikov   // Assume that va_list type is correct; should be pointer to LLVM type:
249992cb984SSergei Barannikov   // struct {
250992cb984SSergei Barannikov   //   i64 __gpr;
251992cb984SSergei Barannikov   //   i64 __fpr;
252992cb984SSergei Barannikov   //   i8 *__overflow_arg_area;
253992cb984SSergei Barannikov   //   i8 *__reg_save_area;
254992cb984SSergei Barannikov   // };
255992cb984SSergei Barannikov 
256992cb984SSergei Barannikov   // Every non-vector argument occupies 8 bytes and is passed by preference
257992cb984SSergei Barannikov   // in either GPRs or FPRs.  Vector arguments occupy 8 or 16 bytes and are
258992cb984SSergei Barannikov   // always passed on the stack.
259992cb984SSergei Barannikov   const SystemZTargetCodeGenInfo &SZCGI =
260992cb984SSergei Barannikov       static_cast<const SystemZTargetCodeGenInfo &>(
261992cb984SSergei Barannikov           CGT.getCGM().getTargetCodeGenInfo());
262992cb984SSergei Barannikov   Ty = getContext().getCanonicalType(Ty);
263992cb984SSergei Barannikov   auto TyInfo = getContext().getTypeInfoInChars(Ty);
264992cb984SSergei Barannikov   llvm::Type *ArgTy = CGF.ConvertTypeForMem(Ty);
265992cb984SSergei Barannikov   llvm::Type *DirectTy = ArgTy;
266992cb984SSergei Barannikov   ABIArgInfo AI = classifyArgumentType(Ty);
267992cb984SSergei Barannikov   bool IsIndirect = AI.isIndirect();
268992cb984SSergei Barannikov   bool InFPRs = false;
269992cb984SSergei Barannikov   bool IsVector = false;
270992cb984SSergei Barannikov   CharUnits UnpaddedSize;
271992cb984SSergei Barannikov   CharUnits DirectAlign;
272992cb984SSergei Barannikov   SZCGI.handleExternallyVisibleObjABI(Ty.getTypePtr(), CGT.getCGM(),
273992cb984SSergei Barannikov                                       /*IsParam*/true);
274992cb984SSergei Barannikov   if (IsIndirect) {
275992cb984SSergei Barannikov     DirectTy = llvm::PointerType::getUnqual(DirectTy);
276992cb984SSergei Barannikov     UnpaddedSize = DirectAlign = CharUnits::fromQuantity(8);
277992cb984SSergei Barannikov   } else {
278992cb984SSergei Barannikov     if (AI.getCoerceToType())
279992cb984SSergei Barannikov       ArgTy = AI.getCoerceToType();
280992cb984SSergei Barannikov     InFPRs = (!IsSoftFloatABI && (ArgTy->isFloatTy() || ArgTy->isDoubleTy()));
281992cb984SSergei Barannikov     IsVector = ArgTy->isVectorTy();
282992cb984SSergei Barannikov     UnpaddedSize = TyInfo.Width;
283992cb984SSergei Barannikov     DirectAlign = TyInfo.Align;
284992cb984SSergei Barannikov   }
285992cb984SSergei Barannikov   CharUnits PaddedSize = CharUnits::fromQuantity(8);
286992cb984SSergei Barannikov   if (IsVector && UnpaddedSize > PaddedSize)
287992cb984SSergei Barannikov     PaddedSize = CharUnits::fromQuantity(16);
288992cb984SSergei Barannikov   assert((UnpaddedSize <= PaddedSize) && "Invalid argument size.");
289992cb984SSergei Barannikov 
290992cb984SSergei Barannikov   CharUnits Padding = (PaddedSize - UnpaddedSize);
291992cb984SSergei Barannikov 
292992cb984SSergei Barannikov   llvm::Type *IndexTy = CGF.Int64Ty;
293992cb984SSergei Barannikov   llvm::Value *PaddedSizeV =
294992cb984SSergei Barannikov     llvm::ConstantInt::get(IndexTy, PaddedSize.getQuantity());
295992cb984SSergei Barannikov 
296992cb984SSergei Barannikov   if (IsVector) {
297992cb984SSergei Barannikov     // Work out the address of a vector argument on the stack.
298992cb984SSergei Barannikov     // Vector arguments are always passed in the high bits of a
299992cb984SSergei Barannikov     // single (8 byte) or double (16 byte) stack slot.
300992cb984SSergei Barannikov     Address OverflowArgAreaPtr =
301992cb984SSergei Barannikov         CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_ptr");
302992cb984SSergei Barannikov     Address OverflowArgArea =
303992cb984SSergei Barannikov         Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"),
304992cb984SSergei Barannikov                 CGF.Int8Ty, TyInfo.Align);
30544e63ffeSYoungsuk Kim     Address MemAddr = OverflowArgArea.withElementType(DirectTy);
306992cb984SSergei Barannikov 
307992cb984SSergei Barannikov     // Update overflow_arg_area_ptr pointer
308992cb984SSergei Barannikov     llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP(
30984780af4SAkira Hatanaka         OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF),
310992cb984SSergei Barannikov         PaddedSizeV, "overflow_arg_area");
311992cb984SSergei Barannikov     CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr);
312992cb984SSergei Barannikov 
3136d973b45SMariya Podchishchaeva     return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(MemAddr, Ty), Slot);
314992cb984SSergei Barannikov   }
315992cb984SSergei Barannikov 
316992cb984SSergei Barannikov   assert(PaddedSize.getQuantity() == 8);
317992cb984SSergei Barannikov 
318992cb984SSergei Barannikov   unsigned MaxRegs, RegCountField, RegSaveIndex;
319992cb984SSergei Barannikov   CharUnits RegPadding;
320992cb984SSergei Barannikov   if (InFPRs) {
321992cb984SSergei Barannikov     MaxRegs = 4; // Maximum of 4 FPR arguments
322992cb984SSergei Barannikov     RegCountField = 1; // __fpr
323992cb984SSergei Barannikov     RegSaveIndex = 16; // save offset for f0
324992cb984SSergei Barannikov     RegPadding = CharUnits(); // floats are passed in the high bits of an FPR
325992cb984SSergei Barannikov   } else {
326992cb984SSergei Barannikov     MaxRegs = 5; // Maximum of 5 GPR arguments
327992cb984SSergei Barannikov     RegCountField = 0; // __gpr
328992cb984SSergei Barannikov     RegSaveIndex = 2; // save offset for r2
329992cb984SSergei Barannikov     RegPadding = Padding; // values are passed in the low bits of a GPR
330992cb984SSergei Barannikov   }
331992cb984SSergei Barannikov 
332992cb984SSergei Barannikov   Address RegCountPtr =
333992cb984SSergei Barannikov       CGF.Builder.CreateStructGEP(VAListAddr, RegCountField, "reg_count_ptr");
334992cb984SSergei Barannikov   llvm::Value *RegCount = CGF.Builder.CreateLoad(RegCountPtr, "reg_count");
335992cb984SSergei Barannikov   llvm::Value *MaxRegsV = llvm::ConstantInt::get(IndexTy, MaxRegs);
336992cb984SSergei Barannikov   llvm::Value *InRegs = CGF.Builder.CreateICmpULT(RegCount, MaxRegsV,
337992cb984SSergei Barannikov                                                  "fits_in_regs");
338992cb984SSergei Barannikov 
339992cb984SSergei Barannikov   llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg");
340992cb984SSergei Barannikov   llvm::BasicBlock *InMemBlock = CGF.createBasicBlock("vaarg.in_mem");
341992cb984SSergei Barannikov   llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end");
342992cb984SSergei Barannikov   CGF.Builder.CreateCondBr(InRegs, InRegBlock, InMemBlock);
343992cb984SSergei Barannikov 
344992cb984SSergei Barannikov   // Emit code to load the value if it was passed in registers.
345992cb984SSergei Barannikov   CGF.EmitBlock(InRegBlock);
346992cb984SSergei Barannikov 
347992cb984SSergei Barannikov   // Work out the address of an argument register.
348992cb984SSergei Barannikov   llvm::Value *ScaledRegCount =
349992cb984SSergei Barannikov     CGF.Builder.CreateMul(RegCount, PaddedSizeV, "scaled_reg_count");
350992cb984SSergei Barannikov   llvm::Value *RegBase =
351992cb984SSergei Barannikov     llvm::ConstantInt::get(IndexTy, RegSaveIndex * PaddedSize.getQuantity()
352992cb984SSergei Barannikov                                       + RegPadding.getQuantity());
353992cb984SSergei Barannikov   llvm::Value *RegOffset =
354992cb984SSergei Barannikov     CGF.Builder.CreateAdd(ScaledRegCount, RegBase, "reg_offset");
355992cb984SSergei Barannikov   Address RegSaveAreaPtr =
356992cb984SSergei Barannikov       CGF.Builder.CreateStructGEP(VAListAddr, 3, "reg_save_area_ptr");
357992cb984SSergei Barannikov   llvm::Value *RegSaveArea =
358992cb984SSergei Barannikov       CGF.Builder.CreateLoad(RegSaveAreaPtr, "reg_save_area");
359992cb984SSergei Barannikov   Address RawRegAddr(
360992cb984SSergei Barannikov       CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, RegOffset, "raw_reg_addr"),
361992cb984SSergei Barannikov       CGF.Int8Ty, PaddedSize);
36244e63ffeSYoungsuk Kim   Address RegAddr = RawRegAddr.withElementType(DirectTy);
363992cb984SSergei Barannikov 
364992cb984SSergei Barannikov   // Update the register count
365992cb984SSergei Barannikov   llvm::Value *One = llvm::ConstantInt::get(IndexTy, 1);
366992cb984SSergei Barannikov   llvm::Value *NewRegCount =
367992cb984SSergei Barannikov     CGF.Builder.CreateAdd(RegCount, One, "reg_count");
368992cb984SSergei Barannikov   CGF.Builder.CreateStore(NewRegCount, RegCountPtr);
369992cb984SSergei Barannikov   CGF.EmitBranch(ContBlock);
370992cb984SSergei Barannikov 
371992cb984SSergei Barannikov   // Emit code to load the value if it was passed in memory.
372992cb984SSergei Barannikov   CGF.EmitBlock(InMemBlock);
373992cb984SSergei Barannikov 
374992cb984SSergei Barannikov   // Work out the address of a stack argument.
375992cb984SSergei Barannikov   Address OverflowArgAreaPtr =
376992cb984SSergei Barannikov       CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_ptr");
377992cb984SSergei Barannikov   Address OverflowArgArea =
378992cb984SSergei Barannikov       Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"),
379992cb984SSergei Barannikov               CGF.Int8Ty, PaddedSize);
380992cb984SSergei Barannikov   Address RawMemAddr =
381992cb984SSergei Barannikov       CGF.Builder.CreateConstByteGEP(OverflowArgArea, Padding, "raw_mem_addr");
38244e63ffeSYoungsuk Kim   Address MemAddr = RawMemAddr.withElementType(DirectTy);
383992cb984SSergei Barannikov 
384992cb984SSergei Barannikov   // Update overflow_arg_area_ptr pointer
38584780af4SAkira Hatanaka   llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP(
38684780af4SAkira Hatanaka       OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF),
38784780af4SAkira Hatanaka       PaddedSizeV, "overflow_arg_area");
388992cb984SSergei Barannikov   CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr);
389992cb984SSergei Barannikov   CGF.EmitBranch(ContBlock);
390992cb984SSergei Barannikov 
391992cb984SSergei Barannikov   // Return the appropriate result.
392992cb984SSergei Barannikov   CGF.EmitBlock(ContBlock);
393992cb984SSergei Barannikov   Address ResAddr = emitMergePHI(CGF, RegAddr, InRegBlock, MemAddr, InMemBlock,
394992cb984SSergei Barannikov                                  "va_arg.addr");
395992cb984SSergei Barannikov 
396992cb984SSergei Barannikov   if (IsIndirect)
397992cb984SSergei Barannikov     ResAddr = Address(CGF.Builder.CreateLoad(ResAddr, "indirect_arg"), ArgTy,
398992cb984SSergei Barannikov                       TyInfo.Align);
399992cb984SSergei Barannikov 
4006d973b45SMariya Podchishchaeva   return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(ResAddr, Ty), Slot);
401992cb984SSergei Barannikov }
402992cb984SSergei Barannikov 
403992cb984SSergei Barannikov ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const {
404992cb984SSergei Barannikov   if (RetTy->isVoidType())
405992cb984SSergei Barannikov     return ABIArgInfo::getIgnore();
406992cb984SSergei Barannikov   if (isVectorArgumentType(RetTy))
407992cb984SSergei Barannikov     return ABIArgInfo::getDirect();
408992cb984SSergei Barannikov   if (isCompoundType(RetTy) || getContext().getTypeSize(RetTy) > 64)
409992cb984SSergei Barannikov     return getNaturalAlignIndirect(RetTy);
410992cb984SSergei Barannikov   return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)
411992cb984SSergei Barannikov                                                : ABIArgInfo::getDirect());
412992cb984SSergei Barannikov }
413992cb984SSergei Barannikov 
414992cb984SSergei Barannikov ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
4159af3628cSUlrich Weigand   // Handle transparent union types.
4169af3628cSUlrich Weigand   Ty = useFirstFieldIfTransparentUnion(Ty);
4179af3628cSUlrich Weigand 
418992cb984SSergei Barannikov   // Handle the generic C++ ABI.
419992cb984SSergei Barannikov   if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
420992cb984SSergei Barannikov     return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
421992cb984SSergei Barannikov 
422992cb984SSergei Barannikov   // Integers and enums are extended to full register width.
423992cb984SSergei Barannikov   if (isPromotableIntegerTypeForABI(Ty))
4249af3628cSUlrich Weigand     return ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty));
425992cb984SSergei Barannikov 
426992cb984SSergei Barannikov   // Handle vector types and vector-like structure types.  Note that
427992cb984SSergei Barannikov   // as opposed to float-like structure types, we do not allow any
428992cb984SSergei Barannikov   // padding for vector-like structures, so verify the sizes match.
429992cb984SSergei Barannikov   uint64_t Size = getContext().getTypeSize(Ty);
430992cb984SSergei Barannikov   QualType SingleElementTy = GetSingleElementType(Ty);
431992cb984SSergei Barannikov   if (isVectorArgumentType(SingleElementTy) &&
432992cb984SSergei Barannikov       getContext().getTypeSize(SingleElementTy) == Size)
433992cb984SSergei Barannikov     return ABIArgInfo::getDirect(CGT.ConvertType(SingleElementTy));
434992cb984SSergei Barannikov 
435992cb984SSergei Barannikov   // Values that are not 1, 2, 4 or 8 bytes in size are passed indirectly.
436992cb984SSergei Barannikov   if (Size != 8 && Size != 16 && Size != 32 && Size != 64)
437992cb984SSergei Barannikov     return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
438992cb984SSergei Barannikov 
439992cb984SSergei Barannikov   // Handle small structures.
440992cb984SSergei Barannikov   if (const RecordType *RT = Ty->getAs<RecordType>()) {
441992cb984SSergei Barannikov     // Structures with flexible arrays have variable length, so really
442992cb984SSergei Barannikov     // fail the size test above.
443992cb984SSergei Barannikov     const RecordDecl *RD = RT->getDecl();
444992cb984SSergei Barannikov     if (RD->hasFlexibleArrayMember())
445992cb984SSergei Barannikov       return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
446992cb984SSergei Barannikov 
447992cb984SSergei Barannikov     // The structure is passed as an unextended integer, a float, or a double.
448992cb984SSergei Barannikov     if (isFPArgumentType(SingleElementTy)) {
449992cb984SSergei Barannikov       assert(Size == 32 || Size == 64);
45014120227SJonas Paulsson       return ABIArgInfo::getDirect(
45114120227SJonas Paulsson           Size == 32 ? llvm::Type::getFloatTy(getVMContext())
45214120227SJonas Paulsson                      : llvm::Type::getDoubleTy(getVMContext()));
45314120227SJonas Paulsson     } else {
45414120227SJonas Paulsson       llvm::IntegerType *PassTy = llvm::IntegerType::get(getVMContext(), Size);
45514120227SJonas Paulsson       return Size <= 32 ? ABIArgInfo::getNoExtend(PassTy)
45614120227SJonas Paulsson                         : ABIArgInfo::getDirect(PassTy);
45714120227SJonas Paulsson     }
458992cb984SSergei Barannikov   }
459992cb984SSergei Barannikov 
460992cb984SSergei Barannikov   // Non-structure compounds are passed indirectly.
461992cb984SSergei Barannikov   if (isCompoundType(Ty))
462992cb984SSergei Barannikov     return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
463992cb984SSergei Barannikov 
464992cb984SSergei Barannikov   return ABIArgInfo::getDirect(nullptr);
465992cb984SSergei Barannikov }
466992cb984SSergei Barannikov 
467992cb984SSergei Barannikov void SystemZABIInfo::computeInfo(CGFunctionInfo &FI) const {
468992cb984SSergei Barannikov   const SystemZTargetCodeGenInfo &SZCGI =
469992cb984SSergei Barannikov       static_cast<const SystemZTargetCodeGenInfo &>(
470992cb984SSergei Barannikov           CGT.getCGM().getTargetCodeGenInfo());
471992cb984SSergei Barannikov   if (!getCXXABI().classifyReturnType(FI))
472992cb984SSergei Barannikov     FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
473992cb984SSergei Barannikov   unsigned Idx = 0;
474992cb984SSergei Barannikov   for (auto &I : FI.arguments()) {
475992cb984SSergei Barannikov     I.info = classifyArgumentType(I.type);
476992cb984SSergei Barannikov     if (FI.isVariadic() && Idx++ >= FI.getNumRequiredArgs())
477992cb984SSergei Barannikov       // Check if a vararg vector argument is passed, in which case the
478992cb984SSergei Barannikov       // vector ABI becomes visible as the va_list could be passed on to
479992cb984SSergei Barannikov       // other functions.
480992cb984SSergei Barannikov       SZCGI.handleExternallyVisibleObjABI(I.type.getTypePtr(), CGT.getCGM(),
481992cb984SSergei Barannikov                                           /*IsParam*/true);
482992cb984SSergei Barannikov   }
483992cb984SSergei Barannikov }
484992cb984SSergei Barannikov 
485992cb984SSergei Barannikov bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty,
486992cb984SSergei Barannikov                                                  bool IsParam) const {
487992cb984SSergei Barannikov   if (!SeenTypes.insert(Ty).second)
488992cb984SSergei Barannikov     return false;
489992cb984SSergei Barannikov 
490992cb984SSergei Barannikov   if (IsParam) {
491992cb984SSergei Barannikov     // A narrow (<16 bytes) vector will as a parameter also expose the ABI as
492992cb984SSergei Barannikov     // it will be passed in a vector register. A wide (>16 bytes) vector will
493992cb984SSergei Barannikov     // be passed via "hidden" pointer where any extra alignment is not
494992cb984SSergei Barannikov     // required (per GCC).
495992cb984SSergei Barannikov     const Type *SingleEltTy = getABIInfo<SystemZABIInfo>()
496992cb984SSergei Barannikov                                   .GetSingleElementType(QualType(Ty, 0))
497992cb984SSergei Barannikov                                   .getTypePtr();
498992cb984SSergei Barannikov     bool SingleVecEltStruct = SingleEltTy != Ty && SingleEltTy->isVectorType() &&
499992cb984SSergei Barannikov       Ctx.getTypeSize(SingleEltTy) == Ctx.getTypeSize(Ty);
500992cb984SSergei Barannikov     if (Ty->isVectorType() || SingleVecEltStruct)
501992cb984SSergei Barannikov       return Ctx.getTypeSize(Ty) / 8 <= 16;
502992cb984SSergei Barannikov   }
503992cb984SSergei Barannikov 
504992cb984SSergei Barannikov   // Assume pointers are dereferenced.
505992cb984SSergei Barannikov   while (Ty->isPointerType() || Ty->isArrayType())
506992cb984SSergei Barannikov     Ty = Ty->getPointeeOrArrayElementType();
507992cb984SSergei Barannikov 
508992cb984SSergei Barannikov   // Vectors >= 16 bytes expose the ABI through alignment requirements.
509992cb984SSergei Barannikov   if (Ty->isVectorType() && Ctx.getTypeSize(Ty) / 8 >= 16)
510992cb984SSergei Barannikov       return true;
511992cb984SSergei Barannikov 
512992cb984SSergei Barannikov   if (const auto *RecordTy = Ty->getAs<RecordType>()) {
513992cb984SSergei Barannikov     const RecordDecl *RD = RecordTy->getDecl();
514992cb984SSergei Barannikov     if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
515992cb984SSergei Barannikov       if (CXXRD->hasDefinition())
516992cb984SSergei Barannikov         for (const auto &I : CXXRD->bases())
517992cb984SSergei Barannikov           if (isVectorTypeBased(I.getType().getTypePtr(), /*IsParam*/false))
518992cb984SSergei Barannikov             return true;
519992cb984SSergei Barannikov     for (const auto *FD : RD->fields())
520992cb984SSergei Barannikov       if (isVectorTypeBased(FD->getType().getTypePtr(), /*IsParam*/false))
521992cb984SSergei Barannikov         return true;
522992cb984SSergei Barannikov   }
523992cb984SSergei Barannikov 
524992cb984SSergei Barannikov   if (const auto *FT = Ty->getAs<FunctionType>())
525992cb984SSergei Barannikov     if (isVectorTypeBased(FT->getReturnType().getTypePtr(), /*IsParam*/true))
526992cb984SSergei Barannikov       return true;
527992cb984SSergei Barannikov   if (const FunctionProtoType *Proto = Ty->getAs<FunctionProtoType>())
528992cb984SSergei Barannikov     for (const auto &ParamType : Proto->getParamTypes())
529992cb984SSergei Barannikov       if (isVectorTypeBased(ParamType.getTypePtr(), /*IsParam*/true))
530992cb984SSergei Barannikov         return true;
531992cb984SSergei Barannikov 
532992cb984SSergei Barannikov   return false;
533992cb984SSergei Barannikov }
534992cb984SSergei Barannikov 
535992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo>
536992cb984SSergei Barannikov CodeGen::createSystemZTargetCodeGenInfo(CodeGenModule &CGM, bool HasVector,
537992cb984SSergei Barannikov                                         bool SoftFloatABI) {
538992cb984SSergei Barannikov   return std::make_unique<SystemZTargetCodeGenInfo>(CGM.getTypes(), HasVector,
539992cb984SSergei Barannikov                                                     SoftFloatABI);
540992cb984SSergei Barannikov }
541