Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/CodeGen/ABIInfoImpl.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- ABIInfoImpl.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
11
using namespace clang;
12
using namespace clang::CodeGen;
13
14
// Pin the vtable to this file.
15
0
DefaultABIInfo::~DefaultABIInfo() = default;
16
17
0
ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {
18
0
  Ty = useFirstFieldIfTransparentUnion(Ty);
19
20
0
  if (isAggregateTypeForABI(Ty)) {
21
    // Records with non-trivial destructors/copy-constructors should not be
22
    // passed by value.
23
0
    if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
24
0
      return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
25
26
0
    return getNaturalAlignIndirect(Ty);
27
0
  }
28
29
  // Treat an enum type as its underlying type.
30
0
  if (const EnumType *EnumTy = Ty->getAs<EnumType>())
31
0
    Ty = EnumTy->getDecl()->getIntegerType();
32
33
0
  ASTContext &Context = getContext();
34
0
  if (const auto *EIT = Ty->getAs<BitIntType>())
35
0
    if (EIT->getNumBits() >
36
0
        Context.getTypeSize(Context.getTargetInfo().hasInt128Type()
37
0
                                ? Context.Int128Ty
38
0
                                : Context.LongLongTy))
39
0
      return getNaturalAlignIndirect(Ty);
40
41
0
  return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty)
42
0
                                            : ABIArgInfo::getDirect());
43
0
}
44
45
0
ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const {
46
0
  if (RetTy->isVoidType())
47
0
    return ABIArgInfo::getIgnore();
48
49
0
  if (isAggregateTypeForABI(RetTy))
50
0
    return getNaturalAlignIndirect(RetTy);
51
52
  // Treat an enum type as its underlying type.
53
0
  if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
54
0
    RetTy = EnumTy->getDecl()->getIntegerType();
55
56
0
  if (const auto *EIT = RetTy->getAs<BitIntType>())
57
0
    if (EIT->getNumBits() >
58
0
        getContext().getTypeSize(getContext().getTargetInfo().hasInt128Type()
59
0
                                     ? getContext().Int128Ty
60
0
                                     : getContext().LongLongTy))
61
0
      return getNaturalAlignIndirect(RetTy);
62
63
0
  return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)
64
0
                                               : ABIArgInfo::getDirect());
