Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/CodeGen/Targets/Mips.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- Mips.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
//===----------------------------------------------------------------------===//
16
// MIPS ABI Implementation.  This works for both little-endian and
17
// big-endian variants.
18
//===----------------------------------------------------------------------===//
19
20
namespace {
21
class MipsABIInfo : public ABIInfo {
22
  bool IsO32;
23
  const unsigned MinABIStackAlignInBytes, StackAlignInBytes;
24
  void CoerceToIntArgs(uint64_t TySize,
25
                       SmallVectorImpl<llvm::Type *> &ArgList) const;
26
  llvm::Type* HandleAggregates(QualType Ty, uint64_t TySize) const;
27
  llvm::Type* returnAggregateInRegs(QualType RetTy, uint64_t Size) const;
28
  llvm::Type* getPaddingType(uint64_t Align, uint64_t Offset) const;
29
public:
30
  MipsABIInfo(CodeGenTypes &CGT, bool _IsO32) :
31
    ABIInfo(CGT), IsO32(_IsO32), MinABIStackAlignInBytes(IsO32 ? 4 : 8),
32
0
    StackAlignInBytes(IsO32 ? 8 : 16) {}
33
34
  ABIArgInfo classifyReturnType(QualType RetTy) const;
35
  ABIArgInfo classifyArgumentType(QualType RetTy, uint64_t &Offset) const;
36
  void computeInfo(CGFunctionInfo &FI) const override;
37
  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
38
                    QualType Ty) const override;
39
  ABIArgInfo extendType(QualType Ty) const;
40
};
41
42
class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
43
  unsigned SizeOfUnwindException;
44
public:
45
  MIPSTargetCodeGenInfo(CodeGenTypes &CGT, bool IsO32)
46
      : TargetCodeGenInfo(std::make_unique<MipsABIInfo>(CGT, IsO32)),
47
0
        SizeOfUnwindException(IsO32 ? 24 : 32) {}
48
49
0
  int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
50
0
    return 29;
51
0
  }
52
53
  void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
54
0
                           CodeGen::CodeGenModule &CGM) const override {
55
0
    const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
56
0
    if (!FD) return;
57
0
    llvm::Function *Fn = cast<llvm::Function>(GV);
58
59
0
    if (FD->hasAttr<MipsLongCallAttr>())
60
0
      Fn->addFnAttr("long-call");
61
0
    else if (FD->hasAttr<MipsShortCallAttr>())
62
0
      Fn->addFnAttr("short-call");
63
64
    // Other attributes do not have a meaning for declarations.
65
0
    if (GV->isDeclaration())
66
0
      return;
67
68
0
    if (FD->hasAttr<Mips16Attr>()) {
69
0
      Fn->addFnAttr("mips16");
70
0
    }
71
0
    else if (FD->hasAttr<NoMips16Attr>()) {
72
0
      Fn->addFnAttr("nomips16");
73
0
    }
74
75
0
    if (FD->hasAttr<MicroMipsAttr>())
76
0
      Fn->addFnAttr("micromips");
77
0
    else if (FD->hasAttr<NoMicroMipsAttr>())
78
0
      Fn->addFnAttr("nomicromips");
79
80
0
    const MipsInterruptAttr *Attr = FD->getAttr<MipsInterruptAttr>();
81
0
    if (!Attr)
82
0
      return;
83
84
0
    const char *Kind;
85
0
    switch (Attr->getInterrupt()) {
86
0
    case MipsInterruptAttr::eic:     Kind = "eic"; break;
87
0
    case MipsInterruptAttr::sw0:     Kind = "sw0"; break;
88
0
    case MipsInterruptAttr::sw1:     Kind = "sw1"; break;
89
0
    case MipsInterruptAttr::hw0:     Kind = "hw0"; break;
90
0
    case MipsInterruptAttr::hw1:     Kind = "hw1"; break;
91
0
    case MipsInterruptAttr::hw2:     Kind = "hw2"; break;
92
0
    case MipsInterruptAttr::hw3:     Kind = "hw3"; break;
93
0
    case MipsInterruptAttr::hw4:     Kind = "hw4"; break;
94
0
    case MipsInterruptAttr::hw5:     Kind = "hw5"; break;
95
0
    }
96
97
0
    Fn->addFnAttr("interrupt", Kind);
98
99
0
  }
