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"
11#include "clang/Basic/Builtins.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
31 bool isPromotableIntegerTypeForABI(QualType Ty) const;
32 bool isCompoundType(QualType Ty) const;
33 bool isVectorArgumentType(QualType Ty) const;
34 llvm::Type *getFPArgumentType(QualType Ty, uint64_t Size) const;
35 QualType GetSingleElementType(QualType Ty) const;
36
37 ABIArgInfo classifyReturnType(QualType RetTy) const;
38 ABIArgInfo classifyArgumentType(QualType ArgTy) const;
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)
61 : TargetCodeGenInfo(
62 std::make_unique<SystemZABIInfo>(args&: CGT, args&: HasVector, args&: SoftFloatABI)),
63 Ctx(CGT.getContext()) {
64 SwiftInfo =
65 std::make_unique<SwiftABIInfo>(args&: CGT, /*SwiftErrorInRegister=*/args: 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(Behavior: llvm::Module::Warning,
77 Key: "s390x-visible-vector-ABI", Val: 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>(Val: D)) {
90 if (VD->isExternallyVisible())
91 handleExternallyVisibleObjABI(Ty: VD->getType().getTypePtr(), M,
92 /*IsParam*/false);
93 }
94 else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: D)) {
95 if (FD->isExternallyVisible())
96 handleExternallyVisibleObjABI(Ty: 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->isHalfTy() || Ty->isFloatTy() || Ty->isDoubleTy() ||
111 Ty->isFP128Ty()) {
112 llvm::Module &M = CGM.getModule();
113 auto &Ctx = M.getContext();
114 llvm::Function *TDCFunc = llvm::Intrinsic::getOrInsertDeclaration(
115 M: &M, id: llvm::Intrinsic::s390_tdc, Tys: Ty);
116 unsigned TDCBits = 0;
117 switch (BuiltinID) {
118 case Builtin::BI__builtin_isnan:
119 TDCBits = 0xf;
120 break;
121 case Builtin::BIfinite:
122 case Builtin::BI__finite:
123 case Builtin::BIfinitef:
124 case Builtin::BI__finitef:
125 case Builtin::BIfinitel:
126 case Builtin::BI__finitel:
127 case Builtin::BI__builtin_isfinite:
128 TDCBits = 0xfc0;
129 break;
130 case Builtin::BI__builtin_isinf:
131 TDCBits = 0x30;
132 break;
133 default:
134 break;
135 }
136 if (TDCBits)
137 return Builder.CreateCall(
138 Callee: TDCFunc,
139 Args: {V, llvm::ConstantInt::get(Ty: llvm::Type::getInt64Ty(C&: Ctx), V: TDCBits)});
140 }
141 return nullptr;
142 }
143};
144}
145
146bool SystemZABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const {
147 // Treat an enum type as its underlying type.
148 if (const EnumType *EnumTy = Ty->getAs<EnumType>())
149 Ty = EnumTy->getDecl()->getIntegerType();
150
151 // Promotable integer types are required to be promoted by the ABI.
152 if (ABIInfo::isPromotableIntegerTypeForABI(Ty))
153 return true;
154
155 if (const auto *EIT = Ty->getAs<BitIntType>())
156 if (EIT->getNumBits() < 64)
157 return true;
158
159 // 32-bit values must also be promoted.
160 if (const BuiltinType *BT = Ty->getAs<BuiltinType>())
161 switch (BT->getKind()) {
162 case BuiltinType::Int:
163 case BuiltinType::UInt:
164 return true;
165 default:
166 return false;
167 }
168 return false;
169}
170
171bool SystemZABIInfo::isCompoundType(QualType Ty) const {
172 return (Ty->isAnyComplexType() ||
173 Ty->isVectorType() ||
174 isAggregateTypeForABI(T: Ty));
175}
176
177bool SystemZABIInfo::isVectorArgumentType(QualType Ty) const {
178 return (HasVector &&
179 Ty->isVectorType() &&
180 getContext().getTypeSize(T: Ty) <= 128);
181}
182
183// The Size argument will in case of af an overaligned single element struct
184// reflect the overalignment value. In such a case the argument will be
185// passed using the type matching Size.
186llvm::Type *SystemZABIInfo::getFPArgumentType(QualType Ty,
187 uint64_t Size) const {
188 if (IsSoftFloatABI)
189 return nullptr;
190
191 if (const BuiltinType *BT = Ty->getAs<BuiltinType>())
192 switch (BT->getKind()) {
193 case BuiltinType::Float16:
194 if (Size == 16)
195 return llvm::Type::getHalfTy(C&: getVMContext());
196 LLVM_FALLTHROUGH;
197 case BuiltinType::Float:
198 if (Size == 32)
199 return llvm::Type::getFloatTy(C&: getVMContext());
200 LLVM_FALLTHROUGH;
201 case BuiltinType::Double:
202 return llvm::Type::getDoubleTy(C&: getVMContext());
203 default:
204 return nullptr;
205 }
206
207 return nullptr;
208}
209
210QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const {
211 const RecordType *RT = Ty->getAs<RecordType>();
212
213 if (RT && RT->isStructureOrClassType()) {
214 const RecordDecl *RD = RT->getDecl();
215 QualType Found;
216
217 // If this is a C++ record, check the bases first.
218 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(Val: RD))
219 if (CXXRD->hasDefinition())
220 for (const auto &I : CXXRD->bases()) {
221 QualType Base = I.getType();
222
223 // Empty bases don't affect things either way.
224 if (isEmptyRecord(Context&: getContext(), T: Base, AllowArrays: true))
225 continue;
226
227 if (!Found.isNull())
228 return Ty;
229 Found = GetSingleElementType(Ty: Base);
230 }
231
232 // Check the fields.
233 for (const auto *FD : RD->fields()) {
234 // Unlike isSingleElementStruct(), empty structure and array fields
235 // do count. So do anonymous bitfields that aren't zero-sized.
236
237 // Like isSingleElementStruct(), ignore C++20 empty data members.
238 if (FD->hasAttr<NoUniqueAddressAttr>() &&
239 isEmptyRecord(Context&: getContext(), T: FD->getType(), AllowArrays: true))
240 continue;
241
242 // Unlike isSingleElementStruct(), arrays do not count.
243 // Nested structures still do though.
244 if (!Found.isNull())
245 return Ty;
246 Found = GetSingleElementType(Ty: FD->getType());
247 }
248
249 // Unlike isSingleElementStruct(), trailing padding is allowed.
250 // An 8-byte aligned struct s { float f; } is passed as a double.
251 if (!Found.isNull())
252 return Found;
253 }
254
255 return Ty;
256}
257
258RValue SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
259 QualType Ty, AggValueSlot Slot) const {
260 // Assume that va_list type is correct; should be pointer to LLVM type:
261 // struct {
262 // i64 __gpr;
263 // i64 __fpr;
264 // i8 *__overflow_arg_area;
265 // i8 *__reg_save_area;
266 // };
267
268 // Every non-vector argument occupies 8 bytes and is passed by preference
269 // in either GPRs or FPRs. Vector arguments occupy 8 or 16 bytes and are
270 // always passed on the stack.
271 const SystemZTargetCodeGenInfo &SZCGI =
272 static_cast<const SystemZTargetCodeGenInfo &>(
273 CGT.getCGM().getTargetCodeGenInfo());
274 Ty = getContext().getCanonicalType(T: Ty);
275 auto TyInfo = getContext().getTypeInfoInChars(T: Ty);
276 llvm::Type *ArgTy = CGF.ConvertTypeForMem(T: Ty);
277 llvm::Type *DirectTy = ArgTy;
278 ABIArgInfo AI = classifyArgumentType(ArgTy: Ty);
279 bool IsIndirect = AI.isIndirect();
280 bool InFPRs = false;
281 bool IsVector = false;
282 CharUnits UnpaddedSize;
283 CharUnits DirectAlign;
284 SZCGI.handleExternallyVisibleObjABI(Ty: Ty.getTypePtr(), M&: CGT.getCGM(),
285 /*IsParam*/true);
286 if (IsIndirect) {
287 DirectTy = llvm::PointerType::getUnqual(C&: DirectTy->getContext());
288 UnpaddedSize = DirectAlign = CharUnits::fromQuantity(Quantity: 8);
289 } else {
290 if (AI.getCoerceToType())
291 ArgTy = AI.getCoerceToType();
292 InFPRs = (!IsSoftFloatABI &&
293 (ArgTy->isHalfTy() || ArgTy->isFloatTy() || ArgTy->isDoubleTy()));
294 IsVector = ArgTy->isVectorTy();
295 UnpaddedSize = TyInfo.Width;
296 DirectAlign = TyInfo.Align;
297 }
298 CharUnits PaddedSize = CharUnits::fromQuantity(Quantity: 8);
299 if (IsVector && UnpaddedSize > PaddedSize)
300 PaddedSize = CharUnits::fromQuantity(Quantity: 16);
301 assert((UnpaddedSize <= PaddedSize) && "Invalid argument size.");
302
303 CharUnits Padding = (PaddedSize - UnpaddedSize);
304
305 llvm::Type *IndexTy = CGF.Int64Ty;
306 llvm::Value *PaddedSizeV =
307 llvm::ConstantInt::get(Ty: IndexTy, V: PaddedSize.getQuantity());
308
309 if (IsVector) {
310 // Work out the address of a vector argument on the stack.
311 // Vector arguments are always passed in the high bits of a
312 // single (8 byte) or double (16 byte) stack slot.
313 Address OverflowArgAreaPtr =
314 CGF.Builder.CreateStructGEP(Addr: VAListAddr, Index: 2, Name: "overflow_arg_area_ptr");
315 Address OverflowArgArea =
316 Address(CGF.Builder.CreateLoad(Addr: OverflowArgAreaPtr, Name: "overflow_arg_area"),
317 CGF.Int8Ty, TyInfo.Align);
318 Address MemAddr = OverflowArgArea.withElementType(ElemTy: DirectTy);
319
320 // Update overflow_arg_area_ptr pointer
321 llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP(
322 Ty: OverflowArgArea.getElementType(), Ptr: OverflowArgArea.emitRawPointer(CGF),
323 IdxList: PaddedSizeV, Name: "overflow_arg_area");
324 CGF.Builder.CreateStore(Val: NewOverflowArgArea, Addr: OverflowArgAreaPtr);
325
326 return CGF.EmitLoadOfAnyValue(V: CGF.MakeAddrLValue(Addr: MemAddr, T: Ty), Slot);
327 }
328
329 assert(PaddedSize.getQuantity() == 8);
330
331 unsigned MaxRegs, RegCountField, RegSaveIndex;
332 CharUnits RegPadding;
333 if (InFPRs) {
334 MaxRegs = 4; // Maximum of 4 FPR arguments
335 RegCountField = 1; // __fpr
336 RegSaveIndex = 16; // save offset for f0
337 RegPadding = CharUnits(); // floats are passed in the high bits of an FPR
338 } else {
339 MaxRegs = 5; // Maximum of 5 GPR arguments
340 RegCountField = 0; // __gpr
341 RegSaveIndex = 2; // save offset for r2
342 RegPadding = Padding; // values are passed in the low bits of a GPR
343 }
344
345 Address RegCountPtr =
346 CGF.Builder.CreateStructGEP(Addr: VAListAddr, Index: RegCountField, Name: "reg_count_ptr");
347 llvm::Value *RegCount = CGF.Builder.CreateLoad(Addr: RegCountPtr, Name: "reg_count");
348 llvm::Value *MaxRegsV = llvm::ConstantInt::get(Ty: IndexTy, V: MaxRegs);
349 llvm::Value *InRegs = CGF.Builder.CreateICmpULT(LHS: RegCount, RHS: MaxRegsV,
350 Name: "fits_in_regs");
351
352 llvm::BasicBlock *InRegBlock = CGF.createBasicBlock(name: "vaarg.in_reg");
353 llvm::BasicBlock *InMemBlock = CGF.createBasicBlock(name: "vaarg.in_mem");
354 llvm::BasicBlock *ContBlock = CGF.createBasicBlock(name: "vaarg.end");
355 CGF.Builder.CreateCondBr(Cond: InRegs, True: InRegBlock, False: InMemBlock);
356
357 // Emit code to load the value if it was passed in registers.
358 CGF.EmitBlock(BB: InRegBlock);
359
360 // Work out the address of an argument register.
361 llvm::Value *ScaledRegCount =
362 CGF.Builder.CreateMul(LHS: RegCount, RHS: PaddedSizeV, Name: "scaled_reg_count");
363 llvm::Value *RegBase =
364 llvm::ConstantInt::get(Ty: IndexTy, V: RegSaveIndex * PaddedSize.getQuantity()
365 + RegPadding.getQuantity());
366 llvm::Value *RegOffset =
367 CGF.Builder.CreateAdd(LHS: ScaledRegCount, RHS: RegBase, Name: "reg_offset");
368 Address RegSaveAreaPtr =
369 CGF.Builder.CreateStructGEP(Addr: VAListAddr, Index: 3, Name: "reg_save_area_ptr");
370 llvm::Value *RegSaveArea =
371 CGF.Builder.CreateLoad(Addr: RegSaveAreaPtr, Name: "reg_save_area");
372 Address RawRegAddr(
373 CGF.Builder.CreateGEP(Ty: CGF.Int8Ty, Ptr: RegSaveArea, IdxList: RegOffset, Name: "raw_reg_addr"),
374 CGF.Int8Ty, PaddedSize);
375 Address RegAddr = RawRegAddr.withElementType(ElemTy: DirectTy);
376
377 // Update the register count
378 llvm::Value *One = llvm::ConstantInt::get(Ty: IndexTy, V: 1);
379 llvm::Value *NewRegCount =
380 CGF.Builder.CreateAdd(LHS: RegCount, RHS: One, Name: "reg_count");
381 CGF.Builder.CreateStore(Val: NewRegCount, Addr: RegCountPtr);
382 CGF.EmitBranch(Block: ContBlock);
383
384 // Emit code to load the value if it was passed in memory.
385 CGF.EmitBlock(BB: InMemBlock);
386
387 // Work out the address of a stack argument.
388 Address OverflowArgAreaPtr =
389 CGF.Builder.CreateStructGEP(Addr: VAListAddr, Index: 2, Name: "overflow_arg_area_ptr");
390 Address OverflowArgArea =
391 Address(CGF.Builder.CreateLoad(Addr: OverflowArgAreaPtr, Name: "overflow_arg_area"),
392 CGF.Int8Ty, PaddedSize);
393 Address RawMemAddr =
394 CGF.Builder.CreateConstByteGEP(Addr: OverflowArgArea, Offset: Padding, Name: "raw_mem_addr");
395 Address MemAddr = RawMemAddr.withElementType(ElemTy: DirectTy);
396
397 // Update overflow_arg_area_ptr pointer
398 llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP(
399 Ty: OverflowArgArea.getElementType(), Ptr: OverflowArgArea.emitRawPointer(CGF),
400 IdxList: PaddedSizeV, Name: "overflow_arg_area");
401 CGF.Builder.CreateStore(Val: NewOverflowArgArea, Addr: OverflowArgAreaPtr);
402 CGF.EmitBranch(Block: ContBlock);
403
404 // Return the appropriate result.
405 CGF.EmitBlock(BB: ContBlock);
406 Address ResAddr = emitMergePHI(CGF, Addr1: RegAddr, Block1: InRegBlock, Addr2: MemAddr, Block2: InMemBlock,
407 Name: "va_arg.addr");
408
409 if (IsIndirect)
410 ResAddr = Address(CGF.Builder.CreateLoad(Addr: ResAddr, Name: "indirect_arg"), ArgTy,
411 TyInfo.Align);
412
413 return CGF.EmitLoadOfAnyValue(V: CGF.MakeAddrLValue(Addr: ResAddr, T: Ty), Slot);
414}
415
416ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const {
417 if (RetTy->isVoidType())
418 return ABIArgInfo::getIgnore();
419 if (isVectorArgumentType(Ty: RetTy))
420 return ABIArgInfo::getDirect();
421 if (isCompoundType(Ty: RetTy) || getContext().getTypeSize(T: RetTy) > 64)
422 return getNaturalAlignIndirect(Ty: RetTy, AddrSpace: getDataLayout().getAllocaAddrSpace());
423 return (isPromotableIntegerTypeForABI(Ty: RetTy) ? ABIArgInfo::getExtend(Ty: RetTy)
424 : ABIArgInfo::getDirect());
425}
426
427ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
428 // Handle transparent union types.
429 Ty = useFirstFieldIfTransparentUnion(Ty);
430
431 // Handle the generic C++ ABI.
432 if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(T: Ty, CXXABI&: getCXXABI()))
433 return getNaturalAlignIndirect(Ty, AddrSpace: getDataLayout().getAllocaAddrSpace(),
434 ByVal: RAA == CGCXXABI::RAA_DirectInMemory);
435
436 // Integers and enums are extended to full register width.
437 if (isPromotableIntegerTypeForABI(Ty))
438 return ABIArgInfo::getExtend(Ty, T: CGT.ConvertType(T: Ty));
439
440 // Handle vector types and vector-like structure types. Note that
441 // as opposed to float-like structure types, we do not allow any
442 // padding for vector-like structures, so verify the sizes match.
443 uint64_t Size = getContext().getTypeSize(T: Ty);
444 QualType SingleElementTy = GetSingleElementType(Ty);
445 if (isVectorArgumentType(Ty: SingleElementTy) &&
446 getContext().getTypeSize(T: SingleElementTy) == Size)
447 return ABIArgInfo::getDirect(T: CGT.ConvertType(T: SingleElementTy));
448
449 // Values that are not 1, 2, 4 or 8 bytes in size are passed indirectly.
450 if (Size != 8 && Size != 16 && Size != 32 && Size != 64)
451 return getNaturalAlignIndirect(Ty, AddrSpace: getDataLayout().getAllocaAddrSpace(),
452 /*ByVal=*/false);
453
454 // Handle small structures.
455 if (const RecordType *RT = Ty->getAs<RecordType>()) {
456 // Structures with flexible arrays have variable length, so really
457 // fail the size test above.
458 const RecordDecl *RD = RT->getDecl();
459 if (RD->hasFlexibleArrayMember())
460 return getNaturalAlignIndirect(Ty, AddrSpace: getDataLayout().getAllocaAddrSpace(),
461 /*ByVal=*/false);
462
463 // The structure is passed as an unextended integer, a half, a float,
464 // or a double.
465 if (llvm::Type *FPArgTy = getFPArgumentType(Ty: SingleElementTy, Size)) {
466 assert(Size == 16 || Size == 32 || Size == 64);
467 return ABIArgInfo::getDirect(T: FPArgTy);
468 } else {
469 llvm::IntegerType *PassTy = llvm::IntegerType::get(C&: getVMContext(), NumBits: Size);
470 return Size <= 32 ? ABIArgInfo::getNoExtend(T: PassTy)
471 : ABIArgInfo::getDirect(T: PassTy);
472 }
473 }
474
475 // Non-structure compounds are passed indirectly.
476 if (isCompoundType(Ty))
477 return getNaturalAlignIndirect(Ty, AddrSpace: getDataLayout().getAllocaAddrSpace(),
478 /*ByVal=*/false);
479
480 return ABIArgInfo::getDirect(T: nullptr);
481}
482
483void SystemZABIInfo::computeInfo(CGFunctionInfo &FI) const {
484 const SystemZTargetCodeGenInfo &SZCGI =
485 static_cast<const SystemZTargetCodeGenInfo &>(
486 CGT.getCGM().getTargetCodeGenInfo());
487 if (!getCXXABI().classifyReturnType(FI))
488 FI.getReturnInfo() = classifyReturnType(RetTy: FI.getReturnType());
489 unsigned Idx = 0;
490 for (auto &I : FI.arguments()) {
491 I.info = classifyArgumentType(Ty: I.type);
492 if (FI.isVariadic() && Idx++ >= FI.getNumRequiredArgs())
493 // Check if a vararg vector argument is passed, in which case the
494 // vector ABI becomes visible as the va_list could be passed on to
495 // other functions.
496 SZCGI.handleExternallyVisibleObjABI(Ty: I.type.getTypePtr(), M&: CGT.getCGM(),
497 /*IsParam*/true);
498 }
499}
500
501bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty,
502 bool IsParam) const {
503 if (!SeenTypes.insert(x: Ty).second)
504 return false;
505
506 if (IsParam) {
507 // A narrow (<16 bytes) vector will as a parameter also expose the ABI as
508 // it will be passed in a vector register. A wide (>16 bytes) vector will
509 // be passed via "hidden" pointer where any extra alignment is not
510 // required (per GCC).
511 const Type *SingleEltTy = getABIInfo<SystemZABIInfo>()
512 .GetSingleElementType(Ty: QualType(Ty, 0))
513 .getTypePtr();
514 bool SingleVecEltStruct = SingleEltTy != Ty && SingleEltTy->isVectorType() &&
515 Ctx.getTypeSize(T: SingleEltTy) == Ctx.getTypeSize(T: Ty);
516 if (Ty->isVectorType() || SingleVecEltStruct)
517 return Ctx.getTypeSize(T: Ty) / 8 <= 16;
518 }
519
520 // Assume pointers are dereferenced.
521 while (Ty->isPointerType() || Ty->isArrayType())
522 Ty = Ty->getPointeeOrArrayElementType();
523
524 // Vectors >= 16 bytes expose the ABI through alignment requirements.
525 if (Ty->isVectorType() && Ctx.getTypeSize(T: Ty) / 8 >= 16)
526 return true;
527
528 if (const auto *RecordTy = Ty->getAs<RecordType>()) {
529 const RecordDecl *RD = RecordTy->getDecl();
530 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(Val: RD))
531 if (CXXRD->hasDefinition())
532 for (const auto &I : CXXRD->bases())
533 if (isVectorTypeBased(Ty: I.getType().getTypePtr(), /*IsParam*/false))
534 return true;
535 for (const auto *FD : RD->fields())
536 if (isVectorTypeBased(Ty: FD->getType().getTypePtr(), /*IsParam*/false))
537 return true;
538 }
539
540 if (const auto *FT = Ty->getAs<FunctionType>())
541 if (isVectorTypeBased(Ty: FT->getReturnType().getTypePtr(), /*IsParam*/true))
542 return true;
543 if (const FunctionProtoType *Proto = Ty->getAs<FunctionProtoType>())
544 for (const auto &ParamType : Proto->getParamTypes())
545 if (isVectorTypeBased(Ty: ParamType.getTypePtr(), /*IsParam*/true))
546 return true;
547
548 return false;
549}
550
551std::unique_ptr<TargetCodeGenInfo>
552CodeGen::createSystemZTargetCodeGenInfo(CodeGenModule &CGM, bool HasVector,
553 bool SoftFloatABI) {
554 return std::make_unique<SystemZTargetCodeGenInfo>(args&: CGM.getTypes(), args&: HasVector,
555 args&: SoftFloatABI);
556}
557