65
0
}
66
67
0
void DefaultABIInfo::computeInfo(CGFunctionInfo &FI) const {
68
0
  if (!getCXXABI().classifyReturnType(FI))
69
0
    FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
70
0
  for (auto &I : FI.arguments())
71
0
    I.info = classifyArgumentType(I.type);
72
0
}
73
74
Address DefaultABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
75
0
                                  QualType Ty) const {
76
0
  return EmitVAArgInstr(CGF, VAListAddr, Ty, classifyArgumentType(Ty));
77
0
}
78
79
ABIArgInfo CodeGen::coerceToIntArray(QualType Ty, ASTContext &Context,
80
0
                                     llvm::LLVMContext &LLVMContext) {
81
  // Alignment and Size are measured in bits.
82
0
  const uint64_t Size = Context.getTypeSize(Ty);
83
0
  const uint64_t Alignment = Context.getTypeAlign(Ty);
84
0
  llvm::Type *IntType = llvm::Type::getIntNTy(LLVMContext, Alignment);
85
0
  const uint64_t NumElements = (Size + Alignment - 1) / Alignment;
86
0
  return ABIArgInfo::getDirect(llvm::ArrayType::get(IntType, NumElements));
87
0
}
88
89
void CodeGen::AssignToArrayRange(CodeGen::CGBuilderTy &Builder,
90
                                 llvm::Value *Array, llvm::Value *Value,
91
0
                                 unsigned FirstIndex, unsigned LastIndex) {
92
  // Alternatively, we could emit this as a loop in the source.
93
0
  for (unsigned I = FirstIndex; I <= LastIndex; ++I) {
94
0
    llvm::Value *Cell =
95
0
        Builder.CreateConstInBoundsGEP1_32(Builder.getInt8Ty(), Array, I);
96
0
    Builder.CreateAlignedStore(Value, Cell, CharUnits::One());
97
0
  }
98
0
}
99
100
0
bool CodeGen::isAggregateTypeForABI(QualType T) {
101
0
  return !CodeGenFunction::hasScalarEvaluationKind(T) ||
102
0
         T->isMemberFunctionPointerType();
103
0
}
104
105
0
llvm::Type *CodeGen::getVAListElementType(CodeGenFunction &CGF) {
106
0
  return CGF.ConvertTypeForMem(
107
0
      CGF.getContext().getBuiltinVaListType()->getPointeeType());
108
0
}
109
110
CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(const RecordType *RT,
111
0
                                                CGCXXABI &CXXABI) {
112
0
  const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
113
0
  if (!RD) {
114
0
    if (!RT->getDecl()->canPassInRegisters())
115
0
      return CGCXXABI::RAA_Indirect;
116
0
    return CGCXXABI::RAA_Default;
117
0
  }
118
0
  return CXXABI.getRecordArgABI(RD);
119
0
}
120
121
0
CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(QualType T, CGCXXABI &CXXABI) {
122
0
  const RecordType *RT = T->getAs<RecordType>();
123
0
  if (!RT)
124
0
    return CGCXXABI::RAA_Default;
125
0
  return getRecordArgABI(RT, CXXABI);
126
0
}
127
128
bool CodeGen::classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI,
129
0
                                 const ABIInfo &Info) {
130
0
  QualType Ty = FI.getReturnType();
131
132
0
  if (const auto *RT = Ty->getAs<RecordType>())
133
0
    if (!isa<CXXRecordDecl>(RT->getDecl()) &&
134
0
        !RT->getDecl()->canPassInRegisters()) {
135
0
      FI.getReturnInfo() = Info.getNaturalAlignIndirect(Ty);
136
0
      return true;
137
0
    }
138
139
0
  return CXXABI.classifyReturnType(FI);
140
0
}
141
142
0
QualType CodeGen::useFirstFieldIfTransparentUnion(QualType Ty) {
143
0
  if (const RecordType *UT = Ty->getAsUnionType()) {
144
0
    const RecordDecl *UD = UT->getDecl();
145
0
    if (UD->hasAttr<TransparentUnionAttr>()) {
146
0
      assert(!UD->field_empty() && "sema created an empty transparent union");
147
0
      return UD->field_begin()->getType();
148
0
    }
149
0
  }
150
0
  return Ty;
151
0
}
152
153
llvm::Value *CodeGen::emitRoundPointerUpToAlignment(CodeGenFunction &CGF,
154
                                                    llvm::Value *Ptr,
155
0
                                                    CharUnits Align) {
156
  // OverflowArgArea = (OverflowArgArea + Align - 1) & -Align;
157
0
  llvm::Value *RoundUp = CGF.Builder.CreateConstInBoundsGEP1_32(
158
0
      CGF.Builder.getInt8Ty(), Ptr, Align.getQuantity() - 1);
159
0
  return CGF.Builder.CreateIntrinsic(
160
0
      llvm::Intrinsic::ptrmask, {CGF.AllocaInt8PtrTy, CGF.IntPtrTy},
161
0
      {RoundUp, llvm::ConstantInt::get(CGF.IntPtrTy, -Align.getQuantity())},
162
0
      nullptr, Ptr->getName() + ".aligned");
163
0
}
164
165
Address
166
CodeGen::emitVoidPtrDirectVAArg(CodeGenFunction &CGF, Address VAListAddr,
167
                                llvm::Type *DirectTy, CharUnits DirectSize,
168
                                CharUnits DirectAlign, CharUnits SlotSize,
169
0
                                bool AllowHigherAlign, bool ForceRightAdjust) {
170
  // Cast the element type to i8* if necessary.  Some platforms define
171
  // va_list as a struct containing an i8* instead of just an i8*.
172
0
  if (VAListAddr.getElementType() != CGF.Int8PtrTy)
173
0
    VAListAddr = VAListAddr.withElementType(CGF.Int8PtrTy);
174
175
0
  llvm::Value *Ptr = CGF.Builder.CreateLoad(VAListAddr, "argp.cur");
176
177
  // If the CC aligns values higher than the slot size, do so if needed.
178
0
  Address Addr = Address::invalid();
179
0
  if (AllowHigherAlign && DirectAlign > SlotSize) {
180
0
    Addr = Address(emitRoundPointerUpToAlignment(CGF, Ptr, DirectAlign),
181
0
                   CGF.Int8Ty, DirectAlign);
182
0
  } else {
183
0
    Addr = Address(Ptr, CGF.Int8Ty, SlotSize);
184
0
  }
185
186
  // Advance the pointer past the argument, then store that back.
187
0
  CharUnits FullDirectSize = DirectSize.alignTo(SlotSize);
188
0
  Address NextPtr =
189
0
      CGF.Builder.CreateConstInBoundsByteGEP(Addr, FullDirectSize, "argp.next");
190
0
  CGF.Builder.CreateStore(NextPtr.getPointer(), VAListAddr);
191
192
  // If the argument is smaller than a slot, and this is a big-endian
193
  // target, the argument will be right-adjusted in its slot.
194
0
  if (DirectSize < SlotSize && CGF.CGM.getDataLayout().isBigEndian() &&
195
0
      (!DirectTy->isStructTy() || ForceRightAdjust)) {
196
0
    Addr = CGF.Builder.CreateConstInBoundsByteGEP(Addr, SlotSize - DirectSize);
197
0
  }
198
199
0
  return Addr.withElementType(DirectTy);
200
0
}
201
202
Address CodeGen::emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr,
203
                                  QualType ValueTy, bool IsIndirect,
