1 //===- ARC.cpp ------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "ABIInfoImpl.h"
10 #include "TargetInfo.h"
12 using namespace clang
;
13 using namespace clang::CodeGen
;
15 // ARC ABI implementation.
18 class ARCABIInfo
: public DefaultABIInfo
{
24 using DefaultABIInfo::DefaultABIInfo
;
27 Address
EmitVAArg(CodeGenFunction
&CGF
, Address VAListAddr
,
28 QualType Ty
) const override
;
30 void updateState(const ABIArgInfo
&Info
, QualType Ty
, CCState
&State
) const {
33 if (Info
.isIndirect() && Info
.getInReg())
35 else if (Info
.isDirect() && Info
.getInReg()) {
36 unsigned sz
= (getContext().getTypeSize(Ty
) + 31) / 32;
37 if (sz
< State
.FreeRegs
)
44 void computeInfo(CGFunctionInfo
&FI
) const override
{
46 // ARC uses 8 registers to pass arguments.
49 if (!getCXXABI().classifyReturnType(FI
))
50 FI
.getReturnInfo() = classifyReturnType(FI
.getReturnType());
51 updateState(FI
.getReturnInfo(), FI
.getReturnType(), State
);
52 for (auto &I
: FI
.arguments()) {
53 I
.info
= classifyArgumentType(I
.type
, State
.FreeRegs
);
54 updateState(I
.info
, I
.type
, State
);
58 ABIArgInfo
getIndirectByRef(QualType Ty
, bool HasFreeRegs
) const;
59 ABIArgInfo
getIndirectByValue(QualType Ty
) const;
60 ABIArgInfo
classifyArgumentType(QualType Ty
, uint8_t FreeRegs
) const;
61 ABIArgInfo
classifyReturnType(QualType RetTy
) const;
64 class ARCTargetCodeGenInfo
: public TargetCodeGenInfo
{
66 ARCTargetCodeGenInfo(CodeGenTypes
&CGT
)
67 : TargetCodeGenInfo(std::make_unique
<ARCABIInfo
>(CGT
)) {}
71 ABIArgInfo
ARCABIInfo::getIndirectByRef(QualType Ty
, bool HasFreeRegs
) const {
72 return HasFreeRegs
? getNaturalAlignIndirectInReg(Ty
) :
73 getNaturalAlignIndirect(Ty
, false);
76 ABIArgInfo
ARCABIInfo::getIndirectByValue(QualType Ty
) const {
77 // Compute the byval alignment.
78 const unsigned MinABIStackAlignInBytes
= 4;
79 unsigned TypeAlign
= getContext().getTypeAlign(Ty
) / 8;
80 return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true,
81 TypeAlign
> MinABIStackAlignInBytes
);
84 Address
ARCABIInfo::EmitVAArg(CodeGenFunction
&CGF
, Address VAListAddr
,
86 return emitVoidPtrVAArg(CGF
, VAListAddr
, Ty
, /*indirect*/ false,
87 getContext().getTypeInfoInChars(Ty
),
88 CharUnits::fromQuantity(4), true);
91 ABIArgInfo
ARCABIInfo::classifyArgumentType(QualType Ty
,
92 uint8_t FreeRegs
) const {
93 // Handle the generic C++ ABI.
94 const RecordType
*RT
= Ty
->getAs
<RecordType
>();
96 CGCXXABI::RecordArgABI RAA
= getRecordArgABI(RT
, getCXXABI());
97 if (RAA
== CGCXXABI::RAA_Indirect
)
98 return getIndirectByRef(Ty
, FreeRegs
> 0);
100 if (RAA
== CGCXXABI::RAA_DirectInMemory
)
101 return getIndirectByValue(Ty
);
104 // Treat an enum type as its underlying type.
105 if (const EnumType
*EnumTy
= Ty
->getAs
<EnumType
>())
106 Ty
= EnumTy
->getDecl()->getIntegerType();
108 auto SizeInRegs
= llvm::alignTo(getContext().getTypeSize(Ty
), 32) / 32;
110 if (isAggregateTypeForABI(Ty
)) {
111 // Structures with flexible arrays are always indirect.
112 if (RT
&& RT
->getDecl()->hasFlexibleArrayMember())
113 return getIndirectByValue(Ty
);
115 // Ignore empty structs/unions.
116 if (isEmptyRecord(getContext(), Ty
, true))
117 return ABIArgInfo::getIgnore();
119 llvm::LLVMContext
&LLVMContext
= getVMContext();
121 llvm::IntegerType
*Int32
= llvm::Type::getInt32Ty(LLVMContext
);
122 SmallVector
<llvm::Type
*, 3> Elements(SizeInRegs
, Int32
);
123 llvm::Type
*Result
= llvm::StructType::get(LLVMContext
, Elements
);
125 return FreeRegs
>= SizeInRegs
?
126 ABIArgInfo::getDirectInReg(Result
) :
127 ABIArgInfo::getDirect(Result
, 0, nullptr, false);
130 if (const auto *EIT
= Ty
->getAs
<BitIntType
>())
131 if (EIT
->getNumBits() > 64)
132 return getIndirectByValue(Ty
);
134 return isPromotableIntegerTypeForABI(Ty
)
135 ? (FreeRegs
>= SizeInRegs
? ABIArgInfo::getExtendInReg(Ty
)
136 : ABIArgInfo::getExtend(Ty
))
137 : (FreeRegs
>= SizeInRegs
? ABIArgInfo::getDirectInReg()
138 : ABIArgInfo::getDirect());
141 ABIArgInfo
ARCABIInfo::classifyReturnType(QualType RetTy
) const {
142 if (RetTy
->isAnyComplexType())
143 return ABIArgInfo::getDirectInReg();
145 // Arguments of size > 4 registers are indirect.
146 auto RetSize
= llvm::alignTo(getContext().getTypeSize(RetTy
), 32) / 32;
148 return getIndirectByRef(RetTy
, /*HasFreeRegs*/ true);
150 return DefaultABIInfo::classifyReturnType(RetTy
);
153 } // End anonymous namespace.
155 std::unique_ptr
<TargetCodeGenInfo
>
156 CodeGen::createARCTargetCodeGenInfo(CodeGenModule
&CGM
) {
157 return std::make_unique
<ARCTargetCodeGenInfo
>(CGM
.getTypes());