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)
155 static const char *SignReturnAddrStr[] = {
"none",
"non-leaf",
"all"};
157 "Unexpected SignReturnAddressScopeKind");
159 "sign-return-address",
162 Fn->addFnAttr(
"branch-target-enforcement",
165 }
else if (CGM.
getLangOpts().BranchTargetEnforcement ||
173 diag::warn_target_unsupported_branch_protection_attribute)
178 const ARMInterruptAttr *
Attr = FD->
getAttr<ARMInterruptAttr>();
183 switch (
Attr->getInterrupt()) {
184 case ARMInterruptAttr::Generic:
Kind =
"";
break;
185 case ARMInterruptAttr::IRQ:
Kind =
"IRQ";
break;
186 case ARMInterruptAttr::FIQ:
Kind =
"FIQ";
break;
187 case ARMInterruptAttr::SWI:
Kind =
"SWI";
break;
188 case ARMInterruptAttr::ABORT:
Kind =
"ABORT";
break;
189 case ARMInterruptAttr::UNDEF:
Kind =
"UNDEF";
break;
192 Fn->addFnAttr(
"interrupt", Kind);
194 ARMABIKind ABI = getABIInfo<ARMABIInfo>().getABIKind();
195 if (ABI == ARMABIKind::APCS)
201 llvm::AttrBuilder B(Fn->getContext());
202 B.addStackAlignmentAttr(8);
207class WindowsARMTargetCodeGenInfo :
public ARMTargetCodeGenInfo {
210 : ARMTargetCodeGenInfo(CGT, K) {}
212 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
215 void getDependentLibraryOption(llvm::StringRef Lib,
217 Opt =
"/DEFAULTLIB:" + qualifyWindowsLibrary(Lib);
220 void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef
Value,
222 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
226void WindowsARMTargetCodeGenInfo::setTargetAttributes(
228 ARMTargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
229 if (GV->isDeclaration())
231 addStackProbeTargetAttributes(D, GV, CGM);
249 llvm::CallingConv::ID cc = getRuntimeCC();
250 if (cc != llvm::CallingConv::C)
255llvm::CallingConv::ID ARMABIInfo::getLLVMDefaultCC()
const {
257 if (isEABIHF() || getTarget().getTriple().isWatchABI())
258 return llvm::CallingConv::ARM_AAPCS_VFP;
260 return llvm::CallingConv::ARM_AAPCS;
262 return llvm::CallingConv::ARM_APCS;
267llvm::CallingConv::ID ARMABIInfo::getABIDefaultCC()
const {
268 switch (getABIKind()) {
269 case ARMABIKind::APCS:
270 return llvm::CallingConv::ARM_APCS;
271 case ARMABIKind::AAPCS:
272 return llvm::CallingConv::ARM_AAPCS;
273 case ARMABIKind::AAPCS_VFP:
274 return llvm::CallingConv::ARM_AAPCS_VFP;
275 case ARMABIKind::AAPCS16_VFP:
276 return llvm::CallingConv::ARM_AAPCS_VFP;
278 llvm_unreachable(
"bad ABI kind");
281void ARMABIInfo::setCCs() {
282 assert(getRuntimeCC() == llvm::CallingConv::C);
286 llvm::CallingConv::ID abiCC = getABIDefaultCC();
287 if (abiCC != getLLVMDefaultCC())
294 llvm::Type *ResType =
295 llvm::Type::getInt32Ty(getVMContext());
298 if (Size == 64 || Size == 128) {
299 auto *ResType = llvm::FixedVectorType::get(
300 llvm::Type::getInt32Ty(getVMContext()), Size / 32);
303 return getNaturalAlignIndirect(Ty,
false);
308 uint64_t Members)
const {
309 assert(
Base &&
"Base class should be set for homogeneous aggregate");
313 if (!getTarget().hasLegalHalfType() && containsAnyFP16Vectors(Ty)) {
315 auto *NewVecTy = llvm::FixedVectorType::get(
316 llvm::Type::getInt32Ty(getVMContext()), Size / 32);
317 llvm::Type *Ty = llvm::ArrayType::get(NewVecTy, Members);
322 if (getABIKind() == ARMABIKind::AAPCS ||
323 getABIKind() == ARMABIKind::AAPCS_VFP) {
326 Align = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity();
327 unsigned BaseAlign = getContext().getTypeAlignInChars(
Base).getQuantity();
328 Align = (Align > BaseAlign && Align >= 8) ? 8 : 0;
334 unsigned functionCallConv)
const {
344 !isVariadic && isEffectivelyAAPCS_VFP(functionCallConv,
false);
349 if (isIllegalVectorType(Ty))
350 return coerceIllegalVector(Ty);
355 Ty = EnumTy->getDecl()->getIntegerType();
359 if (EIT->getNumBits() > 64)
360 return getNaturalAlignIndirect(Ty,
true);
379 if (isHomogeneousAggregate(Ty,
Base, Members))
380 return classifyHomogeneousAggregate(Ty,
Base, Members);
381 }
else if (getABIKind() == ARMABIKind::AAPCS16_VFP) {
387 if (isHomogeneousAggregate(Ty,
Base, Members)) {
388 assert(
Base && Members <= 4 &&
"unexpected homogeneous aggregate");
395 if (getABIKind() == ARMABIKind::AAPCS16_VFP &&
410 if (getABIKind() == ARMABIKind::AAPCS_VFP ||
411 getABIKind() == ARMABIKind::AAPCS) {
412 TyAlign = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity();
413 ABIAlign = std::clamp(TyAlign, (uint64_t)4, (uint64_t)8);
415 TyAlign = getContext().getTypeAlignInChars(Ty).getQuantity();
418 assert(getABIKind() != ARMABIKind::AAPCS16_VFP &&
"unexpected byval");
426 if (getTarget().isRenderScriptTarget()) {
436 ElemTy = llvm::Type::getInt32Ty(getVMContext());
437 SizeRegs = (getContext().getTypeSize(Ty) + 31) / 32;
439 ElemTy = llvm::Type::getInt64Ty(getVMContext());
440 SizeRegs = (getContext().getTypeSize(Ty) + 63) / 64;
447 llvm::LLVMContext &VMContext) {
479 if (!RT)
return false;
490 bool HadField =
false;
493 i != e; ++i, ++idx) {
532 unsigned functionCallConv)
const {
536 !isVariadic && isEffectivelyAAPCS_VFP(functionCallConv,
true);
543 if (getContext().getTypeSize(RetTy) > 128)
544 return getNaturalAlignIndirect(RetTy);
547 if ((!getTarget().hasLegalHalfType() &&
548 (VT->getElementType()->isFloat16Type() ||
549 VT->getElementType()->isHalfType())) ||
551 VT->getElementType()->isBFloat16Type()))
552 return coerceIllegalVector(RetTy);
558 RetTy = EnumTy->getDecl()->getIntegerType();
561 if (EIT->getNumBits() > 64)
562 return getNaturalAlignIndirect(RetTy,
false);
569 if (getABIKind() == ARMABIKind::APCS) {
579 getVMContext(), getContext().getTypeSize(RetTy)));
593 return getNaturalAlignIndirect(RetTy);
605 if (isHomogeneousAggregate(RetTy,
Base, Members))
606 return classifyHomogeneousAggregate(RetTy,
Base, Members);
615 if (getTarget().isRenderScriptTarget()) {
618 if (getDataLayout().isBigEndian())
628 }
else if (Size <= 128 && getABIKind() == ARMABIKind::AAPCS16_VFP) {
629 llvm::Type *Int32Ty = llvm::Type::getInt32Ty(getVMContext());
630 llvm::Type *CoerceTy =
631 llvm::ArrayType::get(Int32Ty, llvm::alignTo(Size, 32) / 32);
635 return getNaturalAlignIndirect(RetTy);
639bool ARMABIInfo::isIllegalVectorType(
QualType Ty)
const {
647 if ((!getTarget().hasLegalHalfType() &&
648 (VT->getElementType()->isFloat16Type() ||
649 VT->getElementType()->isHalfType())) ||
651 VT->getElementType()->isBFloat16Type()))
659 unsigned NumElements = VT->getNumElements();
661 if (!llvm::isPowerOf2_32(NumElements) && NumElements != 3)
665 unsigned NumElements = VT->getNumElements();
668 if (!llvm::isPowerOf2_32(NumElements))
678bool ARMABIInfo::containsAnyFP16Vectors(
QualType Ty)
const {
680 uint64_t NElements = AT->getSize().getZExtValue();
683 return containsAnyFP16Vectors(AT->getElementType());
688 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
690 return containsAnyFP16Vectors(B.getType());
695 return FD && containsAnyFP16Vectors(FD->getType());
702 return (VT->getElementType()->isFloat16Type() ||
703 VT->getElementType()->isBFloat16Type() ||
704 VT->getElementType()->isHalfType());
709bool ARMSwiftABIInfo::isLegalVectorType(
CharUnits VectorSize, llvm::Type *EltTy,
710 unsigned NumElts)
const {
711 if (!llvm::isPowerOf2_32(NumElts))
713 unsigned size = CGT.
getDataLayout().getTypeStoreSizeInBits(EltTy);
722bool ARMABIInfo::isHomogeneousAggregateBaseType(
QualType Ty)
const {
726 if (BT->getKind() == BuiltinType::Float ||
727 BT->getKind() == BuiltinType::Double ||
728 BT->getKind() == BuiltinType::LongDouble)
731 unsigned VecSize = getContext().getTypeSize(VT);
732 if (VecSize == 64 || VecSize == 128)
738bool ARMABIInfo::isHomogeneousAggregateSmallEnough(
const Type *
Base,
739 uint64_t Members)
const {
743bool ARMABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate()
const {
752bool ARMABIInfo::isEffectivelyAAPCS_VFP(
unsigned callConvention,
753 bool acceptHalf)
const {
755 if (callConvention != llvm::CallingConv::C)
756 return (callConvention == llvm::CallingConv::ARM_AAPCS_VFP);
758 return (getABIKind() == ARMABIKind::AAPCS_VFP) ||
759 (acceptHalf && (getABIKind() == ARMABIKind::AAPCS16_VFP));
773 CharUnits TySize = getContext().getTypeSizeInChars(Ty);
774 CharUnits TyAlignForABI = getContext().getTypeUnadjustedAlignInChars(Ty);
777 bool IsIndirect =
false;
786 getABIKind() == ARMABIKind::AAPCS16_VFP &&
787 !isHomogeneousAggregate(Ty,
Base, Members)) {
794 }
else if (getABIKind() == ARMABIKind::AAPCS_VFP ||
795 getABIKind() == ARMABIKind::AAPCS) {
798 }
else if (getABIKind() == ARMABIKind::AAPCS16_VFP) {
806 TypeInfoChars TyInfo(TySize, TyAlignForABI, AlignRequirementKind::None);
811std::unique_ptr<TargetCodeGenInfo>
813 return std::make_unique<ARMTargetCodeGenInfo>(CGM.
getTypes(), Kind);
816std::unique_ptr<TargetCodeGenInfo>
818 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
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)
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::PointerType * Int8PtrTy
Contains information gathered from parsing the contents of TargetAttr.
LangOptions::SignReturnAddressScopeKind SignReturnAddr
bool BranchTargetEnforcement