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;
42 RISCVABIInfo(CodeGen::CodeGenTypes &CGT,
unsigned XLen,
unsigned FLen,
44 : DefaultABIInfo(CGT), XLen(XLen), FLen(FLen), NumArgGPRs(EABI ? 6 : 8),
45 NumArgFPRs(FLen != 0 ? 8 : 0), EABI(EABI) {}
49 void computeInfo(CGFunctionInfo &FI)
const override;
52 int &ArgFPRsLeft,
unsigned ABIVLen)
const;
55 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
56 AggValueSlot Slot)
const override;
58 ABIArgInfo extendType(QualType Ty, llvm::Type *CoerceTy =
nullptr)
const;
60 bool detectFPCCEligibleStruct(QualType Ty, llvm::Type *&Field1Ty,
61 CharUnits &Field1Off, llvm::Type *&Field2Ty,
62 CharUnits &Field2Off,
int &NeededArgGPRs,
63 int &NeededArgFPRs)
const;
64 ABIArgInfo coerceAndExpandFPCCEligibleStruct(llvm::Type *Field1Ty,
67 CharUnits Field2Off)
const;
69 ABIArgInfo coerceVLSVector(QualType Ty,
unsigned ABIVLen = 0)
const;
73 llvm::FixedVectorType *
74 getVLSCCCompatibleType(llvm::FixedVectorType *FixedVecTy)
const;
77 void appendAttributeMangling(TargetClonesAttr *Attr,
unsigned Index,
78 raw_ostream &Out)
const override;
79 void appendAttributeMangling(StringRef AttrStr,
80 raw_ostream &Out)
const override;
81 llvm::Value *createCoercedLoad(Address SrcAddr,
const ABIArgInfo &AI,
82 CodeGenFunction &CGF)
const override;
83 void createCoercedStore(llvm::Value *Val, Address DstAddr,
84 const ABIArgInfo &AI,
bool DestIsVolatile,
85 CodeGenFunction &CGF)
const override;
89void RISCVABIInfo::appendAttributeMangling(TargetClonesAttr *
Attr,
91 raw_ostream &Out)
const {
92 appendAttributeMangling(Attr->getFeatureStr(Index), Out);
95void RISCVABIInfo::appendAttributeMangling(StringRef AttrStr,
96 raw_ostream &Out)
const {
97 if (AttrStr ==
"default") {
104 SmallVector<StringRef, 8> Attrs;
105 AttrStr.split(Attrs,
';');
109 for (
auto &Attr : Attrs) {
110 if (Attr.starts_with(
"arch="))
115 SmallVector<StringRef, 8> Features;
116 ArchStr.consume_front(
"arch=");
117 ArchStr.split(Features,
',');
119 llvm::stable_sort(Features);
121 for (
auto Feat : Features) {
122 Feat.consume_front(
"+");
127void RISCVABIInfo::computeInfo(CGFunctionInfo &FI)
const {
133#define CC_VLS_CASE(ABI_VLEN) \
134 case CallingConv::CC_RISCVVLSCall_##ABI_VLEN: \
135 ABIVLen = ABI_VLEN; \
162 getContext().getTypeSize(RetTy) > (2 * XLen)) {
164 QualType EltTy = RetTy->
castAs<ComplexType>()->getElementType();
165 IsRetIndirect = getContext().getTypeSize(EltTy) > FLen;
168 IsRetIndirect =
true;
172 int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs;
173 int ArgFPRsLeft = NumArgFPRs;
178 bool IsFixed = ArgNum < NumFixedArgs;
180 ArgFPRsLeft, ABIVLen);
189bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff,
190 llvm::Type *&Field1Ty,
191 CharUnits &Field1Off,
192 llvm::Type *&Field2Ty,
193 CharUnits &Field2Off)
const {
197 if (IsInt || IsFloat) {
199 if (IsInt && Size > XLen)
203 if (IsFloat && Size > FLen)
207 if (IsInt && Field1Ty && Field1Ty->isIntegerTy())
210 Field1Ty = CGT.ConvertType(Ty);
215 Field2Ty = CGT.ConvertType(Ty);
222 if (
auto CTy = Ty->
getAs<ComplexType>()) {
225 QualType EltTy = CTy->getElementType();
226 if (getContext().getTypeSize(EltTy) > FLen)
228 Field1Ty = CGT.ConvertType(EltTy);
231 Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy);
235 if (
const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) {
236 uint64_t ArraySize = ATy->getZExtSize();
237 QualType EltTy = ATy->getElementType();
245 CharUnits EltSize = getContext().getTypeSizeInChars(EltTy);
246 for (uint64_t i = 0; i < ArraySize; ++i) {
247 bool Ret = detectFPCCEligibleStructHelper(EltTy, CurOff, Field1Ty,
248 Field1Off, Field2Ty, Field2Off);
263 const RecordDecl *RD = RTy->getDecl()->getDefinitionOrSelf();
267 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
269 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
270 for (
const CXXBaseSpecifier &B : CXXRD->bases()) {
271 const auto *BDecl = B.getType()->castAsCXXRecordDecl();
273 bool Ret = detectFPCCEligibleStructHelper(B.getType(), CurOff + BaseOff,
274 Field1Ty, Field1Off, Field2Ty,
280 int ZeroWidthBitFieldCount = 0;
281 for (
const FieldDecl *FD : RD->
fields()) {
283 QualType QTy = FD->getType();
284 if (FD->isBitField()) {
285 unsigned BitWidth = FD->getBitWidthValue();
288 if (getContext().getTypeSize(QTy) > XLen && BitWidth <= XLen)
289 QTy = getContext().getIntTypeForBitwidth(XLen,
false);
291 else if (getContext().getTypeSize(QTy) > BitWidth) {
293 FD->getType().getTypePtr()->hasSignedIntegerRepresentation();
294 unsigned Bits = std::max(8U, (
unsigned)llvm::PowerOf2Ceil(BitWidth));
295 QTy = getContext().getIntTypeForBitwidth(Bits, IsSigned);
298 ZeroWidthBitFieldCount++;
303 bool Ret = detectFPCCEligibleStructHelper(
304 QTy, CurOff + getContext().toCharUnitsFromBits(FieldOffInBits),
305 Field1Ty, Field1Off, Field2Ty, Field2Off);
312 if (Field2Ty && ZeroWidthBitFieldCount > 0)
315 return Field1Ty !=
nullptr;
325bool RISCVABIInfo::detectFPCCEligibleStruct(QualType Ty, llvm::Type *&Field1Ty,
326 CharUnits &Field1Off,
327 llvm::Type *&Field2Ty,
328 CharUnits &Field2Off,
330 int &NeededArgFPRs)
const {
335 bool IsCandidate = detectFPCCEligibleStructHelper(
340 if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy())
344 if (Field1Ty && Field1Ty->isFloatingPointTy())
348 if (Field2Ty && Field2Ty->isFloatingPointTy())
358ABIArgInfo RISCVABIInfo::coerceAndExpandFPCCEligibleStruct(
359 llvm::Type *Field1Ty, CharUnits Field1Off, llvm::Type *Field2Ty,
360 CharUnits Field2Off)
const {
361 SmallVector<llvm::Type *, 3> CoerceElts;
362 SmallVector<llvm::Type *, 2> UnpaddedCoerceElts;
364 CoerceElts.push_back(llvm::ArrayType::get(
365 llvm::Type::getInt8Ty(getVMContext()), Field1Off.
getQuantity()));
367 CoerceElts.push_back(Field1Ty);
368 UnpaddedCoerceElts.push_back(Field1Ty);
372 llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.
isZero()),
373 UnpaddedCoerceElts[0]);
376 CharUnits Field2Align =
378 CharUnits Field1End = Field1Off +
380 CharUnits Field2OffNoPadNoPack = Field1End.
alignTo(Field2Align);
383 if (Field2Off > Field2OffNoPadNoPack)
384 Padding = Field2Off - Field2OffNoPadNoPack;
385 else if (Field2Off != Field2Align && Field2Off > Field1End)
386 Padding = Field2Off - Field1End;
391 CoerceElts.push_back(llvm::ArrayType::get(
392 llvm::Type::getInt8Ty(getVMContext()), Padding.
getQuantity()));
394 CoerceElts.push_back(Field2Ty);
395 UnpaddedCoerceElts.push_back(Field2Ty);
398 llvm::StructType::get(getVMContext(), CoerceElts, IsPacked);
399 auto UnpaddedCoerceToType =
400 llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked);
405llvm::Type *RISCVABIInfo::detectVLSCCEligibleStruct(QualType Ty,
406 unsigned ABIVLen)
const {
468 llvm::StructType *STy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty));
472 unsigned NumElts = STy->getStructNumElements();
476 auto *FirstEltTy = STy->getElementType(0);
477 if (!STy->containsHomogeneousTypes())
480 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(FirstEltTy)) {
484 FirstEltTy = ArrayTy->getArrayElementType();
485 NumElts = ArrayTy->getNumElements();
488 auto *FixedVecTy = dyn_cast<llvm::FixedVectorType>(FirstEltTy);
493 if (NumElts * llvm::divideCeil(
494 FixedVecTy->getNumElements() *
495 FixedVecTy->getElementType()->getScalarSizeInBits(),
503 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedVecTy);
504 return llvm::ScalableVectorType::get(
505 VLSTy->getElementType(),
506 llvm::divideCeil(VLSTy->getNumElements() * llvm::RISCV::RVVBitsPerBlock,
516 unsigned I8EltCount =
517 llvm::divideCeil(FixedVecTy->getNumElements() *
518 FixedVecTy->getElementType()->getScalarSizeInBits() *
519 llvm::RISCV::RVVBitsPerBlock,
521 return llvm::TargetExtType::get(
522 getVMContext(),
"riscv.vector.tuple",
523 llvm::ScalableVectorType::get(llvm::Type::getInt8Ty(getVMContext()),
528llvm::FixedVectorType *
529RISCVABIInfo::getVLSCCCompatibleType(llvm::FixedVectorType *FixedVecTy)
const {
530 llvm::Type *EltType = FixedVecTy->getElementType();
531 const TargetInfo &TI = getContext().getTargetInfo();
532 if ((EltType->isHalfTy() && !TI.
hasFeature(
"zvfhmin")) ||
533 (EltType->isBFloatTy() &&
535 (EltType->isFloatTy() && !TI.
hasFeature(
"zve32f")) ||
536 (EltType->isDoubleTy() && !TI.
hasFeature(
"zve64d")) ||
537 (EltType->isIntegerTy(64) && !TI.
hasFeature(
"zve64x")) ||
538 EltType->isIntegerTy(128))
539 return llvm::FixedVectorType::get(llvm::Type::getInt8Ty(getVMContext()),
540 FixedVecTy->getNumElements() *
541 EltType->getScalarSizeInBits() / 8);
547ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty,
unsigned ABIVLen)
const {
550 const auto *VT = Ty->
castAs<VectorType>();
551 assert(VT->getElementType()->isBuiltinType() &&
"expected builtin type!");
553 auto VScale = getContext().getTargetInfo().getVScaleRange(
554 getContext().getLangOpts(), TargetInfo::ArmStreamingKind::NotStreaming);
556 unsigned NumElts = VT->getNumElements();
557 llvm::Type *EltType = llvm::Type::getInt1Ty(getVMContext());
558 switch (VT->getVectorKind()) {
559 case VectorKind::RVVFixedLengthMask_1:
561 case VectorKind::RVVFixedLengthMask_2:
564 case VectorKind::RVVFixedLengthMask_4:
567 case VectorKind::RVVFixedLengthMask:
571 assert((VT->getVectorKind() == VectorKind::Generic ||
572 VT->getVectorKind() == VectorKind::RVVFixedLengthData) &&
573 "Unexpected vector kind");
574 EltType = CGT.ConvertType(VT->getElementType());
577 llvm::ScalableVectorType *ResType;
584 ResType = llvm::ScalableVectorType::get(EltType, NumElts / VScale->first);
587 if ((EltType->getScalarSizeInBits() * NumElts / ABIVLen) > 8)
588 return getNaturalAlignIndirect(
589 Ty, getDataLayout().getAllocaAddrSpace(),
594 llvm::FixedVectorType *VLSTy =
595 getVLSCCCompatibleType(llvm::FixedVectorType::get(EltType, NumElts));
596 ResType = llvm::ScalableVectorType::get(
597 VLSTy->getElementType(),
598 llvm::divideCeil(VLSTy->getNumElements() * llvm::RISCV::RVVBitsPerBlock,
605ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty,
bool IsFixed,
608 unsigned ABIVLen)
const {
609 assert(ArgGPRsLeft <= NumArgGPRs &&
"Arg GPR tracking underflow");
617 return getNaturalAlignIndirect(
618 Ty, getDataLayout().getAllocaAddrSpace(),
631 FLen >= Size && ArgFPRsLeft) {
638 if (IsFixed && Ty->
isComplexType() && FLen && ArgFPRsLeft >= 2) {
639 QualType EltTy = Ty->
castAs<ComplexType>()->getElementType();
640 if (getContext().getTypeSize(EltTy) <= FLen) {
647 llvm::Type *Field1Ty =
nullptr;
648 llvm::Type *Field2Ty =
nullptr;
651 int NeededArgGPRs = 0;
652 int NeededArgFPRs = 0;
654 detectFPCCEligibleStruct(Ty, Field1Ty, Field1Off, Field2Ty, Field2Off,
655 NeededArgGPRs, NeededArgFPRs);
656 if (IsCandidate && NeededArgGPRs <= ArgGPRsLeft &&
657 NeededArgFPRs <= ArgFPRsLeft) {
658 ArgGPRsLeft -= NeededArgGPRs;
659 ArgFPRsLeft -= NeededArgFPRs;
660 return coerceAndExpandFPCCEligibleStruct(Field1Ty, Field1Off, Field2Ty,
666 if (llvm::Type *VLSType = detectVLSCCEligibleStruct(Ty, ABIVLen))
670 uint64_t NeededAlign = getContext().getTypeAlign(Ty);
677 int NeededArgGPRs = 1;
678 if (!IsFixed && NeededAlign == 2 * XLen)
679 NeededArgGPRs = 2 + (EABI && XLen == 32 ? 0 : (ArgGPRsLeft % 2));
680 else if (Size > XLen && Size <= 2 * XLen)
683 if (NeededArgGPRs > ArgGPRsLeft) {
684 NeededArgGPRs = ArgGPRsLeft;
687 ArgGPRsLeft -= NeededArgGPRs;
692 Ty = ED->getIntegerType();
694 if (
const auto *EIT = Ty->
getAs<BitIntType>()) {
696 if (XLen == 64 && EIT->getNumBits() == 32)
697 return extendType(Ty, CGT.ConvertType(Ty));
699 if (EIT->getNumBits() <= 2 * XLen)
701 return getNaturalAlignIndirect(
702 Ty, getDataLayout().getAllocaAddrSpace(),
707 if (Size < XLen && Ty->isIntegralOrEnumerationType())
708 return extendType(Ty, CGT.ConvertType(Ty));
716 if (
const VectorType *VT = Ty->
getAs<VectorType>();
717 VT && !VT->getElementType()->isBitIntType()) {
718 if (VT->getVectorKind() == VectorKind::RVVFixedLengthData ||
719 VT->getVectorKind() == VectorKind::RVVFixedLengthMask ||
720 VT->getVectorKind() == VectorKind::RVVFixedLengthMask_1 ||
721 VT->getVectorKind() == VectorKind::RVVFixedLengthMask_2 ||
722 VT->getVectorKind() == VectorKind::RVVFixedLengthMask_4)
723 return coerceVLSVector(Ty);
724 if (VT->getVectorKind() == VectorKind::Generic && ABIVLen != 0)
727 return coerceVLSVector(Ty, ABIVLen);
732 if (Size <= 2 * XLen) {
733 unsigned Alignment = getContext().getTypeAlign(Ty);
738 llvm::IntegerType::get(getVMContext(), Size));
741 if (Alignment == 2 * XLen)
743 llvm::IntegerType::get(getVMContext(), 2 * XLen));
746 llvm::ArrayType::get(llvm::IntegerType::get(getVMContext(), XLen), 2));
748 return getNaturalAlignIndirect(
749 Ty, getDataLayout().getAllocaAddrSpace(),
753ABIArgInfo RISCVABIInfo::classifyReturnType(QualType RetTy,
754 unsigned ABIVLen)
const {
759 int ArgFPRsLeft = FLen ? 2 : 0;
767RValue RISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
768 QualType Ty, AggValueSlot Slot)
const {
775 auto TInfo = getContext().getTypeInfoInChars(Ty);
781 if (EABI && XLen == 32)
785 bool IsIndirect = TInfo.Width > 2 * SlotSize;
791ABIArgInfo RISCVABIInfo::extendType(QualType Ty, llvm::Type *CoerceTy)
const {
792 int TySize = getContext().getTypeSize(Ty);
799llvm::Value *RISCVABIInfo::createCoercedLoad(Address Src,
const ABIArgInfo &AI,
800 CodeGenFunction &CGF)
const {
804 assert((Ty->isScalableTy() || Ty->isTargetExtTy()) &&
805 "Only scalable vector type and vector tuple type are allowed for load "
807 if (llvm::TargetExtType *TupTy = dyn_cast<llvm::TargetExtType>(Ty)) {
823 assert(TupTy->getName() ==
"riscv.vector.tuple");
824 llvm::Type *EltTy = TupTy->getTypeParameter(0);
825 unsigned NumElts = TupTy->getIntParameter(0);
827 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(SrcSTy->getElementType(0)))
831 llvm::Value *TupleVal = llvm::PoisonValue::get(Ty);
833 for (
unsigned i = 0; i < NumElts; ++i) {
835 llvm::Value *ExtractFromLoad = CGF.
Builder.CreateExtractValue(Load, i);
838 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedVecTy);
839 if (VLSTy != FixedVecTy)
840 ExtractFromLoad = CGF.
Builder.CreateBitCast(ExtractFromLoad, VLSTy);
846 llvm::Value *VectorVal = llvm::PoisonValue::get(EltTy);
848 VectorVal = CGF.
Builder.CreateInsertVector(
849 EltTy, VectorVal, ExtractFromLoad,
uint64_t(0),
"cast.scalable");
851 llvm::Value *Idx = CGF.
Builder.getInt32(i);
853 CGF.
Builder.CreateIntrinsic(llvm::Intrinsic::riscv_tuple_insert,
854 {Ty, EltTy}, {TupleVal, VectorVal, Idx});
874 SrcTy = SrcSTy->getElementType(0);
875 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(SrcTy))
876 SrcTy = ArrayTy->getElementType();
880 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedSrcTy);
881 if (VLSTy != FixedSrcTy)
883 auto *VectorVal = llvm::PoisonValue::get(ScalableDstTy);
885 ScalableDstTy, VectorVal, Load,
uint64_t(0),
"cast.scalable");
889void RISCVABIInfo::createCoercedStore(llvm::Value *Val, Address Dst,
890 const ABIArgInfo &AI,
bool DestIsVolatile,
891 CodeGenFunction &CGF)
const {
892 llvm::Type *SrcTy = Val->getType();
894 assert((SrcTy->isScalableTy() || SrcTy->isTargetExtTy()) &&
895 "Only scalable vector type and vector tuple type are allowed for "
897 if (llvm::TargetExtType *TupTy = dyn_cast<llvm::TargetExtType>(SrcTy)) {
913 assert(TupTy->getName() ==
"riscv.vector.tuple");
914 llvm::Type *EltTy = TupTy->getTypeParameter(0);
915 unsigned NumElts = TupTy->getIntParameter(0);
917 llvm::Type *FixedVecTy = DstSTy->getElementType(0);
918 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(DstSTy->getElementType(0))) {
920 FixedVecTy = ArrayTy->getArrayElementType();
923 llvm::FixedVectorType *VLSTy =
927 for (
unsigned i = 0; i < NumElts; ++i) {
934 llvm::Value *Idx = CGF.
Builder.getInt32(i);
935 auto *TupleElement = CGF.
Builder.CreateIntrinsic(
936 llvm::Intrinsic::riscv_tuple_extract, {EltTy, TupTy}, {Val, Idx});
939 llvm::Value *ExtractVec =
941 if (VLSTy != FixedVecTy)
942 ExtractVec = CGF.
Builder.CreateBitCast(ExtractVec, FixedVecTy);
969 llvm::Type *EltTy = DstSTy->getElementType(0);
970 if (
auto *ArrayTy = dyn_cast<llvm::ArrayType>(EltTy)) {
971 assert(ArrayTy->getNumElements() == 1);
972 EltTy = ArrayTy->getElementType();
975 llvm::FixedVectorType *VLSTy = getVLSCCCompatibleType(FixedVecTy);
976 llvm::Value *Coerced =
978 if (VLSTy != FixedVecTy)
979 Coerced = CGF.
Builder.CreateBitCast(Coerced, FixedVecTy);
985class RISCVTargetCodeGenInfo :
public TargetCodeGenInfo {
987 RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
unsigned XLen,
988 unsigned FLen,
bool EABI)
990 std::make_unique<RISCVABIInfo>(CGT, XLen, FLen, EABI)) {
992 std::make_unique<SwiftABIInfo>(CGT,
false);
995 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
996 CodeGen::CodeGenModule &CGM)
const override {
997 const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
1003 Fn->addFnAttr(
"hw-shadow-stack");
1005 const auto *Attr = FD->getAttr<RISCVInterruptAttr>();
1009 StringRef
Kind =
"machine";
1010 bool HasSiFiveCLICPreemptible =
false;
1011 bool HasSiFiveCLICStackSwap =
false;
1012 for (RISCVInterruptAttr::InterruptType
type : Attr->interrupt()) {
1014 case RISCVInterruptAttr::machine:
1018 case RISCVInterruptAttr::supervisor:
1019 Kind =
"supervisor";
1021 case RISCVInterruptAttr::rnmi:
1024 case RISCVInterruptAttr::qcinest:
1027 case RISCVInterruptAttr::qcinonest:
1028 Kind =
"qci-nonest";
1032 case RISCVInterruptAttr::SiFiveCLICPreemptible: {
1033 HasSiFiveCLICPreemptible =
true;
1034 Kind = HasSiFiveCLICStackSwap ?
"SiFive-CLIC-preemptible-stack-swap"
1035 :
"SiFive-CLIC-preemptible";
1038 case RISCVInterruptAttr::SiFiveCLICStackSwap: {
1039 HasSiFiveCLICStackSwap =
true;
1040 Kind = HasSiFiveCLICPreemptible ?
"SiFive-CLIC-preemptible-stack-swap"
1041 :
"SiFive-CLIC-stack-swap";
1047 Fn->addFnAttr(
"interrupt", Kind);
1052std::unique_ptr<TargetCodeGenInfo>
1054 unsigned FLen,
bool EABI) {
1055 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
field_range fields() 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.
@ Address
A pointer to a ValueDecl.
bool Load(InterpState &S, CodePtr OpPC)
PRESERVE_NONE bool Ret(InterpState &S, CodePtr &PC)
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
U cast(CodeGen::Address addr)