Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/CodeGen/Targets/LoongArch.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- LoongArch.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
12
using namespace clang;
13
using namespace clang::CodeGen;
14
15
// LoongArch ABI Implementation. Documented at
16
// https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html
17
//
18
//===----------------------------------------------------------------------===//
19
20
namespace {
21
class LoongArchABIInfo : public DefaultABIInfo {
22
private:
23
  // Size of the integer ('r') registers in bits.
24
  unsigned GRLen;
25
  // Size of the floating point ('f') registers in bits.
26
  unsigned FRLen;
27
  // Number of general-purpose argument registers.
28
  static const int NumGARs = 8;
29
  // Number of floating-point argument registers.
30
  static const int NumFARs = 8;
31
  bool detectFARsEligibleStructHelper(QualType Ty, CharUnits CurOff,
32
                                      llvm::Type *&Field1Ty,
33
                                      CharUnits &Field1Off,
34
                                      llvm::Type *&Field2Ty,
35
                                      CharUnits &Field2Off) const;
36
37
public:
38
  LoongArchABIInfo(CodeGen::CodeGenTypes &CGT, unsigned GRLen, unsigned FRLen)
39
0
      : DefaultABIInfo(CGT), GRLen(GRLen), FRLen(FRLen) {}
40
41
  void computeInfo(CGFunctionInfo &FI) const override;
42
43
  ABIArgInfo classifyArgumentType(QualType Ty, bool IsFixed, int &GARsLeft,
44
                                  int &FARsLeft) const;
45
  ABIArgInfo classifyReturnType(QualType RetTy) const;
46
47
  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
48
                    QualType Ty) const override;
49
50
  ABIArgInfo extendType(QualType Ty) const;
51
52
  bool detectFARsEligibleStruct(QualType Ty, llvm::Type *&Field1Ty,
53
                                CharUnits &Field1Off, llvm::Type *&Field2Ty,
54
                                CharUnits &Field2Off, int &NeededArgGPRs,
55
                                int &NeededArgFPRs) const;
56
  ABIArgInfo coerceAndExpandFARsEligibleStruct(llvm::Type *Field1Ty,
57
                                               CharUnits Field1Off,
58
                                               llvm::Type *Field2Ty,
59
                                               CharUnits Field2Off) const;
60
};
61
} // end anonymous namespace
62
63
0
void LoongArchABIInfo::computeInfo(CGFunctionInfo &FI) const {
64
0
  QualType RetTy = FI.getReturnType();
65
0
  if (!getCXXABI().classifyReturnType(FI))
66
0
    FI.getReturnInfo() = classifyReturnType(RetTy);
67
68
  // IsRetIndirect is true if classifyArgumentType indicated the value should
69
  // be passed indirect, or if the type size is a scalar greater than 2*GRLen
70
  // and not a complex type with elements <= FRLen. e.g. fp128 is passed direct
71
  // in LLVM IR, relying on the backend lowering code to rewrite the argument
72
  // list and pass indirectly on LA32.
73
0
  bool IsRetIndirect = FI.getReturnInfo().getKind() == ABIArgInfo::Indirect;
74
0
  if (!IsRetIndirect && RetTy->isScalarType() &&
75
0
      getContext().getTypeSize(RetTy) > (2 * GRLen)) {
76
0
    if (RetTy->isComplexType() && FRLen) {
77
0
      QualType EltTy = RetTy->castAs<ComplexType>()->getElementType();
78
0
      IsRetIndirect = getContext().getTypeSize(EltTy) > FRLen;
79
0
    } else {
80
      // This is a normal scalar > 2*GRLen, such as fp128 on LA32.
81
0
      IsRetIndirect = true;
82
0
    }
83
0
  }
84
85
  // We must track the number of GARs and FARs used in order to conform to the
86
  // LoongArch ABI. As GAR usage is different for variadic arguments, we must
87
  // also track whether we are examining a vararg or not.
88
0
  int GARsLeft = IsRetIndirect ? NumGARs - 1 : NumGARs;
89
0
  int FARsLeft = FRLen ? NumFARs : 0;
90
0
  int NumFixedArgs = FI.getNumRequiredArgs();
91
92
0
  int ArgNum = 0;
93
0
  for (auto &ArgInfo : FI.arguments()) {
94
0
    ArgInfo.info = classifyArgumentType(
95
0
        ArgInfo.type, /*IsFixed=*/ArgNum < NumFixedArgs, GARsLeft, FARsLeft);
96
0
    ArgNum++;
97
0
  }
98
0
}
99
100
// Returns true if the struct is a potential candidate to be passed in FARs (and
101
// GARs). If this function returns true, the caller is responsible for checking
102
// that if there is only a single field then that field is a float.
103
bool LoongArchABIInfo::detectFARsEligibleStructHelper(
104
    QualType Ty, CharUnits CurOff, llvm::Type *&Field1Ty, CharUnits &Field1Off,
105
0
    llvm::Type *&Field2Ty, CharUnits &Field2Off) const {
106
0
  bool IsInt = Ty->isIntegralOrEnumerationType();
107
0
  bool IsFloat = Ty->isRealFloatingType();
108
109
0
  if (IsInt || IsFloat) {
110
0
    uint64_t Size = getContext().getTypeSize(Ty);
111
0
    if (IsInt && Size > GRLen)
112
0
      return false;
113
    // Can't be eligible if larger than the FP registers. Half precision isn't
114
    // currently supported on LoongArch and the ABI hasn't been confirmed, so
115
    // default to the integer ABI in that case.
116
0
    if (IsFloat && (Size > FRLen || Size < 32))
117
0
      return false;
118
    // Can't be eligible if an integer type was already found (int+int pairs
119
    // are not eligible).
120
0
    if (IsInt && Field1Ty && Field1Ty->isIntegerTy())
121
0
      return false;
122
0
    if (!Field1Ty) {
123
0
      Field1Ty = CGT.ConvertType(Ty);
124
0
      Field1Off = CurOff;
125
0
      return true;
126
0
    }
127
0
    if (!Field2Ty) {
128
0
      Field2Ty = CGT.ConvertType(Ty);
129
0
      Field2Off = CurOff;
130
0
      return true;
131
0
    }
132
0
    return false;
133
0
  }
134
135
0
  if (auto CTy = Ty->getAs<ComplexType>()) {
136
0
    if (Field1Ty)
137
0
      return false;
138
0
    QualType EltTy = CTy->getElementType();
139
0
    if (getContext().getTypeSize(EltTy) > FRLen)
140
0
      return false;
141
0
    Field1Ty = CGT.ConvertType(EltTy);
142
0
    Field1Off = CurOff;
143
0
    Field2Ty = Field1Ty;
144
0
    Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy);
145
0
    return true;
146
0
  }