100
101
  bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
102
                               llvm::Value *Address) const override;
103
104
0
  unsigned getSizeOfUnwindException() const override {
105
0
    return SizeOfUnwindException;
106
0
  }
107
};
108
}
109
110
void MipsABIInfo::CoerceToIntArgs(
111
0
    uint64_t TySize, SmallVectorImpl<llvm::Type *> &ArgList) const {
112
0
  llvm::IntegerType *IntTy =
113
0
    llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
114
115
  // Add (TySize / MinABIStackAlignInBytes) args of IntTy.
116
0
  for (unsigned N = TySize / (MinABIStackAlignInBytes * 8); N; --N)
117
0
    ArgList.push_back(IntTy);
118
119
  // If necessary, add one more integer type to ArgList.
120
0
  unsigned R = TySize % (MinABIStackAlignInBytes * 8);
121
122
0
  if (R)
123
0
    ArgList.push_back(llvm::IntegerType::get(getVMContext(), R));
124
0
}
125
126
// In N32/64, an aligned double precision floating point field is passed in
127
// a register.
128
0
llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const {
129
0
  SmallVector<llvm::Type*, 8> ArgList, IntArgList;
130
131
0
  if (IsO32) {
132
0
    CoerceToIntArgs(TySize, ArgList);
133
0
    return llvm::StructType::get(getVMContext(), ArgList);
134
0
  }
135
136
0
  if (Ty->isComplexType())
137
0
    return CGT.ConvertType(Ty);
138
139
0
  const RecordType *RT = Ty->getAs<RecordType>();
140
141
  // Unions/vectors are passed in integer registers.
142
0
  if (!RT || !RT->isStructureOrClassType()) {
143
0
    CoerceToIntArgs(TySize, ArgList);
144
0
    return llvm::StructType::get(getVMContext(), ArgList);
145
0
  }
146
147
0
  const RecordDecl *RD = RT->getDecl();
148
0
  const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
149
0
  assert(!(TySize % 8) && "Size of structure must be multiple of 8.");
150
151
0
  uint64_t LastOffset = 0;
152
0
  unsigned idx = 0;
153
0
  llvm::IntegerType *I64 = llvm::IntegerType::get(getVMContext(), 64);
154
155
  // Iterate over fields in the struct/class and check if there are any aligned
156
  // double fields.
157
0
  for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
158
0
       i != e; ++i, ++idx) {
159
0
    const QualType Ty = i->getType();
160
0
    const BuiltinType *BT = Ty->getAs<BuiltinType>();
161
162
0
    if (!BT || BT->getKind() != BuiltinType::Double)
163
0
      continue;
164
165
0
    uint64_t Offset = Layout.getFieldOffset(idx);
166
0
    if (Offset % 64) // Ignore doubles that are not aligned.
167
0
      continue;
168
169
    // Add ((Offset - LastOffset) / 64) args of type i64.
170
0
    for (unsigned j = (Offset - LastOffset) / 64; j > 0; --j)
171
0
      ArgList.push_back(I64);
172
173
    // Add double type.
174
0
    ArgList.push_back(llvm::Type::getDoubleTy(getVMContext()));
175
0
    LastOffset = Offset + 64;
176
0
  }
177
178
0
  CoerceToIntArgs(TySize - LastOffset, IntArgList);
179
0
  ArgList.append(IntArgList.begin(), IntArgList.end());
180
181
0
  return llvm::StructType::get(getVMContext(), ArgList);
