xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/Targets/Mips.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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:
MipsABIInfo(CodeGenTypes & CGT,bool _IsO32)30   MipsABIInfo(CodeGenTypes &CGT, bool _IsO32) :
31     ABIInfo(CGT), IsO32(_IsO32), MinABIStackAlignInBytes(IsO32 ? 4 : 8),
32     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   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
38                    AggValueSlot Slot) const override;
39   ABIArgInfo extendType(QualType Ty) const;
40 };
41 
42 class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
43   unsigned SizeOfUnwindException;
44 public:
MIPSTargetCodeGenInfo(CodeGenTypes & CGT,bool IsO32)45   MIPSTargetCodeGenInfo(CodeGenTypes &CGT, bool IsO32)
46       : TargetCodeGenInfo(std::make_unique<MipsABIInfo>(CGT, IsO32)),
47         SizeOfUnwindException(IsO32 ? 24 : 32) {}
48 
getDwarfEHStackPointer(CodeGen::CodeGenModule & CGM) const49   int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
50     return 29;
51   }
52 
setTargetAttributes(const Decl * D,llvm::GlobalValue * GV,CodeGen::CodeGenModule & CGM) const53   void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
54                            CodeGen::CodeGenModule &CGM) const override {
55     const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
56     if (!FD) return;
57     llvm::Function *Fn = cast<llvm::Function>(GV);
58 
59     if (FD->hasAttr<MipsLongCallAttr>())
60       Fn->addFnAttr("long-call");
61     else if (FD->hasAttr<MipsShortCallAttr>())
62       Fn->addFnAttr("short-call");
63 
64     // Other attributes do not have a meaning for declarations.
65     if (GV->isDeclaration())
66       return;
67 
68     if (FD->hasAttr<Mips16Attr>()) {
69       Fn->addFnAttr("mips16");
70     }
71     else if (FD->hasAttr<NoMips16Attr>()) {
72       Fn->addFnAttr("nomips16");
73     }
74 
75     if (FD->hasAttr<MicroMipsAttr>())
76       Fn->addFnAttr("micromips");
77     else if (FD->hasAttr<NoMicroMipsAttr>())
78       Fn->addFnAttr("nomicromips");
79 
80     const MipsInterruptAttr *Attr = FD->getAttr<MipsInterruptAttr>();
81     if (!Attr)
82       return;
83 
84     const char *Kind;
85     switch (Attr->getInterrupt()) {
86     case MipsInterruptAttr::eic:     Kind = "eic"; break;
87     case MipsInterruptAttr::sw0:     Kind = "sw0"; break;
88     case MipsInterruptAttr::sw1:     Kind = "sw1"; break;
89     case MipsInterruptAttr::hw0:     Kind = "hw0"; break;
90     case MipsInterruptAttr::hw1:     Kind = "hw1"; break;
91     case MipsInterruptAttr::hw2:     Kind = "hw2"; break;
92     case MipsInterruptAttr::hw3:     Kind = "hw3"; break;
93     case MipsInterruptAttr::hw4:     Kind = "hw4"; break;
94     case MipsInterruptAttr::hw5:     Kind = "hw5"; break;
95     }
96 
97     Fn->addFnAttr("interrupt", Kind);
98 
99   }
100 
101   bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
102                                llvm::Value *Address) const override;
103 
getSizeOfUnwindException() const104   unsigned getSizeOfUnwindException() const override {
105     return SizeOfUnwindException;
106   }
107 };
108 }
109 
CoerceToIntArgs(uint64_t TySize,SmallVectorImpl<llvm::Type * > & ArgList) const110 void MipsABIInfo::CoerceToIntArgs(
111     uint64_t TySize, SmallVectorImpl<llvm::Type *> &ArgList) const {
112   llvm::IntegerType *IntTy =
113     llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
114 
115   // Add (TySize / MinABIStackAlignInBytes) args of IntTy.
116   for (unsigned N = TySize / (MinABIStackAlignInBytes * 8); N; --N)
117     ArgList.push_back(IntTy);
118 
119   // If necessary, add one more integer type to ArgList.
120   unsigned R = TySize % (MinABIStackAlignInBytes * 8);
121 
122   if (R)
123     ArgList.push_back(llvm::IntegerType::get(getVMContext(), R));
124 }
125 
126 // In N32/64, an aligned double precision floating point field is passed in
127 // a register.
HandleAggregates(QualType Ty,uint64_t TySize) const128 llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const {
129   SmallVector<llvm::Type*, 8> ArgList, IntArgList;
130 
131   if (IsO32) {
132     CoerceToIntArgs(TySize, ArgList);
133     return llvm::StructType::get(getVMContext(), ArgList);
134   }
135 
136   if (Ty->isComplexType())
137     return CGT.ConvertType(Ty);
138 
139   const RecordType *RT = Ty->getAs<RecordType>();
140 
141   // Unions/vectors are passed in integer registers.
142   if (!RT || !RT->isStructureOrClassType()) {
143     CoerceToIntArgs(TySize, ArgList);
144     return llvm::StructType::get(getVMContext(), ArgList);
145   }
146 
147   const RecordDecl *RD = RT->getDecl();
148   const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
149   assert(!(TySize % 8) && "Size of structure must be multiple of 8.");
150 
151   uint64_t LastOffset = 0;
152   unsigned idx = 0;
153   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   for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
158        i != e; ++i, ++idx) {
159     const QualType Ty = i->getType();
160     const BuiltinType *BT = Ty->getAs<BuiltinType>();
161 
162     if (!BT || BT->getKind() != BuiltinType::Double)
163       continue;
164 
165     uint64_t Offset = Layout.getFieldOffset(idx);
166     if (Offset % 64) // Ignore doubles that are not aligned.
167       continue;
168 
169     // Add ((Offset - LastOffset) / 64) args of type i64.
170     for (unsigned j = (Offset - LastOffset) / 64; j > 0; --j)
171       ArgList.push_back(I64);
172 
173     // Add double type.
174     ArgList.push_back(llvm::Type::getDoubleTy(getVMContext()));
175     LastOffset = Offset + 64;
176   }
177 
178   CoerceToIntArgs(TySize - LastOffset, IntArgList);
179   ArgList.append(IntArgList.begin(), IntArgList.end());
180 
181   return llvm::StructType::get(getVMContext(), ArgList);
182 }
183 
getPaddingType(uint64_t OrigOffset,uint64_t Offset) const184 llvm::Type *MipsABIInfo::getPaddingType(uint64_t OrigOffset,
185                                         uint64_t Offset) const {
186   if (OrigOffset + MinABIStackAlignInBytes > Offset)
187     return nullptr;
188 
189   return llvm::IntegerType::get(getVMContext(), (Offset - OrigOffset) * 8);
190 }
191 
192 ABIArgInfo
classifyArgumentType(QualType Ty,uint64_t & Offset) const193 MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
194   Ty = useFirstFieldIfTransparentUnion(Ty);
195 
196   uint64_t OrigOffset = Offset;
197   uint64_t TySize = getContext().getTypeSize(Ty);
198   uint64_t Align = getContext().getTypeAlign(Ty) / 8;
199 
200   Align = std::clamp(Align, (uint64_t)MinABIStackAlignInBytes,
201                      (uint64_t)StackAlignInBytes);
202   unsigned CurrOffset = llvm::alignTo(Offset, Align);
203   Offset = CurrOffset + llvm::alignTo(TySize, Align * 8) / 8;
204 
205   if (isAggregateTypeForABI(Ty) || Ty->isVectorType()) {
206     // Ignore empty aggregates.
207     if (TySize == 0)
208       return ABIArgInfo::getIgnore();
209 
210     if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
211       Offset = OrigOffset + MinABIStackAlignInBytes;
212       return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
213     }
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     ABIArgInfo ArgInfo =
219         ABIArgInfo::getDirect(HandleAggregates(Ty, TySize), 0,
220                               getPaddingType(OrigOffset, CurrOffset));
221     ArgInfo.setInReg(true);
222     return ArgInfo;
223   }
224 
225   // 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 
244 llvm::Type*
returnAggregateInRegs(QualType RetTy,uint64_t Size) const245 MipsABIInfo::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 
classifyReturnType(QualType RetTy) const286 ABIArgInfo 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 
computeInfo(CGFunctionInfo & FI) const337 void 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 
EmitVAArg(CodeGenFunction & CGF,Address VAListAddr,QualType OrigTy,AggValueSlot Slot) const349 RValue MipsABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
350                               QualType OrigTy, AggValueSlot Slot) 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   RValue Res = emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false, TyInfo,
377                                 ArgSlotSize, /*AllowHigherAlign*/ true, Slot);
378 
379   // If there was a promotion, "unpromote".
380   // TODO: can we just use a pointer into a subset of the original slot?
381   if (DidPromote) {
382     llvm::Type *ValTy = CGF.ConvertType(OrigTy);
383     llvm::Value *Promoted = Res.getScalarVal();
384 
385     // Truncate down to the right width.
386     llvm::Type *IntTy = (OrigTy->isIntegerType() ? ValTy : CGF.IntPtrTy);
387     llvm::Value *V = CGF.Builder.CreateTrunc(Promoted, IntTy);
388     if (OrigTy->isPointerType())
389       V = CGF.Builder.CreateIntToPtr(V, ValTy);
390 
391     return RValue::get(V);
392   }
393 
394   return Res;
395 }
396 
extendType(QualType Ty) const397 ABIArgInfo MipsABIInfo::extendType(QualType Ty) const {
398   int TySize = getContext().getTypeSize(Ty);
399 
400   // MIPS64 ABI requires unsigned 32 bit integers to be sign extended.
401   if (Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32)
402     return ABIArgInfo::getSignExtend(Ty);
403 
404   return ABIArgInfo::getExtend(Ty);
405 }
406 
407 bool
initDwarfEHRegSizeTable(CodeGen::CodeGenFunction & CGF,llvm::Value * Address) const408 MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
409                                                llvm::Value *Address) const {
410   // This information comes from gcc's implementation, which seems to
411   // as canonical as it gets.
412 
413   // Everything on MIPS is 4 bytes.  Double-precision FP registers
414   // are aliased to pairs of single-precision FP registers.
415   llvm::Value *Four8 = llvm::ConstantInt::get(CGF.Int8Ty, 4);
416 
417   // 0-31 are the general purpose registers, $0 - $31.
418   // 32-63 are the floating-point registers, $f0 - $f31.
419   // 64 and 65 are the multiply/divide registers, $hi and $lo.
420   // 66 is the (notional, I think) register for signal-handler return.
421   AssignToArrayRange(CGF.Builder, Address, Four8, 0, 65);
422 
423   // 67-74 are the floating-point status registers, $fcc0 - $fcc7.
424   // They are one bit wide and ignored here.
425 
426   // 80-111 are the coprocessor 0 registers, $c0r0 - $c0r31.
427   // (coprocessor 1 is the FP unit)
428   // 112-143 are the coprocessor 2 registers, $c2r0 - $c2r31.
429   // 144-175 are the coprocessor 3 registers, $c3r0 - $c3r31.
430   // 176-181 are the DSP accumulator registers.
431   AssignToArrayRange(CGF.Builder, Address, Four8, 80, 181);
432   return false;
433 }
434 
435 std::unique_ptr<TargetCodeGenInfo>
createMIPSTargetCodeGenInfo(CodeGenModule & CGM,bool IsOS32)436 CodeGen::createMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32) {
437   return std::make_unique<MIPSTargetCodeGenInfo>(CGM.getTypes(), IsOS32);
438 }
439