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 void computeInfo(CGFunctionInfo &FI)
const override;
50 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
51 AggValueSlot Slot)
const override;
52 ABIArgInfo extendType(QualType Ty)
const;
56 unsigned SizeOfUnwindException;
58 MIPSTargetCodeGenInfo(CodeGenTypes &CGT,
bool IsO32)
59 : TargetCodeGenInfo(std::make_unique<MipsABIInfo>(CGT, IsO32)),
60 SizeOfUnwindException(IsO32 ? 24 : 32) {}
62 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM)
const override {
66 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
67 CodeGen::CodeGenModule &CGM)
const override {
68 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
72 if (FD->
hasAttr<MipsLongCallAttr>())
73 Fn->addFnAttr(
"long-call");
74 else if (FD->
hasAttr<MipsShortCallAttr>())
75 Fn->addFnAttr(
"short-call");
78 if (GV->isDeclaration())
81 if (FD->
hasAttr<Mips16Attr>()) {
82 Fn->addFnAttr(
"mips16");
84 else if (FD->
hasAttr<NoMips16Attr>()) {
85 Fn->addFnAttr(
"nomips16");
88 if (FD->
hasAttr<MicroMipsAttr>())
89 Fn->addFnAttr(
"micromips");
90 else if (FD->
hasAttr<NoMicroMipsAttr>())
91 Fn->addFnAttr(
"nomicromips");
93 const MipsInterruptAttr *Attr = FD->
getAttr<MipsInterruptAttr>();
98 switch (Attr->getInterrupt()) {
99 case MipsInterruptAttr::eic:
Kind =
"eic";
break;
100 case MipsInterruptAttr::sw0:
Kind =
"sw0";
break;
101 case MipsInterruptAttr::sw1:
Kind =
"sw1";
break;
102 case MipsInterruptAttr::hw0:
Kind =
"hw0";
break;
103 case MipsInterruptAttr::hw1:
Kind =
"hw1";
break;
104 case MipsInterruptAttr::hw2:
Kind =
"hw2";
break;
105 case MipsInterruptAttr::hw3:
Kind =
"hw3";
break;
106 case MipsInterruptAttr::hw4:
Kind =
"hw4";
break;
107 case MipsInterruptAttr::hw5:
Kind =
"hw5";
break;
110 Fn->addFnAttr(
"interrupt", Kind);
114 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
115 llvm::Value *Address)
const override;
117 unsigned getSizeOfUnwindException()
const override {
118 return SizeOfUnwindException;
122class WindowsMIPSTargetCodeGenInfo :
public MIPSTargetCodeGenInfo {
124 WindowsMIPSTargetCodeGenInfo(CodeGenTypes &CGT,
bool IsO32)
125 : MIPSTargetCodeGenInfo(CGT, IsO32) {}
127 void getDependentLibraryOption(llvm::StringRef Lib,
128 llvm::SmallString<24> &Opt)
const override {
129 Opt =
"/DEFAULTLIB:";
130 Opt += qualifyWindowsLibrary(Lib);
133 void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef
Value,
134 llvm::SmallString<32> &Opt)
const override {
135 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
140void MipsABIInfo::CoerceToIntArgs(
142 llvm::IntegerType *IntTy =
143 llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
146 for (
unsigned N = TySize / (MinABIStackAlignInBytes * 8); N; --N)
147 ArgList.push_back(IntTy);
150 unsigned R = TySize % (MinABIStackAlignInBytes * 8);
153 ArgList.push_back(llvm::IntegerType::get(getVMContext(), R));
158llvm::Type *MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize,
159 bool ComplexFitsInFPRs)
const {
160 SmallVector<llvm::Type*, 8> ArgList, IntArgList;
163 CoerceToIntArgs(TySize, ArgList);
164 return llvm::StructType::get(getVMContext(), ArgList);
170 if (ComplexFitsInFPRs)
171 return CGT.ConvertType(Ty);
173 CoerceToIntArgs(TySize, ArgList);
174 return llvm::StructType::get(getVMContext(), ArgList);
180 if (!RT || !RT->isStructureOrClassType()) {
181 CoerceToIntArgs(TySize, ArgList);
182 return llvm::StructType::get(getVMContext(), ArgList);
185 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
186 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
187 assert(!(TySize % 8) &&
"Size of structure must be multiple of 8.");
191 llvm::IntegerType *I64 = llvm::IntegerType::get(getVMContext(), 64);
196 i != e; ++i, ++idx) {
197 const QualType Ty = i->getType();
198 const BuiltinType *BT = Ty->
getAs<BuiltinType>();
200 if (!BT || BT->
getKind() != BuiltinType::Double)
208 for (
unsigned j = (Offset - LastOffset) / 64; j > 0; --j)
209 ArgList.push_back(I64);
212 ArgList.push_back(llvm::Type::getDoubleTy(getVMContext()));
213 LastOffset = Offset + 64;
216 CoerceToIntArgs(TySize - LastOffset, IntArgList);
217 ArgList.append(IntArgList.begin(), IntArgList.end());
219 return llvm::StructType::get(getVMContext(), ArgList);
222llvm::Type *MipsABIInfo::getPaddingType(uint64_t OrigOffset,
223 uint64_t Offset)
const {
224 if (OrigOffset + MinABIStackAlignInBytes > Offset)
227 return llvm::IntegerType::get(getVMContext(), (Offset - OrigOffset) * 8);
231MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset)
const {
235 uint64_t TySize = getContext().getTypeSize(Ty);
236 uint64_t Align = getContext().getTypeAlign(Ty) / 8;
238 Align = std::clamp(Align, (uint64_t)MinABIStackAlignInBytes,
239 (uint64_t)StackAlignInBytes);
240 unsigned CurrOffset = llvm::alignTo(Offset, Align);
241 Offset = CurrOffset + llvm::alignTo(TySize, Align * 8) / 8;
249 bool ComplexFitsInFPRs =
true;
250 if (!IsO32 && Ty->
isComplexType() && isComplexGnuABI() && TySize < 256) {
251 unsigned NumArgSlots = 8;
252 uint64_t SlotsUsed = CurrOffset / MinABIStackAlignInBytes;
253 if (SlotsUsed + 2 <= NumArgSlots)
256 Offset = CurrOffset + 2 * MinABIStackAlignInBytes;
260 ComplexFitsInFPRs =
false;
269 Offset = OrigOffset + MinABIStackAlignInBytes;
270 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
279 0, getPaddingType(OrigOffset, CurrOffset));
286 Ty = ED->getIntegerType();
289 if (
const auto *EIT = Ty->
getAs<BitIntType>())
290 if (EIT->getNumBits() > 128 ||
291 (EIT->getNumBits() > 64 &&
292 !getContext().getTargetInfo().hasInt128Type()))
293 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
297 return extendType(Ty);
300 nullptr, 0, IsO32 ?
nullptr : getPaddingType(OrigOffset, CurrOffset));
304MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size)
const {
306 SmallVector<llvm::Type*, 8> RTList;
308 if (RT && RT->isStructureOrClassType()) {
310 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
324 for (; b != e; ++b) {
325 const BuiltinType *BT = b->getType()->getAs<BuiltinType>();
330 RTList.push_back(CGT.ConvertType(b->getType()));
334 return llvm::StructType::get(getVMContext(), RTList,
341 CoerceToIntArgs(Size, RTList);
342 return llvm::StructType::get(getVMContext(), RTList);
345ABIArgInfo MipsABIInfo::classifyComplexReturnType(QualType RetTy,
346 uint64_t Size)
const {
350 uint64_t RegisterWidth = MinABIStackAlignInBytes * 8;
351 if (!isComplexGnuABI() || RetTy->
isFloatingType() || Size > RegisterWidth)
359ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy)
const {
367 if (!IsO32 && Size == 0)
373 return classifyComplexReturnType(RetTy, Size);
386 return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace());
391 RetTy = ED->getIntegerType();
394 if (
const auto *EIT = RetTy->
getAs<BitIntType>())
395 if (EIT->getNumBits() > 128 ||
396 (EIT->getNumBits() > 64 &&
397 !getContext().getTargetInfo().hasInt128Type()))
398 return getNaturalAlignIndirect(RetTy,
399 getDataLayout().getAllocaAddrSpace());
401 if (isPromotableIntegerTypeForABI(RetTy))
411void MipsABIInfo::computeInfo(CGFunctionInfo &FI)
const {
423RValue MipsABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
424 QualType OrigTy, AggValueSlot Slot)
const {
425 QualType Ty = OrigTy;
429 unsigned SlotSizeInBits = IsO32 ? 32 : 64;
430 unsigned PtrWidth = getTarget().getPointerWidth(LangAS::Default);
431 bool DidPromote =
false;
433 getContext().getIntWidth(Ty) < SlotSizeInBits) ||
436 Ty = getContext().getIntTypeForBitwidth(SlotSizeInBits,
440 auto TyInfo = getContext().getTypeInfoInChars(Ty);
451 ArgSlotSize,
true, Slot);
461 llvm::Value *
V = CGF.
Builder.CreateTrunc(Promoted, IntTy);
463 V = CGF.
Builder.CreateIntToPtr(
V, ValTy);
471ABIArgInfo MipsABIInfo::extendType(QualType Ty)
const {
472 int TySize = getContext().getTypeSize(Ty);
482MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
483 llvm::Value *Address)
const {
489 llvm::Value *Four8 = llvm::ConstantInt::get(CGF.
Int8Ty, 4);
509std::unique_ptr<TargetCodeGenInfo>
511 return std::make_unique<MIPSTargetCodeGenInfo>(CGM.
getTypes(), IsOS32);
514std::unique_ptr<TargetCodeGenInfo>
516 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 getIgnore()
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)
static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T=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()
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.
The JSON file list parser is used to communicate input to InstallAPI.
U cast(CodeGen::Address addr)
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::IntegerType * IntPtrTy