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::GNUEABIT64:
39 case llvm::Triple::GNUEABIHF:
40 case llvm::Triple::GNUEABIHFT64:
41 case llvm::Triple::MuslEABI:
42 case llvm::Triple::MuslEABIHF:
49 bool isEABIHF()
const {
50 switch (
getTarget().getTriple().getEnvironment()) {
51 case llvm::Triple::EABIHF:
52 case llvm::Triple::GNUEABIHF:
53 case llvm::Triple::GNUEABIHFT64:
54 case llvm::Triple::MuslEABIHF:
69 unsigned functionCallConv)
const;
71 unsigned functionCallConv)
const;
73 uint64_t Members)
const;
75 bool isIllegalVectorType(
QualType Ty)
const;
76 bool containsAnyFP16Vectors(
QualType Ty)
const;
80 uint64_t Members)
const override;
83 bool isEffectivelyAAPCS_VFP(
unsigned callConvention,
bool acceptHalf)
const;
90 llvm::CallingConv::ID getLLVMDefaultCC()
const;
91 llvm::CallingConv::ID getABIDefaultCC()
const;
101 unsigned NumElts)
const override;
108 SwiftInfo = std::make_unique<ARMSwiftABIInfo>(CGT);
116 return "mov\tr7, r7\t\t// marker for objc_retainAutoreleaseReturnValue";
120 llvm::Value *
Address)
const override {
121 llvm::Value *Four8 = llvm::ConstantInt::get(CGF.
Int8Ty, 4);
129 if (getABIInfo<ARMABIInfo>().isEABI())
136 if (GV->isDeclaration())
141 auto *
Fn = cast<llvm::Function>(GV);
143 if (
const auto *TA = FD->
getAttr<TargetAttr>()) {
146 if (!
Attr.BranchProtection.empty()) {
152 Arch, BPI, DiagMsg)) {
155 diag::warn_target_unsupported_branch_protection_attribute)
159 }
else if (CGM.
getLangOpts().BranchTargetEnforcement ||
167 diag::warn_target_unsupported_branch_protection_attribute)
176 const ARMInterruptAttr *
Attr = FD->
getAttr<ARMInterruptAttr>();
181 switch (
Attr->getInterrupt()) {
182 case ARMInterruptAttr::Generic:
Kind =
"";
break;
183 case ARMInterruptAttr::IRQ:
Kind =
"IRQ";
break;
184 case ARMInterruptAttr::FIQ:
Kind =
"FIQ";
break;
185 case ARMInterruptAttr::SWI:
Kind =
"SWI";
break;
186 case ARMInterruptAttr::ABORT:
Kind =
"ABORT";
break;
187 case ARMInterruptAttr::UNDEF:
Kind =
"UNDEF";
break;
190 Fn->addFnAttr(
"interrupt", Kind);
192 ARMABIKind ABI = getABIInfo<ARMABIInfo>().getABIKind();
193 if (ABI == ARMABIKind::APCS)
199 llvm::AttrBuilder B(
Fn->getContext());
200 B.addStackAlignmentAttr(8);
205class WindowsARMTargetCodeGenInfo :
public ARMTargetCodeGenInfo {
208 : ARMTargetCodeGenInfo(CGT, K) {}
210 void setTargetAttributes(
const Decl *
D, llvm::GlobalValue *GV,
213 void getDependentLibraryOption(llvm::StringRef Lib,
215 Opt =
"/DEFAULTLIB:" + qualifyWindowsLibrary(Lib);
218 void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef
Value,
220 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
224void WindowsARMTargetCodeGenInfo::setTargetAttributes(
226 ARMTargetCodeGenInfo::setTargetAttributes(
D, GV, CGM);
227 if (GV->isDeclaration())
229 addStackProbeTargetAttributes(
D, GV, CGM);
247 llvm::CallingConv::ID cc = getRuntimeCC();
248 if (cc != llvm::CallingConv::C)
253llvm::CallingConv::ID ARMABIInfo::getLLVMDefaultCC()
const {
255 if (isEABIHF() || getTarget().getTriple().isWatchABI())
256 return llvm::CallingConv::ARM_AAPCS_VFP;
258 return llvm::CallingConv::ARM_AAPCS;
260 return llvm::CallingConv::ARM_APCS;
265llvm::CallingConv::ID ARMABIInfo::getABIDefaultCC()
const {
266 switch (getABIKind()) {
267 case ARMABIKind::APCS:
268 return llvm::CallingConv::ARM_APCS;
269 case ARMABIKind::AAPCS:
270 return llvm::CallingConv::ARM_AAPCS;
271 case ARMABIKind::AAPCS_VFP:
272 return llvm::CallingConv::ARM_AAPCS_VFP;
273 case ARMABIKind::AAPCS16_VFP:
274 return llvm::CallingConv::ARM_AAPCS_VFP;
276 llvm_unreachable(
"bad ABI kind");
279void ARMABIInfo::setCCs() {
280 assert(getRuntimeCC() == llvm::CallingConv::C);
284 llvm::CallingConv::ID abiCC = getABIDefaultCC();
285 if (abiCC != getLLVMDefaultCC())
292 llvm::Type *ResType =
293 llvm::Type::getInt32Ty(getVMContext());
296 if (Size == 64 || Size == 128) {
297 auto *ResType = llvm::FixedVectorType::get(
298 llvm::Type::getInt32Ty(getVMContext()), Size / 32);
301 return getNaturalAlignIndirect(Ty,
false);
306 uint64_t Members)
const {
307 assert(
Base &&
"Base class should be set for homogeneous aggregate");
311 if (!getTarget().hasLegalHalfType() && containsAnyFP16Vectors(Ty)) {
313 auto *NewVecTy = llvm::FixedVectorType::get(
314 llvm::Type::getInt32Ty(getVMContext()), Size / 32);
315 llvm::Type *Ty = llvm::ArrayType::get(NewVecTy, Members);
320 if (getABIKind() == ARMABIKind::AAPCS ||
321 getABIKind() == ARMABIKind::AAPCS_VFP) {
324 Align = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity();
325 unsigned BaseAlign = getContext().getTypeAlignInChars(
Base).getQuantity();
326 Align = (Align > BaseAlign && Align >= 8) ? 8 : 0;
332 unsigned functionCallConv)
const {
342 !isVariadic && isEffectivelyAAPCS_VFP(functionCallConv,
false);
347 if (isIllegalVectorType(Ty))
348 return coerceIllegalVector(Ty);
353 Ty = EnumTy->getDecl()->getIntegerType();
357 if (EIT->getNumBits() > 64)
358 return getNaturalAlignIndirect(Ty,
true);
360 return (isPromotableIntegerTypeForABI(Ty)
378 if (isHomogeneousAggregate(Ty,
Base, Members))
379 return classifyHomogeneousAggregate(Ty,
Base, Members);
380 }
else if (getABIKind() == ARMABIKind::AAPCS16_VFP) {
386 if (isHomogeneousAggregate(Ty,
Base, Members)) {
387 assert(
Base && Members <= 4 &&
"unexpected homogeneous aggregate");
394 if (getABIKind() == ARMABIKind::AAPCS16_VFP &&
409 if (getABIKind() == ARMABIKind::AAPCS_VFP ||
410 getABIKind() == ARMABIKind::AAPCS) {
411 TyAlign = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity();
412 ABIAlign = std::clamp(TyAlign, (uint64_t)4, (uint64_t)8);
414 TyAlign = getContext().getTypeAlignInChars(Ty).getQuantity();
417 assert(getABIKind() != ARMABIKind::AAPCS16_VFP &&
"unexpected byval");
429 ElemTy = llvm::Type::getInt32Ty(getVMContext());
430 SizeRegs = (getContext().getTypeSize(Ty) + 31) / 32;
432 ElemTy = llvm::Type::getInt64Ty(getVMContext());
433 SizeRegs = (getContext().getTypeSize(Ty) + 63) / 64;
440 llvm::LLVMContext &VMContext) {
472 if (!RT)
return false;
483 bool HadField =
false;
486 i != e; ++i, ++idx) {
525 unsigned functionCallConv)
const {
529 !isVariadic && isEffectivelyAAPCS_VFP(functionCallConv,
true);
536 if (getContext().getTypeSize(RetTy) > 128)
537 return getNaturalAlignIndirect(RetTy);
540 if ((!getTarget().hasLegalHalfType() &&
541 (VT->getElementType()->isFloat16Type() ||
542 VT->getElementType()->isHalfType())) ||
544 VT->getElementType()->isBFloat16Type()))
545 return coerceIllegalVector(RetTy);
551 RetTy = EnumTy->getDecl()->getIntegerType();
554 if (EIT->getNumBits() > 64)
555 return getNaturalAlignIndirect(RetTy,
false);
562 if (getABIKind() == ARMABIKind::APCS) {
572 getVMContext(), getContext().getTypeSize(RetTy)));
586 return getNaturalAlignIndirect(RetTy);
598 if (isHomogeneousAggregate(RetTy,
Base, Members))
599 return classifyHomogeneousAggregate(RetTy,
Base, Members);
606 if (getDataLayout().isBigEndian())
616 }
else if (Size <= 128 && getABIKind() == ARMABIKind::AAPCS16_VFP) {
617 llvm::Type *Int32Ty = llvm::Type::getInt32Ty(getVMContext());
618 llvm::Type *CoerceTy =
619 llvm::ArrayType::get(Int32Ty, llvm::alignTo(Size, 32) / 32);
623 return getNaturalAlignIndirect(RetTy);
627bool ARMABIInfo::isIllegalVectorType(
QualType Ty)
const {
635 if ((!getTarget().hasLegalHalfType() &&
636 (VT->getElementType()->isFloat16Type() ||
637 VT->getElementType()->isHalfType())) ||
639 VT->getElementType()->isBFloat16Type()))
647 unsigned NumElements = VT->getNumElements();
649 if (!llvm::isPowerOf2_32(NumElements) && NumElements != 3)
653 unsigned NumElements = VT->getNumElements();
656 if (!llvm::isPowerOf2_32(NumElements))
666bool ARMABIInfo::containsAnyFP16Vectors(
QualType Ty)
const {
668 uint64_t NElements = AT->getZExtSize();
671 return containsAnyFP16Vectors(AT->getElementType());
676 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
678 return containsAnyFP16Vectors(B.getType());
683 return FD && containsAnyFP16Vectors(FD->getType());
690 return (VT->getElementType()->isFloat16Type() ||
691 VT->getElementType()->isBFloat16Type() ||
692 VT->getElementType()->isHalfType());
697bool ARMSwiftABIInfo::isLegalVectorType(
CharUnits VectorSize, llvm::Type *EltTy,
698 unsigned NumElts)
const {
699 if (!llvm::isPowerOf2_32(NumElts))
701 unsigned size = CGT.
getDataLayout().getTypeStoreSizeInBits(EltTy);
710bool ARMABIInfo::isHomogeneousAggregateBaseType(
QualType Ty)
const {
714 if (BT->getKind() == BuiltinType::Float ||
715 BT->getKind() == BuiltinType::Double ||
716 BT->getKind() == BuiltinType::LongDouble)
719 unsigned VecSize = getContext().getTypeSize(VT);
720 if (VecSize == 64 || VecSize == 128)
726bool ARMABIInfo::isHomogeneousAggregateSmallEnough(
const Type *
Base,
727 uint64_t Members)
const {
731bool ARMABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate()
const {
740bool ARMABIInfo::isEffectivelyAAPCS_VFP(
unsigned callConvention,
741 bool acceptHalf)
const {
743 if (callConvention != llvm::CallingConv::C)
744 return (callConvention == llvm::CallingConv::ARM_AAPCS_VFP);
746 return (getABIKind() == ARMABIKind::AAPCS_VFP) ||
747 (acceptHalf && (getABIKind() == ARMABIKind::AAPCS16_VFP));
758 CharUnits TySize = getContext().getTypeSizeInChars(Ty);
759 CharUnits TyAlignForABI = getContext().getTypeUnadjustedAlignInChars(Ty);
762 bool IsIndirect =
false;
771 getABIKind() == ARMABIKind::AAPCS16_VFP &&
772 !isHomogeneousAggregate(Ty,
Base, Members)) {
779 }
else if (getABIKind() == ARMABIKind::AAPCS_VFP ||
780 getABIKind() == ARMABIKind::AAPCS) {
783 }
else if (getABIKind() == ARMABIKind::AAPCS16_VFP) {
791 TypeInfoChars TyInfo(TySize, TyAlignForABI, AlignRequirementKind::None);
796std::unique_ptr<TargetCodeGenInfo>
798 return std::make_unique<ARMTargetCodeGenInfo>(CGM.
getTypes(), Kind);
801std::unique_ptr<TargetCodeGenInfo>
803 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 ...
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.