204
                                  TypeInfoChars ValueInfo,
205
                                  CharUnits SlotSizeAndAlign,
206
                                  bool AllowHigherAlign,
207
0
                                  bool ForceRightAdjust) {
208
  // The size and alignment of the value that was passed directly.
209
0
  CharUnits DirectSize, DirectAlign;
210
0
  if (IsIndirect) {
211
0
    DirectSize = CGF.getPointerSize();
212
0
    DirectAlign = CGF.getPointerAlign();
213
0
  } else {
214
0
    DirectSize = ValueInfo.Width;
215
0
    DirectAlign = ValueInfo.Align;
216
0
  }
217
218
  // Cast the address we've calculated to the right type.
219
0
  llvm::Type *DirectTy = CGF.ConvertTypeForMem(ValueTy), *ElementTy = DirectTy;
220
0
  if (IsIndirect) {
221
0
    unsigned AllocaAS = CGF.CGM.getDataLayout().getAllocaAddrSpace();
222
0
    DirectTy = llvm::PointerType::get(CGF.getLLVMContext(), AllocaAS);
223
0
  }
224
225
0
  Address Addr = emitVoidPtrDirectVAArg(CGF, VAListAddr, DirectTy, DirectSize,
226
0
                                        DirectAlign, SlotSizeAndAlign,
227
0
                                        AllowHigherAlign, ForceRightAdjust);
228
229
0
  if (IsIndirect) {
230
0
    Addr = Address(CGF.Builder.CreateLoad(Addr), ElementTy, ValueInfo.Align);
231
0
  }
232
233
0
  return Addr;
234
0
}
235
236
Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1,
237
                              llvm::BasicBlock *Block1, Address Addr2,
238
                              llvm::BasicBlock *Block2,
239
0
                              const llvm::Twine &Name) {
240
0
  assert(Addr1.getType() == Addr2.getType());
241
0
  llvm::PHINode *PHI = CGF.Builder.CreatePHI(Addr1.getType(), 2, Name);
242
0
  PHI->addIncoming(Addr1.getPointer(), Block1);
243
0
  PHI->addIncoming(Addr2.getPointer(), Block2);
244
0
  CharUnits Align = std::min(Addr1.getAlignment(), Addr2.getAlignment());
245
0
  return Address(PHI, Addr1.getElementType(), Align);
246
0
}
247
248
bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD,
249
0
                           bool AllowArrays, bool AsIfNoUniqueAddr) {
250
0
  if (FD->isUnnamedBitfield())
251
0
    return true;
252
253
0
  QualType FT = FD->getType();
254
255
  // Constant arrays of empty records count as empty, strip them off.
256
  // Constant arrays of zero length always count as empty.
257
0
  bool WasArray = false;
258
0
  if (AllowArrays)
259
0
    while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) {
260
0
      if (AT->getSize() == 0)
261
0
        return true;
262
0
      FT = AT->getElementType();
263
      // The [[no_unique_address]] special case below does not apply to
264
      // arrays of C++ empty records, so we need to remember this fact.
265
0
      WasArray = true;
266
0
    }