147
148
0
  if (const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) {
149
0
    uint64_t ArraySize = ATy->getSize().getZExtValue();
150
0
    QualType EltTy = ATy->getElementType();
151
    // Non-zero-length arrays of empty records make the struct ineligible to be
152
    // passed via FARs in C++.
153
0
    if (const auto *RTy = EltTy->getAs<RecordType>()) {
154
0
      if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getDecl()) &&
155
0
          isEmptyRecord(getContext(), EltTy, true, true))
156
0
        return false;
157
0
    }
158
0
    CharUnits EltSize = getContext().getTypeSizeInChars(EltTy);
159
0
    for (uint64_t i = 0; i < ArraySize; ++i) {
160
0
      if (!detectFARsEligibleStructHelper(EltTy, CurOff, Field1Ty, Field1Off,
161
0
                                          Field2Ty, Field2Off))
162
0
        return false;
163
0
      CurOff += EltSize;
164
0
    }
165
0
    return true;
166
0
  }
167
168
0
  if (const auto *RTy = Ty->getAs<RecordType>()) {
169
    // Structures with either a non-trivial destructor or a non-trivial
170
    // copy constructor are not eligible for the FP calling convention.
171
0
    if (getRecordArgABI(Ty, CGT.getCXXABI()))
172
0
      return false;
173
0
    const RecordDecl *RD = RTy->getDecl();
174
0
    if (isEmptyRecord(getContext(), Ty, true, true) &&
175
0
        (!RD->isUnion() || !isa<CXXRecordDecl>(RD)))
176
0
      return true;
177
    // Unions aren't eligible unless they're empty in C (which is caught above).
178
0
    if (RD->isUnion())
179
0
      return false;
180
0
    const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
181
    // If this is a C++ record, check the bases first.
182
0
    if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
183
0
      for (const CXXBaseSpecifier &B : CXXRD->bases()) {
184
0
        const auto *BDecl =
185
0
            cast<CXXRecordDecl>(B.getType()->castAs<RecordType>()->getDecl());
186
0
        if (!detectFARsEligibleStructHelper(
187
0
                B.getType(), CurOff + Layout.getBaseClassOffset(BDecl),
188
0
                Field1Ty, Field1Off, Field2Ty, Field2Off))
189
0
          return false;
190
0
      }
191
0
    }
