10#include "TargetInfo.h"
14#include "llvm/TargetParser/AArch64TargetParser.h"
25class AArch64ABIInfo :
public ABIInfo {
28 std::unique_ptr<TargetCodeGenInfo> WinX86_64CodegenInfo;
32 : ABIInfo(CGM.getTypes()),
Kind(
Kind) {
33 if (getTarget().
getTriple().isWindowsArm64EC()) {
34 WinX86_64CodegenInfo =
39 bool isSoftFloat()
const {
return Kind == AArch64ABIKind::AAPCSSoft; }
43 bool isDarwinPCS()
const {
return Kind == AArch64ABIKind::DarwinPCS; }
47 bool IsNamedArg,
unsigned CallingConvention,
48 unsigned &NSRN,
unsigned &NPRN)
const;
49 llvm::Type *convertFixedToScalableVectorType(
const VectorType *VT)
const;
50 ABIArgInfo coerceIllegalVector(QualType Ty,
unsigned &NSRN,
51 unsigned &NPRN)
const;
52 ABIArgInfo coerceAndExpandPureScalableAggregate(
53 QualType Ty,
bool IsNamedArg,
unsigned NVec,
unsigned NPred,
54 const SmallVectorImpl<llvm::Type *> &UnpaddedCoerceToSeq,
unsigned &NSRN,
55 unsigned &NPRN)
const;
56 bool isHomogeneousAggregateBaseType(QualType Ty)
const override;
57 bool isHomogeneousAggregateSmallEnough(
const Type *Ty,
58 uint64_t Members)
const override;
59 bool isZeroLengthBitfieldPermittedInHomogeneousAggregate()
const override;
61 bool isIllegalVectorType(QualType Ty)
const;
63 bool passAsAggregateType(QualType Ty)
const;
64 bool passAsPureScalableType(QualType Ty,
unsigned &NV,
unsigned &NP,
65 SmallVectorImpl<llvm::Type *> &CoerceToSeq)
const;
67 void flattenType(llvm::Type *Ty,
68 SmallVectorImpl<llvm::Type *> &Flattened)
const;
70 void computeInfo(CGFunctionInfo &FI)
const override {
76 unsigned NSRN = 0, NPRN = 0;
78 const bool IsNamedArg =
86 RValue EmitDarwinVAArg(Address VAListAddr, QualType Ty, CodeGenFunction &CGF,
87 AggValueSlot Slot)
const;
89 RValue EmitAAPCSVAArg(Address VAListAddr, QualType Ty, CodeGenFunction &CGF,
92 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
93 AggValueSlot Slot)
const override {
96 llvm::report_fatal_error(
"Passing SVE types to variadic functions is "
97 "currently not supported");
99 return Kind == AArch64ABIKind::Win64
100 ? EmitMSVAArg(CGF, VAListAddr, Ty, Slot)
101 : isDarwinPCS() ? EmitDarwinVAArg(VAListAddr, Ty, CGF, Slot)
102 : EmitAAPCSVAArg(VAListAddr, Ty, CGF,
Kind, Slot);
105 RValue EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
106 AggValueSlot Slot)
const override;
108 bool allowBFloatArgsAndRet()
const override {
109 return getTarget().hasBFloat16Type();
113 void appendAttributeMangling(TargetClonesAttr *Attr,
unsigned Index,
114 raw_ostream &Out)
const override;
115 void appendAttributeMangling(StringRef AttrStr,
116 raw_ostream &Out)
const override;
121 explicit AArch64SwiftABIInfo(CodeGenTypes &CGT)
122 : SwiftABIInfo(CGT,
true) {}
125 unsigned NumElts)
const override;
131 : TargetCodeGenInfo(std::make_unique<AArch64ABIInfo>(CGM,
Kind)) {
132 SwiftInfo = std::make_unique<AArch64SwiftABIInfo>(CGM.
getTypes());
135 StringRef getARCRetainAutoreleasedReturnValueMarker()
const override {
136 return "mov\tfp, fp\t\t// marker for objc_retainAutoreleaseReturnValue";
139 int getDwarfEHStackPointer(CodeGen::CodeGenModule &M)
const override {
143 bool doesReturnSlotInterfereWithArgs()
const override {
return false; }
145 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
146 CodeGen::CodeGenModule &CGM)
const override {
147 auto *
Fn = dyn_cast<llvm::Function>(GV);
151 const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
152 TargetInfo::BranchProtectionInfo BPI(CGM.
getLangOpts());
154 if (FD && FD->hasAttr<TargetAttr>()) {
155 const auto *TA = FD->getAttr<TargetAttr>();
156 ParsedTargetAttr Attr =
158 if (!Attr.BranchProtection.empty()) {
162 assert(
Error.empty());
165 setBranchProtectionFnAttributes(BPI, *Fn);
169 bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF,
170 llvm::Type *Ty)
const override {
172 auto *ST = dyn_cast<llvm::StructType>(Ty);
173 if (ST && ST->getNumElements() == 1) {
174 auto *AT = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
175 if (AT && AT->getNumElements() == 8 &&
176 AT->getElementType()->isIntegerTy(64))
183 void checkFunctionABI(CodeGenModule &CGM,
184 const FunctionDecl *
Decl)
const override;
186 void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc,
187 const FunctionDecl *Caller,
188 const FunctionDecl *Callee,
const CallArgList &Args,
189 QualType ReturnType)
const override;
191 bool wouldInliningViolateFunctionCallABI(
192 const FunctionDecl *Caller,
const FunctionDecl *Callee)
const override;
197 void checkFunctionCallABIStreaming(CodeGenModule &CGM, SourceLocation CallLoc,
198 const FunctionDecl *Caller,
199 const FunctionDecl *Callee)
const;
202 void checkFunctionCallABISoftFloat(CodeGenModule &CGM, SourceLocation CallLoc,
203 const FunctionDecl *Caller,
204 const FunctionDecl *Callee,
205 const CallArgList &Args,
206 QualType ReturnType)
const;
209class WindowsAArch64TargetCodeGenInfo :
public AArch64TargetCodeGenInfo {
211 WindowsAArch64TargetCodeGenInfo(CodeGenModule &CGM,
AArch64ABIKind K)
212 : AArch64TargetCodeGenInfo(CGM, K) {}
214 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
215 CodeGen::CodeGenModule &CGM)
const override;
217 void getDependentLibraryOption(llvm::StringRef Lib,
218 llvm::SmallString<24> &Opt)
const override {
219 Opt =
"/DEFAULTLIB:" + qualifyWindowsLibrary(Lib);
222 void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef
Value,
223 llvm::SmallString<32> &Opt)
const override {
224 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
228void WindowsAArch64TargetCodeGenInfo::setTargetAttributes(
230 AArch64TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
231 if (GV->isDeclaration())
233 addStackProbeTargetAttributes(D, GV, CGM);
238AArch64ABIInfo::convertFixedToScalableVectorType(
const VectorType *VT)
const {
241 if (VT->
getVectorKind() == VectorKind::SveFixedLengthPredicate) {
243 BuiltinType::UChar &&
244 "unexpected builtin type for SVE predicate!");
245 return llvm::ScalableVectorType::get(llvm::Type::getInt1Ty(getVMContext()),
251 switch (BT->getKind()) {
253 llvm_unreachable(
"unexpected builtin type for SVE vector!");
255 case BuiltinType::SChar:
256 case BuiltinType::UChar:
257 case BuiltinType::MFloat8:
258 return llvm::ScalableVectorType::get(
259 llvm::Type::getInt8Ty(getVMContext()), 16);
261 case BuiltinType::Short:
262 case BuiltinType::UShort:
263 return llvm::ScalableVectorType::get(
264 llvm::Type::getInt16Ty(getVMContext()), 8);
266 case BuiltinType::Int:
267 case BuiltinType::UInt:
268 return llvm::ScalableVectorType::get(
269 llvm::Type::getInt32Ty(getVMContext()), 4);
271 case BuiltinType::Long:
272 case BuiltinType::ULong:
273 return llvm::ScalableVectorType::get(
274 llvm::Type::getInt64Ty(getVMContext()), 2);
276 case BuiltinType::Half:
277 return llvm::ScalableVectorType::get(
278 llvm::Type::getHalfTy(getVMContext()), 8);
280 case BuiltinType::Float:
281 return llvm::ScalableVectorType::get(
282 llvm::Type::getFloatTy(getVMContext()), 4);
284 case BuiltinType::Double:
285 return llvm::ScalableVectorType::get(
286 llvm::Type::getDoubleTy(getVMContext()), 2);
288 case BuiltinType::BFloat16:
289 return llvm::ScalableVectorType::get(
290 llvm::Type::getBFloatTy(getVMContext()), 8);
294 llvm_unreachable(
"expected fixed-length SVE vector");
297ABIArgInfo AArch64ABIInfo::coerceIllegalVector(QualType Ty,
unsigned &NSRN,
298 unsigned &NPRN)
const {
301 const auto *VT = Ty->
castAs<VectorType>();
302 if (VT->
getVectorKind() == VectorKind::SveFixedLengthPredicate) {
305 BuiltinType::UChar &&
306 "unexpected builtin type for SVE predicate!");
307 NPRN = std::min(NPRN + 1, 4u);
309 llvm::Type::getInt1Ty(getVMContext()), 16));
313 NSRN = std::min(NSRN + 1, 8u);
319 if ((isAndroid() || isOHOSFamily()) && (Size <= 16)) {
320 llvm::Type *ResType = llvm::Type::getInt16Ty(getVMContext());
324 llvm::Type *ResType = llvm::Type::getInt32Ty(getVMContext());
328 NSRN = std::min(NSRN + 1, 8u);
330 llvm::FixedVectorType::get(llvm::Type::getInt32Ty(getVMContext()), 2);
334 NSRN = std::min(NSRN + 1, 8u);
336 llvm::FixedVectorType::get(llvm::Type::getInt32Ty(getVMContext()), 4);
340 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
344ABIArgInfo AArch64ABIInfo::coerceAndExpandPureScalableAggregate(
345 QualType Ty,
bool IsNamedArg,
unsigned NVec,
unsigned NPred,
346 const SmallVectorImpl<llvm::Type *> &UnpaddedCoerceToSeq,
unsigned &NSRN,
347 unsigned &NPRN)
const {
348 if (!IsNamedArg || NSRN + NVec > 8 || NPRN + NPred > 4)
349 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
358 llvm::Type *UnpaddedCoerceToType =
359 UnpaddedCoerceToSeq.size() == 1
360 ? UnpaddedCoerceToSeq[0]
361 : llvm::StructType::get(CGT.getLLVMContext(), UnpaddedCoerceToSeq,
364 SmallVector<llvm::Type *> CoerceToSeq;
365 flattenType(CGT.ConvertType(Ty), CoerceToSeq);
367 llvm::StructType::get(CGT.getLLVMContext(), CoerceToSeq,
false);
372ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty,
bool IsVariadicFn,
374 unsigned CallingConvention,
376 unsigned &NPRN)
const {
379 if (IsVariadicFn && getTarget().
getTriple().isWindowsArm64EC()) {
382 return WinX86_64CodegenInfo->getABIInfo().classifyArgForArm64ECVarArg(
387 if (isIllegalVectorType(Ty))
388 return coerceIllegalVector(Ty, NSRN, NPRN);
390 if (!passAsAggregateType(Ty)) {
393 Ty = ED->getIntegerType();
395 if (
const auto *EIT = Ty->
getAs<BitIntType>())
396 if (EIT->getNumBits() > 128)
397 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
401 NSRN = std::min(NSRN + 1, 8u);
402 else if (
const auto *BT = Ty->
getAs<BuiltinType>()) {
403 if (BT->isFloatingPoint())
404 NSRN = std::min(NSRN + 1, 8u);
406 switch (BT->getKind()) {
407 case BuiltinType::SveBool:
408 case BuiltinType::SveCount:
409 NPRN = std::min(NPRN + 1, 4u);
411 case BuiltinType::SveBoolx2:
412 NPRN = std::min(NPRN + 2, 4u);
414 case BuiltinType::SveBoolx4:
415 NPRN = std::min(NPRN + 4, 4u);
417 case BuiltinType::MFloat8:
418 NSRN = std::min(NSRN + 1, 8u);
421 if (BT->isSVESizelessBuiltinType())
423 NSRN + getContext().getBuiltinVectorTypeInfo(BT).NumVectors,
429 return (isPromotableIntegerTypeForABI(Ty) && isDarwinPCS()
437 return getNaturalAlignIndirect(
438 Ty, getDataLayout().getAllocaAddrSpace(),
453 if (!getContext().getLangOpts().
CPlusPlus || isDarwinPCS())
466 bool IsWin64 =
Kind == AArch64ABIKind::Win64 ||
467 CallingConvention == llvm::CallingConv::Win64;
468 bool IsWinVariadic = IsWin64 && IsVariadicFn;
471 if (!IsWinVariadic && isHomogeneousAggregate(Ty, Base, Members)) {
472 NSRN = std::min(NSRN + Members,
uint64_t(8));
473 if (Kind != AArch64ABIKind::AAPCS)
475 llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members));
480 getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity();
481 Align = (Align >= 16) ? 16 : 8;
483 llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members), 0,
484 nullptr,
true, Align);
489 if (Kind == AArch64ABIKind::AAPCS) {
490 unsigned NVec = 0, NPred = 0;
491 SmallVector<llvm::Type *> UnpaddedCoerceToSeq;
492 if (passAsPureScalableType(Ty, NVec, NPred, UnpaddedCoerceToSeq) &&
494 return coerceAndExpandPureScalableAggregate(
495 Ty, IsNamedArg, NVec, NPred, UnpaddedCoerceToSeq, NSRN, NPRN);
501 if (Kind == AArch64ABIKind::AAPCS) {
502 Alignment = getContext().getTypeUnadjustedAlign(Ty);
503 Alignment = Alignment < 128 ? 64 : 128;
506 std::max(getContext().getTypeAlign(Ty),
507 (
unsigned)getTarget().getPointerWidth(LangAS::Default));
509 if (Size < 64 && getDataLayout().isLittleEndian() && !isDarwinPCS())
511 llvm::IntegerType::get(getVMContext(), Size));
513 Size = llvm::alignTo(Size, Alignment);
518 auto ContainsOnlyPointers = [&](
const auto &
Self, QualType Ty) {
524 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
525 for (
const auto &I : CXXRD->bases())
529 return all_of(RD->fields(), [&](FieldDecl *FD) {
530 QualType FDTy = FD->getType();
531 if (FDTy->isArrayType())
532 FDTy = getContext().getBaseElementType(FDTy);
533 return (FDTy->isPointerOrReferenceType() &&
534 getContext().getTypeSize(FDTy) == 64 &&
535 !FDTy->getPointeeType().hasAddressSpace()) ||
542 llvm::Type *BaseTy = llvm::Type::getIntNTy(getVMContext(), Alignment);
543 if ((Size == 64 || Size == 128) && Alignment == 64 &&
544 ContainsOnlyPointers(ContainsOnlyPointers, Ty))
545 BaseTy = llvm::PointerType::getUnqual(getVMContext());
547 Size == Alignment ? BaseTy
548 : llvm::ArrayType::get(BaseTy, Size / Alignment));
551 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
555ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy,
556 bool IsVariadicFn)
const {
560 if (
const auto *VT = RetTy->
getAs<VectorType>()) {
562 VT->
getVectorKind() == VectorKind::SveFixedLengthPredicate) {
563 unsigned NSRN = 0, NPRN = 0;
564 return coerceIllegalVector(RetTy, NSRN, NPRN);
569 if (RetTy->
isVectorType() && getContext().getTypeSize(RetTy) > 128)
570 return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace());
572 if (!passAsAggregateType(RetTy)) {
575 RetTy = ED->getIntegerType();
577 if (
const auto *EIT = RetTy->
getAs<BitIntType>())
578 if (EIT->getNumBits() > 128)
579 return getNaturalAlignIndirect(RetTy,
580 getDataLayout().getAllocaAddrSpace());
582 return (isPromotableIntegerTypeForABI(RetTy) && isDarwinPCS()
594 if (isHomogeneousAggregate(RetTy, Base, Members) &&
595 !(getTarget().
getTriple().getArch() == llvm::Triple::aarch64_32 &&
603 if (Kind == AArch64ABIKind::AAPCS) {
604 unsigned NSRN = 0, NPRN = 0;
605 unsigned NVec = 0, NPred = 0;
606 SmallVector<llvm::Type *> UnpaddedCoerceToSeq;
607 if (passAsPureScalableType(RetTy, NVec, NPred, UnpaddedCoerceToSeq) &&
609 return coerceAndExpandPureScalableAggregate(
610 RetTy,
true, NVec, NPred, UnpaddedCoerceToSeq, NSRN,
616 if (Size <= 64 && getDataLayout().isLittleEndian()) {
624 llvm::IntegerType::get(getVMContext(), Size));
627 unsigned Alignment = getContext().getTypeAlign(RetTy);
628 Size = llvm::alignTo(Size, 64);
632 if (Alignment < 128 && Size == 128) {
633 llvm::Type *BaseTy = llvm::Type::getInt64Ty(getVMContext());
639 return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace());
643bool AArch64ABIInfo::isIllegalVectorType(QualType Ty)
const {
644 if (
const VectorType *VT = Ty->
getAs<VectorType>()) {
656 if (!llvm::isPowerOf2_32(NumElements))
661 llvm::Triple Triple = getTarget().getTriple();
662 if (Triple.getArch() == llvm::Triple::aarch64_32 &&
663 Triple.isOSBinFormatMachO())
666 return Size != 64 && (
Size != 128 || NumElements == 1);
671bool AArch64SwiftABIInfo::isLegalVectorType(CharUnits VectorSize,
673 unsigned NumElts)
const {
674 if (!llvm::isPowerOf2_32(NumElts))
682bool AArch64ABIInfo::isHomogeneousAggregateBaseType(QualType Ty)
const {
692 if (
const BuiltinType *BT = Ty->
getAs<BuiltinType>()) {
693 if (BT->isFloatingPoint())
695 }
else if (
const VectorType *VT = Ty->
getAs<VectorType>()) {
697 Kind == VectorKind::SveFixedLengthData ||
698 Kind == VectorKind::SveFixedLengthPredicate)
701 unsigned VecSize = getContext().getTypeSize(VT);
702 if (VecSize == 64 || VecSize == 128)
708bool AArch64ABIInfo::isHomogeneousAggregateSmallEnough(
const Type *Base,
709 uint64_t Members)
const {
713bool AArch64ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate()
723bool AArch64ABIInfo::passAsAggregateType(QualType Ty)
const {
725 const auto *BT = Ty->
castAs<BuiltinType>();
726 return !BT->isSVECount() &&
727 getContext().getBuiltinVectorTypeInfo(BT).NumVectors > 1;
740bool AArch64ABIInfo::passAsPureScalableType(
741 QualType Ty,
unsigned &NVec,
unsigned &NPred,
742 SmallVectorImpl<llvm::Type *> &CoerceToSeq)
const {
743 if (
const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
748 unsigned NV = 0, NP = 0;
749 SmallVector<llvm::Type *> EltCoerceToSeq;
750 if (!passAsPureScalableType(AT->getElementType(), NV, NP, EltCoerceToSeq))
753 if (CoerceToSeq.size() + NElt * EltCoerceToSeq.size() > 12)
756 for (uint64_t I = 0; I < NElt; ++I)
757 llvm::append_range(CoerceToSeq, EltCoerceToSeq);
771 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
776 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
777 for (
const auto &I : CXXRD->bases()) {
780 if (!passAsPureScalableType(I.getType(), NVec, NPred, CoerceToSeq))
786 for (
const auto *FD : RD->
fields()) {
787 QualType FT = FD->getType();
790 if (!passAsPureScalableType(FT, NVec, NPred, CoerceToSeq))
797 if (
const auto *VT = Ty->
getAs<VectorType>()) {
798 if (VT->
getVectorKind() == VectorKind::SveFixedLengthPredicate) {
800 if (CoerceToSeq.size() + 1 > 12)
802 CoerceToSeq.push_back(convertFixedToScalableVectorType(VT));
808 if (CoerceToSeq.size() + 1 > 12)
810 CoerceToSeq.push_back(convertFixedToScalableVectorType(VT));
821 switch (Ty->
castAs<BuiltinType>()->getKind()) {
822#define SVE_VECTOR_TYPE(Name, MangledName, Id, SingletonId) \
823 case BuiltinType::Id: \
824 isPredicate = false; \
826#define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId) \
827 case BuiltinType::Id: \
828 isPredicate = true; \
830#include "clang/Basic/AArch64ACLETypes.def"
835 ASTContext::BuiltinVectorTypeInfo Info =
838 "Expected 1, 2, 3 or 4 vectors!");
844 ? llvm::Type::getInt8Ty(getVMContext())
845 : CGT.ConvertType(Info.ElementType);
846 auto *VTy = llvm::ScalableVectorType::get(EltTy, Info.
EC.getKnownMinValue());
848 if (CoerceToSeq.size() + Info.
NumVectors > 12)
850 std::fill_n(std::back_inserter(CoerceToSeq), Info.
NumVectors, VTy);
858void AArch64ABIInfo::flattenType(
859 llvm::Type *Ty, SmallVectorImpl<llvm::Type *> &Flattened)
const {
862 Flattened.push_back(Ty);
866 if (
const auto *AT = dyn_cast<llvm::ArrayType>(Ty)) {
867 uint64_t NElt = AT->getNumElements();
871 SmallVector<llvm::Type *> EltFlattened;
872 flattenType(AT->getElementType(), EltFlattened);
874 for (uint64_t I = 0; I < NElt; ++I)
875 llvm::append_range(Flattened, EltFlattened);
879 if (
const auto *ST = dyn_cast<llvm::StructType>(Ty)) {
880 for (
auto *ET : ST->elements())
881 flattenType(ET, Flattened);
885 Flattened.push_back(Ty);
888RValue AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr, QualType Ty,
890 AggValueSlot Slot)
const {
894 unsigned NSRN = 0, NPRN = 0;
906 BaseTy = llvm::PointerType::getUnqual(BaseTy->getContext());
910 unsigned NumRegs = 1;
911 if (llvm::ArrayType *ArrTy = dyn_cast<llvm::ArrayType>(BaseTy)) {
912 BaseTy = ArrTy->getElementType();
913 NumRegs = ArrTy->getNumElements();
916 !isSoftFloat() && (BaseTy->isFloatingPointTy() || BaseTy->isVectorTy());
934 CharUnits TySize = getContext().getTypeSizeInChars(Ty);
935 CharUnits TyAlign = getContext().getTypeUnadjustedAlignInChars(Ty);
938 llvm::Value *reg_offs =
nullptr;
940 int RegSize = IsIndirect ? 8 : TySize.
getQuantity();
946 RegSize = llvm::alignTo(RegSize, 8);
952 RegSize = 16 * NumRegs;
963 llvm::Value *UsingStack =
nullptr;
964 UsingStack = CGF.
Builder.CreateICmpSGE(
965 reg_offs, llvm::ConstantInt::get(CGF.
Int32Ty, 0));
967 CGF.
Builder.CreateCondBr(UsingStack, OnStackBlock, MaybeRegBlock);
976 if (!IsFPR && !IsIndirect && TyAlign.
getQuantity() > 8) {
979 reg_offs = CGF.
Builder.CreateAdd(
980 reg_offs, llvm::ConstantInt::get(CGF.
Int32Ty, Align - 1),
982 reg_offs = CGF.
Builder.CreateAnd(
983 reg_offs, llvm::ConstantInt::getSigned(CGF.
Int32Ty, -Align),
991 llvm::Value *NewOffset =
nullptr;
992 NewOffset = CGF.
Builder.CreateAdd(
993 reg_offs, llvm::ConstantInt::get(CGF.
Int32Ty, RegSize),
"new_reg_offs");
998 llvm::Value *InRegs =
nullptr;
999 InRegs = CGF.
Builder.CreateICmpSLE(
1000 NewOffset, llvm::ConstantInt::get(CGF.
Int32Ty, 0),
"inreg");
1002 CGF.
Builder.CreateCondBr(InRegs, InRegBlock, OnStackBlock);
1012 llvm::Value *reg_top =
nullptr;
1024 MemTy = llvm::PointerType::getUnqual(MemTy->getContext());
1029 bool IsHFA = isHomogeneousAggregate(Ty, Base, NumMembers);
1030 if (IsHFA && NumMembers > 1) {
1035 assert(!IsIndirect &&
"Homogeneous aggregates should be passed directly");
1036 auto BaseTyInfo = getContext().getTypeInfoInChars(QualType(Base, 0));
1037 llvm::Type *BaseTy = CGF.
ConvertType(QualType(Base, 0));
1038 llvm::Type *HFATy = llvm::ArrayType::get(BaseTy, NumMembers);
1040 std::max(TyAlign, BaseTyInfo.Align));
1045 BaseTyInfo.Width.getQuantity() < 16)
1046 Offset = 16 - BaseTyInfo.Width.getQuantity();
1048 for (
unsigned i = 0; i < NumMembers; ++i) {
1065 CharUnits SlotSize = BaseAddr.getAlignment();
1068 TySize < SlotSize) {
1069 CharUnits Offset = SlotSize - TySize;
1096 CharUnits StackSize;
1098 StackSize = StackSlotSize;
1100 StackSize = TySize.
alignTo(StackSlotSize);
1104 CGF.
Int8Ty, OnStackPtr, StackSizeC,
"new_stack");
1110 TySize < StackSlotSize) {
1111 CharUnits Offset = StackSlotSize - TySize;
1125 OnStackBlock,
"vaargs.addr");
1138RValue AArch64ABIInfo::EmitDarwinVAArg(Address VAListAddr, QualType Ty,
1139 CodeGenFunction &CGF,
1140 AggValueSlot Slot)
const {
1150 uint64_t PointerSize = getTarget().getPointerWidth(LangAS::Default) / 8;
1159 auto TyInfo = getContext().getTypeInfoInChars(Ty);
1163 bool IsIndirect =
false;
1164 if (TyInfo.Width.getQuantity() > 16) {
1167 IsIndirect = !isHomogeneousAggregate(Ty, Base, Members);
1174RValue AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
1175 QualType Ty, AggValueSlot Slot)
const {
1176 bool AllowHigherAlign =
false;
1177 bool IsIndirect =
false;
1179 if (getTarget().
getTriple().isWindowsArm64EC()) {
1182 uint64_t Width = getContext().getTypeSize(Ty);
1183 IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
1187 AllowHigherAlign =
true;
1202 const StringRef ABIName,
1203 const AArch64ABIInfo &
ABIInfo,
1206 const Type *HABase =
nullptr;
1207 uint64_t HAMembers = 0;
1210 Diags.
Report(loc, diag::err_target_unsupported_type_for_abi)
1218void AArch64TargetCodeGenInfo::checkFunctionABI(
1219 CodeGenModule &CGM,
const FunctionDecl *FuncDecl)
const {
1220 const AArch64ABIInfo &ABIInfo = getABIInfo<AArch64ABIInfo>();
1221 const TargetInfo &TI = ABIInfo.getContext().getTargetInfo();
1223 if (!TI.
hasFeature(
"fp") && !ABIInfo.isSoftFloat()) {
1227 for (ParmVarDecl *PVD : FuncDecl->
parameters()) {
1234void AArch64TargetCodeGenInfo::checkFunctionCallABIStreaming(
1235 CodeGenModule &CGM, SourceLocation CallLoc,
const FunctionDecl *Caller,
1236 const FunctionDecl *Callee)
const {
1237 if (!Caller || !Callee || !
Callee->hasAttr<AlwaysInlineAttr>())
1244 CodeGenUtils::ArmSMEInlinability::IncompatibleStreamingModes) !=
1245 CodeGenUtils::ArmSMEInlinability::Ok)
1249 CodeGenUtils::ArmSMEInlinability::ErrorIncompatibleStreamingModes) ==
1251 ErrorIncompatibleStreamingModes
1252 ? diag::err_function_always_inline_attribute_mismatch
1253 : diag::warn_function_always_inline_attribute_mismatch)
1257 CodeGenUtils::ArmSMEInlinability::ErrorCalleeRequiresNewZA) ==
1258 CodeGenUtils::ArmSMEInlinability::ErrorCalleeRequiresNewZA)
1259 CGM.
getDiags().
Report(CallLoc, diag::err_function_always_inline_new_za)
1260 <<
Callee->getDeclName();
1263 CodeGenUtils::ArmSMEInlinability::ErrorCalleeRequiresNewZT0) ==
1264 CodeGenUtils::ArmSMEInlinability::ErrorCalleeRequiresNewZT0)
1265 CGM.
getDiags().
Report(CallLoc, diag::err_function_always_inline_new_zt0)
1266 <<
Callee->getDeclName();
1272void AArch64TargetCodeGenInfo::checkFunctionCallABISoftFloat(
1273 CodeGenModule &CGM, SourceLocation CallLoc,
const FunctionDecl *Caller,
1274 const FunctionDecl *Callee,
const CallArgList &Args,
1275 QualType ReturnType)
const {
1276 const AArch64ABIInfo &ABIInfo = getABIInfo<AArch64ABIInfo>();
1277 const TargetInfo &TI = ABIInfo.getContext().getTargetInfo();
1279 if (!Caller || TI.
hasFeature(
"fp") || ABIInfo.isSoftFloat())
1283 Callee ? Callee : Caller, CallLoc);
1285 for (
const CallArg &Arg : Args)
1287 Callee ? Callee : Caller, CallLoc);
1290void AArch64TargetCodeGenInfo::checkFunctionCallABI(CodeGenModule &CGM,
1291 SourceLocation CallLoc,
1292 const FunctionDecl *Caller,
1293 const FunctionDecl *Callee,
1294 const CallArgList &Args,
1295 QualType ReturnType)
const {
1296 checkFunctionCallABIStreaming(CGM, CallLoc, Caller, Callee);
1297 checkFunctionCallABISoftFloat(CGM, CallLoc, Caller, Callee, Args, ReturnType);
1300bool AArch64TargetCodeGenInfo::wouldInliningViolateFunctionCallABI(
1301 const FunctionDecl *Caller,
const FunctionDecl *Callee)
const {
1302 return Caller &&
Callee &&
1304 CodeGenUtils::ArmSMEInlinability::Ok;
1307void AArch64ABIInfo::appendAttributeMangling(TargetClonesAttr *Attr,
1309 raw_ostream &Out)
const {
1310 appendAttributeMangling(Attr->getFeatureStr(Index), Out);
1313void AArch64ABIInfo::appendAttributeMangling(StringRef AttrStr,
1314 raw_ostream &Out)
const {
1315 if (AttrStr ==
"default") {
1321 SmallVector<StringRef, 8> Features;
1322 AttrStr.split(Features,
"+");
1323 for (
auto &Feat : Features)
1326 llvm::sort(Features, [](
const StringRef LHS,
const StringRef RHS) {
1327 return LHS.compare(RHS) < 0;
1330 llvm::SmallDenseSet<StringRef, 8> UniqueFeats;
1331 for (
auto &Feat : Features)
1332 if (getTarget().doesFeatureAffectCodeGen(Feat))
1333 if (
auto Ext = llvm::AArch64::parseFMVExtension(Feat))
1334 if (UniqueFeats.insert(Ext->Name).second)
1335 Out <<
'M' << Ext->Name;
1338std::unique_ptr<TargetCodeGenInfo>
1341 return std::make_unique<AArch64TargetCodeGenInfo>(CGM, Kind);
1344std::unique_ptr<TargetCodeGenInfo>
1347 return std::make_unique<WindowsAArch64TargetCodeGenInfo>(CGM, K);
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
CharUnits alignTo(CharUnits Align) const
Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is a multiple...
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
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.
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
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(const ParsedTargetAttr &Attr, BranchProtectionInfo &BPI, const LangOptions &LO, StringRef &Err) const
Determines whether 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
ArmSMEInlinability
The Arm SME ABI issues that can prevent inlining one function into another.
ArmSMEInlinability getArmSMEInlinability(const FunctionDecl *Caller, const FunctionDecl *Callee)
Determines if there are any Arm SME ABI issues with inlining Callee into Caller.
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'.
U cast(CodeGen::Address addr)
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::IntegerType * Int32Ty