10#include "TargetInfo.h"
13#include "llvm/TargetParser/AArch64TargetParser.h"
24class AArch64ABIInfo :
public ABIInfo {
27 std::unique_ptr<TargetCodeGenInfo> WinX86_64CodegenInfo;
31 : ABIInfo(CGM.getTypes()),
Kind(
Kind) {
32 if (getTarget().
getTriple().isWindowsArm64EC()) {
33 WinX86_64CodegenInfo =
38 bool isSoftFloat()
const {
return Kind == AArch64ABIKind::AAPCSSoft; }
42 bool isDarwinPCS()
const {
return Kind == AArch64ABIKind::DarwinPCS; }
46 bool IsNamedArg,
unsigned CallingConvention,
47 unsigned &NSRN,
unsigned &NPRN)
const;
48 llvm::Type *convertFixedToScalableVectorType(
const VectorType *VT)
const;
49 ABIArgInfo coerceIllegalVector(QualType Ty,
unsigned &NSRN,
50 unsigned &NPRN)
const;
51 ABIArgInfo coerceAndExpandPureScalableAggregate(
52 QualType Ty,
bool IsNamedArg,
unsigned NVec,
unsigned NPred,
53 const SmallVectorImpl<llvm::Type *> &UnpaddedCoerceToSeq,
unsigned &NSRN,
54 unsigned &NPRN)
const;
55 bool isHomogeneousAggregateBaseType(QualType Ty)
const override;
56 bool isHomogeneousAggregateSmallEnough(
const Type *Ty,
57 uint64_t Members)
const override;
58 bool isZeroLengthBitfieldPermittedInHomogeneousAggregate()
const override;
60 bool isIllegalVectorType(QualType Ty)
const;
62 bool passAsAggregateType(QualType Ty)
const;
63 bool passAsPureScalableType(QualType Ty,
unsigned &NV,
unsigned &NP,
64 SmallVectorImpl<llvm::Type *> &CoerceToSeq)
const;
66 void flattenType(llvm::Type *Ty,
67 SmallVectorImpl<llvm::Type *> &Flattened)
const;
69 void computeInfo(CGFunctionInfo &FI)
const override {
75 unsigned NSRN = 0, NPRN = 0;
77 const bool IsNamedArg =
85 RValue EmitDarwinVAArg(Address VAListAddr, QualType Ty, CodeGenFunction &CGF,
86 AggValueSlot Slot)
const;
88 RValue EmitAAPCSVAArg(Address VAListAddr, QualType Ty, CodeGenFunction &CGF,
91 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
92 AggValueSlot Slot)
const override {
95 llvm::report_fatal_error(
"Passing SVE types to variadic functions is "
96 "currently not supported");
98 return Kind == AArch64ABIKind::Win64
99 ? EmitMSVAArg(CGF, VAListAddr, Ty, Slot)
100 : isDarwinPCS() ? EmitDarwinVAArg(VAListAddr, Ty, CGF, Slot)
101 : EmitAAPCSVAArg(VAListAddr, Ty, CGF,
Kind, Slot);
104 RValue EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
105 AggValueSlot Slot)
const override;
107 bool allowBFloatArgsAndRet()
const override {
108 return getTarget().hasBFloat16Type();
112 void appendAttributeMangling(TargetClonesAttr *Attr,
unsigned Index,
113 raw_ostream &Out)
const override;
114 void appendAttributeMangling(StringRef AttrStr,
115 raw_ostream &Out)
const override;
120 explicit AArch64SwiftABIInfo(CodeGenTypes &CGT)
121 : SwiftABIInfo(CGT,
true) {}
124 unsigned NumElts)
const override;
130 : TargetCodeGenInfo(std::make_unique<AArch64ABIInfo>(CGM,
Kind)) {
131 SwiftInfo = std::make_unique<AArch64SwiftABIInfo>(CGM.
getTypes());
134 StringRef getARCRetainAutoreleasedReturnValueMarker()
const override {
135 return "mov\tfp, fp\t\t// marker for objc_retainAutoreleaseReturnValue";
138 int getDwarfEHStackPointer(CodeGen::CodeGenModule &M)
const override {
142 bool doesReturnSlotInterfereWithArgs()
const override {
return false; }
144 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
145 CodeGen::CodeGenModule &CGM)
const override {
146 auto *
Fn = dyn_cast<llvm::Function>(GV);
150 const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
151 TargetInfo::BranchProtectionInfo BPI(CGM.
getLangOpts());
153 if (FD && FD->hasAttr<TargetAttr>()) {
154 const auto *TA = FD->getAttr<TargetAttr>();
155 ParsedTargetAttr Attr =
157 if (!Attr.BranchProtection.empty()) {
161 assert(
Error.empty());
164 setBranchProtectionFnAttributes(BPI, *Fn);
168 bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF,
169 llvm::Type *Ty)
const override {
171 auto *ST = dyn_cast<llvm::StructType>(Ty);
172 if (ST && ST->getNumElements() == 1) {
173 auto *AT = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
174 if (AT && AT->getNumElements() == 8 &&
175 AT->getElementType()->isIntegerTy(64))
182 void checkFunctionABI(CodeGenModule &CGM,
183 const FunctionDecl *
Decl)
const override;
185 void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc,
186 const FunctionDecl *Caller,
187 const FunctionDecl *Callee,
const CallArgList &Args,
188 QualType ReturnType)
const override;
190 bool wouldInliningViolateFunctionCallABI(
191 const FunctionDecl *Caller,
const FunctionDecl *Callee)
const override;
196 void checkFunctionCallABIStreaming(CodeGenModule &CGM, SourceLocation CallLoc,
197 const FunctionDecl *Caller,
198 const FunctionDecl *Callee)
const;
201 void checkFunctionCallABISoftFloat(CodeGenModule &CGM, SourceLocation CallLoc,
202 const FunctionDecl *Caller,
203 const FunctionDecl *Callee,
204 const CallArgList &Args,
205 QualType ReturnType)
const;
208class WindowsAArch64TargetCodeGenInfo :
public AArch64TargetCodeGenInfo {
210 WindowsAArch64TargetCodeGenInfo(CodeGenModule &CGM,
AArch64ABIKind K)
211 : AArch64TargetCodeGenInfo(CGM, K) {}
213 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
214 CodeGen::CodeGenModule &CGM)
const override;
216 void getDependentLibraryOption(llvm::StringRef Lib,
217 llvm::SmallString<24> &Opt)
const override {
218 Opt =
"/DEFAULTLIB:" + qualifyWindowsLibrary(Lib);
221 void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef
Value,
222 llvm::SmallString<32> &Opt)
const override {
223 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
227void WindowsAArch64TargetCodeGenInfo::setTargetAttributes(
229 AArch64TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
230 if (GV->isDeclaration())
232 addStackProbeTargetAttributes(D, GV, CGM);
237AArch64ABIInfo::convertFixedToScalableVectorType(
const VectorType *VT)
const {
240 if (VT->
getVectorKind() == VectorKind::SveFixedLengthPredicate) {
242 BuiltinType::UChar &&
243 "unexpected builtin type for SVE predicate!");
244 return llvm::ScalableVectorType::get(llvm::Type::getInt1Ty(getVMContext()),
250 switch (BT->getKind()) {
252 llvm_unreachable(
"unexpected builtin type for SVE vector!");
254 case BuiltinType::SChar:
255 case BuiltinType::UChar:
256 case BuiltinType::MFloat8:
257 return llvm::ScalableVectorType::get(
258 llvm::Type::getInt8Ty(getVMContext()), 16);
260 case BuiltinType::Short:
261 case BuiltinType::UShort:
262 return llvm::ScalableVectorType::get(
263 llvm::Type::getInt16Ty(getVMContext()), 8);
265 case BuiltinType::Int:
266 case BuiltinType::UInt:
267 return llvm::ScalableVectorType::get(
268 llvm::Type::getInt32Ty(getVMContext()), 4);
270 case BuiltinType::Long:
271 case BuiltinType::ULong:
272 return llvm::ScalableVectorType::get(
273 llvm::Type::getInt64Ty(getVMContext()), 2);
275 case BuiltinType::Half:
276 return llvm::ScalableVectorType::get(
277 llvm::Type::getHalfTy(getVMContext()), 8);
279 case BuiltinType::Float:
280 return llvm::ScalableVectorType::get(
281 llvm::Type::getFloatTy(getVMContext()), 4);
283 case BuiltinType::Double:
284 return llvm::ScalableVectorType::get(
285 llvm::Type::getDoubleTy(getVMContext()), 2);
287 case BuiltinType::BFloat16:
288 return llvm::ScalableVectorType::get(
289 llvm::Type::getBFloatTy(getVMContext()), 8);
293 llvm_unreachable(
"expected fixed-length SVE vector");
296ABIArgInfo AArch64ABIInfo::coerceIllegalVector(QualType Ty,
unsigned &NSRN,
297 unsigned &NPRN)
const {
300 const auto *VT = Ty->
castAs<VectorType>();
301 if (VT->
getVectorKind() == VectorKind::SveFixedLengthPredicate) {
304 BuiltinType::UChar &&
305 "unexpected builtin type for SVE predicate!");
306 NPRN = std::min(NPRN + 1, 4u);
308 llvm::Type::getInt1Ty(getVMContext()), 16));
312 NSRN = std::min(NSRN + 1, 8u);
318 if ((isAndroid() || isOHOSFamily()) && (Size <= 16)) {
319 llvm::Type *ResType = llvm::Type::getInt16Ty(getVMContext());
323 llvm::Type *ResType = llvm::Type::getInt32Ty(getVMContext());
327 NSRN = std::min(NSRN + 1, 8u);
329 llvm::FixedVectorType::get(llvm::Type::getInt32Ty(getVMContext()), 2);
333 NSRN = std::min(NSRN + 1, 8u);
335 llvm::FixedVectorType::get(llvm::Type::getInt32Ty(getVMContext()), 4);
339 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
343ABIArgInfo AArch64ABIInfo::coerceAndExpandPureScalableAggregate(
344 QualType Ty,
bool IsNamedArg,
unsigned NVec,
unsigned NPred,
345 const SmallVectorImpl<llvm::Type *> &UnpaddedCoerceToSeq,
unsigned &NSRN,
346 unsigned &NPRN)
const {
347 if (!IsNamedArg || NSRN + NVec > 8 || NPRN + NPred > 4)
348 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
357 llvm::Type *UnpaddedCoerceToType =
358 UnpaddedCoerceToSeq.size() == 1
359 ? UnpaddedCoerceToSeq[0]
360 : llvm::StructType::get(CGT.getLLVMContext(), UnpaddedCoerceToSeq,
363 SmallVector<llvm::Type *> CoerceToSeq;
364 flattenType(CGT.ConvertType(Ty), CoerceToSeq);
366 llvm::StructType::get(CGT.getLLVMContext(), CoerceToSeq,
false);
371ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty,
bool IsVariadicFn,
373 unsigned CallingConvention,
375 unsigned &NPRN)
const {
378 if (IsVariadicFn && getTarget().
getTriple().isWindowsArm64EC()) {
381 return WinX86_64CodegenInfo->getABIInfo().classifyArgForArm64ECVarArg(
386 if (isIllegalVectorType(Ty))
387 return coerceIllegalVector(Ty, NSRN, NPRN);
389 if (!passAsAggregateType(Ty)) {
392 Ty = ED->getIntegerType();
394 if (
const auto *EIT = Ty->
getAs<BitIntType>())
395 if (EIT->getNumBits() > 128)
396 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
400 NSRN = std::min(NSRN + 1, 8u);
401 else if (
const auto *BT = Ty->
getAs<BuiltinType>()) {
402 if (BT->isFloatingPoint())
403 NSRN = std::min(NSRN + 1, 8u);
405 switch (BT->getKind()) {
406 case BuiltinType::SveBool:
407 case BuiltinType::SveCount:
408 NPRN = std::min(NPRN + 1, 4u);
410 case BuiltinType::SveBoolx2:
411 NPRN = std::min(NPRN + 2, 4u);
413 case BuiltinType::SveBoolx4:
414 NPRN = std::min(NPRN + 4, 4u);
416 case BuiltinType::MFloat8:
417 NSRN = std::min(NSRN + 1, 8u);
420 if (BT->isSVESizelessBuiltinType())
422 NSRN + getContext().getBuiltinVectorTypeInfo(BT).NumVectors,
428 return (isPromotableIntegerTypeForABI(Ty) && isDarwinPCS()
436 return getNaturalAlignIndirect(
437 Ty, getDataLayout().getAllocaAddrSpace(),
452 if (!getContext().getLangOpts().
CPlusPlus || isDarwinPCS())
465 bool IsWin64 =
Kind == AArch64ABIKind::Win64 ||
466 CallingConvention == llvm::CallingConv::Win64;
467 bool IsWinVariadic = IsWin64 && IsVariadicFn;
470 if (!IsWinVariadic && isHomogeneousAggregate(Ty, Base, Members)) {
471 NSRN = std::min(NSRN + Members,
uint64_t(8));
472 if (Kind != AArch64ABIKind::AAPCS)
474 llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members));
479 getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity();
480 Align = (Align >= 16) ? 16 : 8;
482 llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members), 0,
483 nullptr,
true, Align);
488 if (Kind == AArch64ABIKind::AAPCS) {
489 unsigned NVec = 0, NPred = 0;
490 SmallVector<llvm::Type *> UnpaddedCoerceToSeq;
491 if (passAsPureScalableType(Ty, NVec, NPred, UnpaddedCoerceToSeq) &&
493 return coerceAndExpandPureScalableAggregate(
494 Ty, IsNamedArg, NVec, NPred, UnpaddedCoerceToSeq, NSRN, NPRN);
500 if (Kind == AArch64ABIKind::AAPCS) {
501 Alignment = getContext().getTypeUnadjustedAlign(Ty);
502 Alignment = Alignment < 128 ? 64 : 128;
505 std::max(getContext().getTypeAlign(Ty),
506 (
unsigned)getTarget().getPointerWidth(LangAS::Default));
508 Size = llvm::alignTo(Size, Alignment);
513 auto ContainsOnlyPointers = [&](
const auto &
Self, QualType Ty) {
519 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
520 for (
const auto &I : CXXRD->bases())
524 return all_of(RD->fields(), [&](FieldDecl *FD) {
525 QualType FDTy = FD->getType();
526 if (FDTy->isArrayType())
527 FDTy = getContext().getBaseElementType(FDTy);
528 return (FDTy->isPointerOrReferenceType() &&
529 getContext().getTypeSize(FDTy) == 64 &&
530 !FDTy->getPointeeType().hasAddressSpace()) ||
537 llvm::Type *BaseTy = llvm::Type::getIntNTy(getVMContext(), Alignment);
538 if ((Size == 64 || Size == 128) && Alignment == 64 &&
539 ContainsOnlyPointers(ContainsOnlyPointers, Ty))
540 BaseTy = llvm::PointerType::getUnqual(getVMContext());
542 Size == Alignment ? BaseTy
543 : llvm::ArrayType::get(BaseTy, Size / Alignment));
546 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
550ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy,
551 bool IsVariadicFn)
const {
555 if (
const auto *VT = RetTy->
getAs<VectorType>()) {
557 VT->
getVectorKind() == VectorKind::SveFixedLengthPredicate) {
558 unsigned NSRN = 0, NPRN = 0;
559 return coerceIllegalVector(RetTy, NSRN, NPRN);
564 if (RetTy->
isVectorType() && getContext().getTypeSize(RetTy) > 128)
565 return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace());
567 if (!passAsAggregateType(RetTy)) {
570 RetTy = ED->getIntegerType();
572 if (
const auto *EIT = RetTy->
getAs<BitIntType>())
573 if (EIT->getNumBits() > 128)
574 return getNaturalAlignIndirect(RetTy,
575 getDataLayout().getAllocaAddrSpace());
577 return (isPromotableIntegerTypeForABI(RetTy) && isDarwinPCS()
589 if (isHomogeneousAggregate(RetTy, Base, Members) &&
590 !(getTarget().
getTriple().getArch() == llvm::Triple::aarch64_32 &&
598 if (Kind == AArch64ABIKind::AAPCS) {
599 unsigned NSRN = 0, NPRN = 0;
600 unsigned NVec = 0, NPred = 0;
601 SmallVector<llvm::Type *> UnpaddedCoerceToSeq;
602 if (passAsPureScalableType(RetTy, NVec, NPred, UnpaddedCoerceToSeq) &&
604 return coerceAndExpandPureScalableAggregate(
605 RetTy,
true, NVec, NPred, UnpaddedCoerceToSeq, NSRN,
611 if (Size <= 64 && getDataLayout().isLittleEndian()) {
619 llvm::IntegerType::get(getVMContext(), Size));
622 unsigned Alignment = getContext().getTypeAlign(RetTy);
623 Size = llvm::alignTo(Size, 64);
627 if (Alignment < 128 && Size == 128) {
628 llvm::Type *BaseTy = llvm::Type::getInt64Ty(getVMContext());
634 return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace());
638bool AArch64ABIInfo::isIllegalVectorType(QualType Ty)
const {
639 if (
const VectorType *VT = Ty->
getAs<VectorType>()) {
651 if (!llvm::isPowerOf2_32(NumElements))
656 llvm::Triple Triple = getTarget().getTriple();
657 if (Triple.getArch() == llvm::Triple::aarch64_32 &&
658 Triple.isOSBinFormatMachO())
661 return Size != 64 && (
Size != 128 || NumElements == 1);
666bool AArch64SwiftABIInfo::isLegalVectorType(CharUnits VectorSize,
668 unsigned NumElts)
const {
669 if (!llvm::isPowerOf2_32(NumElts))
677bool AArch64ABIInfo::isHomogeneousAggregateBaseType(QualType Ty)
const {
687 if (
const BuiltinType *BT = Ty->
getAs<BuiltinType>()) {
688 if (BT->isFloatingPoint())
690 }
else if (
const VectorType *VT = Ty->
getAs<VectorType>()) {
692 Kind == VectorKind::SveFixedLengthData ||
693 Kind == VectorKind::SveFixedLengthPredicate)
696 unsigned VecSize = getContext().getTypeSize(VT);
697 if (VecSize == 64 || VecSize == 128)
703bool AArch64ABIInfo::isHomogeneousAggregateSmallEnough(
const Type *Base,
704 uint64_t Members)
const {
708bool AArch64ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate()
718bool AArch64ABIInfo::passAsAggregateType(QualType Ty)
const {
720 const auto *BT = Ty->
castAs<BuiltinType>();
721 return !BT->isSVECount() &&
722 getContext().getBuiltinVectorTypeInfo(BT).NumVectors > 1;
735bool AArch64ABIInfo::passAsPureScalableType(
736 QualType Ty,
unsigned &NVec,
unsigned &NPred,
737 SmallVectorImpl<llvm::Type *> &CoerceToSeq)
const {
738 if (
const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
743 unsigned NV = 0, NP = 0;
744 SmallVector<llvm::Type *> EltCoerceToSeq;
745 if (!passAsPureScalableType(AT->getElementType(), NV, NP, EltCoerceToSeq))
748 if (CoerceToSeq.size() + NElt * EltCoerceToSeq.size() > 12)
751 for (uint64_t I = 0; I < NElt; ++I)
752 llvm::append_range(CoerceToSeq, EltCoerceToSeq);
766 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
771 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
772 for (
const auto &I : CXXRD->bases()) {
775 if (!passAsPureScalableType(I.getType(), NVec, NPred, CoerceToSeq))
781 for (
const auto *FD : RD->
fields()) {
782 QualType FT = FD->getType();
785 if (!passAsPureScalableType(FT, NVec, NPred, CoerceToSeq))
792 if (
const auto *VT = Ty->
getAs<VectorType>()) {
793 if (VT->
getVectorKind() == VectorKind::SveFixedLengthPredicate) {
795 if (CoerceToSeq.size() + 1 > 12)
797 CoerceToSeq.push_back(convertFixedToScalableVectorType(VT));
803 if (CoerceToSeq.size() + 1 > 12)
805 CoerceToSeq.push_back(convertFixedToScalableVectorType(VT));
816 switch (Ty->
castAs<BuiltinType>()->getKind()) {
817#define SVE_VECTOR_TYPE(Name, MangledName, Id, SingletonId) \
818 case BuiltinType::Id: \
819 isPredicate = false; \
821#define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId) \
822 case BuiltinType::Id: \
823 isPredicate = true; \
825#include "clang/Basic/AArch64ACLETypes.def"
830 ASTContext::BuiltinVectorTypeInfo Info =
833 "Expected 1, 2, 3 or 4 vectors!");
839 ? llvm::Type::getInt8Ty(getVMContext())
840 : CGT.ConvertType(Info.ElementType);
841 auto *VTy = llvm::ScalableVectorType::get(EltTy, Info.
EC.getKnownMinValue());
843 if (CoerceToSeq.size() + Info.
NumVectors > 12)
845 std::fill_n(std::back_inserter(CoerceToSeq), Info.
NumVectors, VTy);
853void AArch64ABIInfo::flattenType(
854 llvm::Type *Ty, SmallVectorImpl<llvm::Type *> &Flattened)
const {
857 Flattened.push_back(Ty);
861 if (
const auto *AT = dyn_cast<llvm::ArrayType>(Ty)) {
862 uint64_t NElt = AT->getNumElements();
866 SmallVector<llvm::Type *> EltFlattened;
867 flattenType(AT->getElementType(), EltFlattened);
869 for (uint64_t I = 0; I < NElt; ++I)
870 llvm::append_range(Flattened, EltFlattened);
874 if (
const auto *ST = dyn_cast<llvm::StructType>(Ty)) {
875 for (
auto *ET : ST->elements())
876 flattenType(ET, Flattened);
880 Flattened.push_back(Ty);
883RValue AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr, QualType Ty,
885 AggValueSlot Slot)
const {
889 unsigned NSRN = 0, NPRN = 0;
901 BaseTy = llvm::PointerType::getUnqual(BaseTy->getContext());
905 unsigned NumRegs = 1;
906 if (llvm::ArrayType *ArrTy = dyn_cast<llvm::ArrayType>(BaseTy)) {
907 BaseTy = ArrTy->getElementType();
908 NumRegs = ArrTy->getNumElements();
911 !isSoftFloat() && (BaseTy->isFloatingPointTy() || BaseTy->isVectorTy());
929 CharUnits TySize = getContext().getTypeSizeInChars(Ty);
930 CharUnits TyAlign = getContext().getTypeUnadjustedAlignInChars(Ty);
933 llvm::Value *reg_offs =
nullptr;
935 int RegSize = IsIndirect ? 8 : TySize.
getQuantity();
941 RegSize = llvm::alignTo(RegSize, 8);
947 RegSize = 16 * NumRegs;
958 llvm::Value *UsingStack =
nullptr;
959 UsingStack = CGF.
Builder.CreateICmpSGE(
960 reg_offs, llvm::ConstantInt::get(CGF.
Int32Ty, 0));
962 CGF.
Builder.CreateCondBr(UsingStack, OnStackBlock, MaybeRegBlock);
971 if (!IsFPR && !IsIndirect && TyAlign.
getQuantity() > 8) {
974 reg_offs = CGF.
Builder.CreateAdd(
975 reg_offs, llvm::ConstantInt::get(CGF.
Int32Ty, Align - 1),
977 reg_offs = CGF.
Builder.CreateAnd(
978 reg_offs, llvm::ConstantInt::getSigned(CGF.
Int32Ty, -Align),
986 llvm::Value *NewOffset =
nullptr;
987 NewOffset = CGF.
Builder.CreateAdd(
988 reg_offs, llvm::ConstantInt::get(CGF.
Int32Ty, RegSize),
"new_reg_offs");
993 llvm::Value *InRegs =
nullptr;
994 InRegs = CGF.
Builder.CreateICmpSLE(
995 NewOffset, llvm::ConstantInt::get(CGF.
Int32Ty, 0),
"inreg");
997 CGF.
Builder.CreateCondBr(InRegs, InRegBlock, OnStackBlock);
1007 llvm::Value *reg_top =
nullptr;
1019 MemTy = llvm::PointerType::getUnqual(MemTy->getContext());
1024 bool IsHFA = isHomogeneousAggregate(Ty, Base, NumMembers);
1025 if (IsHFA && NumMembers > 1) {
1030 assert(!IsIndirect &&
"Homogeneous aggregates should be passed directly");
1031 auto BaseTyInfo = getContext().getTypeInfoInChars(QualType(Base, 0));
1032 llvm::Type *BaseTy = CGF.
ConvertType(QualType(Base, 0));
1033 llvm::Type *HFATy = llvm::ArrayType::get(BaseTy, NumMembers);
1035 std::max(TyAlign, BaseTyInfo.Align));
1040 BaseTyInfo.Width.getQuantity() < 16)
1041 Offset = 16 - BaseTyInfo.Width.getQuantity();
1043 for (
unsigned i = 0; i < NumMembers; ++i) {
1060 CharUnits SlotSize = BaseAddr.getAlignment();
1063 TySize < SlotSize) {
1064 CharUnits Offset = SlotSize - TySize;
1091 CharUnits StackSize;
1093 StackSize = StackSlotSize;
1095 StackSize = TySize.
alignTo(StackSlotSize);
1099 CGF.
Int8Ty, OnStackPtr, StackSizeC,
"new_stack");
1105 TySize < StackSlotSize) {
1106 CharUnits Offset = StackSlotSize - TySize;
1120 OnStackBlock,
"vaargs.addr");
1133RValue AArch64ABIInfo::EmitDarwinVAArg(Address VAListAddr, QualType Ty,
1134 CodeGenFunction &CGF,
1135 AggValueSlot Slot)
const {
1145 uint64_t PointerSize = getTarget().getPointerWidth(LangAS::Default) / 8;
1154 auto TyInfo = getContext().getTypeInfoInChars(Ty);
1158 bool IsIndirect =
false;
1159 if (TyInfo.Width.getQuantity() > 16) {
1162 IsIndirect = !isHomogeneousAggregate(Ty, Base, Members);
1169RValue AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
1170 QualType Ty, AggValueSlot Slot)
const {
1171 bool AllowHigherAlign =
false;
1172 bool IsIndirect =
false;
1174 if (getTarget().
getTriple().isWindowsArm64EC()) {
1177 uint64_t Width = getContext().getTypeSize(Ty);
1178 IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
1182 AllowHigherAlign =
true;
1196 return T->getAArch64SMEAttributes() &
1204 const StringRef ABIName,
1205 const AArch64ABIInfo &
ABIInfo,
1208 const Type *HABase =
nullptr;
1209 uint64_t HAMembers = 0;
1212 Diags.
Report(loc, diag::err_target_unsupported_type_for_abi)
1220void AArch64TargetCodeGenInfo::checkFunctionABI(
1221 CodeGenModule &CGM,
const FunctionDecl *FuncDecl)
const {
1222 const AArch64ABIInfo &ABIInfo = getABIInfo<AArch64ABIInfo>();
1223 const TargetInfo &TI = ABIInfo.getContext().getTargetInfo();
1225 if (!TI.
hasFeature(
"fp") && !ABIInfo.isSoftFloat()) {
1229 for (ParmVarDecl *PVD : FuncDecl->
parameters()) {
1253 bool CallerIsStreaming =
1255 bool CalleeIsStreaming =
1262 if (!CalleeIsStreamingCompatible &&
1263 (CallerIsStreaming != CalleeIsStreaming || CallerIsStreamingCompatible)) {
1264 if (CalleeIsStreaming)
1269 if (
auto *NewAttr = Callee->getAttr<ArmNewAttr>()) {
1270 if (NewAttr->isNewZA())
1272 if (NewAttr->isNewZT0())
1276 return Inlinability;
1279void AArch64TargetCodeGenInfo::checkFunctionCallABIStreaming(
1280 CodeGenModule &CGM, SourceLocation CallLoc,
const FunctionDecl *Caller,
1281 const FunctionDecl *Callee)
const {
1282 if (!Caller || !Callee || !
Callee->hasAttr<AlwaysInlineAttr>())
1293 ? diag::err_function_always_inline_attribute_mismatch
1294 : diag::warn_function_always_inline_attribute_mismatch)
1299 CGM.
getDiags().
Report(CallLoc, diag::err_function_always_inline_new_za)
1300 <<
Callee->getDeclName();
1304 CGM.
getDiags().
Report(CallLoc, diag::err_function_always_inline_new_zt0)
1305 <<
Callee->getDeclName();
1311void AArch64TargetCodeGenInfo::checkFunctionCallABISoftFloat(
1312 CodeGenModule &CGM, SourceLocation CallLoc,
const FunctionDecl *Caller,
1313 const FunctionDecl *Callee,
const CallArgList &Args,
1314 QualType ReturnType)
const {
1315 const AArch64ABIInfo &ABIInfo = getABIInfo<AArch64ABIInfo>();
1316 const TargetInfo &TI = ABIInfo.getContext().getTargetInfo();
1318 if (!Caller || TI.
hasFeature(
"fp") || ABIInfo.isSoftFloat())
1322 Callee ? Callee : Caller, CallLoc);
1324 for (
const CallArg &Arg : Args)
1326 Callee ? Callee : Caller, CallLoc);
1329void AArch64TargetCodeGenInfo::checkFunctionCallABI(CodeGenModule &CGM,
1330 SourceLocation CallLoc,
1331 const FunctionDecl *Caller,
1332 const FunctionDecl *Callee,
1333 const CallArgList &Args,
1334 QualType ReturnType)
const {
1335 checkFunctionCallABIStreaming(CGM, CallLoc, Caller, Callee);
1336 checkFunctionCallABISoftFloat(CGM, CallLoc, Caller, Callee, Args, ReturnType);
1339bool AArch64TargetCodeGenInfo::wouldInliningViolateFunctionCallABI(
1340 const FunctionDecl *Caller,
const FunctionDecl *Callee)
const {
1341 return Caller &&
Callee &&
1345void AArch64ABIInfo::appendAttributeMangling(TargetClonesAttr *Attr,
1347 raw_ostream &Out)
const {
1348 appendAttributeMangling(Attr->getFeatureStr(Index), Out);
1351void AArch64ABIInfo::appendAttributeMangling(StringRef AttrStr,
1352 raw_ostream &Out)
const {
1353 if (AttrStr ==
"default") {
1359 SmallVector<StringRef, 8> Features;
1360 AttrStr.split(Features,
"+");
1361 for (
auto &Feat : Features)
1364 llvm::sort(Features, [](
const StringRef LHS,
const StringRef RHS) {
1365 return LHS.compare(RHS) < 0;
1368 llvm::SmallDenseSet<StringRef, 8> UniqueFeats;
1369 for (
auto &Feat : Features)
1370 if (getTarget().doesFeatureAffectCodeGen(Feat))
1371 if (
auto Ext = llvm::AArch64::parseFMVExtension(Feat))
1372 if (UniqueFeats.insert(Ext->Name).second)
1373 Out <<
'M' << Ext->Name;
1376std::unique_ptr<TargetCodeGenInfo>
1379 return std::make_unique<AArch64TargetCodeGenInfo>(CGM, Kind);
1382std::unique_ptr<TargetCodeGenInfo>
1385 return std::make_unique<WindowsAArch64TargetCodeGenInfo>(CGM, K);
@ ErrorCalleeRequiresNewZA
@ WarnIncompatibleStreamingModes
@ ErrorCalleeRequiresNewZT0
@ IncompatibleStreamingModes
@ LLVM_MARK_AS_BITMASK_ENUM
@ ErrorIncompatibleStreamingModes
static bool isStreamingCompatible(const FunctionDecl *fd)
static ArmSMEInlinability GetArmSMEInlinability(const FunctionDecl *Caller, const FunctionDecl *Callee)
Determines if there are any Arm SME ABI issues with inlining Callee into Caller.
static void diagnoseIfNeedsFPReg(DiagnosticsEngine &Diags, const StringRef ABIName, const AArch64ABIInfo &ABIInfo, const QualType &Ty, const NamedDecl *D, SourceLocation loc)
static StringRef getTriple(const Command &Job)
TypeInfoChars getTypeInfoInChars(const Type *T) const
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
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 ...
PointerAuthOptions PointerAuth
Configuration for pointer-signing.
static ABIArgInfo getIgnore()
static bool isPaddingForCoerceAndExpand(llvm::Type *eltType)
static ABIArgInfo getDirect(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true, unsigned Align=0)
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
ABIInfo - Target specific hooks for defining how a type should be passed or returned from functions.
bool isHomogeneousAggregate(QualType Ty, const Type *&Base, uint64_t &Members) const
isHomogeneousAggregate - Return true if a type is an ELFv2 homogeneous aggregate.
virtual void appendAttributeMangling(TargetAttr *Attr, raw_ostream &Out) const
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 CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name="")
Given a pointer to i8, adjust it by a given constant offset.
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="")
llvm::ConstantInt * getSize(CharUnits N)
Address CreateInBoundsGEP(Address Addr, ArrayRef< llvm::Value * > IdxList, llvm::Type *ElementType, CharUnits Align, const Twine &Name="")
RecordArgABI
Specify how one should pass an argument of a record type.
@ RAA_Default
Pass it using the normal C aggregate rules for the ABI, potentially introducing extra copies and pass...
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
ABIArgInfo & getReturnInfo()
unsigned getCallingConvention() const
getCallingConvention - Return the user specified calling convention, which has been translated into a...
CanQualType getReturnType() const
MutableArrayRef< ArgInfo > arguments()
RequiredArgs getRequiredArgs() const
llvm::Type * ConvertType(QualType T)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
RValue EmitLoadOfAnyValue(LValue V, AggValueSlot Slot=AggValueSlot::ignored(), SourceLocation Loc={})
Like EmitLoadOfLValue but also handles complex and aggregate types.
const TargetInfo & getTarget() const
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
ASTContext & getContext() const
llvm::Type * ConvertTypeForMem(QualType T)
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
const CGFunctionInfo * CurFnInfo
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
This class organizes the cross-function state that is used while generating LLVM code.
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
const llvm::DataLayout & getDataLayout() const
const CodeGenOptions & getCodeGenOpts() const
unsigned getNumRequiredArgs() const
Target specific hooks for defining how a type should be passed or returned from functions with one of...
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
virtual bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF, llvm::Type *Ty) const
Target hook to decide whether an inline asm operand can be passed by value.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getLocation() const
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Represents a function declaration or definition.
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
Represents a prototype with parameter type info, e.g.
@ SME_PStateSMCompatibleMask
This represents a decl that may have a name.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
A (possibly-)qualified type.
field_range fields() const
Encodes a location in the source.
virtual bool validateBranchProtection(StringRef Spec, StringRef Arch, BranchProtectionInfo &BPI, const LangOptions &LO, StringRef &Err) const
Determine if this TargetInfo supports the given branch protection specification.
virtual StringRef getABI() const
Get the ABI currently in use.
virtual ParsedTargetAttr parseTargetAttr(StringRef Str) const
virtual bool hasFeature(StringRef Feature) const
Determine whether the given target has the given feature.
The base class of the type hierarchy.
bool isMFloat8Type() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isSVESizelessBuiltinType() const
Returns true for SVE scalable vector types.
const T * castAs() const
Member-template castAs<specific type>.
bool isBuiltinType() const
Helper methods to distinguish type categories.
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
bool isVectorType() const
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
VectorKind getVectorKind() const
QualType getElementType() const
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to pass a particular type.
bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, llvm::VectorType *vectorTy)
Is the given vector type "legal" for Swift's perspective on the current platform?
@ 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)
Address EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, const ABIArgInfo &AI)
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 ...
Address emitMergePHI(CodeGenFunction &CGF, Address Addr1, llvm::BasicBlock *Block1, Address Addr2, llvm::BasicBlock *Block2, const llvm::Twine &Name="")
bool isEmptyField(ASTContext &Context, const FieldDecl *FD, bool AllowArrays, bool AsIfNoUniqueAddr=false)
isEmptyField - Return true iff a the field is "empty", that is it is an unnamed bit-field or an (arra...
llvm::Value * emitRoundPointerUpToAlignment(CodeGenFunction &CGF, llvm::Value *Ptr, CharUnits Align)
bool isAggregateTypeForABI(QualType T)
std::unique_ptr< TargetCodeGenInfo > createAArch64TargetCodeGenInfo(CodeGenModule &CGM, AArch64ABIKind Kind)
QualType useFirstFieldIfTransparentUnion(QualType Ty)
Pass transparent unions as if they were the type of the first element.
std::unique_ptr< TargetCodeGenInfo > createWindowsAArch64TargetCodeGenInfo(CodeGenModule &CGM, AArch64ABIKind K)
bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, bool AsIfNoUniqueAddr=false)
isEmptyRecord - Return true iff a structure contains only empty fields.
std::unique_ptr< TargetCodeGenInfo > createWinX86_64TargetCodeGenInfo(CodeGenModule &CGM, X86AVXABILevel AVXLevel)
@ Address
A pointer to a ValueDecl.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
const FunctionProtoType * T
@ Type
The name was classified as a type.
U cast(CodeGen::Address addr)
bool IsArmStreamingFunction(const FunctionDecl *FD, bool IncludeLocallyStreaming)
Returns whether the given FunctionDecl has an __arm[_locally]_streaming attribute.
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 uint8_t
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::IntegerType * Int32Ty