267
268
0
  const RecordType *RT = FT->getAs<RecordType>();
269
0
  if (!RT)
270
0
    return false;
271
272
  // C++ record fields are never empty, at least in the Itanium ABI.
273
  //
274
  // FIXME: We should use a predicate for whether this behavior is true in the
275
  // current ABI.
276
  //
277
  // The exception to the above rule are fields marked with the
278
  // [[no_unique_address]] attribute (since C++20).  Those do count as empty
279
  // according to the Itanium ABI.  The exception applies only to records,
280
  // not arrays of records, so we must also check whether we stripped off an
281
  // array type above.
282
0
  if (isa<CXXRecordDecl>(RT->getDecl()) &&
283
0
      (WasArray || (!AsIfNoUniqueAddr && !FD->hasAttr<NoUniqueAddressAttr>())))
284
0
    return false;
285
286
0
  return isEmptyRecord(Context, FT, AllowArrays, AsIfNoUniqueAddr);
287
0
}
288
289
bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays,
290
0
                            bool AsIfNoUniqueAddr) {
291
0
  const RecordType *RT = T->getAs<RecordType>();
292
0
  if (!RT)
293
0
    return false;
294
0
  const RecordDecl *RD = RT->getDecl();
295
0
  if (RD->hasFlexibleArrayMember())
296
0
    return false;
297
298
  // If this is a C++ record, check the bases first.
299
0
  if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
300
0
    for (const auto &I : CXXRD->bases())
301
0
      if (!isEmptyRecord(Context, I.getType(), true, AsIfNoUniqueAddr))
302
0
        return false;
303
304
0
  for (const auto *I : RD->fields())
305
0
    if (!isEmptyField(Context, I, AllowArrays, AsIfNoUniqueAddr))
306
0
      return false;
307
0
  return true;
308
0
}
309
310
0
const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) {
311
0
  const RecordType *RT = T->getAs<RecordType>();
312
0
  if (!RT)
313
0
    return nullptr;
314
315
0
  const RecordDecl *RD = RT->getDecl();
316
0
  if (RD->hasFlexibleArrayMember())
317
0
    return nullptr;
318
319
0
  const Type *Found = nullptr;
320
321
  // If this is a C++ record, check the bases first.
322
0
  if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
323
0
    for (const auto &I : CXXRD->bases()) {
324
      // Ignore empty records.
325
0
      if (isEmptyRecord(Context, I.getType(), true))
326
0
        continue;
327
328
      // If we already found an element then this isn't a single-element struct.
329
0
      if (Found)
330
0
        return nullptr;
331
332
      // If this is non-empty and not a single element struct, the composite
333
      // cannot be a single element struct.
334
0
      Found = isSingleElementStruct(I.getType(), Context);
335
0
      if (!Found)
336
0
        return nullptr;
337
0
    }
338
0
  }
339
340
  // Check for single element.
341
0
  for (const auto *FD : RD->fields()) {
342
0
    QualType FT = FD->getType();
343
344
    // Ignore empty fields.
345
0
    if (isEmptyField(Context, FD, true))
346
0
      continue;
347
348
    // If we already found an element then this isn't a single-element
349
    // struct.
350
0
    if (Found)
351
0
      return nullptr;
352
353
    // Treat single element arrays as the element.
354
0
    while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) {
355
0
      if (AT->getSize().getZExtValue() != 1)
356
0
        break;
357
0
      FT = AT->getElementType();
358
0
    }
359
360
0
    if (!isAggregateTypeForABI(FT)) {
361
0
      Found = FT.getTypePtr();
362
0
    } else {
363
0
      Found = isSingleElementStruct(FT, Context);
364
0
      if (!Found)
365
0
        return nullptr;
366
0
    }
