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 | 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: |
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 | |
110 | void 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. |
128 | 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(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 | |
184 | 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(C&: getVMContext(), NumBits: (Offset - OrigOffset) * 8); |
190 | } |
191 | |
192 | ABIArgInfo |
193 | MipsABIInfo::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 | |
244 | llvm::Type* |
245 | 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(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(Context&: getVMContext(), Elements: RTList, |
276 | isPacked: 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 | |
286 | ABIArgInfo 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 | |
337 | void 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 | |
349 | 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(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 | RValue Res = emitVoidPtrVAArg(CGF, VAListAddr, ValueTy: Ty, /*indirect*/ IsIndirect: false, ValueInfo: TyInfo, |
377 | SlotSizeAndAlign: 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(T: 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(V: Promoted, DestTy: IntTy); |
388 | if (OrigTy->isPointerType()) |
389 | V = CGF.Builder.CreateIntToPtr(V, DestTy: ValTy); |
390 | |
391 | return RValue::get(V); |
392 | } |
393 | |
394 | return Res; |
395 | } |
396 | |
397 | ABIArgInfo MipsABIInfo::extendType(QualType Ty) const { |
398 | int TySize = getContext().getTypeSize(T: 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 |
408 | 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(Ty: CGF.Int8Ty, V: 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(Builder&: CGF.Builder, Array: Address, Value: Four8, FirstIndex: 0, LastIndex: 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(Builder&: CGF.Builder, Array: Address, Value: Four8, FirstIndex: 80, LastIndex: 181); |
432 | return false; |
433 | } |
434 | |
435 | std::unique_ptr<TargetCodeGenInfo> |
436 | CodeGen::createMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32) { |
437 | return std::make_unique<MIPSTargetCodeGenInfo>(args&: CGM.getTypes(), args&: IsOS32); |
438 | } |
439 | |