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())
135 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
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 Fn->addFnAttr(
"branch-target-enforcement",
159 }
else if (CGM.
getLangOpts().BranchTargetEnforcement ||
167 diag::warn_target_unsupported_branch_protection_attribute)
172 const ARMInterruptAttr *
Attr = FD->
getAttr<ARMInterruptAttr>();
177 switch (
Attr->getInterrupt()) {
178 case ARMInterruptAttr::Generic:
Kind =
"";
break;
179 case ARMInterruptAttr::IRQ:
Kind =
"IRQ";
break;
180 case ARMInterruptAttr::FIQ:
Kind =
"FIQ";
break;
181 case ARMInterruptAttr::SWI:
Kind =
"SWI";
break;
182 case ARMInterruptAttr::ABORT:
Kind =
"ABORT";
break;
183 case ARMInterruptAttr::UNDEF:
Kind =
"UNDEF";
break;
186 Fn->addFnAttr(
"interrupt", Kind);
188 ARMABIKind ABI = getABIInfo<ARMABIInfo>().getABIKind();
189 if (ABI == ARMABIKind::APCS)
195 llvm::AttrBuilder B(Fn->getContext());
196 B.addStackAlignmentAttr(8);
201class WindowsARMTargetCodeGenInfo :
public ARMTargetCodeGenInfo {
204 : ARMTargetCodeGenInfo(CGT, K) {}
206 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
209 void getDependentLibraryOption(llvm::StringRef Lib,
211 Opt =
"/DEFAULTLIB:" + qualifyWindowsLibrary(Lib);
214 void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef
Value,
216 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
220void WindowsARMTargetCodeGenInfo::setTargetAttributes(
222 ARMTargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
223 if (GV->isDeclaration())
225 addStackProbeTargetAttributes(D, GV, CGM);
243 llvm::CallingConv::ID cc = getRuntimeCC();
244 if (cc != llvm::CallingConv::C)
249llvm::CallingConv::ID ARMABIInfo::getLLVMDefaultCC()
const {
251 if (isEABIHF() || getTarget().getTriple().isWatchABI())
252 return llvm::CallingConv::ARM_AAPCS_VFP;
254 return llvm::CallingConv::ARM_AAPCS;
256 return llvm::CallingConv::ARM_APCS;
261llvm::CallingConv::ID ARMABIInfo::getABIDefaultCC()
const {
262 switch (getABIKind()) {
263 case ARMABIKind::APCS:
264 return llvm::CallingConv::ARM_APCS;
265 case ARMABIKind::AAPCS:
266 return llvm::CallingConv::ARM_AAPCS;
267 case ARMABIKind::AAPCS_VFP:
268 return llvm::CallingConv::ARM_AAPCS_VFP;
269 case ARMABIKind::AAPCS16_VFP:
270 return llvm::CallingConv::ARM_AAPCS_VFP;
272 llvm_unreachable(
"bad ABI kind");
275void ARMABIInfo::setCCs() {
276 assert(getRuntimeCC() == llvm::CallingConv::C);
280 llvm::CallingConv::ID abiCC = getABIDefaultCC();
281 if (abiCC != getLLVMDefaultCC())
288 llvm::Type *ResType =
289 llvm::Type::getInt32Ty(getVMContext());
292 if (Size == 64 || Size == 128) {
293 auto *ResType = llvm::FixedVectorType::get(
294 llvm::Type::getInt32Ty(getVMContext()), Size / 32);
297 return getNaturalAlignIndirect(Ty,
false);
302 uint64_t Members)
const {
303 assert(
Base &&
"Base class should be set for homogeneous aggregate");
307 if (!getTarget().hasLegalHalfType() && containsAnyFP16Vectors(Ty)) {
309 auto *NewVecTy = llvm::FixedVectorType::get(
310 llvm::Type::getInt32Ty(getVMContext()), Size / 32);
311 llvm::Type *Ty = llvm::ArrayType::get(NewVecTy, Members);
316 if (getABIKind() == ARMABIKind::AAPCS ||
317 getABIKind() == ARMABIKind::AAPCS_VFP) {
320 Align = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity();
321 unsigned BaseAlign = getContext().getTypeAlignInChars(
Base).getQuantity();
322 Align = (Align > BaseAlign && Align >= 8) ? 8 : 0;
328 unsigned functionCallConv)
const {
338 !isVariadic && isEffectivelyAAPCS_VFP(functionCallConv,
false);
343 if (isIllegalVectorType(Ty))
344 return coerceIllegalVector(Ty);
349 Ty = EnumTy->getDecl()->getIntegerType();
353 if (EIT->getNumBits() > 64)
354 return getNaturalAlignIndirect(Ty,
true);
373 if (isHomogeneousAggregate(Ty,
Base, Members))
374 return classifyHomogeneousAggregate(Ty,
Base, Members);
375 }
else if (getABIKind() == ARMABIKind::AAPCS16_VFP) {
381 if (isHomogeneousAggregate(Ty,
Base, Members)) {
382 assert(
Base && Members <= 4 &&
"unexpected homogeneous aggregate");
389 if (getABIKind() == ARMABIKind::AAPCS16_VFP &&
404 if (getABIKind() == ARMABIKind::AAPCS_VFP ||
405 getABIKind() == ARMABIKind::AAPCS) {
406 TyAlign = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity();
407 ABIAlign = std::clamp(TyAlign, (uint64_t)4, (uint64_t)8);
409 TyAlign = getContext().getTypeAlignInChars(Ty).getQuantity();
412 assert(getABIKind() != ARMABIKind::AAPCS16_VFP &&
"unexpected byval");
420 if (getTarget().isRenderScriptTarget()) {
430 ElemTy = llvm::Type::getInt32Ty(getVMContext());
431 SizeRegs = (getContext().getTypeSize(Ty) + 31) / 32;
433 ElemTy = llvm::Type::getInt64Ty(getVMContext());
434 SizeRegs = (getContext().getTypeSize(Ty) + 63) / 64;
441 llvm::LLVMContext &VMContext) {
473 if (!RT)
return false;
484 bool HadField =
false;
487 i != e; ++i, ++idx) {
526 unsigned functionCallConv)
const {
530 !isVariadic && isEffectivelyAAPCS_VFP(functionCallConv,
true);
537 if (getContext().getTypeSize(RetTy) > 128)
538 return getNaturalAlignIndirect(RetTy);
541 if ((!getTarget().hasLegalHalfType() &&
542 (VT->getElementType()->isFloat16Type() ||
543 VT->getElementType()->isHalfType())) ||
545 VT->getElementType()->isBFloat16Type()))
546 return coerceIllegalVector(RetTy);
552 RetTy = EnumTy->getDecl()->getIntegerType();
555 if (EIT->getNumBits() > 64)
556 return getNaturalAlignIndirect(RetTy,
false);
563 if (getABIKind() == ARMABIKind::APCS) {
573 getVMContext(), getContext().getTypeSize(RetTy)));
587 return getNaturalAlignIndirect(RetTy);
599 if (isHomogeneousAggregate(RetTy,
Base, Members))
600 return classifyHomogeneousAggregate(RetTy,
Base, Members);
609 if (getTarget().isRenderScriptTarget()) {
612 if (getDataLayout().isBigEndian())
622 }
else if (Size <= 128 && getABIKind() == ARMABIKind::AAPCS16_VFP) {
623 llvm::Type *Int32Ty = llvm::Type::getInt32Ty(getVMContext());
624 llvm::Type *CoerceTy =
625 llvm::ArrayType::get(Int32Ty, llvm::alignTo(Size, 32) / 32);
629 return getNaturalAlignIndirect(RetTy);
633bool ARMABIInfo::isIllegalVectorType(
QualType Ty)
const {
641 if ((!getTarget().hasLegalHalfType() &&
642 (VT->getElementType()->isFloat16Type() ||
643 VT->getElementType()->isHalfType())) ||
645 VT->getElementType()->isBFloat16Type()))
653 unsigned NumElements = VT->getNumElements();
655 if (!llvm::isPowerOf2_32(NumElements) && NumElements != 3)
659 unsigned NumElements = VT->getNumElements();
662 if (!llvm::isPowerOf2_32(NumElements))
672bool ARMABIInfo::containsAnyFP16Vectors(
QualType Ty)
const {
674 uint64_t NElements = AT->getZExtSize();
677 return containsAnyFP16Vectors(AT->getElementType());
682 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
684 return containsAnyFP16Vectors(B.getType());
689 return FD && containsAnyFP16Vectors(FD->getType());
696 return (VT->getElementType()->isFloat16Type() ||
697 VT->getElementType()->isBFloat16Type() ||
698 VT->getElementType()->isHalfType());
703bool ARMSwiftABIInfo::isLegalVectorType(
CharUnits VectorSize, llvm::Type *EltTy,
704 unsigned NumElts)
const {
705 if (!llvm::isPowerOf2_32(NumElts))
707 unsigned size = CGT.
getDataLayout().getTypeStoreSizeInBits(EltTy);
716bool ARMABIInfo::isHomogeneousAggregateBaseType(
QualType Ty)
const {
720 if (BT->getKind() == BuiltinType::Float ||
721 BT->getKind() == BuiltinType::Double ||
722 BT->getKind() == BuiltinType::LongDouble)
725 unsigned VecSize = getContext().getTypeSize(VT);
726 if (VecSize == 64 || VecSize == 128)
732bool ARMABIInfo::isHomogeneousAggregateSmallEnough(
const Type *
Base,
733 uint64_t Members)
const {
737bool ARMABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate()
const {
746bool ARMABIInfo::isEffectivelyAAPCS_VFP(
unsigned callConvention,
747 bool acceptHalf)
const {
749 if (callConvention != llvm::CallingConv::C)
750 return (callConvention == llvm::CallingConv::ARM_AAPCS_VFP);
752 return (getABIKind() == ARMABIKind::AAPCS_VFP) ||
753 (acceptHalf && (getABIKind() == ARMABIKind::AAPCS16_VFP));
767 CharUnits TySize = getContext().getTypeSizeInChars(Ty);
768 CharUnits TyAlignForABI = getContext().getTypeUnadjustedAlignInChars(Ty);
771 bool IsIndirect =
false;
780 getABIKind() == ARMABIKind::AAPCS16_VFP &&
781 !isHomogeneousAggregate(Ty,
Base, Members)) {
788 }
else if (getABIKind() == ARMABIKind::AAPCS_VFP ||
789 getABIKind() == ARMABIKind::AAPCS) {
792 }
else if (getABIKind() == ARMABIKind::AAPCS16_VFP) {
800 TypeInfoChars TyInfo(TySize, TyAlignForABI, AlignRequirementKind::None);
805std::unique_ptr<TargetCodeGenInfo>
807 return std::make_unique<ARMTargetCodeGenInfo>(CGM.
getTypes(), Kind);
810std::unique_ptr<TargetCodeGenInfo>
812 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 CodeGen::Address EmitVAArg(CodeGen::CodeGenFunction &CGF, CodeGen::Address VAListAddr, QualType Ty) const =0
EmitVAArg - Emit the target dependent code to load a value of.
virtual bool isHomogeneousAggregateSmallEnough(const Type *Base, uint64_t Members) const
const TargetInfo & getTarget() const
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 ...
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
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.
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...
llvm::Type * ConvertTypeForMem(QualType T)
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
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...
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)
Address emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType ValueTy, bool IsIndirect, TypeInfoChars ValueInfo, CharUnits SlotSizeAndAlign, bool AllowHigherAlign, 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.
bool Load(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::PointerType * Int8PtrTy
Contains information gathered from parsing the contents of TargetAttr.
bool BranchTargetEnforcement
const char * getSignReturnAddrStr() const