xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/Targets/ARC.cpp (revision e64bea71c21eb42e97aa615188ba91f6cce0d36d)
1 //===- ARC.cpp ------------------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "ABIInfoImpl.h"
10 #include "TargetInfo.h"
11 
12 using namespace clang;
13 using namespace clang::CodeGen;
14 
15 // ARC ABI implementation.
16 namespace {
17 
18 class ARCABIInfo : public DefaultABIInfo {
19   struct CCState {
20     unsigned FreeRegs;
21   };
22 
23 public:
24   using DefaultABIInfo::DefaultABIInfo;
25 
26 private:
27   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
28                    AggValueSlot Slot) const override;
29 
30   void updateState(const ABIArgInfo &Info, QualType Ty, CCState &State) const {
31     if (!State.FreeRegs)
32       return;
33     if (Info.isIndirect() && Info.getInReg())
34       State.FreeRegs--;
35     else if (Info.isDirect() && Info.getInReg()) {
36       unsigned sz = (getContext().getTypeSize(Ty) + 31) / 32;
37       if (sz < State.FreeRegs)
38         State.FreeRegs -= sz;
39       else
40         State.FreeRegs = 0;
41     }
42   }
43 
44   void computeInfo(CGFunctionInfo &FI) const override {
45     CCState State;
46     // ARC uses 8 registers to pass arguments.
47     State.FreeRegs = 8;
48 
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);
55     }
56   }
57 
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;
62 };
63 
64 class ARCTargetCodeGenInfo : public TargetCodeGenInfo {
65 public:
66   ARCTargetCodeGenInfo(CodeGenTypes &CGT)
67       : TargetCodeGenInfo(std::make_unique<ARCABIInfo>(CGT)) {}
68 };
69 
70 
71 ABIArgInfo ARCABIInfo::getIndirectByRef(QualType Ty, bool HasFreeRegs) const {
72   return HasFreeRegs ? getNaturalAlignIndirectInReg(Ty)
73                      : getNaturalAlignIndirect(
74                            Ty, getDataLayout().getAllocaAddrSpace(), false);
75 }
76 
77 ABIArgInfo ARCABIInfo::getIndirectByValue(QualType Ty) const {
78   // Compute the byval alignment.
79   const unsigned MinABIStackAlignInBytes = 4;
80   unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
81   return ABIArgInfo::getIndirect(
82       CharUnits::fromQuantity(4),
83       /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(),
84       /*ByVal=*/true, TypeAlign > MinABIStackAlignInBytes);
85 }
86 
87 RValue ARCABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
88                              QualType Ty, AggValueSlot Slot) const {
89   return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
90                           getContext().getTypeInfoInChars(Ty),
91                           CharUnits::fromQuantity(4), true, Slot);
92 }
93 
94 ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty,
95                                             uint8_t FreeRegs) const {
96   // Handle the generic C++ ABI.
97   const RecordType *RT = Ty->getAs<RecordType>();
98   if (RT) {
99     CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
100     if (RAA == CGCXXABI::RAA_Indirect)
101       return getIndirectByRef(Ty, FreeRegs > 0);
102 
103     if (RAA == CGCXXABI::RAA_DirectInMemory)
104       return getIndirectByValue(Ty);
105   }
106 
107   // Treat an enum type as its underlying type.
108   if (const EnumType *EnumTy = Ty->getAs<EnumType>())
109     Ty = EnumTy->getDecl()->getIntegerType();
110 
111   auto SizeInRegs = llvm::alignTo(getContext().getTypeSize(Ty), 32) / 32;
112 
113   if (isAggregateTypeForABI(Ty)) {
114     // Structures with flexible arrays are always indirect.
115     if (RT && RT->getDecl()->hasFlexibleArrayMember())
116       return getIndirectByValue(Ty);
117 
118     // Ignore empty structs/unions.
119     if (isEmptyRecord(getContext(), Ty, true))
120       return ABIArgInfo::getIgnore();
121 
122     llvm::LLVMContext &LLVMContext = getVMContext();
123 
124     llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
125     SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32);
126     llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
127 
128     return FreeRegs >= SizeInRegs ?
129         ABIArgInfo::getDirectInReg(Result) :
130         ABIArgInfo::getDirect(Result, 0, nullptr, false);
131   }
132 
133   if (const auto *EIT = Ty->getAs<BitIntType>())
134     if (EIT->getNumBits() > 64)
135       return getIndirectByValue(Ty);
136 
137   return isPromotableIntegerTypeForABI(Ty)
138              ? (FreeRegs >= SizeInRegs ? ABIArgInfo::getExtendInReg(Ty)
139                                        : ABIArgInfo::getExtend(Ty))
140              : (FreeRegs >= SizeInRegs ? ABIArgInfo::getDirectInReg()
141                                        : ABIArgInfo::getDirect());
142 }
143 
144 ABIArgInfo ARCABIInfo::classifyReturnType(QualType RetTy) const {
145   if (RetTy->isAnyComplexType())
146     return ABIArgInfo::getDirectInReg();
147 
148   // Arguments of size > 4 registers are indirect.
149   auto RetSize = llvm::alignTo(getContext().getTypeSize(RetTy), 32) / 32;
150   if (RetSize > 4)
151     return getIndirectByRef(RetTy, /*HasFreeRegs*/ true);
152 
153   return DefaultABIInfo::classifyReturnType(RetTy);
154 }
155 
156 } // End anonymous namespace.
157 
158 std::unique_ptr<TargetCodeGenInfo>
159 CodeGen::createARCTargetCodeGenInfo(CodeGenModule &CGM) {
160   return std::make_unique<ARCTargetCodeGenInfo>(CGM.getTypes());
161 }
162