10#include "TargetInfo.h"
21class MipsABIInfo :
public ABIInfo {
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;
35 bool isComplexGnuABI()
const {
36 return !getContext().getLangOpts().isCompatibleWith(
37 LangOptions::ClangABI::Ver23);
40 ABIArgInfo classifyComplexReturnType(QualType RetTy, uint64_t Size)
const;
43 MipsABIInfo(CodeGenTypes &CGT,
bool _IsO32) :
44 ABIInfo(CGT), IsO32(_IsO32), MinABIStackAlignInBytes(IsO32 ? 4 : 8),
45 StackAlignInBytes(IsO32 ? 8 : 16) {}
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;
57 unsigned SizeOfUnwindException;
59 MIPSTargetCodeGenInfo(CodeGenTypes &CGT,
bool IsO32)
60 : TargetCodeGenInfo(std::make_unique<MipsABIInfo>(CGT, IsO32)),
61 SizeOfUnwindException(IsO32 ? 24 : 32) {}
63 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM)
const override {
67 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
68 CodeGen::CodeGenModule &CGM)
const override {
69 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
73 if (FD->
hasAttr<MipsLongCallAttr>())
74 Fn->addFnAttr(
"long-call");
75 else if (FD->
hasAttr<MipsShortCallAttr>())
76 Fn->addFnAttr(
"short-call");
79 if (GV->isDeclaration())
82 if (FD->
hasAttr<Mips16Attr>()) {
83 Fn->addFnAttr(
"mips16");
85 else if (FD->
hasAttr<NoMips16Attr>()) {
86 Fn->addFnAttr(
"nomips16");
89 if (FD->
hasAttr<MicroMipsAttr>())
90 Fn->addFnAttr(
"micromips");
91 else if (FD->
hasAttr<NoMicroMipsAttr>())
92 Fn->addFnAttr(
"nomicromips");
94 const MipsInterruptAttr *Attr = FD->
getAttr<MipsInterruptAttr>();
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;
111 Fn->addFnAttr(
"interrupt", Kind);
115 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
116 llvm::Value *Address)
const override;
118 unsigned getSizeOfUnwindException()
const override {
119 return SizeOfUnwindException;
123class WindowsMIPSTargetCodeGenInfo :
public MIPSTargetCodeGenInfo {
125 WindowsMIPSTargetCodeGenInfo(CodeGenTypes &CGT,
bool IsO32)
126 : MIPSTargetCodeGenInfo(CGT, IsO32) {}
128 void getDependentLibraryOption(llvm::StringRef Lib,
129 llvm::SmallString<24> &Opt)
const override {
130 Opt =
"/DEFAULTLIB:";
131 Opt += qualifyWindowsLibrary(Lib);
134 void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef
Value,
135 llvm::SmallString<32> &Opt)
const override {
136 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
141void MipsABIInfo::CoerceToIntArgs(
143 llvm::IntegerType *IntTy =
144 llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
147 for (
unsigned N = TySize / (MinABIStackAlignInBytes * 8); N; --N)
148 ArgList.push_back(IntTy);
151 unsigned R = TySize % (MinABIStackAlignInBytes * 8);
154 ArgList.push_back(llvm::IntegerType::get(getVMContext(), R));
159llvm::Type *MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize,
160 bool ComplexFitsInFPRs)
const {
161 SmallVector<llvm::Type*, 8> ArgList, IntArgList;
164 CoerceToIntArgs(TySize, ArgList);
165 return llvm::StructType::get(getVMContext(), ArgList);
171 if (ComplexFitsInFPRs)
172 return CGT.ConvertType(Ty);
174 CoerceToIntArgs(TySize, ArgList);
175 return llvm::StructType::get(getVMContext(), ArgList);
181 if (!RT || !RT->isStructureOrClassType()) {
182 CoerceToIntArgs(TySize, ArgList);
183 return llvm::StructType::get(getVMContext(), ArgList);
186 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
187 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
188 assert(!(TySize % 8) &&
"Size of structure must be multiple of 8.");
192 llvm::IntegerType *I64 = llvm::IntegerType::get(getVMContext(), 64);
197 i != e; ++i, ++idx) {
198 const QualType Ty = i->getType();
199 const BuiltinType *BT = Ty->
getAs<BuiltinType>();
201 if (!BT || BT->
getKind() != BuiltinType::Double)
209 for (
unsigned j = (Offset - LastOffset) / 64; j > 0; --j)
210 ArgList.push_back(I64);
213 ArgList.push_back(llvm::Type::getDoubleTy(getVMContext()));
214 LastOffset = Offset + 64;
217 CoerceToIntArgs(TySize - LastOffset, IntArgList);
218 ArgList.append(IntArgList.begin(), IntArgList.end());
220 return llvm::StructType::get(getVMContext(), ArgList);
223llvm::Type *MipsABIInfo::getPaddingType(uint64_t OrigOffset,
224 uint64_t Offset)
const {
225 if (OrigOffset + MinABIStackAlignInBytes > Offset)
228 return llvm::IntegerType::get(getVMContext(), (Offset - OrigOffset) * 8);
231ABIArgInfo MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset,
232 bool IsNamedArg)
const {
236 uint64_t TySize = getContext().getTypeSize(Ty);
237 uint64_t Align = getContext().getTypeAlign(Ty) / 8;
239 Align = std::clamp(Align, (uint64_t)MinABIStackAlignInBytes,
240 (uint64_t)StackAlignInBytes);
241 unsigned CurrOffset = llvm::alignTo(Offset, Align);
242 Offset = CurrOffset + llvm::alignTo(TySize, Align * 8) / 8;
250 bool ComplexFitsInFPRs = IsNamedArg;
251 if (!IsO32 && IsNamedArg && Ty->
isComplexType() && isComplexGnuABI() &&
253 unsigned NumArgSlots = 8;
254 uint64_t SlotsUsed = CurrOffset / MinABIStackAlignInBytes;
255 if (SlotsUsed + 2 <= NumArgSlots)
258 Offset = CurrOffset + 2 * MinABIStackAlignInBytes;
262 ComplexFitsInFPRs =
false;
269 if (llvm::Type *Padding = getPaddingType(OrigOffset, CurrOffset))
276 Offset = OrigOffset + MinABIStackAlignInBytes;
277 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
286 0, getPaddingType(OrigOffset, CurrOffset));
293 Ty = ED->getIntegerType();
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, getDataLayout().getAllocaAddrSpace());
307 llvm::Type *Padding =
308 IsO32 ?
nullptr : getPaddingType(OrigOffset, CurrOffset);
312 return extendType(Ty, Padding);
318MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size)
const {
320 SmallVector<llvm::Type*, 8> RTList;
322 if (RT && RT->isStructureOrClassType()) {
324 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
338 for (; b != e; ++b) {
339 const BuiltinType *BT = b->getType()->getAs<BuiltinType>();
344 RTList.push_back(CGT.ConvertType(b->getType()));
348 return llvm::StructType::get(getVMContext(), RTList,
355 CoerceToIntArgs(Size, RTList);
356 return llvm::StructType::get(getVMContext(), RTList);
359ABIArgInfo MipsABIInfo::classifyComplexReturnType(QualType RetTy,
360 uint64_t Size)
const {
364 uint64_t RegisterWidth = MinABIStackAlignInBytes * 8;
365 if (!isComplexGnuABI() || RetTy->
isFloatingType() || Size > RegisterWidth)
373ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy)
const {
381 if (!IsO32 && Size == 0)
387 return classifyComplexReturnType(RetTy, Size);
400 return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace());
405 RetTy = ED->getIntegerType();
408 if (
const auto *EIT = RetTy->
getAs<BitIntType>())
409 if (EIT->getNumBits() > 128 ||
410 (EIT->getNumBits() > 64 &&
411 !getContext().getTargetInfo().hasInt128Type()))
412 return getNaturalAlignIndirect(RetTy,
413 getDataLayout().getAllocaAddrSpace());
415 if (isPromotableIntegerTypeForABI(RetTy))
425void MipsABIInfo::computeInfo(CGFunctionInfo &FI)
const {
434 bool SawZeroSizedArg =
false;
436 for (
auto [ArgNo, I] : llvm::enumerate(FI.
arguments())) {
444 if (getContext().getTypeSize(I.type) == 0)
445 SawZeroSizedArg =
true;
446 else if (SawZeroSizedArg && I.type->isRealFloatingType()) {
452 getVMContext(), getContext().getTypeSize(I.type)));
457RValue MipsABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
458 QualType OrigTy, AggValueSlot Slot)
const {
459 QualType Ty = OrigTy;
463 unsigned SlotSizeInBits = IsO32 ? 32 : 64;
464 unsigned PtrWidth = getTarget().getPointerWidth(LangAS::Default);
465 bool DidPromote =
false;
467 getContext().getIntWidth(Ty) < SlotSizeInBits) ||
470 Ty = getContext().getIntTypeForBitwidth(SlotSizeInBits,
474 auto TyInfo = getContext().getTypeInfoInChars(Ty);
485 ArgSlotSize,
true, Slot);
495 llvm::Value *
V = CGF.
Builder.CreateTrunc(Promoted, IntTy);
497 V = CGF.
Builder.CreateIntToPtr(
V, ValTy);
505ABIArgInfo MipsABIInfo::extendType(QualType Ty, llvm::Type *Padding)
const {
506 int TySize = getContext().getTypeSize(Ty);
516MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
517 llvm::Value *Address)
const {
523 llvm::Value *Four8 = llvm::ConstantInt::get(CGF.
Int8Ty, 4);
543std::unique_ptr<TargetCodeGenInfo>
545 return std::make_unique<MIPSTargetCodeGenInfo>(CGM.
getTypes(), IsOS32);
548std::unique_ptr<TargetCodeGenInfo>
550 return std::make_unique<WindowsMIPSTargetCodeGenInfo>(CGM.
getTypes(), IsOS32);
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
bool isFloatingPoint() const
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T=nullptr, llvm::Type *Padding=nullptr)
static ABIArgInfo getIgnore()
static ABIArgInfo getExpandWithPadding(bool PaddingInReg, llvm::Type *Padding)
static ABIArgInfo getDirect(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true, unsigned Align=0)
static ABIArgInfo getExtend(QualType Ty, llvm::Type *T=nullptr, llvm::Type *Padding=nullptr)
ABIInfo - Target specific hooks for defining how a type should be passed or returned from functions.
RecordArgABI
Specify how one should pass an argument of a record type.
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
ABIArgInfo & getReturnInfo()
CanQualType getReturnType() const
MutableArrayRef< ArgInfo > arguments()
unsigned getNumRequiredArgs() const
llvm::Type * ConvertType(QualType T)
This class organizes the cross-function state that is used while generating LLVM code.
CodeGenTypes & getTypes()
static RValue get(llvm::Value *V)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
field_iterator field_end() const
specific_decl_iterator< FieldDecl > field_iterator
RecordDecl * getDefinitionOrSelf() const
field_iterator field_begin() const
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
bool isComplexType() const
isComplexType() does not include complex integers (a GCC extension).
bool isUnsignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isAnyComplexType() const
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
bool isVectorType() const
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
bool isFloatingType() const
const T * getAs() const
Member-template getAs<specific type>'.
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to pass a particular type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI)
bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info)
std::unique_ptr< TargetCodeGenInfo > createMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32)
RValue emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType ValueTy, bool IsIndirect, TypeInfoChars ValueInfo, CharUnits SlotSizeAndAlign, bool AllowHigherAlign, AggValueSlot Slot, bool ForceRightAdjust=false)
Emit va_arg for a platform using the common void* representation, where arguments are simply emitted ...
bool isAggregateTypeForABI(QualType T)
std::unique_ptr< TargetCodeGenInfo > createWindowsMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32)
void AssignToArrayRange(CodeGen::CGBuilderTy &Builder, llvm::Value *Array, llvm::Value *Value, unsigned FirstIndex, unsigned LastIndex)
QualType useFirstFieldIfTransparentUnion(QualType Ty)
Pass transparent unions as if they were the type of the first element.
Top level wrappers for InstallAPI frontend operations.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
U cast(CodeGen::Address addr)
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::IntegerType * IntPtrTy