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,
27 bool ComplexFitsInFPRs) const;
28 llvm::Type* returnAggregateInRegs(QualType RetTy, uint64_t Size) const;
29 llvm::Type* getPaddingType(uint64_t Align, uint64_t Offset) const;
30
31 /// Whether `_Complex` values with an integer element type are returned the
32 /// way GCC returns them. Clang 23 and earlier returned the real and the
33 /// imaginary part in two separate GPRs, later versions match GCC and pack
34 /// them into one when possible.
35 bool isComplexGnuABI() const {
36 return !getContext().getLangOpts().isCompatibleWith(
37 Version: LangOptions::ClangABI::Ver23);
38 }
39
40 ABIArgInfo classifyComplexReturnType(QualType RetTy, uint64_t Size) const;
41
42public:
43 MipsABIInfo(CodeGenTypes &CGT, bool _IsO32) :
44 ABIInfo(CGT), IsO32(_IsO32), MinABIStackAlignInBytes(IsO32 ? 4 : 8),
45 StackAlignInBytes(IsO32 ? 8 : 16) {}
46
47 ABIArgInfo classifyReturnType(QualType RetTy) const;
48 ABIArgInfo classifyArgumentType(QualType RetTy, uint64_t &Offset,
49 bool IsNamedArg) const;
50 void computeInfo(CGFunctionInfo &FI) const override;
51 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
52 AggValueSlot Slot) const override;
53 ABIArgInfo extendType(QualType Ty, llvm::Type *Padding = nullptr) const;
54};
55
56class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
57 unsigned SizeOfUnwindException;
58public:
59 MIPSTargetCodeGenInfo(CodeGenTypes &CGT, bool IsO32)
60 : TargetCodeGenInfo(std::make_unique<MipsABIInfo>(args&: CGT, args&: IsO32)),
61 SizeOfUnwindException(IsO32 ? 24 : 32) {}
62
63 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
64 return 29;
65 }
66
67 void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
68 CodeGen::CodeGenModule &CGM) const override {
69 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Val: D);
70 if (!FD) return;
71 llvm::Function *Fn = cast<llvm::Function>(Val: GV);
72
73 if (FD->hasAttr<MipsLongCallAttr>())
74 Fn->addFnAttr(Kind: "long-call");
75 else if (FD->hasAttr<MipsShortCallAttr>())
76 Fn->addFnAttr(Kind: "short-call");
77
78 // Other attributes do not have a meaning for declarations.
79 if (GV->isDeclaration())
80 return;
81
82 if (FD->hasAttr<Mips16Attr>()) {
83 Fn->addFnAttr(Kind: "mips16");
84 }
85 else if (FD->hasAttr<NoMips16Attr>()) {
86 Fn->addFnAttr(Kind: "nomips16");
87 }
88
89 if (FD->hasAttr<MicroMipsAttr>())
90 Fn->addFnAttr(Kind: "micromips");
91 else if (FD->hasAttr<NoMicroMipsAttr>())
92 Fn->addFnAttr(Kind: "nomicromips");
93
94 const MipsInterruptAttr *Attr = FD->getAttr<MipsInterruptAttr>();
95 if (!Attr)
96 return;
97
98 const char *Kind;
99 switch (Attr->getInterrupt()) {
100 case MipsInterruptAttr::eic: Kind = "eic"; break;
101 case MipsInterruptAttr::sw0: Kind = "sw0"; break;
102 case MipsInterruptAttr::sw1: Kind = "sw1"; break;
103 case MipsInterruptAttr::hw0: Kind = "hw0"; break;
104 case MipsInterruptAttr::hw1: Kind = "hw1"; break;
105 case MipsInterruptAttr::hw2: Kind = "hw2"; break;
106 case MipsInterruptAttr::hw3: Kind = "hw3"; break;
107 case MipsInterruptAttr::hw4: Kind = "hw4"; break;
108 case MipsInterruptAttr::hw5: Kind = "hw5"; break;
109 }
110
111 Fn->addFnAttr(Kind: "interrupt", Val: Kind);
112
113 }
114
115 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
116 llvm::Value *Address) const override;
117
118 unsigned getSizeOfUnwindException() const override {
119 return SizeOfUnwindException;
120 }
121};
122
123class WindowsMIPSTargetCodeGenInfo : public MIPSTargetCodeGenInfo {
124public:
125 WindowsMIPSTargetCodeGenInfo(CodeGenTypes &CGT, bool IsO32)
126 : MIPSTargetCodeGenInfo(CGT, IsO32) {}
127
128 void getDependentLibraryOption(llvm::StringRef Lib,
129 llvm::SmallString<24> &Opt) const override {
130 Opt = "/DEFAULTLIB:";
131 Opt += qualifyWindowsLibrary(Lib);
132 }
133
134 void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef Value,
135 llvm::SmallString<32> &Opt) const override {
136 Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"";
137 }
138};
139}
140
141void MipsABIInfo::CoerceToIntArgs(
142 uint64_t TySize, SmallVectorImpl<llvm::Type *> &ArgList) const {
143 llvm::IntegerType *IntTy =
144 llvm::IntegerType::get(C&: getVMContext(), NumBits: MinABIStackAlignInBytes * 8);
145
146 // Add (TySize / MinABIStackAlignInBytes) args of IntTy.
147 for (unsigned N = TySize / (MinABIStackAlignInBytes * 8); N; --N)
148 ArgList.push_back(Elt: IntTy);
149
150 // If necessary, add one more integer type to ArgList.
151 unsigned R = TySize % (MinABIStackAlignInBytes * 8);
152
153 if (R)
154 ArgList.push_back(Elt: llvm::IntegerType::get(C&: getVMContext(), NumBits: R));
155}
156
157// In N32/64, an aligned double precision floating point field is passed in
158// a register.
159llvm::Type *MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize,
160 bool ComplexFitsInFPRs) const {
161 SmallVector<llvm::Type*, 8> ArgList, IntArgList;
162
163 if (IsO32) {
164 CoerceToIntArgs(TySize, ArgList);
165 return llvm::StructType::get(Context&: getVMContext(), Elements: ArgList);
166 }
167
168 // A `_Complex` value that stays in FPRs is passed as its two parts.
169 // When that does not fit, it is passed like an integer of the same size.
170 if (Ty->isComplexType()) {
171 if (ComplexFitsInFPRs)
172 return CGT.ConvertType(T: Ty);
173
174 CoerceToIntArgs(TySize, ArgList);
175 return llvm::StructType::get(Context&: getVMContext(), Elements: ArgList);
176 }
177
178 const RecordType *RT = Ty->getAsCanonical<RecordType>();
179
180 // Unions/vectors are passed in integer registers.
181 if (!RT || !RT->isStructureOrClassType()) {
182 CoerceToIntArgs(TySize, ArgList);
183 return llvm::StructType::get(Context&: getVMContext(), Elements: ArgList);
184 }
185
186 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
187 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(D: RD);
188 assert(!(TySize % 8) && "Size of structure must be multiple of 8.");
189
190 uint64_t LastOffset = 0;
191 unsigned idx = 0;
192 llvm::IntegerType *I64 = llvm::IntegerType::get(C&: getVMContext(), NumBits: 64);
193
194 // Iterate over fields in the struct/class and check if there are any aligned
195 // double fields.
196 for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
197 i != e; ++i, ++idx) {
198 const QualType Ty = i->getType();
199 const BuiltinType *BT = Ty->getAs<BuiltinType>();
200
201 if (!BT || BT->getKind() != BuiltinType::Double)
202 continue;
203
204 uint64_t Offset = Layout.getFieldOffset(FieldNo: idx);
205 if (Offset % 64) // Ignore doubles that are not aligned.
206 continue;
207
208 // Add ((Offset - LastOffset) / 64) args of type i64.
209 for (unsigned j = (Offset - LastOffset) / 64; j > 0; --j)
210 ArgList.push_back(Elt: I64);
211
212 // Add double type.
213 ArgList.push_back(Elt: llvm::Type::getDoubleTy(C&: getVMContext()));
214 LastOffset = Offset + 64;
215 }
216
217 CoerceToIntArgs(TySize: TySize - LastOffset, ArgList&: IntArgList);
218 ArgList.append(in_start: IntArgList.begin(), in_end: IntArgList.end());
219
220 return llvm::StructType::get(Context&: getVMContext(), Elements: ArgList);
221}
222
223llvm::Type *MipsABIInfo::getPaddingType(uint64_t OrigOffset,
224 uint64_t Offset) const {
225 if (OrigOffset + MinABIStackAlignInBytes > Offset)
226 return nullptr;
227
228 return llvm::IntegerType::get(C&: getVMContext(), NumBits: (Offset - OrigOffset) * 8);
229}
230
231ABIArgInfo MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset,
232 bool IsNamedArg) const {
233 Ty = useFirstFieldIfTransparentUnion(Ty);
234
235 uint64_t OrigOffset = Offset;
236 uint64_t TySize = getContext().getTypeSize(T: Ty);
237 uint64_t Align = getContext().getTypeAlign(T: Ty) / 8;
238
239 Align = std::clamp(val: Align, lo: (uint64_t)MinABIStackAlignInBytes,
240 hi: (uint64_t)StackAlignInBytes);
241 unsigned CurrOffset = llvm::alignTo(Value: Offset, Align);
242 Offset = CurrOffset + llvm::alignTo(Value: TySize, Align: Align * 8) / 8;
243
244 // Only pass _Complex float and _Complex double in FPRs when there are 2 free
245 // slots, and it's not a variadic argument otherwise use GPRs (or the stack).
246 //
247 // _Complex long double never uses GPRs. Its parts are an FPR pair each,
248 // so passing them as they are puts each part in a pair and spills to
249 // the stack the parts that don't fit.
250 bool ComplexFitsInFPRs = IsNamedArg;
251 if (!IsO32 && IsNamedArg && Ty->isComplexType() && isComplexGnuABI() &&
252 TySize < 256) {
253 unsigned NumArgSlots = 8;
254 uint64_t SlotsUsed = CurrOffset / MinABIStackAlignInBytes;
255 if (SlotsUsed + 2 <= NumArgSlots)
256 // Claim 2 slots. Only a `_Complex float` needs this,
257 // a `_Complex double` is already two slots.
258 Offset = CurrOffset + 2 * MinABIStackAlignInBytes;
259 else
260 // Pass like an integer of the same size, packing both parts into GPRs
261 // (or the stack).
262 ComplexFitsInFPRs = false;
263 }
264
265 if (isAggregateTypeForABI(T: Ty) || Ty->isVectorType()) {
266 // Ignore empty aggregates, but do insert padding for over-aligned
267 // zero-sized types.
268 if (TySize == 0) {
269 if (llvm::Type *Padding = getPaddingType(OrigOffset, Offset: CurrOffset))
270 return ABIArgInfo::getExpandWithPadding(/*PaddingInReg=*/false,
271 Padding);
272 return ABIArgInfo::getIgnore();
273 }
274
275 if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(T: Ty, CXXABI&: getCXXABI())) {
276 Offset = OrigOffset + MinABIStackAlignInBytes;
277 return getNaturalAlignIndirect(Ty, AddrSpace: getDataLayout().getAllocaAddrSpace(),
278 ByVal: RAA == CGCXXABI::RAA_DirectInMemory);
279 }
280
281 // If we have reached here, aggregates are passed directly by coercing to
282 // another structure type. Padding is inserted if the offset of the
283 // aggregate is unaligned.
284 ABIArgInfo ArgInfo =
285 ABIArgInfo::getDirect(T: HandleAggregates(Ty, TySize, ComplexFitsInFPRs),
286 Offset: 0, Padding: getPaddingType(OrigOffset, Offset: CurrOffset));
287 ArgInfo.setInReg(true);
288 return ArgInfo;
289 }
290
291 // Treat an enum type as its underlying type.
292 if (const auto *ED = Ty->getAsEnumDecl())
293 Ty = ED->getIntegerType();
294
295 // Make sure we pass indirectly things that are too large.
296 if (const auto *EIT = Ty->getAs<BitIntType>())
297 if (EIT->getNumBits() > 128 ||
298 (EIT->getNumBits() > 64 &&
299 !getContext().getTargetInfo().hasInt128Type()))
300 return getNaturalAlignIndirect(Ty, AddrSpace: getDataLayout().getAllocaAddrSpace());
301
302 // Scalars never get explicit padding on O32: CC_MipsO32 already does the
303 // alignment itself based on the argument's original alignment.
304 //
305 // For __int128 and other types that are 16-byte aligned this padding ensures
306 // that the value starts in an even-numbered register or stack slot.
307 llvm::Type *Padding =
308 IsO32 ? nullptr : getPaddingType(OrigOffset, Offset: CurrOffset);
309
310 // All integral types are promoted to the GPR width.
311 if (Ty->isIntegralOrEnumerationType())
312 return extendType(Ty, Padding);
313
314 return ABIArgInfo::getDirect(T: nullptr, Offset: 0, Padding);
315}
316
317llvm::Type*
318MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const {
319 const RecordType *RT = RetTy->getAsCanonical<RecordType>();
320 SmallVector<llvm::Type*, 8> RTList;
321
322 if (RT && RT->isStructureOrClassType()) {
323 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
324 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(D: RD);
325 unsigned FieldCnt = Layout.getFieldCount();
326
327 // N32/64 returns struct/classes in floating point registers if the
328 // following conditions are met:
329 // 1. The size of the struct/class is no larger than 128-bit.
330 // 2. The struct/class has one or two fields all of which are floating
331 // point types.
332 // 3. The offset of the first field is zero (this follows what gcc does).
333 //
334 // Any other composite results are returned in integer registers.
335 //
336 if (FieldCnt && (FieldCnt <= 2) && !Layout.getFieldOffset(FieldNo: 0)) {
337 RecordDecl::field_iterator b = RD->field_begin(), e = RD->field_end();
338 for (; b != e; ++b) {
339 const BuiltinType *BT = b->getType()->getAs<BuiltinType>();
340
341 if (!BT || !BT->isFloatingPoint())
342 break;
343
344 RTList.push_back(Elt: CGT.ConvertType(T: b->getType()));
345 }
346
347 if (b == e)
348 return llvm::StructType::get(Context&: getVMContext(), Elements: RTList,
349 isPacked: RD->hasAttr<PackedAttr>());
350
351 RTList.clear();
352 }
353 }
354
355 CoerceToIntArgs(TySize: Size, ArgList&: RTList);
356 return llvm::StructType::get(Context&: getVMContext(), Elements: RTList);
357}
358
359ABIArgInfo MipsABIInfo::classifyComplexReturnType(QualType RetTy,
360 uint64_t Size) const {
361 // A `_Complex` value with a floating-point element type is returned in FPRs,
362 // `_Complex long long` is returned in 2 GPRs. For older ABI versions all
363 // `_Complex {integer}` types are returned in 2 GPRs.
364 uint64_t RegisterWidth = MinABIStackAlignInBytes * 8;
365 if (!isComplexGnuABI() || RetTy->isFloatingType() || Size > RegisterWidth)
366 return ABIArgInfo::getDirect();
367
368 // Match GCC for `_Complex int`, `_Complex short` and `_Complex char` by
369 // packing the real and imaginary field into one GPR.
370 return ABIArgInfo::getDirect(T: llvm::IntegerType::get(C&: getVMContext(), NumBits: Size));
371}
372
373ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const {
374 uint64_t Size = getContext().getTypeSize(T: RetTy);
375
376 if (RetTy->isVoidType())
377 return ABIArgInfo::getIgnore();
378
379 // O32 doesn't treat zero-sized structs differently from other structs.
380 // However, N32/N64 ignores zero sized return values.
381 if (!IsO32 && Size == 0)
382 return ABIArgInfo::getIgnore();
383
384 if (isAggregateTypeForABI(T: RetTy) || RetTy->isVectorType()) {
385 if (Size <= 128) {
386 if (RetTy->isAnyComplexType())
387 return classifyComplexReturnType(RetTy, Size);
388
389 // O32 returns integer vectors in registers and N32/N64 returns all small
390 // aggregates in registers.
391 if (!IsO32 ||
392 (RetTy->isVectorType() && !RetTy->hasFloatingRepresentation())) {
393 ABIArgInfo ArgInfo =
394 ABIArgInfo::getDirect(T: returnAggregateInRegs(RetTy, Size));
395 ArgInfo.setInReg(true);
396 return ArgInfo;
397 }
398 }
399
400 return getNaturalAlignIndirect(Ty: RetTy, AddrSpace: getDataLayout().getAllocaAddrSpace());
401 }
402
403 // Treat an enum type as its underlying type.
404 if (const auto *ED = RetTy->getAsEnumDecl())
405 RetTy = ED->getIntegerType();
406
407 // Make sure we pass indirectly things that are too large.
408 if (const auto *EIT = RetTy->getAs<BitIntType>())
409 if (EIT->getNumBits() > 128 ||
410 (EIT->getNumBits() > 64 &&
411 !getContext().getTargetInfo().hasInt128Type()))
412 return getNaturalAlignIndirect(Ty: RetTy,
413 AddrSpace: getDataLayout().getAllocaAddrSpace());
414
415 if (isPromotableIntegerTypeForABI(Ty: RetTy))
416 return ABIArgInfo::getExtend(Ty: RetTy);
417
418 if ((RetTy->isUnsignedIntegerOrEnumerationType() ||
419 RetTy->isSignedIntegerOrEnumerationType()) && Size == 32 && !IsO32)
420 return ABIArgInfo::getSignExtend(Ty: RetTy);
421
422 return ABIArgInfo::getDirect();
423}
424
425void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const {
426 ABIArgInfo &RetInfo = FI.getReturnInfo();
427 if (!getCXXABI().classifyReturnType(FI))
428 RetInfo = classifyReturnType(RetTy: FI.getReturnType());
429
430 // Check if a pointer to an aggregate is passed as a hidden argument.
431 uint64_t Offset = RetInfo.isIndirect() ? MinABIStackAlignInBytes : 0;
432
433 // Zero-sized arguments are not passed, but do end the run of floats.
434 bool SawZeroSizedArg = false;
435
436 for (auto [ArgNo, I] : llvm::enumerate(First: FI.arguments())) {
437 bool IsNamedArg = ArgNo < FI.getNumRequiredArgs();
438 I.info = classifyArgumentType(Ty: I.type, Offset, IsNamedArg);
439
440 // N32 and N64 always pass floating points in float registers.
441 if (!IsO32)
442 continue;
443
444 if (getContext().getTypeSize(T: I.type) == 0)
445 SawZeroSizedArg = true;
446 else if (SawZeroSizedArg && I.type->isRealFloatingType()) {
447 // A zero-sized type ends the leading run of float arguments that is
448 // passed in FPRs. Any subsequent floats must be passed via GPRs. Cast the
449 // float to an integer now because we drop the zero-sized argument here
450 // and later stages have no way of inferring that it was there.
451 I.info = ABIArgInfo::getDirect(T: llvm::IntegerType::get(
452 C&: getVMContext(), NumBits: getContext().getTypeSize(T: I.type)));
453 }
454 }
455}
456
457RValue MipsABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
458 QualType OrigTy, AggValueSlot Slot) const {
459 QualType Ty = OrigTy;
460
461 // Integer arguments are promoted to 32-bit on O32 and 64-bit on N32/N64.
462 // Pointers are also promoted in the same way but this only matters for N32.
463 unsigned SlotSizeInBits = IsO32 ? 32 : 64;
464 unsigned PtrWidth = getTarget().getPointerWidth(AddrSpace: LangAS::Default);
465 bool DidPromote = false;
466 if ((Ty->isIntegerType() &&
467 getContext().getIntWidth(T: Ty) < SlotSizeInBits) ||
468 (Ty->isPointerType() && PtrWidth < SlotSizeInBits)) {
469 DidPromote = true;
470 Ty = getContext().getIntTypeForBitwidth(DestWidth: SlotSizeInBits,
471 Signed: Ty->isSignedIntegerType());
472 }
473
474 auto TyInfo = getContext().getTypeInfoInChars(T: Ty);
475
476 // The alignment of things in the argument area is never larger than
477 // StackAlignInBytes.
478 TyInfo.Align =
479 std::min(a: TyInfo.Align, b: CharUnits::fromQuantity(Quantity: StackAlignInBytes));
480
481 // MinABIStackAlignInBytes is the size of argument slots on the stack.
482 CharUnits ArgSlotSize = CharUnits::fromQuantity(Quantity: MinABIStackAlignInBytes);
483
484 RValue Res = emitVoidPtrVAArg(CGF, VAListAddr, ValueTy: Ty, /*indirect*/ IsIndirect: false, ValueInfo: TyInfo,
485 SlotSizeAndAlign: ArgSlotSize, /*AllowHigherAlign*/ true, Slot);
486
487 // If there was a promotion, "unpromote".
488 // TODO: can we just use a pointer into a subset of the original slot?
489 if (DidPromote) {
490 llvm::Type *ValTy = CGF.ConvertType(T: OrigTy);
491 llvm::Value *Promoted = Res.getScalarVal();
492
493 // Truncate down to the right width.
494 llvm::Type *IntTy = (OrigTy->isIntegerType() ? ValTy : CGF.IntPtrTy);
495 llvm::Value *V = CGF.Builder.CreateTrunc(V: Promoted, DestTy: IntTy);
496 if (OrigTy->isPointerType())
497 V = CGF.Builder.CreateIntToPtr(V, DestTy: ValTy);
498
499 return RValue::get(V);
500 }
501
502 return Res;
503}
504
505ABIArgInfo MipsABIInfo::extendType(QualType Ty, llvm::Type *Padding) const {
506 int TySize = getContext().getTypeSize(T: Ty);
507
508 // MIPS64 ABI requires unsigned 32 bit integers to be sign extended.
509 if (Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32)
510 return ABIArgInfo::getSignExtend(Ty, /*T=*/nullptr, Padding);
511
512 return ABIArgInfo::getExtend(Ty, /*T=*/nullptr, Padding);
513}
514
515bool
516MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
517 llvm::Value *Address) const {
518 // This information comes from gcc's implementation, which seems to
519 // as canonical as it gets.
520
521 // Everything on MIPS is 4 bytes. Double-precision FP registers
522 // are aliased to pairs of single-precision FP registers.
523 llvm::Value *Four8 = llvm::ConstantInt::get(Ty: CGF.Int8Ty, V: 4);
524
525 // 0-31 are the general purpose registers, $0 - $31.
526 // 32-63 are the floating-point registers, $f0 - $f31.
527 // 64 and 65 are the multiply/divide registers, $hi and $lo.
528 // 66 is the (notional, I think) register for signal-handler return.
529 AssignToArrayRange(Builder&: CGF.Builder, Array: Address, Value: Four8, FirstIndex: 0, LastIndex: 65);
530
531 // 67-74 are the floating-point status registers, $fcc0 - $fcc7.
532 // They are one bit wide and ignored here.
533
534 // 80-111 are the coprocessor 0 registers, $c0r0 - $c0r31.
535 // (coprocessor 1 is the FP unit)
536 // 112-143 are the coprocessor 2 registers, $c2r0 - $c2r31.
537 // 144-175 are the coprocessor 3 registers, $c3r0 - $c3r31.
538 // 176-181 are the DSP accumulator registers.
539 AssignToArrayRange(Builder&: CGF.Builder, Array: Address, Value: Four8, FirstIndex: 80, LastIndex: 181);
540 return false;
541}
542
543std::unique_ptr<TargetCodeGenInfo>
544CodeGen::createMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32) {
545 return std::make_unique<MIPSTargetCodeGenInfo>(args&: CGM.getTypes(), args&: IsOS32);
546}
547
548std::unique_ptr<TargetCodeGenInfo>
549CodeGen::createWindowsMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32) {
550 return std::make_unique<WindowsMIPSTargetCodeGenInfo>(args&: CGM.getTypes(), args&: IsOS32);
551}
552