192
0
    for (const FieldDecl *FD : RD->fields()) {
193
0
      QualType QTy = FD->getType();
194
0
      if (FD->isBitField()) {
195
0
        unsigned BitWidth = FD->getBitWidthValue(getContext());
196
        // Zero-width bitfields are ignored.
197
0
        if (BitWidth == 0)
198
0
          continue;
199
        // Allow a bitfield with a type greater than GRLen as long as the
200
        // bitwidth is GRLen or less.
201
0
        if (getContext().getTypeSize(QTy) > GRLen && BitWidth <= GRLen) {
202
0
          QTy = getContext().getIntTypeForBitwidth(GRLen, false);
203
0
        }
204
0
      }
205
206
0
      if (!detectFARsEligibleStructHelper(
207
0
              QTy,
208
0
              CurOff + getContext().toCharUnitsFromBits(
209
0
                           Layout.getFieldOffset(FD->getFieldIndex())),
210
0
              Field1Ty, Field1Off, Field2Ty, Field2Off))
211
0
        return false;
212
0
    }
213
0
    return Field1Ty != nullptr;
214
0
  }
215
216
0
  return false;
217
0
}
218
219
// Determine if a struct is eligible to be passed in FARs (and GARs) (i.e., when
220
// flattened it contains a single fp value, fp+fp, or int+fp of appropriate
221
// size). If so, NeededFARs and NeededGARs are incremented appropriately.
222
bool LoongArchABIInfo::detectFARsEligibleStruct(
223
    QualType Ty, llvm::Type *&Field1Ty, CharUnits &Field1Off,
224
    llvm::Type *&Field2Ty, CharUnits &Field2Off, int &NeededGARs,
225
0
    int &NeededFARs) const {
226
0
  Field1Ty = nullptr;
227
0
  Field2Ty = nullptr;
228
0
  NeededGARs = 0;
229
0
  NeededFARs = 0;
230
0
  if (!detectFARsEligibleStructHelper(Ty, CharUnits::Zero(), Field1Ty,
231
0
                                      Field1Off, Field2Ty, Field2Off))
232
0
    return false;
233
0
  if (!Field1Ty)
234
0
    return false;
235
  // Not really a candidate if we have a single int but no float.
236
0
  if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy())
237
0
    return false;
238
0
  if (Field1Ty && Field1Ty->isFloatingPointTy())
239
0
    NeededFARs++;
240
0
  else if (Field1Ty)
241
0
    NeededGARs++;
242
0
  if (Field2Ty && Field2Ty->isFloatingPointTy())
243
0
    NeededFARs++;
244
0
  else if (Field2Ty)
245
0
    NeededGARs++;
246
0
  return true;
247
0
}
248
249
// Call getCoerceAndExpand for the two-element flattened struct described by
250
// Field1Ty, Field1Off, Field2Ty, Field2Off. This method will create an
251
// appropriate coerceToType and unpaddedCoerceToType.
252
ABIArgInfo LoongArchABIInfo::coerceAndExpandFARsEligibleStruct(
253
    llvm::Type *Field1Ty, CharUnits Field1Off, llvm::Type *Field2Ty,
254
0
    CharUnits Field2Off) const {
255
0
  SmallVector<llvm::Type *, 3> CoerceElts;
256
0
  SmallVector<llvm::Type *, 2> UnpaddedCoerceElts;
257
0
  if (!Field1Off.isZero())
258
0
    CoerceElts.push_back(llvm::ArrayType::get(
259
0
        llvm::Type::getInt8Ty(getVMContext()), Field1Off.getQuantity()));
260
261
0
  CoerceElts.push_back(Field1Ty);
262
0
  UnpaddedCoerceElts.push_back(Field1Ty);
263
264
0
  if (!Field2Ty) {
265
0
    return ABIArgInfo::getCoerceAndExpand(
266
0
        llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.isZero()),
267
0
        UnpaddedCoerceElts[0]);
268
0
  }
269
270
0
  CharUnits Field2Align =
271
0
      CharUnits::fromQuantity(getDataLayout().getABITypeAlign(Field2Ty));
272
0
  CharUnits Field1End =
273
0
      Field1Off +
274
0
      CharUnits::fromQuantity(getDataLayout().getTypeStoreSize(Field1Ty));
275
0
  CharUnits Field2OffNoPadNoPack = Field1End.alignTo(Field2Align);
276
277
0
  CharUnits Padding = CharUnits::Zero();
278
0
  if (Field2Off > Field2OffNoPadNoPack)
279
0
    Padding = Field2Off - Field2OffNoPadNoPack;
280
0
  else if (Field2Off != Field2Align && Field2Off > Field1End)