182
0
}
183
184
llvm::Type *MipsABIInfo::getPaddingType(uint64_t OrigOffset,
185
0
                                        uint64_t Offset) const {
186
0
  if (OrigOffset + MinABIStackAlignInBytes > Offset)
187
0
    return nullptr;
188
189
0
  return llvm::IntegerType::get(getVMContext(), (Offset - OrigOffset) * 8);
190
0
}
191
192
ABIArgInfo
193
0
MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
194
0
  Ty = useFirstFieldIfTransparentUnion(Ty);
195
196
0
  uint64_t OrigOffset = Offset;
197
0
  uint64_t TySize = getContext().getTypeSize(Ty);
198
0
  uint64_t Align = getContext().getTypeAlign(Ty) / 8;
199
200
0
  Align = std::clamp(Align, (uint64_t)MinABIStackAlignInBytes,
201
0
                     (uint64_t)StackAlignInBytes);
202
0
  unsigned CurrOffset = llvm::alignTo(Offset, Align);
203
0
  Offset = CurrOffset + llvm::alignTo(TySize, Align * 8) / 8;
204
205
0
  if (isAggregateTypeForABI(Ty) || Ty->isVectorType()) {
206
    // Ignore empty aggregates.
207
0
    if (TySize == 0)
208
0
      return ABIArgInfo::getIgnore();
209
210
0
    if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
211
0
      Offset = OrigOffset + MinABIStackAlignInBytes;
212
0
      return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
213
0
    }
214
215
    // If we have reached here, aggregates are passed directly by coercing to
216
    // another structure type. Padding is inserted if the offset of the
217
    // aggregate is unaligned.
218
0
    ABIArgInfo ArgInfo =
219
0
        ABIArgInfo::getDirect(HandleAggregates(Ty, TySize), 0,
220
0
                              getPaddingType(OrigOffset, CurrOffset));
221
0
    ArgInfo.setInReg(true);
222
0
    return ArgInfo;
223
0
  }
224
225
  // Treat an enum type as its underlying type.
226
0
  if (const EnumType *EnumTy = Ty->getAs<EnumType>())
227
0
    Ty = EnumTy->getDecl()->getIntegerType();
228
229
  // Make sure we pass indirectly things that are too large.
230
0
  if (const auto *EIT = Ty->getAs<BitIntType>())
231
0
    if (EIT->getNumBits() > 128 ||
232
0
        (EIT->getNumBits() > 64 &&
233
0
         !getContext().getTargetInfo().hasInt128Type()))
234
0
      return getNaturalAlignIndirect(Ty);
235
236
  // All integral types are promoted to the GPR width.
237
0
  if (Ty->isIntegralOrEnumerationType())
238
0
    return extendType(Ty);
239
240
0
  return ABIArgInfo::getDirect(
241
0
      nullptr, 0, IsO32 ? nullptr : getPaddingType(OrigOffset, CurrOffset));
