Coverage Report

Created: 2024-01-17 10:31

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