10#include "TargetInfo.h"
21class ARMABIInfo :
public ABIInfo {
23 bool IsFloatABISoftFP;
33 switch (
getTarget().getTriple().getEnvironment()) {
34 case llvm::Triple::Android:
35 case llvm::Triple::EABI:
36 case llvm::Triple::EABIHF:
37 case llvm::Triple::GNUEABI:
38 case llvm::Triple::GNUEABIHF:
39 case llvm::Triple::MuslEABI:
40 case llvm::Triple::MuslEABIHF:
47 bool isEABIHF()
const {
48 switch (
getTarget().getTriple().getEnvironment()) {
49 case llvm::Triple::EABIHF:
50 case llvm::Triple::GNUEABIHF:
51 case llvm::Triple::MuslEABIHF:
66 unsigned functionCallConv)
const;
68 unsigned functionCallConv)
const;
70 uint64_t Members)
const;
72 bool isIllegalVectorType(
QualType Ty)
const;
73 bool containsAnyFP16Vectors(
QualType Ty)
const;
77 uint64_t Members)
const override;
80 bool isEffectivelyAAPCS_VFP(
unsigned callConvention,
bool acceptHalf)
const;
87 llvm::CallingConv::ID getLLVMDefaultCC()
const;
88 llvm::CallingConv::ID getABIDefaultCC()
const;
98 unsigned NumElts)
const override;
105 SwiftInfo = std::make_unique<ARMSwiftABIInfo>(CGT);
113 return "mov\tr7, r7\t\t// marker for objc_retainAutoreleaseReturnValue";
117 llvm::Value *
Address)
const override {
118 llvm::Value *Four8 = llvm::ConstantInt::get(CGF.
Int8Ty, 4);
126 if (getABIInfo<ARMABIInfo>().isEABI())
133 if (GV->isDeclaration())
138 auto *
Fn = cast<llvm::Function>(GV);
140 if (
const auto *TA = FD->
getAttr<TargetAttr>()) {
143 if (!
Attr.BranchProtection.empty()) {
149 Arch, BPI, DiagMsg)) {
152 diag::warn_target_unsupported_branch_protection_attribute)
156 }
else if (CGM.
getLangOpts().BranchTargetEnforcement ||
164 diag::warn_target_unsupported_branch_protection_attribute)
173 const ARMInterruptAttr *
Attr = FD->
getAttr<ARMInterruptAttr>();
178 switch (
Attr->getInterrupt()) {
179 case ARMInterruptAttr::Generic:
Kind =
"";
break;
180 case ARMInterruptAttr::IRQ:
Kind =
"IRQ";
break;
181 case ARMInterruptAttr::FIQ:
Kind =
"FIQ";
break;
182 case ARMInterruptAttr::SWI:
Kind =
"SWI";
break;
183 case ARMInterruptAttr::ABORT:
Kind =
"ABORT";
break;
184 case ARMInterruptAttr::UNDEF:
Kind =
"UNDEF";
break;
187 Fn->addFnAttr(
"interrupt", Kind);
189 ARMABIKind ABI = getABIInfo<ARMABIInfo>().getABIKind();
190 if (ABI == ARMABIKind::APCS)
196 llvm::AttrBuilder B(
Fn->getContext());
197 B.addStackAlignmentAttr(8);
202class WindowsARMTargetCodeGenInfo :
public ARMTargetCodeGenInfo {
205 : ARMTargetCodeGenInfo(CGT, K) {}
207 void setTargetAttributes(
const Decl *
D, llvm::GlobalValue *GV,
210 void getDependentLibraryOption(llvm::StringRef Lib,
212 Opt =
"/DEFAULTLIB:" + qualifyWindowsLibrary(Lib);
215 void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef
Value,
217 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
221void WindowsARMTargetCodeGenInfo::setTargetAttributes(
223 ARMTargetCodeGenInfo::setTargetAttributes(
D, GV, CGM);
224 if (GV->isDeclaration())
226 addStackProbeTargetAttributes(
D, GV, CGM);
244 llvm::CallingConv::ID cc = getRuntimeCC();
245 if (cc != llvm::CallingConv::C)
250llvm::CallingConv::ID ARMABIInfo::getLLVMDefaultCC()
const {
252 if (isEABIHF() || getTarget().getTriple().isWatchABI())
253 return llvm::CallingConv::ARM_AAPCS_VFP;
255 return llvm::CallingConv::ARM_AAPCS;
257 return llvm::CallingConv::ARM_APCS;
262llvm::CallingConv::ID ARMABIInfo::getABIDefaultCC()
const {
263 switch (getABIKind()) {
264 case ARMABIKind::APCS:
265 return llvm::CallingConv::ARM_APCS;
266 case ARMABIKind::AAPCS:
267 return llvm::CallingConv::ARM_AAPCS;
268 case ARMABIKind::AAPCS_VFP:
269 return llvm::CallingConv::ARM_AAPCS_VFP;
270 case ARMABIKind::AAPCS16_VFP:
271 return llvm::CallingConv::ARM_AAPCS_VFP;
273 llvm_unreachable(
"bad ABI kind");
276void ARMABIInfo::setCCs() {
277 assert(getRuntimeCC() == llvm::CallingConv::C);
281 llvm::CallingConv::ID abiCC = getABIDefaultCC();
282 if (abiCC != getLLVMDefaultCC())
289 llvm::Type *ResType =
290 llvm::Type::getInt32Ty(getVMContext());
293 if (Size == 64 || Size == 128) {
294 auto *ResType = llvm::FixedVectorType::get(
295 llvm::Type::getInt32Ty(getVMContext()), Size / 32);
298 return getNaturalAlignIndirect(Ty,
false);
303 uint64_t Members)
const {
304 assert(
Base &&
"Base class should be set for homogeneous aggregate");
308 if (!getTarget().hasLegalHalfType() && containsAnyFP16Vectors(Ty)) {
310 auto *NewVecTy = llvm::FixedVectorType::get(
311 llvm::Type::getInt32Ty(getVMContext()), Size / 32);
312 llvm::Type *Ty = llvm::ArrayType::get(NewVecTy, Members);
317 if (getABIKind() == ARMABIKind::AAPCS ||
318 getABIKind() == ARMABIKind::AAPCS_VFP) {
321 Align = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity();
322 unsigned BaseAlign = getContext().getTypeAlignInChars(
Base).getQuantity();
323 Align = (Align > BaseAlign && Align >= 8) ? 8 : 0;
329 unsigned functionCallConv)
const {
339 !isVariadic && isEffectivelyAAPCS_VFP(functionCallConv,
false);
344 if (isIllegalVectorType(Ty))
345 return coerceIllegalVector(Ty);
350 Ty = EnumTy->getDecl()->getIntegerType();
354 if (EIT->getNumBits() > 64)
355 return getNaturalAlignIndirect(Ty,
true);
374 if (isHomogeneousAggregate(Ty,
Base, Members))
375 return classifyHomogeneousAggregate(Ty,
Base, Members);
376 }
else if (getABIKind() == ARMABIKind::AAPCS16_VFP) {
382 if (isHomogeneousAggregate(Ty,
Base, Members)) {
383 assert(
Base && Members <= 4 &&
"unexpected homogeneous aggregate");
390 if (getABIKind() == ARMABIKind::AAPCS16_VFP &&
405 if (getABIKind() == ARMABIKind::AAPCS_VFP ||
406 getABIKind() == ARMABIKind::AAPCS) {
407 TyAlign = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity();
408 ABIAlign = std::clamp(TyAlign, (uint64_t)4, (uint64_t)8);
410 TyAlign = getContext().getTypeAlignInChars(Ty).getQuantity();
413 assert(getABIKind() != ARMABIKind::AAPCS16_VFP &&
"unexpected byval");
421 if (getTarget().isRenderScriptTarget()) {
431 ElemTy = llvm::Type::getInt32Ty(getVMContext());
432 SizeRegs = (getContext().getTypeSize(Ty) + 31) / 32;
434 ElemTy = llvm::Type::getInt64Ty(getVMContext());
435 SizeRegs = (getContext().getTypeSize(Ty) + 63) / 64;
442 llvm::LLVMContext &VMContext) {
474 if (!RT)
return false;
485 bool HadField =
false;
488 i != e; ++i, ++idx) {
527 unsigned functionCallConv)
const {
531 !isVariadic && isEffectivelyAAPCS_VFP(functionCallConv,
true);
538 if (getContext().getTypeSize(RetTy) > 128)
539 return getNaturalAlignIndirect(RetTy);
542 if ((!getTarget().hasLegalHalfType() &&
543 (VT->getElementType()->isFloat16Type() ||
544 VT->getElementType()->isHalfType())) ||
546 VT->getElementType()->isBFloat16Type()))
547 return coerceIllegalVector(RetTy);
553 RetTy = EnumTy->getDecl()->getIntegerType();
556 if (EIT->getNumBits() > 64)
557 return getNaturalAlignIndirect(RetTy,
false);
564 if (getABIKind() == ARMABIKind::APCS) {
574 getVMContext(), getContext().getTypeSize(RetTy)));
588 return getNaturalAlignIndirect(RetTy);
600 if (isHomogeneousAggregate(RetTy,
Base, Members))
601 return classifyHomogeneousAggregate(RetTy,
Base, Members);
610 if (getTarget().isRenderScriptTarget()) {
613 if (getDataLayout().isBigEndian())
623 }
else if (Size <= 128 && getABIKind() == ARMABIKind::AAPCS16_VFP) {
624 llvm::Type *Int32Ty = llvm::Type::getInt32Ty(getVMContext());
625 llvm::Type *CoerceTy =
626 llvm::ArrayType::get(Int32Ty, llvm::alignTo(Size, 32) / 32);
630 return getNaturalAlignIndirect(RetTy);
634bool ARMABIInfo::isIllegalVectorType(
QualType Ty)
const {
642 if ((!getTarget().hasLegalHalfType() &&
643 (VT->getElementType()->isFloat16Type() ||
644 VT->getElementType()->isHalfType())) ||
646 VT->getElementType()->isBFloat16Type()))
654 unsigned NumElements = VT->getNumElements();
656 if (!llvm::isPowerOf2_32(NumElements) && NumElements != 3)
660 unsigned NumElements = VT->getNumElements();
663 if (!llvm::isPowerOf2_32(NumElements))
673bool ARMABIInfo::containsAnyFP16Vectors(
QualType Ty)
const {
675 uint64_t NElements = AT->getZExtSize();
678 return containsAnyFP16Vectors(AT->getElementType());
683 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
685 return containsAnyFP16Vectors(B.getType());
690 return FD && containsAnyFP16Vectors(FD->getType());
697 return (VT->getElementType()->isFloat16Type() ||
698 VT->getElementType()->isBFloat16Type() ||
699 VT->getElementType()->isHalfType());
704bool ARMSwiftABIInfo::isLegalVectorType(
CharUnits VectorSize, llvm::Type *EltTy,
705 unsigned NumElts)
const {
706 if (!llvm::isPowerOf2_32(NumElts))
708 unsigned size = CGT.
getDataLayout().getTypeStoreSizeInBits(EltTy);
717bool ARMABIInfo::isHomogeneousAggregateBaseType(
QualType Ty)
const {
721 if (BT->getKind() == BuiltinType::Float ||
722 BT->getKind() == BuiltinType::Double ||
723 BT->getKind() == BuiltinType::LongDouble)
726 unsigned VecSize = getContext().getTypeSize(VT);
727 if (VecSize == 64 || VecSize == 128)
733bool ARMABIInfo::isHomogeneousAggregateSmallEnough(
const Type *
Base,
734 uint64_t Members)
const {
738bool ARMABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate()
const {
747bool ARMABIInfo::isEffectivelyAAPCS_VFP(
unsigned callConvention,
748 bool acceptHalf)
const {
750 if (callConvention != llvm::CallingConv::C)
751 return (callConvention == llvm::CallingConv::ARM_AAPCS_VFP);
753 return (getABIKind() == ARMABIKind::AAPCS_VFP) ||
754 (acceptHalf && (getABIKind() == ARMABIKind::AAPCS16_VFP));
765 CharUnits TySize = getContext().getTypeSizeInChars(Ty);
766 CharUnits TyAlignForABI = getContext().getTypeUnadjustedAlignInChars(Ty);
769 bool IsIndirect =
false;
778 getABIKind() == ARMABIKind::AAPCS16_VFP &&
779 !isHomogeneousAggregate(Ty,
Base, Members)) {
786 }
else if (getABIKind() == ARMABIKind::AAPCS_VFP ||
787 getABIKind() == ARMABIKind::AAPCS) {
790 }
else if (getABIKind() == ARMABIKind::AAPCS16_VFP) {
798 TypeInfoChars TyInfo(TySize, TyAlignForABI, AlignRequirementKind::None);
803std::unique_ptr<TargetCodeGenInfo>
805 return std::make_unique<ARMTargetCodeGenInfo>(CGM.
getTypes(), Kind);
808std::unique_ptr<TargetCodeGenInfo>
810 return std::make_unique<WindowsARMTargetCodeGenInfo>(CGM.
getTypes(), K);
static bool isIntegerLikeType(QualType Ty, ASTContext &Context, llvm::LLVMContext &VMContext)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
Attr - This represents one attribute.
A fixed int type of a specified bitwidth.
This class is used for builtin types like 'int'.
Represents a base class of a C++ class.
Represents a C++ struct/union/class.
CharUnits - This is an opaque type for sizes expressed in character units.
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.
std::string FloatABI
The ABI to use for passing floating point arguments.
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
static ABIArgInfo getIgnore()
static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal=true, bool Realign=false, llvm::Type *Padding=nullptr)
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)
ABIInfo - Target specific hooks for defining how a type should be passed or returned from functions.
virtual bool allowBFloatArgsAndRet() const
virtual bool isHomogeneousAggregateBaseType(QualType Ty) const
virtual bool isHomogeneousAggregateSmallEnough(const Type *Base, uint64_t Members) const
const TargetInfo & getTarget() const
virtual RValue EmitVAArg(CodeGen::CodeGenFunction &CGF, CodeGen::Address VAListAddr, QualType Ty, AggValueSlot Slot) const =0
EmitVAArg - Emit the target dependent code to load a value of.
virtual bool isZeroLengthBitfieldPermittedInHomogeneousAggregate() const
virtual void computeInfo(CodeGen::CGFunctionInfo &FI) const =0
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
RecordArgABI
Specify how one should pass an argument of a record type.
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
CGFunctionInfo - Class to encapsulate the information about a function definition.
ABIArgInfo & getReturnInfo()
unsigned getCallingConvention() const
getCallingConvention - Return the user specified calling convention, which has been translated into a...
CanQualType getReturnType() const
MutableArrayRef< ArgInfo > arguments()
void setEffectiveCallingConvention(unsigned Value)
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
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
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
const CodeGenOptions & getCodeGenOpts() const
const llvm::DataLayout & getDataLayout() const
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
Target specific hooks for defining how a type should be passed or returned from functions with one of...
virtual bool isLegalVectorType(CharUnits VectorSize, llvm::Type *EltTy, unsigned NumElts) const
Returns true if the given vector type is legal from Swift's calling convention perspective.
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
virtual unsigned getSizeOfUnwindException() const
Determines the size of struct _Unwind_Exception on this platform, in 8-bit units.
virtual StringRef getARCRetainAutoreleasedReturnValueMarker() const
Retrieve the address of a function to call immediately before calling objc_retainAutoreleasedReturnVa...
static void setBranchProtectionFnAttributes(const TargetInfo::BranchProtectionInfo &BPI, llvm::Function &F)
virtual bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const
Initializes the given DWARF EH register-size table, a char*.
virtual void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const
setTargetAttributes - Provides a convenient hook to handle extra target-specific attributes for the g...
virtual int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const
Determines the DWARF register number for the stack pointer, for exception-handling purposes.
Complex values, per C99 6.2.5p11.
Represents the canonical version of C arrays with a specified constant size.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
Decl - This represents one declaration (or definition), e.g.
SourceLocation getLocation() const
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
Represents a function declaration or definition.
bool hasSignReturnAddress() const
Check if return address signing is enabled.
A (possibly-)qualified type.
Represents a struct/union/class.
bool hasFlexibleArrayMember() const
field_iterator field_end() const
field_range fields() const
field_iterator field_begin() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
TargetOptions & getTargetOpts() const
Retrieve the target options.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
virtual bool isBranchProtectionSupportedArch(StringRef Arch) const
Determine if the Architecture in this TargetInfo supports branch protection.
virtual ParsedTargetAttr parseTargetAttr(StringRef Str) const
virtual bool hasBFloat16Type() const
Determine whether the _BFloat16 type is supported on this target.
virtual bool validateBranchProtection(StringRef Spec, StringRef Arch, BranchProtectionInfo &BPI, StringRef &Err) const
Determine if this TargetInfo supports the given branch protection specification.
std::string CPU
If given, the name of the target CPU to generate code for.
The base class of the type hierarchy.
bool isPointerType() const
bool isAnyComplexType() const
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
const T * getAs() const
Member-template getAs<specific type>'.
Represents a GCC generic vector type.
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to pass a particular type.
std::unique_ptr< TargetCodeGenInfo > createARMTargetCodeGenInfo(CodeGenModule &CGM, ARMABIKind Kind)
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 ...
ABIArgInfo coerceToIntArray(QualType Ty, ASTContext &Context, llvm::LLVMContext &LLVMContext)
bool isAggregateTypeForABI(QualType T)
std::unique_ptr< TargetCodeGenInfo > createWindowsARMTargetCodeGenInfo(CodeGenModule &CGM, ARMABIKind K)
void AssignToArrayRange(CodeGen::CGBuilderTy &Builder, llvm::Value *Array, llvm::Value *Value, unsigned FirstIndex, unsigned LastIndex)
QualType useFirstFieldIfTransparentUnion(QualType Ty)
Pass transparent unions as if they were the type of the first element.
bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, bool AsIfNoUniqueAddr=false)
isEmptyRecord - Return true iff a structure contains only empty fields.
The JSON file list parser is used to communicate input to InstallAPI.
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
Contains information gathered from parsing the contents of TargetAttr.