242
0
}
243
244
llvm::Type*
245
0
MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const {
246
0
  const RecordType *RT = RetTy->getAs<RecordType>();
247
0
  SmallVector<llvm::Type*, 8> RTList;
248
249
0
  if (RT && RT->isStructureOrClassType()) {
250
0
    const RecordDecl *RD = RT->getDecl();
251
0
    const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
252
0
    unsigned FieldCnt = Layout.getFieldCount();
253
254
    // N32/64 returns struct/classes in floating point registers if the
255
    // following conditions are met:
256
    // 1. The size of the struct/class is no larger than 128-bit.
257
    // 2. The struct/class has one or two fields all of which are floating
258
    //    point types.
259
    // 3. The offset of the first field is zero (this follows what gcc does).
260
    //
261
    // Any other composite results are returned in integer registers.
262
    //
263
0
    if (FieldCnt && (FieldCnt <= 2) && !Layout.getFieldOffset(0)) {
264
0
      RecordDecl::field_iterator b = RD->field_begin(), e = RD->field_end();
265
0
      for (; b != e; ++b) {
266
0
        const BuiltinType *BT = b->getType()->getAs<BuiltinType>();
267
268
0
        if (!BT || !BT->isFloatingPoint())
269
0
          break;
270
271
0
        RTList.push_back(CGT.ConvertType(b->getType()));
272
0
      }
273
274
0
      if (b == e)
275
0
        return llvm::StructType::get(getVMContext(), RTList,
276
0
                                     RD->hasAttr<PackedAttr>());
277
278
0
      RTList.clear();
279
0
    }
280
0
  }
281
282
0
  CoerceToIntArgs(Size, RTList);
283
0
  return llvm::StructType::get(getVMContext(), RTList);
284
0
}
285
286
0
ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const {
287
0
  uint64_t Size = getContext().getTypeSize(RetTy);
288
289
0
  if (RetTy->isVoidType())
290
0
    return ABIArgInfo::getIgnore();
291
292
  // O32 doesn't treat zero-sized structs differently from other structs.
293
  // However, N32/N64 ignores zero sized return values.
294
0
  if (!IsO32 && Size == 0)
295
0
    return ABIArgInfo::getIgnore();
296
297
0
  if (isAggregateTypeForABI(RetTy) || RetTy->isVectorType()) {
298
0
    if (Size <= 128) {
299
0
      if (RetTy->isAnyComplexType())
300
0
        return ABIArgInfo::getDirect();
301
302
      // O32 returns integer vectors in registers and N32/N64 returns all small
303
      // aggregates in registers.
304
0
      if (!IsO32 ||
305
0
          (RetTy->isVectorType() && !RetTy->hasFloatingRepresentation())) {
306
0
        ABIArgInfo ArgInfo =
307
0
            ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size));
308
0
        ArgInfo.setInReg(true);
309
0
        return ArgInfo;
310
0
      }
311
0
    }
312
313
0
    return getNaturalAlignIndirect(RetTy);
314
0
  }
315
316
  // Treat an enum type as its underlying type.
317
0
  if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
318
0
    RetTy = EnumTy->getDecl()->getIntegerType();
319
320
  // Make sure we pass indirectly things that are too large.
321
0
  if (const auto *EIT = RetTy->getAs<BitIntType>())
322
0
    if (EIT->getNumBits() > 128 ||
323
0
        (EIT->getNumBits() > 64 &&
324
0
         !getContext().getTargetInfo().hasInt128Type()))
325
0
      return getNaturalAlignIndirect(RetTy);
326
327
0
  if (isPromotableIntegerTypeForABI(RetTy))
328
0
    return ABIArgInfo::getExtend(RetTy);
329
330
0
  if ((RetTy->isUnsignedIntegerOrEnumerationType() ||
331
0
      RetTy->isSignedIntegerOrEnumerationType()) && Size == 32 && !IsO32)
332
0
    return ABIArgInfo::getSignExtend(RetTy);
333
334
0
  return ABIArgInfo::getDirect();
335
0
}
336
337
0
void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const {
338
0
  ABIArgInfo &RetInfo = FI.getReturnInfo();
339
0
  if (!getCXXABI().classifyReturnType(FI))
340
0
    RetInfo = classifyReturnType(FI.getReturnType());
341
342
  // Check if a pointer to an aggregate is passed as a hidden argument.
343
0
  uint64_t Offset = RetInfo.isIndirect() ? MinABIStackAlignInBytes : 0;
344
345
0
  for (auto &I : FI.arguments())
346
0
    I.info = classifyArgumentType(I.type, Offset);
347
0
}
348
349
Address MipsABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
350
0
                               QualType OrigTy) const {
351
0
  QualType Ty = OrigTy;
352
353
  // Integer arguments are promoted to 32-bit on O32 and 64-bit on N32/N64.
354
  // Pointers are also promoted in the same way but this only matters for N32.
355
0
  unsigned SlotSizeInBits = IsO32 ? 32 : 64;
356
0
  unsigned PtrWidth = getTarget().getPointerWidth(LangAS::Default);
357
0
  bool DidPromote = false;
358
0
  if ((Ty->isIntegerType() &&
359
0
          getContext().getIntWidth(Ty) < SlotSizeInBits) ||
360
0
      (Ty->isPointerType() && PtrWidth < SlotSizeInBits)) {
361
0
    DidPromote = true;
362
0
    Ty = getContext().getIntTypeForBitwidth(SlotSizeInBits,
363
0
                                            Ty->isSignedIntegerType());
364
0
  }
365
366
0
  auto TyInfo = getContext().getTypeInfoInChars(Ty);
367
368
  // The alignment of things in the argument area is never larger than
369
  // StackAlignInBytes.
370
0
  TyInfo.Align =
371
0
    std::min(TyInfo.Align, CharUnits::fromQuantity(StackAlignInBytes));
372
373
  // MinABIStackAlignInBytes is the size of argument slots on the stack.
374
0
  CharUnits ArgSlotSize = CharUnits::fromQuantity(MinABIStackAlignInBytes);
375
376
0
  Address Addr = emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
377
0
                          TyInfo, ArgSlotSize, /*AllowHigherAlign*/ true);
