xref: /llvm-project/clang/lib/CodeGen/Targets/ARC.cpp (revision 6d973b4548e281d0b8e75e85833804bb45b6a0e8)
1992cb984SSergei Barannikov //===- ARC.cpp ------------------------------------------------------------===//
2992cb984SSergei Barannikov //
3992cb984SSergei Barannikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4992cb984SSergei Barannikov // See https://llvm.org/LICENSE.txt for license information.
5992cb984SSergei Barannikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6992cb984SSergei Barannikov //
7992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
8992cb984SSergei Barannikov 
9992cb984SSergei Barannikov #include "ABIInfoImpl.h"
10992cb984SSergei Barannikov #include "TargetInfo.h"
11992cb984SSergei Barannikov 
12992cb984SSergei Barannikov using namespace clang;
13992cb984SSergei Barannikov using namespace clang::CodeGen;
14992cb984SSergei Barannikov 
15992cb984SSergei Barannikov // ARC ABI implementation.
16992cb984SSergei Barannikov namespace {
17992cb984SSergei Barannikov 
18992cb984SSergei Barannikov class ARCABIInfo : public DefaultABIInfo {
19992cb984SSergei Barannikov   struct CCState {
20992cb984SSergei Barannikov     unsigned FreeRegs;
21992cb984SSergei Barannikov   };
22992cb984SSergei Barannikov 
23992cb984SSergei Barannikov public:
24992cb984SSergei Barannikov   using DefaultABIInfo::DefaultABIInfo;
25992cb984SSergei Barannikov 
26992cb984SSergei Barannikov private:
27*6d973b45SMariya Podchishchaeva   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
28*6d973b45SMariya Podchishchaeva                    AggValueSlot Slot) const override;
29992cb984SSergei Barannikov 
updateState(const ABIArgInfo & Info,QualType Ty,CCState & State) const30992cb984SSergei Barannikov   void updateState(const ABIArgInfo &Info, QualType Ty, CCState &State) const {
31992cb984SSergei Barannikov     if (!State.FreeRegs)
32992cb984SSergei Barannikov       return;
33992cb984SSergei Barannikov     if (Info.isIndirect() && Info.getInReg())
34992cb984SSergei Barannikov       State.FreeRegs--;
35992cb984SSergei Barannikov     else if (Info.isDirect() && Info.getInReg()) {
36992cb984SSergei Barannikov       unsigned sz = (getContext().getTypeSize(Ty) + 31) / 32;
37992cb984SSergei Barannikov       if (sz < State.FreeRegs)
38992cb984SSergei Barannikov         State.FreeRegs -= sz;
39992cb984SSergei Barannikov       else
40992cb984SSergei Barannikov         State.FreeRegs = 0;
41992cb984SSergei Barannikov     }
42992cb984SSergei Barannikov   }
43992cb984SSergei Barannikov 
computeInfo(CGFunctionInfo & FI) const44992cb984SSergei Barannikov   void computeInfo(CGFunctionInfo &FI) const override {
45992cb984SSergei Barannikov     CCState State;
46992cb984SSergei Barannikov     // ARC uses 8 registers to pass arguments.
47992cb984SSergei Barannikov     State.FreeRegs = 8;
48992cb984SSergei Barannikov 
49992cb984SSergei Barannikov     if (!getCXXABI().classifyReturnType(FI))
50992cb984SSergei Barannikov       FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
51992cb984SSergei Barannikov     updateState(FI.getReturnInfo(), FI.getReturnType(), State);
52992cb984SSergei Barannikov     for (auto &I : FI.arguments()) {
53992cb984SSergei Barannikov       I.info = classifyArgumentType(I.type, State.FreeRegs);
54992cb984SSergei Barannikov       updateState(I.info, I.type, State);
55992cb984SSergei Barannikov     }
56992cb984SSergei Barannikov   }
57992cb984SSergei Barannikov 
58992cb984SSergei Barannikov   ABIArgInfo getIndirectByRef(QualType Ty, bool HasFreeRegs) const;
59992cb984SSergei Barannikov   ABIArgInfo getIndirectByValue(QualType Ty) const;
60992cb984SSergei Barannikov   ABIArgInfo classifyArgumentType(QualType Ty, uint8_t FreeRegs) const;
61992cb984SSergei Barannikov   ABIArgInfo classifyReturnType(QualType RetTy) const;
62992cb984SSergei Barannikov };
63992cb984SSergei Barannikov 
64992cb984SSergei Barannikov class ARCTargetCodeGenInfo : public TargetCodeGenInfo {
65992cb984SSergei Barannikov public:
ARCTargetCodeGenInfo(CodeGenTypes & CGT)66992cb984SSergei Barannikov   ARCTargetCodeGenInfo(CodeGenTypes &CGT)
67992cb984SSergei Barannikov       : TargetCodeGenInfo(std::make_unique<ARCABIInfo>(CGT)) {}
68992cb984SSergei Barannikov };
69992cb984SSergei Barannikov 
70992cb984SSergei Barannikov 
getIndirectByRef(QualType Ty,bool HasFreeRegs) const71992cb984SSergei Barannikov ABIArgInfo ARCABIInfo::getIndirectByRef(QualType Ty, bool HasFreeRegs) const {
72992cb984SSergei Barannikov   return HasFreeRegs ? getNaturalAlignIndirectInReg(Ty) :
73992cb984SSergei Barannikov                        getNaturalAlignIndirect(Ty, false);
74992cb984SSergei Barannikov }
75992cb984SSergei Barannikov 
getIndirectByValue(QualType Ty) const76992cb984SSergei Barannikov ABIArgInfo ARCABIInfo::getIndirectByValue(QualType Ty) const {
77992cb984SSergei Barannikov   // Compute the byval alignment.
78992cb984SSergei Barannikov   const unsigned MinABIStackAlignInBytes = 4;
79992cb984SSergei Barannikov   unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
80992cb984SSergei Barannikov   return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true,
81992cb984SSergei Barannikov                                  TypeAlign > MinABIStackAlignInBytes);
82992cb984SSergei Barannikov }
83992cb984SSergei Barannikov 
EmitVAArg(CodeGenFunction & CGF,Address VAListAddr,QualType Ty,AggValueSlot Slot) const84*6d973b45SMariya Podchishchaeva RValue ARCABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
85*6d973b45SMariya Podchishchaeva                              QualType Ty, AggValueSlot Slot) const {
86992cb984SSergei Barannikov   return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
87992cb984SSergei Barannikov                           getContext().getTypeInfoInChars(Ty),
88*6d973b45SMariya Podchishchaeva                           CharUnits::fromQuantity(4), true, Slot);
89992cb984SSergei Barannikov }
90992cb984SSergei Barannikov 
classifyArgumentType(QualType Ty,uint8_t FreeRegs) const91992cb984SSergei Barannikov ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty,
92992cb984SSergei Barannikov                                             uint8_t FreeRegs) const {
93992cb984SSergei Barannikov   // Handle the generic C++ ABI.
94992cb984SSergei Barannikov   const RecordType *RT = Ty->getAs<RecordType>();
95992cb984SSergei Barannikov   if (RT) {
96992cb984SSergei Barannikov     CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
97992cb984SSergei Barannikov     if (RAA == CGCXXABI::RAA_Indirect)
98992cb984SSergei Barannikov       return getIndirectByRef(Ty, FreeRegs > 0);
99992cb984SSergei Barannikov 
100992cb984SSergei Barannikov     if (RAA == CGCXXABI::RAA_DirectInMemory)
101992cb984SSergei Barannikov       return getIndirectByValue(Ty);
102992cb984SSergei Barannikov   }
103992cb984SSergei Barannikov 
104992cb984SSergei Barannikov   // Treat an enum type as its underlying type.
105992cb984SSergei Barannikov   if (const EnumType *EnumTy = Ty->getAs<EnumType>())
106992cb984SSergei Barannikov     Ty = EnumTy->getDecl()->getIntegerType();
107992cb984SSergei Barannikov 
108992cb984SSergei Barannikov   auto SizeInRegs = llvm::alignTo(getContext().getTypeSize(Ty), 32) / 32;
109992cb984SSergei Barannikov 
110992cb984SSergei Barannikov   if (isAggregateTypeForABI(Ty)) {
111992cb984SSergei Barannikov     // Structures with flexible arrays are always indirect.
112992cb984SSergei Barannikov     if (RT && RT->getDecl()->hasFlexibleArrayMember())
113992cb984SSergei Barannikov       return getIndirectByValue(Ty);
114992cb984SSergei Barannikov 
115992cb984SSergei Barannikov     // Ignore empty structs/unions.
116992cb984SSergei Barannikov     if (isEmptyRecord(getContext(), Ty, true))
117992cb984SSergei Barannikov       return ABIArgInfo::getIgnore();
118992cb984SSergei Barannikov 
119992cb984SSergei Barannikov     llvm::LLVMContext &LLVMContext = getVMContext();
120992cb984SSergei Barannikov 
121992cb984SSergei Barannikov     llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
122992cb984SSergei Barannikov     SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32);
123992cb984SSergei Barannikov     llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
124992cb984SSergei Barannikov 
125992cb984SSergei Barannikov     return FreeRegs >= SizeInRegs ?
126992cb984SSergei Barannikov         ABIArgInfo::getDirectInReg(Result) :
127992cb984SSergei Barannikov         ABIArgInfo::getDirect(Result, 0, nullptr, false);
128992cb984SSergei Barannikov   }
129992cb984SSergei Barannikov 
130992cb984SSergei Barannikov   if (const auto *EIT = Ty->getAs<BitIntType>())
131992cb984SSergei Barannikov     if (EIT->getNumBits() > 64)
132992cb984SSergei Barannikov       return getIndirectByValue(Ty);
133992cb984SSergei Barannikov 
134992cb984SSergei Barannikov   return isPromotableIntegerTypeForABI(Ty)
135992cb984SSergei Barannikov              ? (FreeRegs >= SizeInRegs ? ABIArgInfo::getExtendInReg(Ty)
136992cb984SSergei Barannikov                                        : ABIArgInfo::getExtend(Ty))
137992cb984SSergei Barannikov              : (FreeRegs >= SizeInRegs ? ABIArgInfo::getDirectInReg()
138992cb984SSergei Barannikov                                        : ABIArgInfo::getDirect());
139992cb984SSergei Barannikov }
140992cb984SSergei Barannikov 
classifyReturnType(QualType RetTy) const141992cb984SSergei Barannikov ABIArgInfo ARCABIInfo::classifyReturnType(QualType RetTy) const {
142992cb984SSergei Barannikov   if (RetTy->isAnyComplexType())
143992cb984SSergei Barannikov     return ABIArgInfo::getDirectInReg();
144992cb984SSergei Barannikov 
145992cb984SSergei Barannikov   // Arguments of size > 4 registers are indirect.
146992cb984SSergei Barannikov   auto RetSize = llvm::alignTo(getContext().getTypeSize(RetTy), 32) / 32;
147992cb984SSergei Barannikov   if (RetSize > 4)
148992cb984SSergei Barannikov     return getIndirectByRef(RetTy, /*HasFreeRegs*/ true);
149992cb984SSergei Barannikov 
150992cb984SSergei Barannikov   return DefaultABIInfo::classifyReturnType(RetTy);
151992cb984SSergei Barannikov }
152992cb984SSergei Barannikov 
153992cb984SSergei Barannikov } // End anonymous namespace.
154992cb984SSergei Barannikov 
155992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo>
createARCTargetCodeGenInfo(CodeGenModule & CGM)156992cb984SSergei Barannikov CodeGen::createARCTargetCodeGenInfo(CodeGenModule &CGM) {
157992cb984SSergei Barannikov   return std::make_unique<ARCTargetCodeGenInfo>(CGM.getTypes());
158992cb984SSergei Barannikov }
159