10#include "TargetInfo.h"
32 llvm::Type *&Field1Ty,
34 llvm::Type *&Field2Ty,
40 :
DefaultABIInfo(CGT), XLen(XLen), FLen(FLen), NumArgGPRs(EABI ? 6 : 8),
41 NumArgFPRs(FLen != 0 ? 8 : 0), EABI(EABI) {}
48 int &ArgFPRsLeft)
const;
56 bool detectFPCCEligibleStruct(
QualType Ty, llvm::Type *&Field1Ty,
57 CharUnits &Field1Off, llvm::Type *&Field2Ty,
59 int &NeededArgFPRs)
const;
60 ABIArgInfo coerceAndExpandFPCCEligibleStruct(llvm::Type *Field1Ty,
81 getContext().getTypeSize(RetTy) > (2 * XLen)) {
84 IsRetIndirect = getContext().getTypeSize(EltTy) > FLen;
91 int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs;
92 int ArgFPRsLeft = NumArgFPRs;
97 bool IsFixed = ArgNum < NumFixedArgs;
109 llvm::Type *&Field1Ty,
111 llvm::Type *&Field2Ty,
116 if (IsInt || IsFloat) {
118 if (IsInt && Size > XLen)
122 if (IsFloat && Size > FLen)
126 if (IsInt && Field1Ty && Field1Ty->isIntegerTy())
129 Field1Ty = CGT.ConvertType(Ty);
134 Field2Ty = CGT.ConvertType(Ty);
144 QualType EltTy = CTy->getElementType();
145 if (getContext().getTypeSize(EltTy) > FLen)
147 Field1Ty = CGT.ConvertType(EltTy);
150 Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy);
155 uint64_t ArraySize = ATy->getZExtSize();
156 QualType EltTy = ATy->getElementType();
160 if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getDecl()) &&
164 CharUnits EltSize = getContext().getTypeSizeInChars(EltTy);
165 for (uint64_t i = 0; i < ArraySize; ++i) {
166 bool Ret = detectFPCCEligibleStructHelper(EltTy, CurOff, Field1Ty,
167 Field1Off, Field2Ty, Field2Off);
188 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
193 bool Ret = detectFPCCEligibleStructHelper(B.getType(), CurOff + BaseOff,
194 Field1Ty, Field1Off, Field2Ty,
200 int ZeroWidthBitFieldCount = 0;
204 if (FD->isBitField()) {
205 unsigned BitWidth = FD->getBitWidthValue(getContext());
208 if (getContext().getTypeSize(QTy) > XLen && BitWidth <= XLen)
209 QTy = getContext().getIntTypeForBitwidth(XLen,
false);
211 ZeroWidthBitFieldCount++;
216 bool Ret = detectFPCCEligibleStructHelper(
217 QTy, CurOff + getContext().toCharUnitsFromBits(FieldOffInBits),
218 Field1Ty, Field1Off, Field2Ty, Field2Off);
225 if (Field2Ty && ZeroWidthBitFieldCount > 0)
228 return Field1Ty !=
nullptr;
238bool RISCVABIInfo::detectFPCCEligibleStruct(
QualType Ty, llvm::Type *&Field1Ty,
240 llvm::Type *&Field2Ty,
243 int &NeededArgFPRs)
const {
248 bool IsCandidate = detectFPCCEligibleStructHelper(
253 if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy())
257 if (Field1Ty && Field1Ty->isFloatingPointTy())
261 if (Field2Ty && Field2Ty->isFloatingPointTy())
271ABIArgInfo RISCVABIInfo::coerceAndExpandFPCCEligibleStruct(
272 llvm::Type *Field1Ty,
CharUnits Field1Off, llvm::Type *Field2Ty,
277 CoerceElts.push_back(llvm::ArrayType::get(
278 llvm::Type::getInt8Ty(getVMContext()), Field1Off.
getQuantity()));
280 CoerceElts.push_back(Field1Ty);
281 UnpaddedCoerceElts.push_back(Field1Ty);
285 llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.
isZero()),
286 UnpaddedCoerceElts[0]);
296 if (Field2Off > Field2OffNoPadNoPack)
297 Padding = Field2Off - Field2OffNoPadNoPack;
298 else if (Field2Off != Field2Align && Field2Off > Field1End)
299 Padding = Field2Off - Field1End;
304 CoerceElts.push_back(llvm::ArrayType::get(
305 llvm::Type::getInt8Ty(getVMContext()), Padding.
getQuantity()));
307 CoerceElts.push_back(Field2Ty);
308 UnpaddedCoerceElts.push_back(Field2Ty);
311 llvm::StructType::get(getVMContext(), CoerceElts, IsPacked);
312 auto UnpaddedCoerceToType =
313 llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked);
324 assert(VT->getElementType()->isBuiltinType() &&
"expected builtin type!");
327 getContext().getTargetInfo().getVScaleRange(getContext().getLangOpts());
329 unsigned NumElts = VT->getNumElements();
330 llvm::Type *EltType = llvm::Type::getInt1Ty(getVMContext());
331 switch (VT->getVectorKind()) {
332 case VectorKind::RVVFixedLengthMask_1:
334 case VectorKind::RVVFixedLengthMask_2:
337 case VectorKind::RVVFixedLengthMask_4:
340 case VectorKind::RVVFixedLengthMask:
344 assert(VT->getVectorKind() == VectorKind::RVVFixedLengthData &&
345 "Unexpected vector kind");
346 EltType = CGT.ConvertType(VT->getElementType());
353 llvm::ScalableVectorType *ResType =
354 llvm::ScalableVectorType::get(EltType, NumElts / VScale->first);
360 int &ArgFPRsLeft)
const {
361 assert(ArgGPRsLeft <= NumArgGPRs &&
"Arg GPR tracking underflow");
369 return getNaturalAlignIndirect(Ty, RAA ==
382 FLen >= Size && ArgFPRsLeft) {
389 if (IsFixed && Ty->
isComplexType() && FLen && ArgFPRsLeft >= 2) {
391 if (getContext().getTypeSize(EltTy) <= FLen) {
398 llvm::Type *Field1Ty =
nullptr;
399 llvm::Type *Field2Ty =
nullptr;
402 int NeededArgGPRs = 0;
403 int NeededArgFPRs = 0;
405 detectFPCCEligibleStruct(Ty, Field1Ty, Field1Off, Field2Ty, Field2Off,
406 NeededArgGPRs, NeededArgFPRs);
407 if (IsCandidate && NeededArgGPRs <= ArgGPRsLeft &&
408 NeededArgFPRs <= ArgFPRsLeft) {
409 ArgGPRsLeft -= NeededArgGPRs;
410 ArgFPRsLeft -= NeededArgFPRs;
411 return coerceAndExpandFPCCEligibleStruct(Field1Ty, Field1Off, Field2Ty,
416 uint64_t NeededAlign = getContext().getTypeAlign(Ty);
423 int NeededArgGPRs = 1;
424 if (!IsFixed && NeededAlign == 2 * XLen)
425 NeededArgGPRs = 2 + (EABI && XLen == 32 ? 0 : (ArgGPRsLeft % 2));
426 else if (Size > XLen && Size <= 2 * XLen)
429 if (NeededArgGPRs > ArgGPRsLeft) {
430 NeededArgGPRs = ArgGPRsLeft;
433 ArgGPRsLeft -= NeededArgGPRs;
438 Ty = EnumTy->getDecl()->getIntegerType();
441 if (Size < XLen && Ty->isIntegralOrEnumerationType()) {
442 return extendType(Ty);
446 if (EIT->getNumBits() < XLen)
447 return extendType(Ty);
448 if (EIT->getNumBits() > 128 ||
449 (!getContext().getTargetInfo().hasInt128Type() &&
450 EIT->getNumBits() > 64))
451 return getNaturalAlignIndirect(Ty,
false);
457 if (llvm::StructType *STy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty)))
464 if (VT->getVectorKind() == VectorKind::RVVFixedLengthData ||
465 VT->getVectorKind() == VectorKind::RVVFixedLengthMask ||
466 VT->getVectorKind() == VectorKind::RVVFixedLengthMask_1 ||
467 VT->getVectorKind() == VectorKind::RVVFixedLengthMask_2 ||
468 VT->getVectorKind() == VectorKind::RVVFixedLengthMask_4)
469 return coerceVLSVector(Ty);
473 if (Size <= 2 * XLen) {
474 unsigned Alignment = getContext().getTypeAlign(Ty);
480 llvm::IntegerType::get(getVMContext(), XLen));
481 }
else if (Alignment == 2 * XLen) {
483 llvm::IntegerType::get(getVMContext(), 2 * XLen));
486 llvm::IntegerType::get(getVMContext(), XLen), 2));
489 return getNaturalAlignIndirect(Ty,
false);
497 int ArgFPRsLeft = FLen ? 2 : 0;
513 auto TInfo = getContext().getTypeInfoInChars(Ty);
519 if (EABI && XLen == 32)
523 bool IsIndirect = TInfo.Width > 2 * SlotSize;
530 int TySize = getContext().getTypeSize(Ty);
541 unsigned FLen,
bool EABI)
543 std::make_unique<RISCVABIInfo>(CGT, XLen, FLen, EABI)) {
545 std::make_unique<SwiftABIInfo>(CGT,
false);
550 const auto *FD = dyn_cast_or_null<FunctionDecl>(
D);
553 const auto *
Attr = FD->getAttr<RISCVInterruptAttr>();
558 switch (
Attr->getInterrupt()) {
559 case RISCVInterruptAttr::supervisor:
Kind =
"supervisor";
break;
560 case RISCVInterruptAttr::machine:
Kind =
"machine";
break;
563 auto *
Fn = cast<llvm::Function>(GV);
565 Fn->addFnAttr(
"interrupt", Kind);
570std::unique_ptr<TargetCodeGenInfo>
572 unsigned FLen,
bool EABI) {
573 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)
void setCanBeFlattened(bool Flatten)
static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T=nullptr)
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
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...
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
RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, AggValueSlot Slot) const override
EmitVAArg - Emit the target dependent code to load a value of.
ABIArgInfo classifyReturnType(QualType RetTy) const
void computeInfo(CGFunctionInfo &FI) const override
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
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)
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)
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 EABI)
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)
The JSON file list parser is used to communicate input to InstallAPI.