378
379
380
  // If there was a promotion, "unpromote" into a temporary.
381
  // TODO: can we just use a pointer into a subset of the original slot?
382
0
  if (DidPromote) {
383
0
    Address Temp = CGF.CreateMemTemp(OrigTy, "vaarg.promotion-temp");
384
0
    llvm::Value *Promoted = CGF.Builder.CreateLoad(Addr);
385
386
    // Truncate down to the right width.
387
0
    llvm::Type *IntTy = (OrigTy->isIntegerType() ? Temp.getElementType()
388
0
                                                 : CGF.IntPtrTy);
389
0
    llvm::Value *V = CGF.Builder.CreateTrunc(Promoted, IntTy);
390
0
    if (OrigTy->isPointerType())
391
0
      V = CGF.Builder.CreateIntToPtr(V, Temp.getElementType());
392
393
0
    CGF.Builder.CreateStore(V, Temp);
394
0
    Addr = Temp;
395
0
  }
396
397
0
  return Addr;
398
0
}
399
400
0
ABIArgInfo MipsABIInfo::extendType(QualType Ty) const {
401
0
  int TySize = getContext().getTypeSize(Ty);
402
403
  // MIPS64 ABI requires unsigned 32 bit integers to be sign extended.
404
0
  if (Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32)
405
0
    return ABIArgInfo::getSignExtend(Ty);
406
407
0
  return ABIArgInfo::getExtend(Ty);
408
0
}
409
410
bool
411
MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
412
0
                                               llvm::Value *Address) const {
413
  // This information comes from gcc's implementation, which seems to
414
  // as canonical as it gets.
415
416
  // Everything on MIPS is 4 bytes.  Double-precision FP registers
417
  // are aliased to pairs of single-precision FP registers.
418
0
  llvm::Value *Four8 = llvm::ConstantInt::get(CGF.Int8Ty, 4);
419
420
  // 0-31 are the general purpose registers, $0 - $31.
421
  // 32-63 are the floating-point registers, $f0 - $f31.
422
  // 64 and 65 are the multiply/divide registers, $hi and $lo.
423
  // 66 is the (notional, I think) register for signal-handler return.
424
0
  AssignToArrayRange(CGF.Builder, Address, Four8, 0, 65);
425
426
  // 67-74 are the floating-point status registers, $fcc0 - $fcc7.
427
  // They are one bit wide and ignored here.
428
429
  // 80-111 are the coprocessor 0 registers, $c0r0 - $c0r31.
430
  // (coprocessor 1 is the FP unit)
431
  // 112-143 are the coprocessor 2 registers, $c2r0 - $c2r31.
432
  // 144-175 are the coprocessor 3 registers, $c3r0 - $c3r31.
433
  // 176-181 are the DSP accumulator registers.
434
0
  AssignToArrayRange(CGF.Builder, Address, Four8, 80, 181);
435
0
  return false;
436
0
}
437
438
std::unique_ptr<TargetCodeGenInfo>
439
0
CodeGen::createMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32) {
440
0
  return std::make_unique<MIPSTargetCodeGenInfo>(CGM.getTypes(), IsOS32);
441
0
}