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
12using namespace clang;
13using namespace clang::CodeGen;
14
15//===----------------------------------------------------------------------===//
16// MIPS ABI Implementation. This works for both little-endian and
17// big-endian variants.
18//===----------------------------------------------------------------------===//
19
20namespace {
21class 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;
29public:
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 Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
38 QualType Ty) const override;
39 ABIArgInfo extendType(QualType Ty) const;
40};
41
42class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
43 unsigned SizeOfUnwindException;
44public:
45 MIPSTargetCodeGenInfo(CodeGenTypes &CGT, bool IsO32)
46 : TargetCodeGenInfo(std::make_unique<MipsABIInfo>(args&: CGT, args&: IsO32)),
47 SizeOfUnwindException(IsO32 ? 24 : 32) {}
48
49 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
50 return 29;
51 }
52
53 void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
54 CodeGen::CodeGenModule &CGM) const override {
55 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Val: D);
56 if (!FD) return;
57 llvm::Function *Fn = cast<llvm::Function>(Val: GV);
58
59 if (FD->hasAttr<MipsLongCallAttr>())
60 Fn->addFnAttr(Kind: "long-call");
61 else if (FD->hasAttr<MipsShortCallAttr>())
62 Fn->addFnAttr(Kind: "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(Kind: "mips16");
70 }
71 else if (FD->hasAttr<NoMips16Attr>()) {
72 Fn->addFnAttr(Kind: "nomips16");
73 }
74
75 if (FD->hasAttr<MicroMipsAttr>())
76 Fn->addFnAttr(Kind: "micromips");
77 else if (FD->hasAttr<NoMicroMipsAttr>())
78 Fn->addFnAttr(Kind: "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(Kind: "interrupt", Val: Kind);
98
99 }
100
101 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
102 llvm::Value *Address) const override;
103
104 unsigned getSizeOfUnwindException() const override {
105 return SizeOfUnwindException;
106 }
107};
108}
109
110void MipsABIInfo::CoerceToIntArgs(
111 uint64_t TySize, SmallVectorImpl<llvm::Type *> &ArgList) const {
112 llvm::IntegerType *IntTy =
113 llvm::IntegerType::get(C&: getVMContext(), NumBits: MinABIStackAlignInBytes * 8);
114
115 // Add (TySize / MinABIStackAlignInBytes) args of IntTy.
116 for (unsigned N = TySize / (MinABIStackAlignInBytes * 8); N; --N)
117 ArgList.push_back(Elt: 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(Elt: llvm::IntegerType::get(C&: getVMContext(), NumBits: R));
124}
125
126// In N32/64, an aligned double precision floating point field is passed in
127// a register.
128llvm::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(Context&: getVMContext(), Elements: ArgList);
134 }
135
136 if (Ty->isComplexType())
137 return CGT.ConvertType(T: 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(Context&: getVMContext(), Elements: ArgList);
145 }
146
147 const RecordDecl *RD = RT->getDecl();
148 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(D: 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(C&: getVMContext(), NumBits: 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(FieldNo: 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(Elt: I64);
172
173 // Add double type.
174 ArgList.push_back(Elt: llvm::Type::getDoubleTy(C&: getVMContext()));
175 LastOffset = Offset + 64;
176 }
177
178 CoerceToIntArgs(TySize: TySize - LastOffset, ArgList&: IntArgList);
179 ArgList.append(in_start: IntArgList.begin(), in_end: IntArgList.end());
180
181 return llvm::StructType::get(Context&: getVMContext(), Elements: ArgList);
182}
183
184llvm::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(C&: getVMContext(), NumBits: (Offset - OrigOffset) * 8);
190}
191
192ABIArgInfo
193MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
194 Ty = useFirstFieldIfTransparentUnion(Ty);
195
196 uint64_t OrigOffset = Offset;
197 uint64_t TySize = getContext().getTypeSize(T: Ty);
198 uint64_t Align = getContext().getTypeAlign(T: Ty) / 8;
199
200 Align = std::clamp(val: Align, lo: (uint64_t)MinABIStackAlignInBytes,
201 hi: (uint64_t)StackAlignInBytes);
202 unsigned CurrOffset = llvm::alignTo(Value: Offset, Align);
203 Offset = CurrOffset + llvm::alignTo(Value: TySize, Align: Align * 8) / 8;
204
205 if (isAggregateTypeForABI(T: Ty) || Ty->isVectorType()) {
206 // Ignore empty aggregates.
207 if (TySize == 0)
208 return ABIArgInfo::getIgnore();
209
210 if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(T: Ty, CXXABI&: getCXXABI())) {
211 Offset = OrigOffset + MinABIStackAlignInBytes;
212 return getNaturalAlignIndirect(Ty, ByVal: 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(T: HandleAggregates(Ty, TySize), Offset: 0,
220 Padding: getPaddingType(OrigOffset, Offset: 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 T: nullptr, Offset: 0, Padding: IsO32 ? nullptr : getPaddingType(OrigOffset, Offset: 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(D: 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(FieldNo: 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(Elt: CGT.ConvertType(T: 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(TySize: Size, ArgList&: RTList);
283 return llvm::StructType::get(Context&: getVMContext(), Elements: RTList);
284}
285
286ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const {
287 uint64_t Size = getContext().getTypeSize(T: 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(T: 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(T: returnAggregateInRegs(RetTy, Size));
308 ArgInfo.setInReg(true);
309 return ArgInfo;
310 }
311 }
312
313 return getNaturalAlignIndirect(Ty: 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(Ty: RetTy);
326
327 if (isPromotableIntegerTypeForABI(Ty: RetTy))
328 return ABIArgInfo::getExtend(Ty: RetTy);
329
330 if ((RetTy->isUnsignedIntegerOrEnumerationType() ||
331 RetTy->isSignedIntegerOrEnumerationType()) && Size == 32 && !IsO32)
332 return ABIArgInfo::getSignExtend(Ty: 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(RetTy: 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(Ty: 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(AddrSpace: LangAS::Default);
357 bool DidPromote = false;
358 if ((Ty->isIntegerType() &&
359 getContext().getIntWidth(T: Ty) < SlotSizeInBits) ||
360 (Ty->isPointerType() && PtrWidth < SlotSizeInBits)) {
361 DidPromote = true;
362 Ty = getContext().getIntTypeForBitwidth(DestWidth: SlotSizeInBits,
363 Signed: Ty->isSignedIntegerType());
364 }
365
366 auto TyInfo = getContext().getTypeInfoInChars(T: Ty);
367
368 // The alignment of things in the argument area is never larger than
369 // StackAlignInBytes.
370 TyInfo.Align =
371 std::min(a: TyInfo.Align, b: CharUnits::fromQuantity(Quantity: StackAlignInBytes));
372
373 // MinABIStackAlignInBytes is the size of argument slots on the stack.
374 CharUnits ArgSlotSize = CharUnits::fromQuantity(Quantity: MinABIStackAlignInBytes);
375
376 Address Addr = emitVoidPtrVAArg(CGF, VAListAddr, ValueTy: Ty, /*indirect*/ IsIndirect: false,
377 ValueInfo: TyInfo, SlotSizeAndAlign: 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(T: OrigTy, Name: "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(V: Promoted, DestTy: IntTy);
390 if (OrigTy->isPointerType())
391 V = CGF.Builder.CreateIntToPtr(V, DestTy: Temp.getElementType());
392
393 CGF.Builder.CreateStore(Val: V, Addr: Temp);
394 Addr = Temp;
395 }
396
397 return Addr;
398}
399
400ABIArgInfo MipsABIInfo::extendType(QualType Ty) const {
401 int TySize = getContext().getTypeSize(T: 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(Ty: CGF.Int8Ty, V: 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(Builder&: CGF.Builder, Array: Address, Value: Four8, FirstIndex: 0, LastIndex: 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(Builder&: CGF.Builder, Array: Address, Value: Four8, FirstIndex: 80, LastIndex: 181);
435 return false;
436}
437
438std::unique_ptr<TargetCodeGenInfo>
439CodeGen::createMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32) {
440 return std::make_unique<MIPSTargetCodeGenInfo>(args&: CGM.getTypes(), args&: IsOS32);
441}
442

source code of clang/lib/CodeGen/Targets/Mips.cpp