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)
const;
27 llvm::Type* returnAggregateInRegs(QualType RetTy, uint64_t Size)
const;
28 llvm::Type* getPaddingType(uint64_t Align, uint64_t Offset)
const;
30 MipsABIInfo(CodeGenTypes &CGT,
bool _IsO32) :
31 ABIInfo(CGT), IsO32(_IsO32), MinABIStackAlignInBytes(IsO32 ? 4 : 8),
32 StackAlignInBytes(IsO32 ? 8 : 16) {}
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;
43 unsigned SizeOfUnwindException;
45 MIPSTargetCodeGenInfo(CodeGenTypes &CGT,
bool IsO32)
46 : TargetCodeGenInfo(std::make_unique<MipsABIInfo>(CGT, IsO32)),
47 SizeOfUnwindException(IsO32 ? 24 : 32) {}
49 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM)
const override {
53 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
54 CodeGen::CodeGenModule &CGM)
const override {
55 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
59 if (FD->
hasAttr<MipsLongCallAttr>())
60 Fn->addFnAttr(
"long-call");
61 else if (FD->
hasAttr<MipsShortCallAttr>())
62 Fn->addFnAttr(
"short-call");
65 if (GV->isDeclaration())
68 if (FD->
hasAttr<Mips16Attr>()) {
69 Fn->addFnAttr(
"mips16");
71 else if (FD->
hasAttr<NoMips16Attr>()) {
72 Fn->addFnAttr(
"nomips16");
75 if (FD->
hasAttr<MicroMipsAttr>())
76 Fn->addFnAttr(
"micromips");
77 else if (FD->
hasAttr<NoMicroMipsAttr>())
78 Fn->addFnAttr(
"nomicromips");
80 const MipsInterruptAttr *Attr = FD->
getAttr<MipsInterruptAttr>();
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;
97 Fn->addFnAttr(
"interrupt", Kind);
101 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
102 llvm::Value *Address)
const override;
104 unsigned getSizeOfUnwindException()
const override {
105 return SizeOfUnwindException;
109class WindowsMIPSTargetCodeGenInfo :
public MIPSTargetCodeGenInfo {
111 WindowsMIPSTargetCodeGenInfo(CodeGenTypes &CGT,
bool IsO32)
112 : MIPSTargetCodeGenInfo(CGT, IsO32) {}
114 void getDependentLibraryOption(llvm::StringRef Lib,
115 llvm::SmallString<24> &Opt)
const override {
116 Opt =
"/DEFAULTLIB:";
117 Opt += qualifyWindowsLibrary(Lib);
120 void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef
Value,
121 llvm::SmallString<32> &Opt)
const override {
122 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
127void MipsABIInfo::CoerceToIntArgs(
129 llvm::IntegerType *IntTy =
130 llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
133 for (
unsigned N = TySize / (MinABIStackAlignInBytes * 8); N; --N)
134 ArgList.push_back(IntTy);
137 unsigned R = TySize % (MinABIStackAlignInBytes * 8);
140 ArgList.push_back(llvm::IntegerType::get(getVMContext(), R));
145llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize)
const {
146 SmallVector<llvm::Type*, 8> ArgList, IntArgList;
149 CoerceToIntArgs(TySize, ArgList);
150 return llvm::StructType::get(getVMContext(), ArgList);
154 return CGT.ConvertType(Ty);
159 if (!RT || !RT->isStructureOrClassType()) {
160 CoerceToIntArgs(TySize, ArgList);
161 return llvm::StructType::get(getVMContext(), ArgList);
164 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
165 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
166 assert(!(TySize % 8) &&
"Size of structure must be multiple of 8.");
170 llvm::IntegerType *I64 = llvm::IntegerType::get(getVMContext(), 64);
175 i != e; ++i, ++idx) {
176 const QualType Ty = i->getType();
177 const BuiltinType *BT = Ty->
getAs<BuiltinType>();
179 if (!BT || BT->
getKind() != BuiltinType::Double)
187 for (
unsigned j = (Offset - LastOffset) / 64; j > 0; --j)
188 ArgList.push_back(I64);
191 ArgList.push_back(llvm::Type::getDoubleTy(getVMContext()));
192 LastOffset = Offset + 64;
195 CoerceToIntArgs(TySize - LastOffset, IntArgList);
196 ArgList.append(IntArgList.begin(), IntArgList.end());
198 return llvm::StructType::get(getVMContext(), ArgList);
201llvm::Type *MipsABIInfo::getPaddingType(uint64_t OrigOffset,
202 uint64_t Offset)
const {
203 if (OrigOffset + MinABIStackAlignInBytes > Offset)
206 return llvm::IntegerType::get(getVMContext(), (Offset - OrigOffset) * 8);
210MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset)
const {
214 uint64_t TySize = getContext().getTypeSize(Ty);
215 uint64_t Align = getContext().getTypeAlign(Ty) / 8;
217 Align = std::clamp(Align, (uint64_t)MinABIStackAlignInBytes,
218 (uint64_t)StackAlignInBytes);
219 unsigned CurrOffset = llvm::alignTo(Offset, Align);
220 Offset = CurrOffset + llvm::alignTo(TySize, Align * 8) / 8;
228 Offset = OrigOffset + MinABIStackAlignInBytes;
229 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
238 getPaddingType(OrigOffset, CurrOffset));
245 Ty = ED->getIntegerType();
248 if (
const auto *EIT = Ty->
getAs<BitIntType>())
249 if (EIT->getNumBits() > 128 ||
250 (EIT->getNumBits() > 64 &&
251 !getContext().getTargetInfo().hasInt128Type()))
252 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
256 return extendType(Ty);
259 nullptr, 0, IsO32 ?
nullptr : getPaddingType(OrigOffset, CurrOffset));
263MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size)
const {
265 SmallVector<llvm::Type*, 8> RTList;
267 if (RT && RT->isStructureOrClassType()) {
268 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
269 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
283 for (;
b != e; ++
b) {
284 const BuiltinType *BT =
b->getType()->
getAs<BuiltinType>();
289 RTList.push_back(CGT.ConvertType(
b->getType()));
293 return llvm::StructType::get(getVMContext(), RTList,
300 CoerceToIntArgs(Size, RTList);
301 return llvm::StructType::get(getVMContext(), RTList);
304ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy)
const {
312 if (!IsO32 && Size == 0)
331 return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace());
336 RetTy = ED->getIntegerType();
339 if (
const auto *EIT = RetTy->
getAs<BitIntType>())
340 if (EIT->getNumBits() > 128 ||
341 (EIT->getNumBits() > 64 &&
342 !getContext().getTargetInfo().hasInt128Type()))
343 return getNaturalAlignIndirect(RetTy,
344 getDataLayout().getAllocaAddrSpace());
346 if (isPromotableIntegerTypeForABI(RetTy))
356void MipsABIInfo::computeInfo(CGFunctionInfo &FI)
const {
368RValue MipsABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
369 QualType OrigTy, AggValueSlot Slot)
const {
370 QualType Ty = OrigTy;
374 unsigned SlotSizeInBits = IsO32 ? 32 : 64;
375 unsigned PtrWidth = getTarget().getPointerWidth(LangAS::Default);
376 bool DidPromote =
false;
378 getContext().getIntWidth(Ty) < SlotSizeInBits) ||
381 Ty = getContext().getIntTypeForBitwidth(SlotSizeInBits,
385 auto TyInfo = getContext().getTypeInfoInChars(Ty);
396 ArgSlotSize,
true, Slot);
406 llvm::Value *
V = CGF.
Builder.CreateTrunc(Promoted, IntTy);
408 V = CGF.
Builder.CreateIntToPtr(
V, ValTy);
416ABIArgInfo MipsABIInfo::extendType(QualType Ty)
const {
417 int TySize = getContext().getTypeSize(Ty);
427MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
428 llvm::Value *Address)
const {
434 llvm::Value *Four8 = llvm::ConstantInt::get(CGF.
Int8Ty, 4);
454std::unique_ptr<TargetCodeGenInfo>
456 return std::make_unique<MIPSTargetCodeGenInfo>(CGM.
getTypes(), IsOS32);
459std::unique_ptr<TargetCodeGenInfo>
461 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
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...
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