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();
228 if (getContext().getTypeSize(EltTy) > FLen)
230 Field1Ty = CGT.ConvertType(EltTy);
233 Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy);
237 if (
const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) {
238 uint64_t ArraySize = ATy->getZExtSize();
239 QualType EltTy = ATy->getElementType();
247 CharUnits EltSize = getContext().getTypeSizeInChars(EltTy);
248 for (uint64_t i = 0; i < ArraySize; ++i) {
249 bool Ret = detectFPCCEligibleStructHelper(EltTy, CurOff, Field1Ty,
250 Field1Off, Field2Ty, Field2Off);
265 const RecordDecl *RD = RTy->getDecl()->getDefinitionOrSelf();
269 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
271 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
272 for (
const CXXBaseSpecifier &B : CXXRD->bases()) {
273 const auto *BDecl = B.getType()->castAsCXXRecordDecl();
275 bool Ret = detectFPCCEligibleStructHelper(B.getType(), CurOff + BaseOff,
276 Field1Ty, Field1Off, Field2Ty,
282 int ZeroWidthBitFieldCount = 0;
283 for (
const FieldDecl *FD : RD->
fields()) {
285 QualType QTy = FD->getType();
286 if (FD->isBitField()) {
287 unsigned BitWidth = FD->getBitWidthValue();
290 if (getContext().getTypeSize(QTy) > XLen && BitWidth <= XLen)
291 QTy = getContext().getIntTypeForBitwidth(XLen,
false);
293 else if (getContext().getTypeSize(QTy) > BitWidth) {
295 FD->getType().getTypePtr()->hasSignedIntegerRepresentation();
296 unsigned Bits = std::max(8U, (
unsigned)llvm::PowerOf2Ceil(BitWidth));
297 QTy = getContext().getIntTypeForBitwidth(Bits, IsSigned);
300 ZeroWidthBitFieldCount++;
305 bool Ret = detectFPCCEligibleStructHelper(
306 QTy, CurOff + getContext().toCharUnitsFromBits(FieldOffInBits),
307 Field1Ty, Field1Off, Field2Ty, Field2Off);
314 if (Field2Ty && ZeroWidthBitFieldCount > 0)
317 return Field1Ty !=
nullptr;
327bool RISCVABIInfo::detectFPCCEligibleStruct(QualType Ty, llvm::Type *&Field1Ty,
328 CharUnits &Field1Off,
329 llvm::Type *&Field2Ty,
330 CharUnits &Field2Off,
332 int &NeededArgFPRs)
const {
337 bool IsCandidate = detectFPCCEligibleStructHelper(
342 if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy())
346 if (Field1Ty && Field1Ty->isFloatingPointTy())
350 if (Field2Ty && Field2Ty->isFloatingPointTy())
360ABIArgInfo RISCVABIInfo::coerceAndExpandFPCCEligibleStruct(
361 llvm::Type *Field1Ty, CharUnits Field1Off, llvm::Type *Field2Ty,
362 CharUnits Field2Off)
const {
363 SmallVector<llvm::Type *, 3> CoerceElts;
364 SmallVector<llvm::Type *, 2> UnpaddedCoerceElts;
366 CoerceElts.push_back(llvm::ArrayType::get(
367 llvm::Type::getInt8Ty(getVMContext()), Field1Off.
getQuantity()));
369 CoerceElts.push_back(Field1Ty);
370 UnpaddedCoerceElts.push_back(Field1Ty);
374 llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.
isZero()),
375 UnpaddedCoerceElts[0]);
378 CharUnits Field2Align =
380 CharUnits Field1End = Field1Off +
382 CharUnits Field2OffNoPadNoPack = Field1End.
alignTo(Field2Align);
385 if (Field2Off > Field2OffNoPadNoPack)
386 Padding = Field2Off - Field2OffNoPadNoPack;
387 else if (Field2Off != Field2Align && Field2Off > Field1End)
388 Padding = Field2Off - Field1End;
393 CoerceElts.push_back(llvm::ArrayType::get(
394 llvm::Type::getInt8Ty(getVMContext()), Padding.
getQuantity()));
396 CoerceElts.push_back(Field2Ty);
397 UnpaddedCoerceElts.push_back(Field2Ty);
400 llvm::StructType::get(getVMContext(), CoerceElts, IsPacked);
401 auto UnpaddedCoerceToType =
402 llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked);
407llvm::Type *RISCVABIInfo::detectVLSCCEligibleStruct(QualType Ty,
408 unsigned ABIVLen)
const {
470 llvm::StructType *STy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty));
474 unsigned NumElts = STy->getStructNumElements();
478 auto *FirstEltTy = STy->getElementType(0);
479 if (!STy->containsHomogeneousTypes())
482 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(FirstEltTy)) {
486 FirstEltTy = ArrayTy->getArrayElementType();
487 NumElts = ArrayTy->getNumElements();
490 auto *FixedVecTy = dyn_cast<llvm::FixedVectorType>(FirstEltTy);
495 if (NumElts * llvm::divideCeil(
496 FixedVecTy->getNumElements() *
497 FixedVecTy->getElementType()->getScalarSizeInBits(),
505 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedVecTy);
506 return llvm::ScalableVectorType::get(
507 VLSTy->getElementType(),
508 llvm::divideCeil(VLSTy->getNumElements() * llvm::RISCV::RVVBitsPerBlock,
518 unsigned I8EltCount =
519 llvm::divideCeil(FixedVecTy->getNumElements() *
520 FixedVecTy->getElementType()->getScalarSizeInBits() *
521 llvm::RISCV::RVVBitsPerBlock,
523 return llvm::TargetExtType::get(
524 getVMContext(),
"riscv.vector.tuple",
525 llvm::ScalableVectorType::get(llvm::Type::getInt8Ty(getVMContext()),
531RISCVABIInfo::detectHomogeneousRVVFixedLengthStruct(QualType Ty)
const {
543 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
544 if (CXXRD->getNumBases() != 0)
547 SmallVector<const FieldDecl *, 8> Fields(RD->
fields());
552 auto IsFixedLengthRVVVector = [](
const VectorType *VT) {
553 switch (VT->getVectorKind()) {
554 case VectorKind::RVVFixedLengthData:
555 case VectorKind::RVVFixedLengthMask:
556 case VectorKind::RVVFixedLengthMask_1:
557 case VectorKind::RVVFixedLengthMask_2:
558 case VectorKind::RVVFixedLengthMask_4:
569 if (Fields.size() == 1) {
570 QualType FieldTy = Fields[0]->getType().getCanonicalType();
571 if (
const ConstantArrayType *AT =
572 getContext().getAsConstantArrayType(FieldTy)) {
573 QualType EltTy = AT->getElementType().getCanonicalType();
574 if (
const auto *VT = EltTy->
getAs<VectorType>();
575 VT && IsFixedLengthRVVVector(VT)) {
577 Count = AT->getZExtSize();
584 if (Fields.size() > 8)
586 for (
const FieldDecl *FD : Fields) {
587 QualType FieldTy = FD->getType().getCanonicalType();
588 const auto *VT = FieldTy->
getAs<VectorType>();
589 if (!VT || !IsFixedLengthRVVVector(VT))
593 else if (!getContext().hasSameType(CommonTy, FieldTy))
596 Count = Fields.size();
599 if (Count == 0 || Count > 8)
602 const auto *VT = CommonTy->
castAs<VectorType>();
603 llvm::Type *EltType = CGT.ConvertType(VT->getElementType());
604 auto VScale = getContext().getTargetInfo().getVScaleRange(
605 getContext().getLangOpts(), TargetInfo::ArmStreamingKind::NotStreaming);
609 Count * llvm::divideCeil((uint64_t)VT->getNumElements() *
610 EltType->getScalarSizeInBits(),
611 VScale->first * llvm::RISCV::RVVBitsPerBlock) >
615 unsigned MinElts = llvm::divideCeil(VT->getNumElements(), VScale->first);
617 return llvm::ScalableVectorType::get(EltType, MinElts);
619 unsigned I8EltCount = llvm::divideCeil((uint64_t)VT->getNumElements() *
620 EltType->getScalarSizeInBits(),
622 auto *I8Vec = llvm::ScalableVectorType::get(
623 llvm::Type::getInt8Ty(getVMContext()), I8EltCount);
624 return llvm::TargetExtType::get(getVMContext(),
"riscv.vector.tuple", I8Vec,
628llvm::FixedVectorType *
629RISCVABIInfo::getVLSCCCompatibleType(llvm::FixedVectorType *FixedVecTy)
const {
630 llvm::Type *EltType = FixedVecTy->getElementType();
631 const TargetInfo &TI = getContext().getTargetInfo();
632 if ((EltType->isHalfTy() && !TI.
hasFeature(
"zvfhmin")) ||
633 (EltType->isBFloatTy() &&
635 (EltType->isFloatTy() && !TI.
hasFeature(
"zve32f")) ||
636 (EltType->isDoubleTy() && !TI.
hasFeature(
"zve64d")) ||
637 (EltType->isIntegerTy(64) && !TI.
hasFeature(
"zve64x")) ||
638 EltType->isIntegerTy(128))
639 return llvm::FixedVectorType::get(llvm::Type::getInt8Ty(getVMContext()),
640 FixedVecTy->getNumElements() *
641 EltType->getScalarSizeInBits() / 8);
647ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty,
unsigned ABIVLen)
const {
650 const auto *VT = Ty->
castAs<VectorType>();
651 assert(VT->getElementType()->isBuiltinType() &&
"expected builtin type!");
653 auto VScale = getContext().getTargetInfo().getVScaleRange(
654 getContext().getLangOpts(), TargetInfo::ArmStreamingKind::NotStreaming);
656 unsigned NumElts = VT->getNumElements();
657 llvm::Type *EltType = llvm::Type::getInt1Ty(getVMContext());
658 switch (VT->getVectorKind()) {
659 case VectorKind::RVVFixedLengthMask_1:
661 case VectorKind::RVVFixedLengthMask_2:
664 case VectorKind::RVVFixedLengthMask_4:
667 case VectorKind::RVVFixedLengthMask:
671 assert((VT->getVectorKind() == VectorKind::Generic ||
672 VT->getVectorKind() == VectorKind::RVVFixedLengthData) &&
673 "Unexpected vector kind");
674 EltType = CGT.ConvertType(VT->getElementType());
677 llvm::ScalableVectorType *ResType;
684 ResType = llvm::ScalableVectorType::get(EltType, NumElts / VScale->first);
687 if ((EltType->getScalarSizeInBits() * NumElts / ABIVLen) > 8)
688 return getNaturalAlignIndirect(
689 Ty, getDataLayout().getAllocaAddrSpace(),
694 llvm::FixedVectorType *VLSTy =
695 getVLSCCCompatibleType(llvm::FixedVectorType::get(EltType, NumElts));
696 ResType = llvm::ScalableVectorType::get(
697 VLSTy->getElementType(),
698 llvm::divideCeil(VLSTy->getNumElements() * llvm::RISCV::RVVBitsPerBlock,
705ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty,
bool IsFixed,
708 unsigned ABIVLen)
const {
709 assert(ArgGPRsLeft <= NumArgGPRs &&
"Arg GPR tracking underflow");
717 return getNaturalAlignIndirect(
718 Ty, getDataLayout().getAllocaAddrSpace(),
731 FLen >= Size && ArgFPRsLeft) {
738 if (IsFixed && Ty->
isComplexType() && FLen && ArgFPRsLeft >= 2) {
739 QualType EltTy = Ty->
castAs<ComplexType>()->getElementType();
740 if (getContext().getTypeSize(EltTy) <= FLen) {
747 llvm::Type *Field1Ty =
nullptr;
748 llvm::Type *Field2Ty =
nullptr;
751 int NeededArgGPRs = 0;
752 int NeededArgFPRs = 0;
754 detectFPCCEligibleStruct(Ty, Field1Ty, Field1Off, Field2Ty, Field2Off,
755 NeededArgGPRs, NeededArgFPRs);
756 if (IsCandidate && NeededArgGPRs <= ArgGPRsLeft &&
757 NeededArgFPRs <= ArgFPRsLeft) {
758 ArgGPRsLeft -= NeededArgGPRs;
759 ArgFPRsLeft -= NeededArgFPRs;
760 return coerceAndExpandFPCCEligibleStruct(Field1Ty, Field1Off, Field2Ty,
766 if (llvm::Type *CoerceTy = detectHomogeneousRVVFixedLengthStruct(Ty))
769 if (llvm::Type *VLSType = detectVLSCCEligibleStruct(Ty, ABIVLen))
773 uint64_t NeededAlign = getContext().getTypeAlign(Ty);
780 int NeededArgGPRs = 1;
781 if (!IsFixed && NeededAlign == 2 * XLen)
782 NeededArgGPRs = 2 + (EABI && XLen == 32 ? 0 : (ArgGPRsLeft % 2));
783 else if (Size > XLen && Size <= 2 * XLen)
786 if (NeededArgGPRs > ArgGPRsLeft) {
787 NeededArgGPRs = ArgGPRsLeft;
790 ArgGPRsLeft -= NeededArgGPRs;
795 Ty = ED->getIntegerType();
797 if (
const auto *EIT = Ty->
getAs<BitIntType>()) {
799 if (XLen == 64 && EIT->getNumBits() == 32)
800 return extendType(Ty, CGT.ConvertType(Ty));
802 if (EIT->getNumBits() <= 2 * XLen)
804 return getNaturalAlignIndirect(
805 Ty, getDataLayout().getAllocaAddrSpace(),
810 if (Size < XLen && Ty->isIntegralOrEnumerationType())
811 return extendType(Ty, CGT.ConvertType(Ty));
819 if (
const VectorType *VT = Ty->
getAs<VectorType>();
820 VT && !VT->getElementType()->isBitIntType()) {
821 if (VT->getVectorKind() == VectorKind::RVVFixedLengthData ||
822 VT->getVectorKind() == VectorKind::RVVFixedLengthMask ||
823 VT->getVectorKind() == VectorKind::RVVFixedLengthMask_1 ||
824 VT->getVectorKind() == VectorKind::RVVFixedLengthMask_2 ||
825 VT->getVectorKind() == VectorKind::RVVFixedLengthMask_4)
826 return coerceVLSVector(Ty);
827 if (VT->getVectorKind() == VectorKind::Generic && ABIVLen != 0)
830 return coerceVLSVector(Ty, ABIVLen);
835 if (Size <= 2 * XLen) {
836 unsigned Alignment = getContext().getTypeAlign(Ty);
841 llvm::IntegerType::get(getVMContext(), Size));
844 if (Alignment == 2 * XLen)
846 llvm::IntegerType::get(getVMContext(), 2 * XLen));
849 llvm::ArrayType::get(llvm::IntegerType::get(getVMContext(), XLen), 2));
851 return getNaturalAlignIndirect(
852 Ty, getDataLayout().getAllocaAddrSpace(),
856ABIArgInfo RISCVABIInfo::classifyReturnType(QualType RetTy,
857 unsigned ABIVLen)
const {
862 int ArgFPRsLeft = FLen ? 2 : 0;
870RValue RISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
871 QualType Ty, AggValueSlot Slot)
const {
878 auto TInfo = getContext().getTypeInfoInChars(Ty);
884 if (EABI && XLen == 32)
888 bool IsIndirect = TInfo.Width > 2 * SlotSize;
894ABIArgInfo RISCVABIInfo::extendType(QualType Ty, llvm::Type *CoerceTy)
const {
895 int TySize = getContext().getTypeSize(Ty);
902llvm::Value *RISCVABIInfo::createCoercedLoad(Address Src,
const ABIArgInfo &AI,
903 CodeGenFunction &CGF)
const {
907 assert((Ty->isScalableTy() || Ty->isTargetExtTy()) &&
908 "Only scalable vector type and vector tuple type are allowed for load "
910 if (llvm::TargetExtType *TupTy = dyn_cast<llvm::TargetExtType>(Ty)) {
926 assert(TupTy->getName() ==
"riscv.vector.tuple");
927 llvm::Type *EltTy = TupTy->getTypeParameter(0);
928 unsigned NumElts = TupTy->getIntParameter(0);
930 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(SrcSTy->getElementType(0)))
934 llvm::Value *TupleVal = llvm::PoisonValue::get(Ty);
936 for (
unsigned i = 0; i < NumElts; ++i) {
938 llvm::Value *ExtractFromLoad = CGF.
Builder.CreateExtractValue(Load, i);
941 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedVecTy);
942 if (VLSTy != FixedVecTy)
943 ExtractFromLoad = CGF.
Builder.CreateBitCast(ExtractFromLoad, VLSTy);
949 llvm::Value *VectorVal = llvm::PoisonValue::get(EltTy);
951 VectorVal = CGF.
Builder.CreateInsertVector(
952 EltTy, VectorVal, ExtractFromLoad,
uint64_t(0),
"cast.scalable");
954 llvm::Value *Idx = CGF.
Builder.getInt32(i);
956 CGF.
Builder.CreateIntrinsic(llvm::Intrinsic::riscv_tuple_insert,
957 {Ty, EltTy}, {TupleVal, VectorVal, Idx});
977 SrcTy = SrcSTy->getElementType(0);
978 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(SrcTy))
979 SrcTy = ArrayTy->getElementType();
983 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedSrcTy);
984 if (VLSTy != FixedSrcTy)
986 auto *VectorVal = llvm::PoisonValue::get(ScalableDstTy);
988 ScalableDstTy, VectorVal, Load,
uint64_t(0),
"cast.scalable");
992void RISCVABIInfo::createCoercedStore(llvm::Value *Val, Address Dst,
993 const ABIArgInfo &AI,
bool DestIsVolatile,
994 CodeGenFunction &CGF)
const {
995 llvm::Type *SrcTy = Val->getType();
997 assert((SrcTy->isScalableTy() || SrcTy->isTargetExtTy()) &&
998 "Only scalable vector type and vector tuple type are allowed for "
1000 if (llvm::TargetExtType *TupTy = dyn_cast<llvm::TargetExtType>(SrcTy)) {
1016 assert(TupTy->getName() ==
"riscv.vector.tuple");
1017 llvm::Type *EltTy = TupTy->getTypeParameter(0);
1018 unsigned NumElts = TupTy->getIntParameter(0);
1020 llvm::Type *FixedVecTy = DstSTy->getElementType(0);
1021 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(DstSTy->getElementType(0))) {
1023 FixedVecTy = ArrayTy->getArrayElementType();
1026 llvm::FixedVectorType *VLSTy =
1030 for (
unsigned i = 0; i < NumElts; ++i) {
1037 llvm::Value *Idx = CGF.
Builder.getInt32(i);
1038 auto *TupleElement = CGF.
Builder.CreateIntrinsic(
1039 llvm::Intrinsic::riscv_tuple_extract, {EltTy, TupTy}, {Val, Idx});
1042 llvm::Value *ExtractVec =
1044 if (VLSTy != FixedVecTy)
1045 ExtractVec = CGF.
Builder.CreateBitCast(ExtractVec, FixedVecTy);
1072 llvm::Type *EltTy = DstSTy->getElementType(0);
1073 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(EltTy)) {
1074 assert(ArrayTy->getNumElements() == 1);
1075 EltTy = ArrayTy->getElementType();
1078 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedVecTy);
1079 llvm::Value *Coerced =
1081 if (VLSTy != FixedVecTy)
1082 Coerced = CGF.
Builder.CreateBitCast(Coerced, FixedVecTy);
1088class RISCVTargetCodeGenInfo :
public TargetCodeGenInfo {
1090 RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
unsigned XLen,
1091 unsigned FLen,
bool EABI)
1092 : TargetCodeGenInfo(
1093 std::make_unique<RISCVABIInfo>(CGT, XLen, FLen, EABI)) {
1095 std::make_unique<SwiftABIInfo>(CGT,
false);
1098 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1099 CodeGen::CodeGenModule &CGM)
const override {
1100 const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
1106 Fn->addFnAttr(
"hw-shadow-stack");
1108 const auto *Attr = FD->getAttr<RISCVInterruptAttr>();
1112 StringRef
Kind =
"machine";
1113 bool HasSiFiveCLICPreemptible =
false;
1114 bool HasSiFiveCLICStackSwap =
false;
1115 for (RISCVInterruptAttr::InterruptType
type : Attr->interrupt()) {
1117 case RISCVInterruptAttr::machine:
1121 case RISCVInterruptAttr::supervisor:
1122 Kind =
"supervisor";
1124 case RISCVInterruptAttr::rnmi:
1127 case RISCVInterruptAttr::qcinest:
1130 case RISCVInterruptAttr::qcinonest:
1131 Kind =
"qci-nonest";
1135 case RISCVInterruptAttr::SiFiveCLICPreemptible: {
1136 HasSiFiveCLICPreemptible =
true;
1137 Kind = HasSiFiveCLICStackSwap ?
"SiFive-CLIC-preemptible-stack-swap"
1138 :
"SiFive-CLIC-preemptible";
1141 case RISCVInterruptAttr::SiFiveCLICStackSwap: {
1142 HasSiFiveCLICStackSwap =
true;
1143 Kind = HasSiFiveCLICPreemptible ?
"SiFive-CLIC-preemptible-stack-swap"
1144 :
"SiFive-CLIC-stack-swap";
1150 Fn->addFnAttr(
"interrupt", Kind);
1155std::unique_ptr<TargetCodeGenInfo>
1157 unsigned FLen,
bool EABI) {
1158 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 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)
static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType, llvm::Type *unpaddedCoerceToType)
llvm::Type * getCoerceToType() const
static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T=nullptr)
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)
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
U cast(CodeGen::Address addr)