10#include "TargetInfo.h"
28 static const int NumArgGPRs = 8;
29 static const int NumArgFPRs = 8;
31 llvm::Type *&Field1Ty,
33 llvm::Type *&Field2Ty,
45 int &ArgFPRsLeft)
const;
53 bool detectFPCCEligibleStruct(
QualType Ty, llvm::Type *&Field1Ty,
54 CharUnits &Field1Off, llvm::Type *&Field2Ty,
56 int &NeededArgFPRs)
const;
57 ABIArgInfo coerceAndExpandFPCCEligibleStruct(llvm::Type *Field1Ty,
78 getContext().getTypeSize(RetTy) > (2 * XLen)) {
81 IsRetIndirect = getContext().getTypeSize(EltTy) > FLen;
88 int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs;
89 int ArgFPRsLeft = FLen ? NumArgFPRs : 0;
94 bool IsFixed = ArgNum < NumFixedArgs;
106 llvm::Type *&Field1Ty,
108 llvm::Type *&Field2Ty,
113 if (IsInt || IsFloat) {
115 if (IsInt && Size > XLen)
119 if (IsFloat && Size > FLen)
123 if (IsInt && Field1Ty && Field1Ty->isIntegerTy())
126 Field1Ty = CGT.ConvertType(Ty);
131 Field2Ty = CGT.ConvertType(Ty);
141 QualType EltTy = CTy->getElementType();
142 if (getContext().getTypeSize(EltTy) > FLen)
144 Field1Ty = CGT.ConvertType(EltTy);
147 Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy);
152 uint64_t ArraySize = ATy->getSize().getZExtValue();
153 QualType EltTy = ATy->getElementType();
157 if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getDecl()) &&
161 CharUnits EltSize = getContext().getTypeSizeInChars(EltTy);
162 for (uint64_t i = 0; i < ArraySize; ++i) {
163 bool Ret = detectFPCCEligibleStructHelper(EltTy, CurOff, Field1Ty,
164 Field1Off, Field2Ty, Field2Off);
185 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
190 bool Ret = detectFPCCEligibleStructHelper(B.getType(), CurOff + BaseOff,
191 Field1Ty, Field1Off, Field2Ty,
197 int ZeroWidthBitFieldCount = 0;
201 if (FD->isBitField()) {
202 unsigned BitWidth = FD->getBitWidthValue(getContext());
205 if (getContext().getTypeSize(QTy) > XLen && BitWidth <= XLen)
206 QTy = getContext().getIntTypeForBitwidth(XLen,
false);
208 ZeroWidthBitFieldCount++;
213 bool Ret = detectFPCCEligibleStructHelper(
214 QTy, CurOff + getContext().toCharUnitsFromBits(FieldOffInBits),
215 Field1Ty, Field1Off, Field2Ty, Field2Off);
222 if (Field2Ty && ZeroWidthBitFieldCount > 0)
225 return Field1Ty !=
nullptr;
235bool RISCVABIInfo::detectFPCCEligibleStruct(
QualType Ty, llvm::Type *&Field1Ty,
237 llvm::Type *&Field2Ty,
240 int &NeededArgFPRs)
const {
245 bool IsCandidate = detectFPCCEligibleStructHelper(
250 if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy())
254 if (Field1Ty && Field1Ty->isFloatingPointTy())
258 if (Field2Ty && Field2Ty->isFloatingPointTy())
268ABIArgInfo RISCVABIInfo::coerceAndExpandFPCCEligibleStruct(
269 llvm::Type *Field1Ty,
CharUnits Field1Off, llvm::Type *Field2Ty,
274 CoerceElts.push_back(llvm::ArrayType::get(
275 llvm::Type::getInt8Ty(getVMContext()), Field1Off.
getQuantity()));
277 CoerceElts.push_back(Field1Ty);
278 UnpaddedCoerceElts.push_back(Field1Ty);
282 llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.
isZero()),
283 UnpaddedCoerceElts[0]);
293 if (Field2Off > Field2OffNoPadNoPack)
294 Padding = Field2Off - Field2OffNoPadNoPack;
295 else if (Field2Off != Field2Align && Field2Off > Field1End)
296 Padding = Field2Off - Field1End;
301 CoerceElts.push_back(llvm::ArrayType::get(
302 llvm::Type::getInt8Ty(getVMContext()), Padding.
getQuantity()));
304 CoerceElts.push_back(Field2Ty);
305 UnpaddedCoerceElts.push_back(Field2Ty);
308 llvm::StructType::get(getVMContext(), CoerceElts, IsPacked);
309 auto UnpaddedCoerceToType =
310 llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked);
321 assert(VT->getVectorKind() == VectorKind::RVVFixedLengthData &&
322 "Unexpected vector kind");
324 assert(VT->getElementType()->isBuiltinType() &&
"expected builtin type!");
327 getContext().getTargetInfo().getVScaleRange(getContext().getLangOpts());
332 llvm::ScalableVectorType *ResType =
333 llvm::ScalableVectorType::get(CGT.ConvertType(VT->getElementType()),
334 VT->getNumElements() / VScale->first);
340 int &ArgFPRsLeft)
const {
341 assert(ArgGPRsLeft <= NumArgGPRs &&
"Arg GPR tracking underflow");
349 return getNaturalAlignIndirect(Ty, RAA ==
361 FLen >= Size && ArgFPRsLeft) {
368 if (IsFixed && Ty->
isComplexType() && FLen && ArgFPRsLeft >= 2) {
370 if (getContext().getTypeSize(EltTy) <= FLen) {
377 llvm::Type *Field1Ty =
nullptr;
378 llvm::Type *Field2Ty =
nullptr;
381 int NeededArgGPRs = 0;
382 int NeededArgFPRs = 0;
384 detectFPCCEligibleStruct(Ty, Field1Ty, Field1Off, Field2Ty, Field2Off,
385 NeededArgGPRs, NeededArgFPRs);
386 if (IsCandidate && NeededArgGPRs <= ArgGPRsLeft &&
387 NeededArgFPRs <= ArgFPRsLeft) {
388 ArgGPRsLeft -= NeededArgGPRs;
389 ArgFPRsLeft -= NeededArgFPRs;
390 return coerceAndExpandFPCCEligibleStruct(Field1Ty, Field1Off, Field2Ty,
395 uint64_t NeededAlign = getContext().getTypeAlign(Ty);
399 int NeededArgGPRs = 1;
400 if (!IsFixed && NeededAlign == 2 * XLen)
401 NeededArgGPRs = 2 + (ArgGPRsLeft % 2);
402 else if (Size > XLen && Size <= 2 * XLen)
405 if (NeededArgGPRs > ArgGPRsLeft) {
406 NeededArgGPRs = ArgGPRsLeft;
409 ArgGPRsLeft -= NeededArgGPRs;
414 Ty = EnumTy->getDecl()->getIntegerType();
417 if (Size < XLen && Ty->isIntegralOrEnumerationType()) {
418 return extendType(Ty);
422 if (EIT->getNumBits() < XLen)
423 return extendType(Ty);
424 if (EIT->getNumBits() > 128 ||
425 (!getContext().getTargetInfo().hasInt128Type() &&
426 EIT->getNumBits() > 64))
427 return getNaturalAlignIndirect(Ty,
false);
434 if (VT->getVectorKind() == VectorKind::RVVFixedLengthData)
435 return coerceVLSVector(Ty);
439 if (Size <= 2 * XLen) {
440 unsigned Alignment = getContext().getTypeAlign(Ty);
446 llvm::IntegerType::get(getVMContext(), XLen));
447 }
else if (Alignment == 2 * XLen) {
449 llvm::IntegerType::get(getVMContext(), 2 * XLen));
452 llvm::IntegerType::get(getVMContext(), XLen), 2));
455 return getNaturalAlignIndirect(Ty,
false);
463 int ArgFPRsLeft = FLen ? 2 : 0;
481 auto TInfo = getContext().getTypeInfoInChars(Ty);
484 bool IsIndirect = TInfo.Width > 2 * SlotSize;
491 int TySize = getContext().getTypeSize(Ty);
507 const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
510 const auto *
Attr = FD->getAttr<RISCVInterruptAttr>();
515 switch (
Attr->getInterrupt()) {
516 case RISCVInterruptAttr::supervisor:
Kind =
"supervisor";
break;
517 case RISCVInterruptAttr::machine:
Kind =
"machine";
break;
520 auto *Fn = cast<llvm::Function>(GV);
522 Fn->addFnAttr(
"interrupt", Kind);
527std::unique_ptr<TargetCodeGenInfo>
530 return std::make_unique<RISCVTargetCodeGenInfo>(CGM.
getTypes(), XLen, FLen);
static CharUnits getTypeStoreSize(CodeGenModule &CGM, llvm::Type *type)
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
Attr - This represents one attribute.
A fixed int type of a specified bitwidth.
Represents a base class of a C++ class.
Represents a C++ struct/union/class.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
bool isMultipleOf(CharUnits N) const
Test whether this is a multiple of the other value.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
static ABIArgInfo getIgnore()
static ABIArgInfo getDirect(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true, unsigned Align=0)
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
static ABIArgInfo getExtend(QualType Ty, llvm::Type *T=nullptr)
static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType, llvm::Type *unpaddedCoerceToType)
static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T=nullptr)
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
RecordArgABI
Specify how one should pass an argument of a record type.
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
CGFunctionInfo - Class to encapsulate the information about a function definition.
ABIArgInfo & getReturnInfo()
CanQualType getReturnType() const
MutableArrayRef< ArgInfo > arguments()
unsigned getNumRequiredArgs() const
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::Type * ConvertTypeForMem(QualType T)
This class organizes the cross-function state that is used while generating LLVM code.
CodeGenTypes & getTypes()
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
DefaultABIInfo - The default implementation for ABI specific details.
ABIArgInfo classifyArgumentType(QualType RetTy) const
ABIArgInfo classifyReturnType(QualType RetTy) const
void computeInfo(CGFunctionInfo &FI) const override
Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty) const override
EmitVAArg - Emit the target dependent code to load a value of.
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
virtual void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const
setTargetAttributes - Provides a convenient hook to handle extra target-specific attributes for the g...
Complex values, per C99 6.2.5p11.
Represents the canonical version of C arrays with a specified constant size.
Decl - This represents one declaration (or definition), e.g.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Represents a member of a struct/union/class.
A (possibly-)qualified type.
Represents a struct/union/class.
field_range fields() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
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 ...
const T * castAs() const
Member-template castAs<specific type>.
bool isScalarType() const
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isStructureOrClassType() const
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
bool isFloatingType() const
const T * getAs() const
Member-template getAs<specific type>'.
Represents a GCC generic vector type.
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to pass a particular type.
CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI)
bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info)
Address emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType ValueTy, bool IsIndirect, TypeInfoChars ValueInfo, CharUnits SlotSizeAndAlign, bool AllowHigherAlign, bool ForceRightAdjust=false)
Emit va_arg for a platform using the common void* representation, where arguments are simply emitted ...
bool isAggregateTypeForABI(QualType T)
QualType useFirstFieldIfTransparentUnion(QualType Ty)
Pass transparent unions as if they were the type of the first element.
std::unique_ptr< TargetCodeGenInfo > createRISCVTargetCodeGenInfo(CodeGenModule &CGM, unsigned XLen, unsigned FLen)
bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, bool AsIfNoUniqueAddr=false)
isEmptyRecord - Return true iff a structure contains only empty fields.
bool Ret(InterpState &S, CodePtr &PC, APValue &Result)