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;
44 RISCVABIInfo(CodeGen::CodeGenTypes &CGT,
unsigned XLen,
unsigned FLen,
46 : DefaultABIInfo(CGT), XLen(XLen), FLen(FLen), NumArgGPRs(EABI ? 6 : 8),
47 NumArgFPRs(FLen != 0 ? 8 : 0), EABI(EABI) {}
51 void computeInfo(CGFunctionInfo &FI)
const override;
54 int &ArgFPRsLeft,
unsigned ABIVLen)
const;
57 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
58 AggValueSlot Slot)
const override;
60 ABIArgInfo extendType(QualType Ty, llvm::Type *CoerceTy =
nullptr)
const;
62 bool detectFPCCEligibleStruct(QualType Ty, llvm::Type *&Field1Ty,
63 CharUnits &Field1Off, llvm::Type *&Field2Ty,
64 CharUnits &Field2Off,
int &NeededArgGPRs,
65 int &NeededArgFPRs)
const;
66 ABIArgInfo coerceAndExpandFPCCEligibleStruct(llvm::Type *Field1Ty,
69 CharUnits Field2Off)
const;
71 ABIArgInfo coerceVLSVector(QualType Ty,
unsigned ABIVLen = 0)
const;
75 llvm::FixedVectorType *
76 getVLSCCCompatibleType(llvm::FixedVectorType *FixedVecTy)
const;
79 void appendAttributeMangling(TargetClonesAttr *Attr,
unsigned Index,
80 raw_ostream &Out)
const override;
81 void appendAttributeMangling(StringRef AttrStr,
82 raw_ostream &Out)
const override;
83 llvm::Value *createCoercedLoad(Address SrcAddr,
const ABIArgInfo &AI,
84 CodeGenFunction &CGF)
const override;
85 void createCoercedStore(llvm::Value *Val, Address DstAddr,
86 const ABIArgInfo &AI,
bool DestIsVolatile,
87 CodeGenFunction &CGF)
const override;
91void RISCVABIInfo::appendAttributeMangling(TargetClonesAttr *
Attr,
93 raw_ostream &Out)
const {
94 appendAttributeMangling(Attr->getFeatureStr(Index), Out);
97void RISCVABIInfo::appendAttributeMangling(StringRef AttrStr,
98 raw_ostream &Out)
const {
99 if (AttrStr ==
"default") {
106 SmallVector<StringRef, 8> Attrs;
107 AttrStr.split(Attrs,
';');
111 for (
auto &Attr : Attrs) {
112 if (Attr.starts_with(
"arch="))
117 SmallVector<StringRef, 8> Features;
118 ArchStr.consume_front(
"arch=");
119 ArchStr.split(Features,
',');
121 llvm::stable_sort(Features);
123 for (
auto Feat : Features) {
124 Feat.consume_front(
"+");
129void RISCVABIInfo::computeInfo(CGFunctionInfo &FI)
const {
135#define CC_VLS_CASE(ABI_VLEN) \
136 case CallingConv::CC_RISCVVLSCall_##ABI_VLEN: \
137 ABIVLen = ABI_VLEN; \
164 getContext().getTypeSize(RetTy) > (2 * XLen)) {
166 QualType EltTy = RetTy->
castAs<ComplexType>()->getElementType();
167 IsRetIndirect = getContext().getTypeSize(EltTy) > FLen;
170 IsRetIndirect =
true;
174 int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs;
175 int ArgFPRsLeft = NumArgFPRs;
180 bool IsFixed = ArgNum < NumFixedArgs;
182 ArgFPRsLeft, ABIVLen);
191bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff,
192 llvm::Type *&Field1Ty,
193 CharUnits &Field1Off,
194 llvm::Type *&Field2Ty,
195 CharUnits &Field2Off)
const {
199 if (IsInt || IsFloat) {
201 if (IsInt && Size > XLen)
205 if (IsFloat && Size > FLen)
209 if (IsInt && Field1Ty && Field1Ty->isIntegerTy())
212 Field1Ty = CGT.ConvertType(Ty);
217 Field2Ty = CGT.ConvertType(Ty);
224 if (
auto CTy = Ty->
getAs<ComplexType>()) {
227 QualType EltTy = CTy->getElementType();
234 if (getContext().getTypeSize(EltTy) > FLen)
236 Field1Ty = CGT.ConvertType(EltTy);
239 Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy);
243 if (
const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) {
244 uint64_t ArraySize = ATy->getZExtSize();
245 QualType EltTy = ATy->getElementType();
253 CharUnits EltSize = getContext().getTypeSizeInChars(EltTy);
254 for (uint64_t i = 0; i < ArraySize; ++i) {
255 bool Ret = detectFPCCEligibleStructHelper(EltTy, CurOff, Field1Ty,
256 Field1Off, Field2Ty, Field2Off);
271 const RecordDecl *RD = RTy->getDecl()->getDefinitionOrSelf();
275 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
277 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
278 for (
const CXXBaseSpecifier &B : CXXRD->bases()) {
279 const auto *BDecl = B.getType()->castAsCXXRecordDecl();
281 bool Ret = detectFPCCEligibleStructHelper(B.getType(), CurOff + BaseOff,
282 Field1Ty, Field1Off, Field2Ty,
288 int ZeroWidthBitFieldCount = 0;
289 for (
const FieldDecl *FD : RD->
fields()) {
291 QualType QTy = FD->getType();
292 if (FD->isBitField()) {
293 unsigned BitWidth = FD->getBitWidthValue();
296 if (getContext().getTypeSize(QTy) > XLen && BitWidth <= XLen)
297 QTy = getContext().getIntTypeForBitwidth(XLen,
false);
299 else if (getContext().getTypeSize(QTy) > BitWidth) {
301 FD->getType().getTypePtr()->hasSignedIntegerRepresentation();
302 unsigned Bits = std::max(8U, (
unsigned)llvm::PowerOf2Ceil(BitWidth));
303 QTy = getContext().getIntTypeForBitwidth(Bits, IsSigned);
306 ZeroWidthBitFieldCount++;
311 bool Ret = detectFPCCEligibleStructHelper(
312 QTy, CurOff + getContext().toCharUnitsFromBits(FieldOffInBits),
313 Field1Ty, Field1Off, Field2Ty, Field2Off);
320 if (Field2Ty && ZeroWidthBitFieldCount > 0)
323 return Field1Ty !=
nullptr;
333bool RISCVABIInfo::detectFPCCEligibleStruct(QualType Ty, llvm::Type *&Field1Ty,
334 CharUnits &Field1Off,
335 llvm::Type *&Field2Ty,
336 CharUnits &Field2Off,
338 int &NeededArgFPRs)
const {
343 bool IsCandidate = detectFPCCEligibleStructHelper(
348 if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy())
352 if (Field1Ty && Field1Ty->isFloatingPointTy())
356 if (Field2Ty && Field2Ty->isFloatingPointTy())
366ABIArgInfo RISCVABIInfo::coerceAndExpandFPCCEligibleStruct(
367 llvm::Type *Field1Ty, CharUnits Field1Off, llvm::Type *Field2Ty,
368 CharUnits Field2Off)
const {
369 SmallVector<llvm::Type *, 3> CoerceElts;
370 SmallVector<llvm::Type *, 2> UnpaddedCoerceElts;
372 CoerceElts.push_back(llvm::ArrayType::get(
373 llvm::Type::getInt8Ty(getVMContext()), Field1Off.
getQuantity()));
375 CoerceElts.push_back(Field1Ty);
376 UnpaddedCoerceElts.push_back(Field1Ty);
380 llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.
isZero()),
381 UnpaddedCoerceElts[0]);
384 CharUnits Field2Align =
386 CharUnits Field1End = Field1Off +
388 CharUnits Field2OffNoPadNoPack = Field1End.
alignTo(Field2Align);
391 if (Field2Off > Field2OffNoPadNoPack)
392 Padding = Field2Off - Field2OffNoPadNoPack;
393 else if (Field2Off != Field2Align && Field2Off > Field1End)
394 Padding = Field2Off - Field1End;
399 CoerceElts.push_back(llvm::ArrayType::get(
400 llvm::Type::getInt8Ty(getVMContext()), Padding.
getQuantity()));
402 CoerceElts.push_back(Field2Ty);
403 UnpaddedCoerceElts.push_back(Field2Ty);
406 llvm::StructType::get(getVMContext(), CoerceElts, IsPacked);
407 auto UnpaddedCoerceToType =
408 llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked);
413llvm::Type *RISCVABIInfo::detectVLSCCEligibleStruct(QualType Ty,
414 unsigned ABIVLen)
const {
476 llvm::StructType *STy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty));
480 unsigned NumElts = STy->getStructNumElements();
484 auto *FirstEltTy = STy->getElementType(0);
485 if (!STy->containsHomogeneousTypes())
488 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(FirstEltTy)) {
492 FirstEltTy = ArrayTy->getArrayElementType();
493 NumElts = ArrayTy->getNumElements();
496 auto *FixedVecTy = dyn_cast<llvm::FixedVectorType>(FirstEltTy);
501 if (NumElts * llvm::divideCeil(
502 FixedVecTy->getNumElements() *
503 FixedVecTy->getElementType()->getScalarSizeInBits(),
511 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedVecTy);
512 return llvm::ScalableVectorType::get(
513 VLSTy->getElementType(),
514 llvm::divideCeil(VLSTy->getNumElements() * llvm::RISCV::RVVBitsPerBlock,
524 unsigned I8EltCount =
525 llvm::divideCeil(FixedVecTy->getNumElements() *
526 FixedVecTy->getElementType()->getScalarSizeInBits() *
527 llvm::RISCV::RVVBitsPerBlock,
529 return llvm::TargetExtType::get(
530 getVMContext(),
"riscv.vector.tuple",
531 llvm::ScalableVectorType::get(llvm::Type::getInt8Ty(getVMContext()),
537RISCVABIInfo::detectHomogeneousRVVFixedLengthStruct(QualType Ty)
const {
549 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
550 if (CXXRD->getNumBases() != 0)
553 SmallVector<const FieldDecl *, 8> Fields(RD->
fields());
558 auto IsFixedLengthRVVVector = [](
const VectorType *VT) {
559 switch (VT->getVectorKind()) {
560 case VectorKind::RVVFixedLengthData:
561 case VectorKind::RVVFixedLengthMask:
562 case VectorKind::RVVFixedLengthMask_1:
563 case VectorKind::RVVFixedLengthMask_2:
564 case VectorKind::RVVFixedLengthMask_4:
575 if (Fields.size() == 1) {
576 QualType FieldTy = Fields[0]->getType().getCanonicalType();
577 if (
const ConstantArrayType *AT =
578 getContext().getAsConstantArrayType(FieldTy)) {
579 QualType EltTy = AT->getElementType().getCanonicalType();
580 if (
const auto *VT = EltTy->
getAs<VectorType>();
581 VT && IsFixedLengthRVVVector(VT)) {
583 Count = AT->getZExtSize();
590 if (Fields.size() > 8)
592 for (
const FieldDecl *FD : Fields) {
593 QualType FieldTy = FD->getType().getCanonicalType();
594 const auto *VT = FieldTy->
getAs<VectorType>();
595 if (!VT || !IsFixedLengthRVVVector(VT))
599 else if (!getContext().hasSameType(CommonTy, FieldTy))
602 Count = Fields.size();
605 if (Count == 0 || Count > 8)
608 const auto *VT = CommonTy->
castAs<VectorType>();
609 llvm::Type *EltType = CGT.ConvertType(VT->getElementType());
610 auto VScale = getContext().getTargetInfo().getVScaleRange(
611 getContext().getLangOpts(), TargetInfo::ArmStreamingKind::NotStreaming);
615 Count * llvm::divideCeil((uint64_t)VT->getNumElements() *
616 EltType->getScalarSizeInBits(),
617 VScale->first * llvm::RISCV::RVVBitsPerBlock) >
621 unsigned MinElts = llvm::divideCeil(VT->getNumElements(), VScale->first);
623 return llvm::ScalableVectorType::get(EltType, MinElts);
625 unsigned I8EltCount = llvm::divideCeil((uint64_t)VT->getNumElements() *
626 EltType->getScalarSizeInBits(),
628 auto *I8Vec = llvm::ScalableVectorType::get(
629 llvm::Type::getInt8Ty(getVMContext()), I8EltCount);
630 return llvm::TargetExtType::get(getVMContext(),
"riscv.vector.tuple", I8Vec,
634llvm::FixedVectorType *
635RISCVABIInfo::getVLSCCCompatibleType(llvm::FixedVectorType *FixedVecTy)
const {
636 llvm::Type *EltType = FixedVecTy->getElementType();
637 const TargetInfo &TI = getContext().getTargetInfo();
638 if ((EltType->isHalfTy() && !TI.
hasFeature(
"zvfhmin")) ||
639 (EltType->isBFloatTy() &&
641 (EltType->isFloatTy() && !TI.
hasFeature(
"zve32f")) ||
642 (EltType->isDoubleTy() && !TI.
hasFeature(
"zve64d")) ||
643 (EltType->isIntegerTy(64) && !TI.
hasFeature(
"zve64x")) ||
644 EltType->isIntegerTy(128))
645 return llvm::FixedVectorType::get(llvm::Type::getInt8Ty(getVMContext()),
646 FixedVecTy->getNumElements() *
647 EltType->getScalarSizeInBits() / 8);
653ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty,
unsigned ABIVLen)
const {
656 const auto *VT = Ty->
castAs<VectorType>();
657 assert(VT->getElementType()->isBuiltinType() &&
"expected builtin type!");
659 auto VScale = getContext().getTargetInfo().getVScaleRange(
660 getContext().getLangOpts(), TargetInfo::ArmStreamingKind::NotStreaming);
662 unsigned NumElts = VT->getNumElements();
663 llvm::Type *EltType = llvm::Type::getInt1Ty(getVMContext());
664 switch (VT->getVectorKind()) {
665 case VectorKind::RVVFixedLengthMask_1:
667 case VectorKind::RVVFixedLengthMask_2:
670 case VectorKind::RVVFixedLengthMask_4:
673 case VectorKind::RVVFixedLengthMask:
677 assert((VT->getVectorKind() == VectorKind::Generic ||
678 VT->getVectorKind() == VectorKind::RVVFixedLengthData) &&
679 "Unexpected vector kind");
680 EltType = CGT.ConvertType(VT->getElementType());
683 llvm::ScalableVectorType *ResType;
690 ResType = llvm::ScalableVectorType::get(EltType, NumElts / VScale->first);
693 if ((EltType->getScalarSizeInBits() * NumElts / ABIVLen) > 8)
694 return getNaturalAlignIndirect(
695 Ty, getDataLayout().getAllocaAddrSpace(),
700 llvm::FixedVectorType *VLSTy =
701 getVLSCCCompatibleType(llvm::FixedVectorType::get(EltType, NumElts));
702 ResType = llvm::ScalableVectorType::get(
703 VLSTy->getElementType(),
704 llvm::divideCeil(VLSTy->getNumElements() * llvm::RISCV::RVVBitsPerBlock,
711ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty,
bool IsFixed,
714 unsigned ABIVLen)
const {
715 assert(ArgGPRsLeft <= NumArgGPRs &&
"Arg GPR tracking underflow");
723 return getNaturalAlignIndirect(
724 Ty, getDataLayout().getAllocaAddrSpace(),
737 FLen >= Size && ArgFPRsLeft) {
744 if (IsFixed && Ty->
isComplexType() && FLen && ArgFPRsLeft >= 2) {
745 QualType EltTy = Ty->
castAs<ComplexType>()->getElementType();
746 if (getContext().getTypeSize(EltTy) <= FLen) {
753 llvm::Type *Field1Ty =
nullptr;
754 llvm::Type *Field2Ty =
nullptr;
757 int NeededArgGPRs = 0;
758 int NeededArgFPRs = 0;
760 detectFPCCEligibleStruct(Ty, Field1Ty, Field1Off, Field2Ty, Field2Off,
761 NeededArgGPRs, NeededArgFPRs);
762 if (IsCandidate && NeededArgGPRs <= ArgGPRsLeft &&
763 NeededArgFPRs <= ArgFPRsLeft) {
764 ArgGPRsLeft -= NeededArgGPRs;
765 ArgFPRsLeft -= NeededArgFPRs;
766 return coerceAndExpandFPCCEligibleStruct(Field1Ty, Field1Off, Field2Ty,
772 if (llvm::Type *CoerceTy = detectHomogeneousRVVFixedLengthStruct(Ty))
775 if (llvm::Type *VLSType = detectVLSCCEligibleStruct(Ty, ABIVLen))
779 uint64_t NeededAlign = getContext().getTypeAlign(Ty);
786 int NeededArgGPRs = 1;
787 if (!IsFixed && NeededAlign == 2 * XLen)
788 NeededArgGPRs = 2 + (EABI && XLen == 32 ? 0 : (ArgGPRsLeft % 2));
789 else if (Size > XLen && Size <= 2 * XLen)
792 if (NeededArgGPRs > ArgGPRsLeft) {
793 NeededArgGPRs = ArgGPRsLeft;
796 ArgGPRsLeft -= NeededArgGPRs;
801 Ty = ED->getIntegerType();
803 if (
const auto *EIT = Ty->
getAs<BitIntType>()) {
805 if (XLen == 64 && EIT->getNumBits() == 32)
806 return extendType(Ty, CGT.ConvertType(Ty));
808 if (EIT->getNumBits() <= 2 * XLen)
810 return getNaturalAlignIndirect(
811 Ty, getDataLayout().getAllocaAddrSpace(),
816 if (Size < XLen && Ty->isIntegralOrEnumerationType())
817 return extendType(Ty, CGT.ConvertType(Ty));
825 if (
const VectorType *VT = Ty->
getAs<VectorType>();
826 VT && !VT->getElementType()->isBitIntType()) {
827 if (VT->getVectorKind() == VectorKind::RVVFixedLengthData ||
828 VT->getVectorKind() == VectorKind::RVVFixedLengthMask ||
829 VT->getVectorKind() == VectorKind::RVVFixedLengthMask_1 ||
830 VT->getVectorKind() == VectorKind::RVVFixedLengthMask_2 ||
831 VT->getVectorKind() == VectorKind::RVVFixedLengthMask_4)
832 return coerceVLSVector(Ty);
833 if (VT->getVectorKind() == VectorKind::Generic && ABIVLen != 0)
836 return coerceVLSVector(Ty, ABIVLen);
841 if (Size <= 2 * XLen) {
842 unsigned Alignment = getContext().getTypeAlign(Ty);
847 llvm::IntegerType::get(getVMContext(), Size));
850 if (Alignment == 2 * XLen)
852 llvm::IntegerType::get(getVMContext(), 2 * XLen));
855 llvm::ArrayType::get(llvm::IntegerType::get(getVMContext(), XLen), 2));
857 return getNaturalAlignIndirect(
858 Ty, getDataLayout().getAllocaAddrSpace(),
862ABIArgInfo RISCVABIInfo::classifyReturnType(QualType RetTy,
863 unsigned ABIVLen)
const {
868 int ArgFPRsLeft = FLen ? 2 : 0;
876RValue RISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
877 QualType Ty, AggValueSlot Slot)
const {
884 auto TInfo = getContext().getTypeInfoInChars(Ty);
890 if (EABI && XLen == 32)
894 bool IsIndirect = TInfo.Width > 2 * SlotSize;
900ABIArgInfo RISCVABIInfo::extendType(QualType Ty, llvm::Type *CoerceTy)
const {
901 int TySize = getContext().getTypeSize(Ty);
908llvm::Value *RISCVABIInfo::createCoercedLoad(Address Src,
const ABIArgInfo &AI,
909 CodeGenFunction &CGF)
const {
913 assert((Ty->isScalableTy() || Ty->isTargetExtTy()) &&
914 "Only scalable vector type and vector tuple type are allowed for load "
916 if (llvm::TargetExtType *TupTy = dyn_cast<llvm::TargetExtType>(Ty)) {
932 assert(TupTy->getName() ==
"riscv.vector.tuple");
933 llvm::Type *EltTy = TupTy->getTypeParameter(0);
934 unsigned NumElts = TupTy->getIntParameter(0);
936 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(SrcSTy->getElementType(0)))
940 llvm::Value *TupleVal = llvm::PoisonValue::get(Ty);
942 for (
unsigned i = 0; i < NumElts; ++i) {
944 llvm::Value *ExtractFromLoad = CGF.
Builder.CreateExtractValue(Load, i);
947 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedVecTy);
948 if (VLSTy != FixedVecTy)
949 ExtractFromLoad = CGF.
Builder.CreateBitCast(ExtractFromLoad, VLSTy);
955 llvm::Value *VectorVal = llvm::PoisonValue::get(EltTy);
957 VectorVal = CGF.
Builder.CreateInsertVector(
958 EltTy, VectorVal, ExtractFromLoad,
uint64_t(0),
"cast.scalable");
960 llvm::Value *Idx = CGF.
Builder.getInt32(i);
962 CGF.
Builder.CreateIntrinsic(llvm::Intrinsic::riscv_tuple_insert,
963 {Ty, EltTy}, {TupleVal, VectorVal, Idx});
983 SrcTy = SrcSTy->getElementType(0);
984 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(SrcTy))
985 SrcTy = ArrayTy->getElementType();
989 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedSrcTy);
990 if (VLSTy != FixedSrcTy)
992 auto *VectorVal = llvm::PoisonValue::get(ScalableDstTy);
994 ScalableDstTy, VectorVal, Load,
uint64_t(0),
"cast.scalable");
998void RISCVABIInfo::createCoercedStore(llvm::Value *Val, Address Dst,
999 const ABIArgInfo &AI,
bool DestIsVolatile,
1000 CodeGenFunction &CGF)
const {
1001 llvm::Type *SrcTy = Val->getType();
1003 assert((SrcTy->isScalableTy() || SrcTy->isTargetExtTy()) &&
1004 "Only scalable vector type and vector tuple type are allowed for "
1006 if (llvm::TargetExtType *TupTy = dyn_cast<llvm::TargetExtType>(SrcTy)) {
1022 assert(TupTy->getName() ==
"riscv.vector.tuple");
1023 llvm::Type *EltTy = TupTy->getTypeParameter(0);
1024 unsigned NumElts = TupTy->getIntParameter(0);
1026 llvm::Type *FixedVecTy = DstSTy->getElementType(0);
1027 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(DstSTy->getElementType(0))) {
1029 FixedVecTy = ArrayTy->getArrayElementType();
1032 llvm::FixedVectorType *VLSTy =
1036 for (
unsigned i = 0; i < NumElts; ++i) {
1043 llvm::Value *Idx = CGF.
Builder.getInt32(i);
1044 auto *TupleElement = CGF.
Builder.CreateIntrinsic(
1045 llvm::Intrinsic::riscv_tuple_extract, {EltTy, TupTy}, {Val, Idx});
1048 llvm::Value *ExtractVec =
1050 if (VLSTy != FixedVecTy)
1051 ExtractVec = CGF.
Builder.CreateBitCast(ExtractVec, FixedVecTy);
1078 llvm::Type *EltTy = DstSTy->getElementType(0);
1079 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(EltTy)) {
1080 assert(ArrayTy->getNumElements() == 1);
1081 EltTy = ArrayTy->getElementType();
1084 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedVecTy);
1085 llvm::Value *Coerced =
1087 if (VLSTy != FixedVecTy)
1088 Coerced = CGF.
Builder.CreateBitCast(Coerced, FixedVecTy);
1094class RISCVTargetCodeGenInfo :
public TargetCodeGenInfo {
1096 RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
unsigned XLen,
1097 unsigned FLen,
bool EABI)
1098 : TargetCodeGenInfo(
1099 std::make_unique<RISCVABIInfo>(CGT, XLen, FLen, EABI)) {
1101 std::make_unique<SwiftABIInfo>(CGT,
false);
1104 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1105 CodeGen::CodeGenModule &CGM)
const override {
1106 const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
1112 Fn->addFnAttr(
"hw-shadow-stack");
1114 const auto *Attr = FD->getAttr<RISCVInterruptAttr>();
1118 StringRef
Kind =
"machine";
1119 bool HasSiFiveCLICPreemptible =
false;
1120 bool HasSiFiveCLICStackSwap =
false;
1121 for (RISCVInterruptAttr::InterruptType
type : Attr->interrupt()) {
1123 case RISCVInterruptAttr::machine:
1127 case RISCVInterruptAttr::supervisor:
1128 Kind =
"supervisor";
1130 case RISCVInterruptAttr::rnmi:
1133 case RISCVInterruptAttr::qcinest:
1136 case RISCVInterruptAttr::qcinonest:
1137 Kind =
"qci-nonest";
1141 case RISCVInterruptAttr::SiFiveCLICPreemptible: {
1142 HasSiFiveCLICPreemptible =
true;
1143 Kind = HasSiFiveCLICStackSwap ?
"SiFive-CLIC-preemptible-stack-swap"
1144 :
"SiFive-CLIC-preemptible";
1147 case RISCVInterruptAttr::SiFiveCLICStackSwap: {
1148 HasSiFiveCLICStackSwap =
true;
1149 Kind = HasSiFiveCLICPreemptible ?
"SiFive-CLIC-preemptible-stack-swap"
1150 :
"SiFive-CLIC-stack-swap";
1156 Fn->addFnAttr(
"interrupt", Kind);
1161std::unique_ptr<TargetCodeGenInfo>
1163 unsigned FLen,
bool EABI) {
1164 return std::make_unique<RISCVTargetCodeGenInfo>(CGM.
getTypes(), XLen, FLen,
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
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.
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.
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>'.
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)
U cast(CodeGen::Address addr)