10#include "TargetInfo.h"
11#include "llvm/IR/IntrinsicsRISCV.h"
12#include "llvm/TargetParser/RISCVTargetParser.h"
33 bool detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff,
34 llvm::Type *&Field1Ty,
36 llvm::Type *&Field2Ty,
37 CharUnits &Field2Off)
const;
39 llvm::Type *detectVLSCCEligibleStruct(QualType Ty,
unsigned ABIVLen)
const;
41 llvm::Type *detectHomogeneousRVVFixedLengthStruct(QualType Ty)
const;
43 unsigned getRVVFixedLengthMinElts(
const VectorType *VT)
const;
46 RISCVABIInfo(CodeGen::CodeGenTypes &CGT,
unsigned XLen,
unsigned FLen,
48 : DefaultABIInfo(CGT), XLen(XLen), FLen(FLen), NumArgGPRs(EABI ? 6 : 8),
49 NumArgFPRs(FLen != 0 ? 8 : 0), EABI(EABI) {}
53 void computeInfo(CGFunctionInfo &FI)
const override;
56 int &ArgFPRsLeft,
unsigned ABIVLen)
const;
59 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
60 AggValueSlot Slot)
const override;
62 ABIArgInfo extendType(QualType Ty, llvm::Type *CoerceTy =
nullptr)
const;
64 bool detectFPCCEligibleStruct(QualType Ty, llvm::Type *&Field1Ty,
65 CharUnits &Field1Off, llvm::Type *&Field2Ty,
66 CharUnits &Field2Off,
int &NeededArgGPRs,
67 int &NeededArgFPRs)
const;
68 ABIArgInfo coerceAndExpandFPCCEligibleStruct(llvm::Type *Field1Ty,
71 CharUnits Field2Off)
const;
73 ABIArgInfo coerceVLSVector(QualType Ty,
unsigned ABIVLen = 0)
const;
77 llvm::FixedVectorType *
78 getVLSCCCompatibleType(llvm::FixedVectorType *FixedVecTy)
const;
81 void appendAttributeMangling(TargetClonesAttr *Attr,
unsigned Index,
82 raw_ostream &Out)
const override;
83 void appendAttributeMangling(StringRef AttrStr,
84 raw_ostream &Out)
const override;
85 llvm::Value *createCoercedLoad(Address SrcAddr,
const ABIArgInfo &AI,
86 CodeGenFunction &CGF)
const override;
87 void createCoercedStore(llvm::Value *Val, Address DstAddr,
88 const ABIArgInfo &AI,
bool DestIsVolatile,
89 CodeGenFunction &CGF)
const override;
93void RISCVABIInfo::appendAttributeMangling(TargetClonesAttr *
Attr,
95 raw_ostream &Out)
const {
96 appendAttributeMangling(Attr->getFeatureStr(Index), Out);
99void RISCVABIInfo::appendAttributeMangling(StringRef AttrStr,
100 raw_ostream &Out)
const {
101 if (AttrStr ==
"default") {
108 SmallVector<StringRef, 8> Attrs;
109 AttrStr.split(Attrs,
';');
113 for (
auto &Attr : Attrs) {
114 if (Attr.starts_with(
"arch="))
119 SmallVector<StringRef, 8> Features;
120 ArchStr.consume_front(
"arch=");
121 ArchStr.split(Features,
',');
123 llvm::stable_sort(Features);
125 for (
auto Feat : Features) {
126 Feat.consume_front(
"+");
131void RISCVABIInfo::computeInfo(CGFunctionInfo &FI)
const {
137#define CC_VLS_CASE(ABI_VLEN) \
138 case CallingConv::CC_RISCVVLSCall_##ABI_VLEN: \
139 ABIVLen = ABI_VLEN; \
166 getContext().getTypeSize(RetTy) > (2 * XLen)) {
168 QualType EltTy = RetTy->
castAs<ComplexType>()->getElementType();
169 IsRetIndirect = getContext().getTypeSize(EltTy) > FLen;
172 IsRetIndirect =
true;
176 int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs;
177 int ArgFPRsLeft = NumArgFPRs;
182 bool IsFixed = ArgNum < NumFixedArgs;
184 ArgFPRsLeft, ABIVLen);
193bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff,
194 llvm::Type *&Field1Ty,
195 CharUnits &Field1Off,
196 llvm::Type *&Field2Ty,
197 CharUnits &Field2Off)
const {
201 if (IsInt || IsFloat) {
203 if (IsInt && Size > XLen)
207 if (IsFloat && Size > FLen)
211 if (IsInt && Field1Ty && Field1Ty->isIntegerTy())
214 Field1Ty = CGT.ConvertType(Ty);
219 Field2Ty = CGT.ConvertType(Ty);
226 if (
auto CTy = Ty->
getAs<ComplexType>()) {
229 QualType EltTy = CTy->getElementType();
236 if (getContext().getTypeSize(EltTy) > FLen)
238 Field1Ty = CGT.ConvertType(EltTy);
241 Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy);
245 if (
const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) {
246 uint64_t ArraySize = ATy->getZExtSize();
247 QualType EltTy = ATy->getElementType();
255 CharUnits EltSize = getContext().getTypeSizeInChars(EltTy);
256 for (uint64_t i = 0; i < ArraySize; ++i) {
257 bool Ret = detectFPCCEligibleStructHelper(EltTy, CurOff, Field1Ty,
258 Field1Off, Field2Ty, Field2Off);
273 const RecordDecl *RD = RTy->getDecl()->getDefinitionOrSelf();
277 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
279 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
280 for (
const CXXBaseSpecifier &B : CXXRD->bases()) {
281 const auto *BDecl = B.getType()->castAsCXXRecordDecl();
283 bool Ret = detectFPCCEligibleStructHelper(B.getType(), CurOff + BaseOff,
284 Field1Ty, Field1Off, Field2Ty,
290 int ZeroWidthBitFieldCount = 0;
291 for (
const FieldDecl *FD : RD->
fields()) {
293 QualType QTy = FD->getType();
294 if (FD->isBitField()) {
295 unsigned BitWidth = FD->getBitWidthValue();
298 if (getContext().getTypeSize(QTy) > XLen && BitWidth <= XLen)
299 QTy = getContext().getIntTypeForBitwidth(XLen,
false);
301 else if (getContext().getTypeSize(QTy) > BitWidth) {
303 FD->getType().getTypePtr()->hasSignedIntegerRepresentation();
304 unsigned Bits = std::max(8U, (
unsigned)llvm::PowerOf2Ceil(BitWidth));
305 QTy = getContext().getIntTypeForBitwidth(Bits, IsSigned);
308 ZeroWidthBitFieldCount++;
313 bool Ret = detectFPCCEligibleStructHelper(
314 QTy, CurOff + getContext().toCharUnitsFromBits(FieldOffInBits),
315 Field1Ty, Field1Off, Field2Ty, Field2Off);
322 if (Field2Ty && ZeroWidthBitFieldCount > 0)
325 return Field1Ty !=
nullptr;
335bool RISCVABIInfo::detectFPCCEligibleStruct(QualType Ty, llvm::Type *&Field1Ty,
336 CharUnits &Field1Off,
337 llvm::Type *&Field2Ty,
338 CharUnits &Field2Off,
340 int &NeededArgFPRs)
const {
345 bool IsCandidate = detectFPCCEligibleStructHelper(
350 if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy())
354 if (Field1Ty && Field1Ty->isFloatingPointTy())
358 if (Field2Ty && Field2Ty->isFloatingPointTy())
368ABIArgInfo RISCVABIInfo::coerceAndExpandFPCCEligibleStruct(
369 llvm::Type *Field1Ty, CharUnits Field1Off, llvm::Type *Field2Ty,
370 CharUnits Field2Off)
const {
371 SmallVector<llvm::Type *, 3> CoerceElts;
372 SmallVector<llvm::Type *, 2> UnpaddedCoerceElts;
374 CoerceElts.push_back(llvm::ArrayType::get(
375 llvm::Type::getInt8Ty(getVMContext()), Field1Off.
getQuantity()));
377 CoerceElts.push_back(Field1Ty);
378 UnpaddedCoerceElts.push_back(Field1Ty);
382 llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.
isZero()),
383 UnpaddedCoerceElts[0]);
386 CharUnits Field2Align =
388 CharUnits Field1End = Field1Off +
390 CharUnits Field2OffNoPadNoPack = Field1End.
alignTo(Field2Align);
393 if (Field2Off > Field2OffNoPadNoPack)
394 Padding = Field2Off - Field2OffNoPadNoPack;
395 else if (Field2Off != Field2Align && Field2Off > Field1End)
396 Padding = Field2Off - Field1End;
401 CoerceElts.push_back(llvm::ArrayType::get(
402 llvm::Type::getInt8Ty(getVMContext()), Padding.
getQuantity()));
404 CoerceElts.push_back(Field2Ty);
405 UnpaddedCoerceElts.push_back(Field2Ty);
408 llvm::StructType::get(getVMContext(), CoerceElts, IsPacked);
409 auto UnpaddedCoerceToType =
410 llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked);
420 unsigned EltSizeInBits) {
424 unsigned SizeAtVScale1 = LMulLog2 >= 0
425 ? llvm::RISCV::RVVBitsPerBlock << LMulLog2
426 : llvm::RISCV::RVVBitsPerBlock >> -LMulLog2;
427 assert(SizeAtVScale1 >= EltSizeInBits &&
"LMUL too small for element type");
428 return SizeAtVScale1 / EltSizeInBits;
440unsigned RISCVABIInfo::getRVVFixedLengthMinElts(
const VectorType *VT)
const {
441 unsigned EltSizeInBits = getContext().getTypeSize(VT->
getElementType());
445 "not an RVV fixed-length vector");
450llvm::Type *RISCVABIInfo::detectVLSCCEligibleStruct(QualType Ty,
451 unsigned ABIVLen)
const {
513 llvm::StructType *STy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty));
517 unsigned NumElts = STy->getStructNumElements();
521 auto *FirstEltTy = STy->getElementType(0);
522 if (!STy->containsHomogeneousTypes())
525 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(FirstEltTy)) {
529 FirstEltTy = ArrayTy->getArrayElementType();
530 NumElts = ArrayTy->getNumElements();
533 auto *FixedVecTy = dyn_cast<llvm::FixedVectorType>(FirstEltTy);
538 if (NumElts * llvm::divideCeil(
539 FixedVecTy->getNumElements() *
540 FixedVecTy->getElementType()->getScalarSizeInBits(),
548 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedVecTy);
549 return llvm::ScalableVectorType::get(
550 VLSTy->getElementType(),
551 llvm::divideCeil(VLSTy->getNumElements() * llvm::RISCV::RVVBitsPerBlock,
561 unsigned I8EltCount =
562 llvm::divideCeil(FixedVecTy->getNumElements() *
563 FixedVecTy->getElementType()->getScalarSizeInBits() *
564 llvm::RISCV::RVVBitsPerBlock,
566 return llvm::TargetExtType::get(
567 getVMContext(),
"riscv.vector.tuple",
568 llvm::ScalableVectorType::get(llvm::Type::getInt8Ty(getVMContext()),
574RISCVABIInfo::detectHomogeneousRVVFixedLengthStruct(QualType Ty)
const {
586 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
587 if (CXXRD->getNumBases() != 0)
590 SmallVector<const FieldDecl *, 8> Fields(RD->
fields());
595 auto IsFixedLengthRVVVector = [](
const VectorType *VT) {
603 if (Fields.size() == 1) {
604 QualType FieldTy = Fields[0]->getType().getCanonicalType();
605 if (
const ConstantArrayType *AT =
606 getContext().getAsConstantArrayType(FieldTy)) {
607 QualType EltTy = AT->getElementType().getCanonicalType();
608 if (
const auto *VT = EltTy->
getAs<VectorType>();
609 VT && IsFixedLengthRVVVector(VT)) {
611 Count = AT->getZExtSize();
618 if (Fields.size() > 8)
620 for (
const FieldDecl *FD : Fields) {
621 QualType FieldTy = FD->getType().getCanonicalType();
622 const auto *VT = FieldTy->
getAs<VectorType>();
623 if (!VT || !IsFixedLengthRVVVector(VT))
627 else if (!getContext().hasSameType(CommonTy, FieldTy))
630 Count = Fields.size();
633 if (Count == 0 || Count > 8)
636 const auto *VT = CommonTy->
castAs<VectorType>();
638 unsigned MinElts = getRVVFixedLengthMinElts(VT);
643 llvm::divideCeil((uint64_t)MinElts * EltType->getScalarSizeInBits(),
644 llvm::RISCV::RVVBitsPerBlock);
645 if (Count > 1 && Count * RegsPerVec > 8)
649 return llvm::ScalableVectorType::get(EltType, MinElts);
651 unsigned I8EltCount =
652 llvm::divideCeil((uint64_t)MinElts * EltType->getScalarSizeInBits(), 8);
653 auto *I8Vec = llvm::ScalableVectorType::get(
654 llvm::Type::getInt8Ty(getVMContext()), I8EltCount);
655 return llvm::TargetExtType::get(getVMContext(),
"riscv.vector.tuple", I8Vec,
659llvm::FixedVectorType *
660RISCVABIInfo::getVLSCCCompatibleType(llvm::FixedVectorType *FixedVecTy)
const {
661 llvm::Type *EltType = FixedVecTy->getElementType();
662 const TargetInfo &TI = getContext().getTargetInfo();
663 if ((EltType->isHalfTy() && !TI.
hasFeature(
"zvfhmin")) ||
664 (EltType->isBFloatTy() &&
666 (EltType->isFloatTy() && !TI.
hasFeature(
"zve32f")) ||
667 (EltType->isDoubleTy() && !TI.
hasFeature(
"zve64d")) ||
668 (EltType->isIntegerTy(64) && !TI.
hasFeature(
"zve64x")) ||
669 EltType->isIntegerTy(128))
670 return llvm::FixedVectorType::get(llvm::Type::getInt8Ty(getVMContext()),
671 FixedVecTy->getNumElements() *
672 EltType->getScalarSizeInBits() / 8);
678ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty,
unsigned ABIVLen)
const {
681 const auto *VT = Ty->
castAs<VectorType>();
684 auto VScale = getContext().getTargetInfo().getVScaleRange(
685 getContext().getLangOpts(), TargetInfo::ArmStreamingKind::NotStreaming);
691 EltType = llvm::Type::getInt1Ty(getVMContext());
695 "Unexpected vector kind");
700 llvm::ScalableVectorType *ResType;
703 unsigned MinScalableElts;
716 MinScalableElts = NumElts / VScale->first;
718 ResType = llvm::ScalableVectorType::get(EltType, MinScalableElts);
721 if ((EltType->getScalarSizeInBits() * NumElts / ABIVLen) > 8)
722 return getNaturalAlignIndirect(
723 Ty, getDataLayout().getAllocaAddrSpace(),
728 llvm::FixedVectorType *VLSTy =
729 getVLSCCCompatibleType(llvm::FixedVectorType::get(EltType, NumElts));
730 ResType = llvm::ScalableVectorType::get(
731 VLSTy->getElementType(),
732 llvm::divideCeil(VLSTy->getNumElements() * llvm::RISCV::RVVBitsPerBlock,
739ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty,
bool IsFixed,
742 unsigned ABIVLen)
const {
743 assert(ArgGPRsLeft <= NumArgGPRs &&
"Arg GPR tracking underflow");
751 return getNaturalAlignIndirect(
752 Ty, getDataLayout().getAllocaAddrSpace(),
765 FLen >= Size && ArgFPRsLeft) {
772 if (IsFixed && Ty->
isComplexType() && FLen && ArgFPRsLeft >= 2) {
773 QualType EltTy = Ty->
castAs<ComplexType>()->getElementType();
774 if (getContext().getTypeSize(EltTy) <= FLen) {
781 llvm::Type *Field1Ty =
nullptr;
782 llvm::Type *Field2Ty =
nullptr;
785 int NeededArgGPRs = 0;
786 int NeededArgFPRs = 0;
788 detectFPCCEligibleStruct(Ty, Field1Ty, Field1Off, Field2Ty, Field2Off,
789 NeededArgGPRs, NeededArgFPRs);
790 if (IsCandidate && NeededArgGPRs <= ArgGPRsLeft &&
791 NeededArgFPRs <= ArgFPRsLeft) {
792 ArgGPRsLeft -= NeededArgGPRs;
793 ArgFPRsLeft -= NeededArgFPRs;
794 return coerceAndExpandFPCCEligibleStruct(Field1Ty, Field1Off, Field2Ty,
800 if (llvm::Type *CoerceTy = detectHomogeneousRVVFixedLengthStruct(Ty))
803 if (llvm::Type *VLSType = detectVLSCCEligibleStruct(Ty, ABIVLen))
807 uint64_t NeededAlign = getContext().getTypeAlign(Ty);
814 int NeededArgGPRs = 1;
815 if (!IsFixed && NeededAlign == 2 * XLen)
816 NeededArgGPRs = 2 + (EABI ? 0 : (ArgGPRsLeft % 2));
817 else if (Size > XLen && Size <= 2 * XLen)
820 if (NeededArgGPRs > ArgGPRsLeft) {
821 NeededArgGPRs = ArgGPRsLeft;
824 ArgGPRsLeft -= NeededArgGPRs;
829 Ty = ED->getIntegerType();
831 if (
const auto *EIT = Ty->
getAs<BitIntType>()) {
833 if (XLen == 64 && EIT->getNumBits() == 32)
834 return extendType(Ty, CGT.ConvertType(Ty));
836 if (EIT->getNumBits() <= 2 * XLen)
838 return getNaturalAlignIndirect(
839 Ty, getDataLayout().getAllocaAddrSpace(),
844 if (Size < XLen && Ty->isIntegralOrEnumerationType())
845 return extendType(Ty, CGT.ConvertType(Ty));
853 if (
const VectorType *VT = Ty->
getAs<VectorType>();
856 return coerceVLSVector(Ty);
857 if (VT->
getVectorKind() == VectorKind::Generic && ABIVLen != 0)
860 return coerceVLSVector(Ty, ABIVLen);
865 if (Size <= 2 * XLen) {
866 unsigned Alignment = getContext().getTypeAlign(Ty);
871 llvm::IntegerType::get(getVMContext(), Size));
874 if (Alignment == 2 * XLen)
876 llvm::IntegerType::get(getVMContext(), 2 * XLen));
879 llvm::ArrayType::get(llvm::IntegerType::get(getVMContext(), XLen), 2));
881 return getNaturalAlignIndirect(
882 Ty, getDataLayout().getAllocaAddrSpace(),
886ABIArgInfo RISCVABIInfo::classifyReturnType(QualType RetTy,
887 unsigned ABIVLen)
const {
892 int ArgFPRsLeft = FLen ? 2 : 0;
900RValue RISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
901 QualType Ty, AggValueSlot Slot)
const {
908 auto TInfo = getContext().getTypeInfoInChars(Ty);
916 TInfo.Align = std::min(TInfo.Align, SlotSize);
919 bool IsIndirect = TInfo.Width > 2 * SlotSize;
925ABIArgInfo RISCVABIInfo::extendType(QualType Ty, llvm::Type *CoerceTy)
const {
926 int TySize = getContext().getTypeSize(Ty);
933llvm::Value *RISCVABIInfo::createCoercedLoad(Address Src,
const ABIArgInfo &AI,
934 CodeGenFunction &CGF)
const {
938 assert((Ty->isScalableTy() || Ty->isTargetExtTy()) &&
939 "Only scalable vector type and vector tuple type are allowed for load "
941 if (llvm::TargetExtType *TupTy = dyn_cast<llvm::TargetExtType>(Ty)) {
957 assert(TupTy->getName() ==
"riscv.vector.tuple");
958 llvm::Type *EltTy = TupTy->getTypeParameter(0);
959 unsigned NumElts = TupTy->getIntParameter(0);
961 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(SrcSTy->getElementType(0)))
965 llvm::Value *TupleVal = llvm::PoisonValue::get(Ty);
967 for (
unsigned i = 0; i < NumElts; ++i) {
969 llvm::Value *ExtractFromLoad = CGF.
Builder.CreateExtractValue(Load, i);
972 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedVecTy);
973 if (VLSTy != FixedVecTy)
974 ExtractFromLoad = CGF.
Builder.CreateBitCast(ExtractFromLoad, VLSTy);
980 llvm::Value *VectorVal = llvm::PoisonValue::get(EltTy);
982 VectorVal = CGF.
Builder.CreateInsertVector(
983 EltTy, VectorVal, ExtractFromLoad,
uint64_t(0),
"cast.scalable");
985 llvm::Value *Idx = CGF.
Builder.getInt32(i);
987 CGF.
Builder.CreateIntrinsic(llvm::Intrinsic::riscv_tuple_insert,
988 {Ty, EltTy}, {TupleVal, VectorVal, Idx});
1008 SrcTy = SrcSTy->getElementType(0);
1009 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(SrcTy))
1010 SrcTy = ArrayTy->getElementType();
1014 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedSrcTy);
1015 if (VLSTy != FixedSrcTy)
1017 auto *VectorVal = llvm::PoisonValue::get(ScalableDstTy);
1019 ScalableDstTy, VectorVal, Load,
uint64_t(0),
"cast.scalable");
1023void RISCVABIInfo::createCoercedStore(llvm::Value *Val, Address Dst,
1024 const ABIArgInfo &AI,
bool DestIsVolatile,
1025 CodeGenFunction &CGF)
const {
1026 llvm::Type *SrcTy = Val->getType();
1028 assert((SrcTy->isScalableTy() || SrcTy->isTargetExtTy()) &&
1029 "Only scalable vector type and vector tuple type are allowed for "
1031 if (llvm::TargetExtType *TupTy = dyn_cast<llvm::TargetExtType>(SrcTy)) {
1047 assert(TupTy->getName() ==
"riscv.vector.tuple");
1048 llvm::Type *EltTy = TupTy->getTypeParameter(0);
1049 unsigned NumElts = TupTy->getIntParameter(0);
1051 llvm::Type *FixedVecTy = DstSTy->getElementType(0);
1052 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(DstSTy->getElementType(0))) {
1054 FixedVecTy = ArrayTy->getArrayElementType();
1057 llvm::FixedVectorType *VLSTy =
1061 for (
unsigned i = 0; i < NumElts; ++i) {
1068 llvm::Value *Idx = CGF.
Builder.getInt32(i);
1069 auto *TupleElement = CGF.
Builder.CreateIntrinsic(
1070 llvm::Intrinsic::riscv_tuple_extract, {EltTy, TupTy}, {Val, Idx});
1073 llvm::Value *ExtractVec =
1075 if (VLSTy != FixedVecTy)
1076 ExtractVec = CGF.
Builder.CreateBitCast(ExtractVec, FixedVecTy);
1103 llvm::Type *EltTy = DstSTy->getElementType(0);
1104 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(EltTy)) {
1105 assert(ArrayTy->getNumElements() == 1);
1106 EltTy = ArrayTy->getElementType();
1109 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedVecTy);
1110 llvm::Value *Coerced =
1112 if (VLSTy != FixedVecTy)
1113 Coerced = CGF.
Builder.CreateBitCast(Coerced, FixedVecTy);
1119class RISCVTargetCodeGenInfo :
public TargetCodeGenInfo {
1121 RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
unsigned XLen,
1122 unsigned FLen,
bool EABI)
1123 : TargetCodeGenInfo(
1124 std::make_unique<RISCVABIInfo>(CGT, XLen, FLen, EABI)) {
1126 std::make_unique<SwiftABIInfo>(CGT,
false);
1129 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1130 CodeGen::CodeGenModule &CGM)
const override {
1131 const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
1137 Fn->addFnAttr(
"hw-shadow-stack");
1139 const auto *Attr = FD->getAttr<RISCVInterruptAttr>();
1143 StringRef
Kind =
"machine";
1144 bool HasSiFiveCLICPreemptible =
false;
1145 bool HasSiFiveCLICStackSwap =
false;
1146 for (RISCVInterruptAttr::InterruptType
type : Attr->interrupt()) {
1148 case RISCVInterruptAttr::machine:
1152 case RISCVInterruptAttr::supervisor:
1153 Kind =
"supervisor";
1155 case RISCVInterruptAttr::rnmi:
1158 case RISCVInterruptAttr::qcinest:
1161 case RISCVInterruptAttr::qcinonest:
1162 Kind =
"qci-nonest";
1166 case RISCVInterruptAttr::SiFiveCLICPreemptible: {
1167 HasSiFiveCLICPreemptible =
true;
1168 Kind = HasSiFiveCLICStackSwap ?
"SiFive-CLIC-preemptible-stack-swap"
1169 :
"SiFive-CLIC-preemptible";
1172 case RISCVInterruptAttr::SiFiveCLICStackSwap: {
1173 HasSiFiveCLICStackSwap =
true;
1174 Kind = HasSiFiveCLICPreemptible ?
"SiFive-CLIC-preemptible-stack-swap"
1175 :
"SiFive-CLIC-stack-swap";
1181 Fn->addFnAttr(
"interrupt", Kind);
1186std::unique_ptr<TargetCodeGenInfo>
1188 unsigned FLen,
bool EABI) {
1189 return std::make_unique<RISCVTargetCodeGenInfo>(CGM.
getTypes(), XLen, FLen,
static unsigned getRVVFixedLengthMaskMinElts(VectorKind VK)
Minimum element count of the scalable vector a vbool<R>_t mask is coerced to, i.e.
static unsigned getRVVFixedLengthDataMinElts(VectorKind VK, unsigned EltSizeInBits)
Minimum element count of the scalable vector an RVV fixed-length data vector is coerced to,...
Result
Implement __builtin_bit_cast and related operations.
#define CC_VLS_CASE(ABI_VLEN)
static CharUnits getTypeStoreSize(CodeGenModule &CGM, llvm::Type *type)
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.
bool isZero() const
Test whether the quantity equals zero.
CharUnits alignTo(CharUnits Align) const
Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is a multiple...
QuantityType getQuantity() const
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)
Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Construct a CharUnits quantity of zero.
static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T=nullptr, llvm::Type *Padding=nullptr)
static ABIArgInfo getIgnore()
static ABIArgInfo getTargetSpecific(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true, unsigned Align=0)
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, llvm::Type *Padding=nullptr)
static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType, llvm::Type *unpaddedCoerceToType)
llvm::Type * getCoerceToType() const
virtual void appendAttributeMangling(TargetAttr *Attr, raw_ostream &Out) const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateConstArrayGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = [n x T]* ... produce name = getelementptr inbounds addr, i64 0, i64 index where i64 is a...
Address CreateStructGEP(Address Addr, unsigned Index, const llvm::Twine &Name="")
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.
FunctionType::ExtInfo getExtInfo() const
ABIArgInfo & getReturnInfo()
CanQualType getReturnType() const
MutableArrayRef< ArgInfo > arguments()
unsigned getNumRequiredArgs() const
void addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction, llvm::Value *Backup)
See CGDebugInfo::addInstToCurrentSourceAtom.
This class organizes the cross-function state that is used while generating LLVM code.
CodeGenTypes & getTypes()
const CodeGenOptions & getCodeGenOpts() const
DefaultABIInfo - The default implementation for ABI specific details.
CallingConv getCC() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
field_range fields() const
RecordDecl * getDefinitionOrSelf() const
virtual bool hasFeature(StringRef Feature) const
Determine whether the given target has the given feature.
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 isBitIntType() const
bool isBuiltinType() const
Helper methods to distinguish type categories.
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
bool isStructureOrClassType() const
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
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>'.
unsigned getNumElements() const
unsigned getRVVFixedLengthMaskLanes() const
Return the number of lanes of an RVV fixed-length mask vector.
VectorKind getVectorKind() const
QualType getElementType() const
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)
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.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
PRESERVE_NONE bool Ret(InterpState &S)
@ Address
A pointer to a ValueDecl.
bool Load(InterpState &S, CodePtr OpPC)
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
bool isRVVFixedLengthDataVectorKind(VectorKind VK)
True if VK is one of the RVV fixed-length data vector kinds, i.e.
unsigned getRVVFixedLengthMaskRatioLog2(VectorKind VK)
Return log2 of the R of the vbool<R>_t type recorded in an RVV fixed-length mask vector kind: Ratio1 ...
bool isRVVFixedLengthVectorKind(VectorKind VK)
True if VK is one of the RVV fixed-length data or mask vector kinds.
int getRVVFixedLengthDataLMulLog2(VectorKind VK)
Return log2 of the LMUL recorded in an RVV fixed-length data vector kind: MF8 -> -3,...
U cast(CodeGen::Address addr)
bool isRVVFixedLengthMaskVectorKind(VectorKind VK)
True if VK is one of the RVV fixed-length mask vector kinds, i.e.