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,
69 raw_ostream &Out)
const override;
71 raw_ostream &Out)
const override;
75void RISCVABIInfo::appendAttributeMangling(TargetClonesAttr *
Attr,
77 raw_ostream &Out)
const {
78 appendAttributeMangling(
Attr->getFeatureStr(Index), Out);
81void RISCVABIInfo::appendAttributeMangling(StringRef AttrStr,
82 raw_ostream &Out)
const {
83 if (AttrStr ==
"default") {
91 AttrStr.split(Attrs,
';');
95 for (
auto &
Attr : Attrs) {
96 if (
Attr.starts_with(
"arch="))
102 ArchStr.consume_front(
"arch=");
103 ArchStr.split(Features,
',');
105 llvm::stable_sort(Features);
107 for (
auto Feat : Features) {
108 Feat.consume_front(
"+");
125 getContext().getTypeSize(RetTy) > (2 * XLen)) {
128 IsRetIndirect = getContext().getTypeSize(EltTy) > FLen;
131 IsRetIndirect =
true;
135 int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs;
136 int ArgFPRsLeft = NumArgFPRs;
141 bool IsFixed = ArgNum < NumFixedArgs;
153 llvm::Type *&Field1Ty,
155 llvm::Type *&Field2Ty,
160 if (IsInt || IsFloat) {
162 if (IsInt && Size > XLen)
166 if (IsFloat && Size > FLen)
170 if (IsInt && Field1Ty && Field1Ty->isIntegerTy())
173 Field1Ty = CGT.ConvertType(Ty);
178 Field2Ty = CGT.ConvertType(Ty);
188 QualType EltTy = CTy->getElementType();
189 if (getContext().getTypeSize(EltTy) > FLen)
191 Field1Ty = CGT.ConvertType(EltTy);
194 Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy);
199 uint64_t ArraySize = ATy->getZExtSize();
200 QualType EltTy = ATy->getElementType();
204 if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getDecl()) &&
208 CharUnits EltSize = getContext().getTypeSizeInChars(EltTy);
209 for (uint64_t i = 0; i < ArraySize; ++i) {
210 bool Ret = detectFPCCEligibleStructHelper(EltTy, CurOff, Field1Ty,
211 Field1Off, Field2Ty, Field2Off);
232 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
237 bool Ret = detectFPCCEligibleStructHelper(B.getType(), CurOff + BaseOff,
238 Field1Ty, Field1Off, Field2Ty,
244 int ZeroWidthBitFieldCount = 0;
248 if (FD->isBitField()) {
249 unsigned BitWidth = FD->getBitWidthValue(getContext());
252 if (getContext().getTypeSize(QTy) > XLen && BitWidth <= XLen)
253 QTy = getContext().getIntTypeForBitwidth(XLen,
false);
255 ZeroWidthBitFieldCount++;
260 bool Ret = detectFPCCEligibleStructHelper(
261 QTy, CurOff + getContext().toCharUnitsFromBits(FieldOffInBits),
262 Field1Ty, Field1Off, Field2Ty, Field2Off);
269 if (Field2Ty && ZeroWidthBitFieldCount > 0)
272 return Field1Ty !=
nullptr;
282bool RISCVABIInfo::detectFPCCEligibleStruct(
QualType Ty, llvm::Type *&Field1Ty,
284 llvm::Type *&Field2Ty,
287 int &NeededArgFPRs)
const {
292 bool IsCandidate = detectFPCCEligibleStructHelper(
297 if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy())
301 if (Field1Ty && Field1Ty->isFloatingPointTy())
305 if (Field2Ty && Field2Ty->isFloatingPointTy())
315ABIArgInfo RISCVABIInfo::coerceAndExpandFPCCEligibleStruct(
316 llvm::Type *Field1Ty,
CharUnits Field1Off, llvm::Type *Field2Ty,
321 CoerceElts.push_back(llvm::ArrayType::get(
322 llvm::Type::getInt8Ty(getVMContext()), Field1Off.
getQuantity()));
324 CoerceElts.push_back(Field1Ty);
325 UnpaddedCoerceElts.push_back(Field1Ty);
329 llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.
isZero()),
330 UnpaddedCoerceElts[0]);
340 if (Field2Off > Field2OffNoPadNoPack)
341 Padding = Field2Off - Field2OffNoPadNoPack;
342 else if (Field2Off != Field2Align && Field2Off > Field1End)
343 Padding = Field2Off - Field1End;
348 CoerceElts.push_back(llvm::ArrayType::get(
349 llvm::Type::getInt8Ty(getVMContext()), Padding.
getQuantity()));
351 CoerceElts.push_back(Field2Ty);
352 UnpaddedCoerceElts.push_back(Field2Ty);
355 llvm::StructType::get(getVMContext(), CoerceElts, IsPacked);
356 auto UnpaddedCoerceToType =
357 llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked);
368 assert(VT->getElementType()->isBuiltinType() &&
"expected builtin type!");
371 getContext().getTargetInfo().getVScaleRange(getContext().getLangOpts());
373 unsigned NumElts = VT->getNumElements();
374 llvm::Type *EltType = llvm::Type::getInt1Ty(getVMContext());
375 switch (VT->getVectorKind()) {
376 case VectorKind::RVVFixedLengthMask_1:
378 case VectorKind::RVVFixedLengthMask_2:
381 case VectorKind::RVVFixedLengthMask_4:
384 case VectorKind::RVVFixedLengthMask:
388 assert(VT->getVectorKind() == VectorKind::RVVFixedLengthData &&
389 "Unexpected vector kind");
390 EltType = CGT.ConvertType(VT->getElementType());
397 llvm::ScalableVectorType *ResType =
398 llvm::ScalableVectorType::get(EltType, NumElts / VScale->first);
404 int &ArgFPRsLeft)
const {
405 assert(ArgGPRsLeft <= NumArgGPRs &&
"Arg GPR tracking underflow");
413 return getNaturalAlignIndirect(Ty, RAA ==
426 FLen >= Size && ArgFPRsLeft) {
433 if (IsFixed && Ty->
isComplexType() && FLen && ArgFPRsLeft >= 2) {
435 if (getContext().getTypeSize(EltTy) <= FLen) {
442 llvm::Type *Field1Ty =
nullptr;
443 llvm::Type *Field2Ty =
nullptr;
446 int NeededArgGPRs = 0;
447 int NeededArgFPRs = 0;
449 detectFPCCEligibleStruct(Ty, Field1Ty, Field1Off, Field2Ty, Field2Off,
450 NeededArgGPRs, NeededArgFPRs);
451 if (IsCandidate && NeededArgGPRs <= ArgGPRsLeft &&
452 NeededArgFPRs <= ArgFPRsLeft) {
453 ArgGPRsLeft -= NeededArgGPRs;
454 ArgFPRsLeft -= NeededArgFPRs;
455 return coerceAndExpandFPCCEligibleStruct(Field1Ty, Field1Off, Field2Ty,
460 uint64_t NeededAlign = getContext().getTypeAlign(Ty);
467 int NeededArgGPRs = 1;
468 if (!IsFixed && NeededAlign == 2 * XLen)
469 NeededArgGPRs = 2 + (EABI && XLen == 32 ? 0 : (ArgGPRsLeft % 2));
470 else if (Size > XLen && Size <= 2 * XLen)
473 if (NeededArgGPRs > ArgGPRsLeft) {
474 NeededArgGPRs = ArgGPRsLeft;
477 ArgGPRsLeft -= NeededArgGPRs;
482 Ty = EnumTy->getDecl()->getIntegerType();
485 if (Size < XLen && Ty->isIntegralOrEnumerationType()) {
486 return extendType(Ty, CGT.ConvertType(Ty));
490 if (EIT->getNumBits() < XLen)
491 return extendType(Ty, CGT.ConvertType(Ty));
492 if (EIT->getNumBits() > 128 ||
493 (!getContext().getTargetInfo().hasInt128Type() &&
494 EIT->getNumBits() > 64))
495 return getNaturalAlignIndirect(Ty,
false);
501 if (llvm::StructType *STy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty)))
508 if (VT->getVectorKind() == VectorKind::RVVFixedLengthData ||
509 VT->getVectorKind() == VectorKind::RVVFixedLengthMask ||
510 VT->getVectorKind() == VectorKind::RVVFixedLengthMask_1 ||
511 VT->getVectorKind() == VectorKind::RVVFixedLengthMask_2 ||
512 VT->getVectorKind() == VectorKind::RVVFixedLengthMask_4)
513 return coerceVLSVector(Ty);
517 if (Size <= 2 * XLen) {
518 unsigned Alignment = getContext().getTypeAlign(Ty);
524 llvm::IntegerType::get(getVMContext(), XLen));
525 }
else if (Alignment == 2 * XLen) {
527 llvm::IntegerType::get(getVMContext(), 2 * XLen));
530 llvm::IntegerType::get(getVMContext(), XLen), 2));
533 return getNaturalAlignIndirect(Ty,
false);
541 int ArgFPRsLeft = FLen ? 2 : 0;
557 auto TInfo = getContext().getTypeInfoInChars(Ty);
563 if (EABI && XLen == 32)
567 bool IsIndirect = TInfo.Width > 2 * SlotSize;
574 int TySize = getContext().getTypeSize(Ty);
585 unsigned FLen,
bool EABI)
587 std::make_unique<RISCVABIInfo>(CGT, XLen, FLen, EABI)) {
589 std::make_unique<SwiftABIInfo>(CGT,
false);
594 const auto *FD = dyn_cast_or_null<FunctionDecl>(
D);
597 auto *
Fn = cast<llvm::Function>(GV);
600 Fn->addFnAttr(
"hw-shadow-stack");
602 const auto *
Attr = FD->getAttr<RISCVInterruptAttr>();
607 switch (
Attr->getInterrupt()) {
608 case RISCVInterruptAttr::supervisor:
Kind =
"supervisor";
break;
609 case RISCVInterruptAttr::machine:
Kind =
"machine";
break;
612 Fn->addFnAttr(
"interrupt", Kind);
617std::unique_ptr<TargetCodeGenInfo>
619 unsigned FLen,
bool EABI) {
620 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)
virtual void appendAttributeMangling(TargetAttr *Attr, raw_ostream &Out) const
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()
const CodeGenOptions & getCodeGenOpts() const
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)
The JSON file list parser is used to communicate input to InstallAPI.