281
0
    Padding = Field2Off - Field1End;
282
283
0
  bool IsPacked = !Field2Off.isMultipleOf(Field2Align);
284
285
0
  if (!Padding.isZero())
286
0
    CoerceElts.push_back(llvm::ArrayType::get(
287
0
        llvm::Type::getInt8Ty(getVMContext()), Padding.getQuantity()));
288
289
0
  CoerceElts.push_back(Field2Ty);
290
0
  UnpaddedCoerceElts.push_back(Field2Ty);
291
292
0
  return ABIArgInfo::getCoerceAndExpand(
293
0
      llvm::StructType::get(getVMContext(), CoerceElts, IsPacked),
294
0
      llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked));
295
0
}
296
297
ABIArgInfo LoongArchABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
298
                                                  int &GARsLeft,
299
0
                                                  int &FARsLeft) const {
300
0
  assert(GARsLeft <= NumGARs && "GAR tracking underflow");
301
0
  Ty = useFirstFieldIfTransparentUnion(Ty);
302
303
  // Structures with either a non-trivial destructor or a non-trivial
304
  // copy constructor are always passed indirectly.
305
0
  if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
306
0
    if (GARsLeft)
307
0
      GARsLeft -= 1;
308
0
    return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA ==
309
0
                                           CGCXXABI::RAA_DirectInMemory);
310
0
  }
311
312
0
  uint64_t Size = getContext().getTypeSize(Ty);
313
314
  // Ignore empty struct or union whose size is zero, e.g. `struct { }` in C or
315
  // `struct { int a[0]; }` in C++. In C++, `struct { }` is empty but it's size
316
  // is 1 byte and g++ doesn't ignore it; clang++ matches this behaviour.
317
0
  if (isEmptyRecord(getContext(), Ty, true) && Size == 0)
318
0
    return ABIArgInfo::getIgnore();
319
320
  // Pass floating point values via FARs if possible.
321
0
  if (IsFixed && Ty->isFloatingType() && !Ty->isComplexType() &&
322
0
      FRLen >= Size && FARsLeft) {
323
0
    FARsLeft--;
324
0
    return ABIArgInfo::getDirect();
325
0
  }
326
327
  // Complex types for the *f or *d ABI must be passed directly rather than
328
  // using CoerceAndExpand.
329
0
  if (IsFixed && Ty->isComplexType() && FRLen && FARsLeft >= 2) {
330
0
    QualType EltTy = Ty->castAs<ComplexType>()->getElementType();
331
0
    if (getContext().getTypeSize(EltTy) <= FRLen) {
332
0
      FARsLeft -= 2;
333
0
      return ABIArgInfo::getDirect();
334
0
    }
335
0
  }
336
337
0
  if (IsFixed && FRLen && Ty->isStructureOrClassType()) {
338
0
    llvm::Type *Field1Ty = nullptr;
339
0
    llvm::Type *Field2Ty = nullptr;
340
0
    CharUnits Field1Off = CharUnits::Zero();
341
0
    CharUnits Field2Off = CharUnits::Zero();
342
0
    int NeededGARs = 0;
343
0
    int NeededFARs = 0;
344
0
    bool IsCandidate = detectFARsEligibleStruct(
345
0
        Ty, Field1Ty, Field1Off, Field2Ty, Field2Off, NeededGARs, NeededFARs);
346
0
    if (IsCandidate && NeededGARs <= GARsLeft && NeededFARs <= FARsLeft) {
347
0
      GARsLeft -= NeededGARs;
348
0
      FARsLeft -= NeededFARs;
349
0
      return coerceAndExpandFARsEligibleStruct(Field1Ty, Field1Off, Field2Ty,
350
0
                                               Field2Off);
351
0
    }
352
0
  }
353
354
0
  uint64_t NeededAlign = getContext().getTypeAlign(Ty);
355
  // Determine the number of GARs needed to pass the current argument
356
  // according to the ABI. 2*GRLen-aligned varargs are passed in "aligned"
357
  // register pairs, so may consume 3 registers.
358
0
  int NeededGARs = 1;
359
0
  if (!IsFixed && NeededAlign == 2 * GRLen)
360
0
    NeededGARs = 2 + (GARsLeft % 2);
361
0
  else if (Size > GRLen && Size <= 2 * GRLen)
362
0
    NeededGARs = 2;
363
364
0
  if (NeededGARs > GARsLeft)
365
0
    NeededGARs = GARsLeft;
366
367
0
  GARsLeft -= NeededGARs;
