1209139Srpaulo//===- Mips.cpp -----------------------------------------------------------===//
2209139Srpaulo//
3209139Srpaulo// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4209139Srpaulo// See https://llvm.org/LICENSE.txt for license information.
5252726Srpaulo// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6252726Srpaulo//
7209139Srpaulo//===----------------------------------------------------------------------===//
8209139Srpaulo
9209139Srpaulo#include "ABIInfoImpl.h"
10209139Srpaulo#include "TargetInfo.h"
11209139Srpaulo
12209139Srpaulousing namespace clang;
13209139Srpaulousing namespace clang::CodeGen;
14209139Srpaulo
15209139Srpaulo//===----------------------------------------------------------------------===//
16209139Srpaulo// MIPS ABI Implementation.  This works for both little-endian and
17209139Srpaulo// big-endian variants.
18209139Srpaulo//===----------------------------------------------------------------------===//
19209139Srpaulo
20209139Srpaulonamespace {
21209139Srpauloclass MipsABIInfo : public ABIInfo {
22209139Srpaulo  bool IsO32;
23209139Srpaulo  const unsigned MinABIStackAlignInBytes, StackAlignInBytes;
24209139Srpaulo  void CoerceToIntArgs(uint64_t TySize,
25209139Srpaulo                       SmallVectorImpl<llvm::Type *> &ArgList) const;
26209139Srpaulo  llvm::Type* HandleAggregates(QualType Ty, uint64_t TySize) const;
27209139Srpaulo  llvm::Type* returnAggregateInRegs(QualType RetTy, uint64_t Size) const;
28209139Srpaulo  llvm::Type* getPaddingType(uint64_t Align, uint64_t Offset) const;
29209139Srpaulopublic:
30209139Srpaulo  MipsABIInfo(CodeGenTypes &CGT, bool _IsO32) :
31209139Srpaulo    ABIInfo(CGT), IsO32(_IsO32), MinABIStackAlignInBytes(IsO32 ? 4 : 8),
32209139Srpaulo    StackAlignInBytes(IsO32 ? 8 : 16) {}
33209139Srpaulo
34209139Srpaulo  ABIArgInfo classifyReturnType(QualType RetTy) const;
35252726Srpaulo  ABIArgInfo classifyArgumentType(QualType RetTy, uint64_t &Offset) const;
36252726Srpaulo  void computeInfo(CGFunctionInfo &FI) const override;
37252726Srpaulo  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
38252726Srpaulo                    QualType Ty) const override;
39209139Srpaulo  ABIArgInfo extendType(QualType Ty) const;
40252726Srpaulo};
41209139Srpaulo
42209139Srpauloclass MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
43209139Srpaulo  unsigned SizeOfUnwindException;
44209139Srpaulopublic:
45209139Srpaulo  MIPSTargetCodeGenInfo(CodeGenTypes &CGT, bool IsO32)
46209139Srpaulo      : TargetCodeGenInfo(std::make_unique<MipsABIInfo>(CGT, IsO32)),
47209139Srpaulo        SizeOfUnwindException(IsO32 ? 24 : 32) {}
48209139Srpaulo
49209139Srpaulo  int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
50209139Srpaulo    return 29;
51209139Srpaulo  }
52209139Srpaulo
53209139Srpaulo  void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
54209139Srpaulo                           CodeGen::CodeGenModule &CGM) const override {
55209139Srpaulo    const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
56209139Srpaulo    if (!FD) return;
57209139Srpaulo    llvm::Function *Fn = cast<llvm::Function>(GV);
58209139Srpaulo
59209139Srpaulo    if (FD->hasAttr<MipsLongCallAttr>())
60209139Srpaulo      Fn->addFnAttr("long-call");
61209139Srpaulo    else if (FD->hasAttr<MipsShortCallAttr>())
62209139Srpaulo      Fn->addFnAttr("short-call");
63209139Srpaulo
64209139Srpaulo    // Other attributes do not have a meaning for declarations.
65209139Srpaulo    if (GV->isDeclaration())
66209139Srpaulo      return;
67209139Srpaulo
68209139Srpaulo    if (FD->hasAttr<Mips16Attr>()) {
69209139Srpaulo      Fn->addFnAttr("mips16");
70209139Srpaulo    }
71209139Srpaulo    else if (FD->hasAttr<NoMips16Attr>()) {
72209139Srpaulo      Fn->addFnAttr("nomips16");
73209139Srpaulo    }
74209139Srpaulo
75209139Srpaulo    if (FD->hasAttr<MicroMipsAttr>())
76209139Srpaulo      Fn->addFnAttr("micromips");
77209139Srpaulo    else if (FD->hasAttr<NoMicroMipsAttr>())
78209139Srpaulo      Fn->addFnAttr("nomicromips");
79209139Srpaulo
80209139Srpaulo    const MipsInterruptAttr *Attr = FD->getAttr<MipsInterruptAttr>();
81209139Srpaulo    if (!Attr)
82209139Srpaulo      return;
83209139Srpaulo
84209139Srpaulo    const char *Kind;
85209139Srpaulo    switch (Attr->getInterrupt()) {
86209139Srpaulo    case MipsInterruptAttr::eic:     Kind = "eic"; break;
87209139Srpaulo    case MipsInterruptAttr::sw0:     Kind = "sw0"; break;
88209139Srpaulo    case MipsInterruptAttr::sw1:     Kind = "sw1"; break;
89209139Srpaulo    case MipsInterruptAttr::hw0:     Kind = "hw0"; break;
90209139Srpaulo    case MipsInterruptAttr::hw1:     Kind = "hw1"; break;
91209139Srpaulo    case MipsInterruptAttr::hw2:     Kind = "hw2"; break;
92209139Srpaulo    case MipsInterruptAttr::hw3:     Kind = "hw3"; break;
93209139Srpaulo    case MipsInterruptAttr::hw4:     Kind = "hw4"; break;
94209139Srpaulo    case MipsInterruptAttr::hw5:     Kind = "hw5"; break;
95209139Srpaulo    }
96209139Srpaulo
97209139Srpaulo    Fn->addFnAttr("interrupt", Kind);
98209139Srpaulo
99209139Srpaulo  }
100209139Srpaulo
101209139Srpaulo  bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
102209139Srpaulo                               llvm::Value *Address) const override;
103209139Srpaulo
104209139Srpaulo  unsigned getSizeOfUnwindException() const override {
105209139Srpaulo    return SizeOfUnwindException;
106209139Srpaulo  }
107209139Srpaulo};
108209139Srpaulo}
109209139Srpaulo
110209139Srpaulovoid MipsABIInfo::CoerceToIntArgs(
111209139Srpaulo    uint64_t TySize, SmallVectorImpl<llvm::Type *> &ArgList) const {
112209139Srpaulo  llvm::IntegerType *IntTy =
113209139Srpaulo    llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
114209139Srpaulo
115209139Srpaulo  // Add (TySize / MinABIStackAlignInBytes) args of IntTy.
116209139Srpaulo  for (unsigned N = TySize / (MinABIStackAlignInBytes * 8); N; --N)
117209139Srpaulo    ArgList.push_back(IntTy);
118209139Srpaulo
119209139Srpaulo  // If necessary, add one more integer type to ArgList.
120209139Srpaulo  unsigned R = TySize % (MinABIStackAlignInBytes * 8);
121209139Srpaulo
122209139Srpaulo  if (R)
123209139Srpaulo    ArgList.push_back(llvm::IntegerType::get(getVMContext(), R));
124209139Srpaulo}
125209139Srpaulo
126209139Srpaulo// In N32/64, an aligned double precision floating point field is passed in
127209139Srpaulo// a register.
128209139Srpaulollvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const {
129209139Srpaulo  SmallVector<llvm::Type*, 8> ArgList, IntArgList;
130209139Srpaulo
131209139Srpaulo  if (IsO32) {
132209139Srpaulo    CoerceToIntArgs(TySize, ArgList);
133209139Srpaulo    return llvm::StructType::get(getVMContext(), ArgList);
134209139Srpaulo  }
135209139Srpaulo
136209139Srpaulo  if (Ty->isComplexType())
137209139Srpaulo    return CGT.ConvertType(Ty);
138209139Srpaulo
139209139Srpaulo  const RecordType *RT = Ty->getAs<RecordType>();
140209139Srpaulo
141209139Srpaulo  // Unions/vectors are passed in integer registers.
142209139Srpaulo  if (!RT || !RT->isStructureOrClassType()) {
143209139Srpaulo    CoerceToIntArgs(TySize, ArgList);
144209139Srpaulo    return llvm::StructType::get(getVMContext(), ArgList);
145209139Srpaulo  }
146209139Srpaulo
147209139Srpaulo  const RecordDecl *RD = RT->getDecl();
148209139Srpaulo  const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
149209139Srpaulo  assert(!(TySize % 8) && "Size of structure must be multiple of 8.");
150209139Srpaulo
151209139Srpaulo  uint64_t LastOffset = 0;
152209139Srpaulo  unsigned idx = 0;
153209139Srpaulo  llvm::IntegerType *I64 = llvm::IntegerType::get(getVMContext(), 64);
154209139Srpaulo
155209139Srpaulo  // Iterate over fields in the struct/class and check if there are any aligned
156209139Srpaulo  // double fields.
157209139Srpaulo  for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
158209139Srpaulo       i != e; ++i, ++idx) {
159209139Srpaulo    const QualType Ty = i->getType();
160209139Srpaulo    const BuiltinType *BT = Ty->getAs<BuiltinType>();
161209139Srpaulo
162209139Srpaulo    if (!BT || BT->getKind() != BuiltinType::Double)
163209139Srpaulo      continue;
164209139Srpaulo
165209139Srpaulo    uint64_t Offset = Layout.getFieldOffset(idx);
166209139Srpaulo    if (Offset % 64) // Ignore doubles that are not aligned.
167209139Srpaulo      continue;
168209139Srpaulo
169209139Srpaulo    // Add ((Offset - LastOffset) / 64) args of type i64.
170209139Srpaulo    for (unsigned j = (Offset - LastOffset) / 64; j > 0; --j)
171209139Srpaulo      ArgList.push_back(I64);
172209139Srpaulo
173209139Srpaulo    // Add double type.
174209139Srpaulo    ArgList.push_back(llvm::Type::getDoubleTy(getVMContext()));
175209139Srpaulo    LastOffset = Offset + 64;
176209139Srpaulo  }
177209139Srpaulo
178209139Srpaulo  CoerceToIntArgs(TySize - LastOffset, IntArgList);
179209139Srpaulo  ArgList.append(IntArgList.begin(), IntArgList.end());
180209139Srpaulo
181209139Srpaulo  return llvm::StructType::get(getVMContext(), ArgList);
182209139Srpaulo}
183209139Srpaulo
184209139Srpaulollvm::Type *MipsABIInfo::getPaddingType(uint64_t OrigOffset,
185209139Srpaulo                                        uint64_t Offset) const {
186209139Srpaulo  if (OrigOffset + MinABIStackAlignInBytes > Offset)
187209139Srpaulo    return nullptr;
188209139Srpaulo
189209139Srpaulo  return llvm::IntegerType::get(getVMContext(), (Offset - OrigOffset) * 8);
190209139Srpaulo}
191209139Srpaulo
192209139SrpauloABIArgInfo
193209139SrpauloMipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
194209139Srpaulo  Ty = useFirstFieldIfTransparentUnion(Ty);
195209139Srpaulo
196209139Srpaulo  uint64_t OrigOffset = Offset;
197209139Srpaulo  uint64_t TySize = getContext().getTypeSize(Ty);
198209139Srpaulo  uint64_t Align = getContext().getTypeAlign(Ty) / 8;
199209139Srpaulo
200209139Srpaulo  Align = std::clamp(Align, (uint64_t)MinABIStackAlignInBytes,
201209139Srpaulo                     (uint64_t)StackAlignInBytes);
202209139Srpaulo  unsigned CurrOffset = llvm::alignTo(Offset, Align);
203209139Srpaulo  Offset = CurrOffset + llvm::alignTo(TySize, Align * 8) / 8;
204209139Srpaulo
205209139Srpaulo  if (isAggregateTypeForABI(Ty) || Ty->isVectorType()) {
206209139Srpaulo    // Ignore empty aggregates.
207209139Srpaulo    if (TySize == 0)
208209139Srpaulo      return ABIArgInfo::getIgnore();
209209139Srpaulo
210209139Srpaulo    if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
211209139Srpaulo      Offset = OrigOffset + MinABIStackAlignInBytes;
212209139Srpaulo      return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
213209139Srpaulo    }
214209139Srpaulo
215209139Srpaulo    // If we have reached here, aggregates are passed directly by coercing to
216209139Srpaulo    // another structure type. Padding is inserted if the offset of the
217209139Srpaulo    // aggregate is unaligned.
218209139Srpaulo    ABIArgInfo ArgInfo =
219209139Srpaulo        ABIArgInfo::getDirect(HandleAggregates(Ty, TySize), 0,
220209139Srpaulo                              getPaddingType(OrigOffset, CurrOffset));
221209139Srpaulo    ArgInfo.setInReg(true);
222209139Srpaulo    return ArgInfo;
223209139Srpaulo  }
224209139Srpaulo
225209139Srpaulo  // Treat an enum type as its underlying type.
226  if (const EnumType *EnumTy = Ty->getAs<EnumType>())
227    Ty = EnumTy->getDecl()->getIntegerType();
228
229  // Make sure we pass indirectly things that are too large.
230  if (const auto *EIT = Ty->getAs<BitIntType>())
231    if (EIT->getNumBits() > 128 ||
232        (EIT->getNumBits() > 64 &&
233         !getContext().getTargetInfo().hasInt128Type()))
234      return getNaturalAlignIndirect(Ty);
235
236  // All integral types are promoted to the GPR width.
237  if (Ty->isIntegralOrEnumerationType())
238    return extendType(Ty);
239
240  return ABIArgInfo::getDirect(
241      nullptr, 0, IsO32 ? nullptr : getPaddingType(OrigOffset, CurrOffset));
242}
243
244llvm::Type*
245MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const {
246  const RecordType *RT = RetTy->getAs<RecordType>();
247  SmallVector<llvm::Type*, 8> RTList;
248
249  if (RT && RT->isStructureOrClassType()) {
250    const RecordDecl *RD = RT->getDecl();
251    const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
252    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    if (FieldCnt && (FieldCnt <= 2) && !Layout.getFieldOffset(0)) {
264      RecordDecl::field_iterator b = RD->field_begin(), e = RD->field_end();
265      for (; b != e; ++b) {
266        const BuiltinType *BT = b->getType()->getAs<BuiltinType>();
267
268        if (!BT || !BT->isFloatingPoint())
269          break;
270
271        RTList.push_back(CGT.ConvertType(b->getType()));
272      }
273
274      if (b == e)
275        return llvm::StructType::get(getVMContext(), RTList,
276                                     RD->hasAttr<PackedAttr>());
277
278      RTList.clear();
279    }
280  }
281
282  CoerceToIntArgs(Size, RTList);
283  return llvm::StructType::get(getVMContext(), RTList);
284}
285
286ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const {
287  uint64_t Size = getContext().getTypeSize(RetTy);
288
289  if (RetTy->isVoidType())
290    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  if (!IsO32 && Size == 0)
295    return ABIArgInfo::getIgnore();
296
297  if (isAggregateTypeForABI(RetTy) || RetTy->isVectorType()) {
298    if (Size <= 128) {
299      if (RetTy->isAnyComplexType())
300        return ABIArgInfo::getDirect();
301
302      // O32 returns integer vectors in registers and N32/N64 returns all small
303      // aggregates in registers.
304      if (!IsO32 ||
305          (RetTy->isVectorType() && !RetTy->hasFloatingRepresentation())) {
306        ABIArgInfo ArgInfo =
307            ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size));
308        ArgInfo.setInReg(true);
309        return ArgInfo;
310      }
311    }
312
313    return getNaturalAlignIndirect(RetTy);
314  }
315
316  // Treat an enum type as its underlying type.
317  if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
318    RetTy = EnumTy->getDecl()->getIntegerType();
319
320  // Make sure we pass indirectly things that are too large.
321  if (const auto *EIT = RetTy->getAs<BitIntType>())
322    if (EIT->getNumBits() > 128 ||
323        (EIT->getNumBits() > 64 &&
324         !getContext().getTargetInfo().hasInt128Type()))
325      return getNaturalAlignIndirect(RetTy);
326
327  if (isPromotableIntegerTypeForABI(RetTy))
328    return ABIArgInfo::getExtend(RetTy);
329
330  if ((RetTy->isUnsignedIntegerOrEnumerationType() ||
331      RetTy->isSignedIntegerOrEnumerationType()) && Size == 32 && !IsO32)
332    return ABIArgInfo::getSignExtend(RetTy);
333
334  return ABIArgInfo::getDirect();
335}
336
337void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const {
338  ABIArgInfo &RetInfo = FI.getReturnInfo();
339  if (!getCXXABI().classifyReturnType(FI))
340    RetInfo = classifyReturnType(FI.getReturnType());
341
342  // Check if a pointer to an aggregate is passed as a hidden argument.
343  uint64_t Offset = RetInfo.isIndirect() ? MinABIStackAlignInBytes : 0;
344
345  for (auto &I : FI.arguments())
346    I.info = classifyArgumentType(I.type, Offset);
347}
348
349Address MipsABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
350                               QualType OrigTy) const {
351  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  unsigned SlotSizeInBits = IsO32 ? 32 : 64;
356  unsigned PtrWidth = getTarget().getPointerWidth(LangAS::Default);
357  bool DidPromote = false;
358  if ((Ty->isIntegerType() &&
359          getContext().getIntWidth(Ty) < SlotSizeInBits) ||
360      (Ty->isPointerType() && PtrWidth < SlotSizeInBits)) {
361    DidPromote = true;
362    Ty = getContext().getIntTypeForBitwidth(SlotSizeInBits,
363                                            Ty->isSignedIntegerType());
364  }
365
366  auto TyInfo = getContext().getTypeInfoInChars(Ty);
367
368  // The alignment of things in the argument area is never larger than
369  // StackAlignInBytes.
370  TyInfo.Align =
371    std::min(TyInfo.Align, CharUnits::fromQuantity(StackAlignInBytes));
372
373  // MinABIStackAlignInBytes is the size of argument slots on the stack.
374  CharUnits ArgSlotSize = CharUnits::fromQuantity(MinABIStackAlignInBytes);
375
376  Address Addr = emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
377                          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  if (DidPromote) {
383    Address Temp = CGF.CreateMemTemp(OrigTy, "vaarg.promotion-temp");
384    llvm::Value *Promoted = CGF.Builder.CreateLoad(Addr);
385
386    // Truncate down to the right width.
387    llvm::Type *IntTy = (OrigTy->isIntegerType() ? Temp.getElementType()
388                                                 : CGF.IntPtrTy);
389    llvm::Value *V = CGF.Builder.CreateTrunc(Promoted, IntTy);
390    if (OrigTy->isPointerType())
391      V = CGF.Builder.CreateIntToPtr(V, Temp.getElementType());
392
393    CGF.Builder.CreateStore(V, Temp);
394    Addr = Temp;
395  }
396
397  return Addr;
398}
399
400ABIArgInfo MipsABIInfo::extendType(QualType Ty) const {
401  int TySize = getContext().getTypeSize(Ty);
402
403  // MIPS64 ABI requires unsigned 32 bit integers to be sign extended.
404  if (Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32)
405    return ABIArgInfo::getSignExtend(Ty);
406
407  return ABIArgInfo::getExtend(Ty);
408}
409
410bool
411MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
412                                               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  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  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  AssignToArrayRange(CGF.Builder, Address, Four8, 80, 181);
435  return false;
436}
437
438std::unique_ptr<TargetCodeGenInfo>
439CodeGen::createMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32) {
440  return std::make_unique<MIPSTargetCodeGenInfo>(CGM.getTypes(), IsOS32);
441}
442