367
0
  }
368
369
  // We don't consider a struct a single-element struct if it has
370
  // padding beyond the element type.
371
0
  if (Found && Context.getTypeSize(Found) != Context.getTypeSize(T))
372
0
    return nullptr;
373
374
0
  return Found;
375
0
}
376
377
Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr,
378
0
                                QualType Ty, const ABIArgInfo &AI) {
379
  // This default implementation defers to the llvm backend's va_arg
380
  // instruction. It can handle only passing arguments directly
381
  // (typically only handled in the backend for primitive types), or
382
  // aggregates passed indirectly by pointer (NOTE: if the "byval"
383
  // flag has ABI impact in the callee, this implementation cannot
384
  // work.)
385
386
  // Only a few cases are covered here at the moment -- those needed
387
  // by the default abi.
388
0
  llvm::Value *Val;
389
390
0
  if (AI.isIndirect()) {
391
0
    assert(!AI.getPaddingType() &&
392
0
           "Unexpected PaddingType seen in arginfo in generic VAArg emitter!");
393
0
    assert(
394
0
        !AI.getIndirectRealign() &&
395
0
        "Unexpected IndirectRealign seen in arginfo in generic VAArg emitter!");
396
397
0
    auto TyInfo = CGF.getContext().getTypeInfoInChars(Ty);
398
0
    CharUnits TyAlignForABI = TyInfo.Align;
399
400
0
    llvm::Type *ElementTy = CGF.ConvertTypeForMem(Ty);
401
0
    llvm::Type *BaseTy = llvm::PointerType::getUnqual(ElementTy);
402
0
    llvm::Value *Addr =
403
0
        CGF.Builder.CreateVAArg(VAListAddr.getPointer(), BaseTy);
404
0
    return Address(Addr, ElementTy, TyAlignForABI);
405
0
  } else {
406
0
    assert((AI.isDirect() || AI.isExtend()) &&
407
0
           "Unexpected ArgInfo Kind in generic VAArg emitter!");
408
409
0
    assert(!AI.getInReg() &&
410
0
           "Unexpected InReg seen in arginfo in generic VAArg emitter!");
411
0
    assert(!AI.getPaddingType() &&
412
0
           "Unexpected PaddingType seen in arginfo in generic VAArg emitter!");
413
0
    assert(!AI.getDirectOffset() &&
414
0
           "Unexpected DirectOffset seen in arginfo in generic VAArg emitter!");
415
0
    assert(!AI.getCoerceToType() &&
416
0
           "Unexpected CoerceToType seen in arginfo in generic VAArg emitter!");
417
418
0
    Address Temp = CGF.CreateMemTemp(Ty, "varet");
419
0
    Val = CGF.Builder.CreateVAArg(VAListAddr.getPointer(),
420
0
                                  CGF.ConvertTypeForMem(Ty));
421
0
    CGF.Builder.CreateStore(Val, Temp);
422
0
    return Temp;
423
0
  }
424
0
}
425
426
0
bool CodeGen::isSIMDVectorType(ASTContext &Context, QualType Ty) {
427
0
  return Ty->getAs<VectorType>() && Context.getTypeSize(Ty) == 128;
428
0
}
429
430
0
bool CodeGen::isRecordWithSIMDVectorType(ASTContext &Context, QualType Ty) {
431
0
  const RecordType *RT = Ty->getAs<RecordType>();
432
0
  if (!RT)
433
0
    return false;
434
0
  const RecordDecl *RD = RT->getDecl();
435
436
  // If this is a C++ record, check the bases first.
437
0
  if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
438
0
    for (const auto &I : CXXRD->bases())
439
0
      if (!isRecordWithSIMDVectorType(Context, I.getType()))
440
0
        return false;
441
442
0
  for (const auto *i : RD->fields()) {
443
0
    QualType FT = i->getType();
444
445
0
    if (isSIMDVectorType(Context, FT))
446
0
      return true;
447
448
0
    if (isRecordWithSIMDVectorType(Context, FT))
449
0
      return true;
450
0
  }
451
452
0
  return false;
453
0
}