368
369
0
  if (!isAggregateTypeForABI(Ty) && !Ty->isVectorType()) {
370
    // Treat an enum type as its underlying type.
371
0
    if (const EnumType *EnumTy = Ty->getAs<EnumType>())
372
0
      Ty = EnumTy->getDecl()->getIntegerType();
373
374
    // All integral types are promoted to GRLen width.
375
0
    if (Size < GRLen && Ty->isIntegralOrEnumerationType())
376
0
      return extendType(Ty);
377
378
0
    if (const auto *EIT = Ty->getAs<BitIntType>()) {
379
0
      if (EIT->getNumBits() < GRLen)
380
0
        return extendType(Ty);
381
0
      if (EIT->getNumBits() > 128 ||
382
0
          (!getContext().getTargetInfo().hasInt128Type() &&
383
0
           EIT->getNumBits() > 64))
384
0
        return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
385
0
    }
386
387
0
    return ABIArgInfo::getDirect();
388
0
  }
389
390
  // Aggregates which are <= 2*GRLen will be passed in registers if possible,
391
  // so coerce to integers.
392
0
  if (Size <= 2 * GRLen) {
393
    // Use a single GRLen int if possible, 2*GRLen if 2*GRLen alignment is
394
    // required, and a 2-element GRLen array if only GRLen alignment is
395
    // required.
396
0
    if (Size <= GRLen) {
397
0
      return ABIArgInfo::getDirect(
398
0
          llvm::IntegerType::get(getVMContext(), GRLen));
399
0
    }
400
0
    if (getContext().getTypeAlign(Ty) == 2 * GRLen) {
401
0
      return ABIArgInfo::getDirect(
402
0
          llvm::IntegerType::get(getVMContext(), 2 * GRLen));
403
0
    }
404
0
    return ABIArgInfo::getDirect(
405
0
        llvm::ArrayType::get(llvm::IntegerType::get(getVMContext(), GRLen), 2));
406
0
  }
407
0
  return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
408
0
}
409
410
0
ABIArgInfo LoongArchABIInfo::classifyReturnType(QualType RetTy) const {
411
0
  if (RetTy->isVoidType())
412
0
    return ABIArgInfo::getIgnore();
413
  // The rules for return and argument types are the same, so defer to
414
  // classifyArgumentType.
415
0
  int GARsLeft = 2;
416
0
  int FARsLeft = FRLen ? 2 : 0;
417
0
  return classifyArgumentType(RetTy, /*IsFixed=*/true, GARsLeft, FARsLeft);
418
0
}
419
420
Address LoongArchABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
421
0
                                    QualType Ty) const {
422
0
  CharUnits SlotSize = CharUnits::fromQuantity(GRLen / 8);
423
424
  // Empty records are ignored for parameter passing purposes.
425
0
  if (isEmptyRecord(getContext(), Ty, true))
426
0
    return Address(CGF.Builder.CreateLoad(VAListAddr),
427
0
                   CGF.ConvertTypeForMem(Ty), SlotSize);
428
429
0
  auto TInfo = getContext().getTypeInfoInChars(Ty);
430
431
  // Arguments bigger than 2*GRLen bytes are passed indirectly.
432
0
  return emitVoidPtrVAArg(CGF, VAListAddr, Ty,
433
0
                          /*IsIndirect=*/TInfo.Width > 2 * SlotSize, TInfo,
434
0
                          SlotSize,
435
0
                          /*AllowHigherAlign=*/true);
436
0
}
437
438
0
ABIArgInfo LoongArchABIInfo::extendType(QualType Ty) const {
439
0
  int TySize = getContext().getTypeSize(Ty);
440
  // LA64 ABI requires unsigned 32 bit integers to be sign extended.
441
0
  if (GRLen == 64 && Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32)
442
0
    return ABIArgInfo::getSignExtend(Ty);
443
0
  return ABIArgInfo::getExtend(Ty);
444
0
}
445
446
namespace {
447
class LoongArchTargetCodeGenInfo : public TargetCodeGenInfo {
448
public:
449
  LoongArchTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned GRLen,
450
                             unsigned FRLen)
451
      : TargetCodeGenInfo(
452
0
            std::make_unique<LoongArchABIInfo>(CGT, GRLen, FRLen)) {}
453
};
454
} // namespace
455
456
std::unique_ptr<TargetCodeGenInfo>
457
CodeGen::createLoongArchTargetCodeGenInfo(CodeGenModule &CGM, unsigned GRLen,
458
0
                                          unsigned FLen) {
459
0
  return std::make_unique<LoongArchTargetCodeGenInfo>(CGM.getTypes(), GRLen,
460
0
                                                      FLen);
461
0
}