xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/Targets/Lanai.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1*06c3fb27SDimitry Andric //===- Lanai.cpp ----------------------------------------------------------===//
2*06c3fb27SDimitry Andric //
3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*06c3fb27SDimitry Andric //
7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
8*06c3fb27SDimitry Andric 
9*06c3fb27SDimitry Andric #include "ABIInfoImpl.h"
10*06c3fb27SDimitry Andric #include "TargetInfo.h"
11*06c3fb27SDimitry Andric 
12*06c3fb27SDimitry Andric using namespace clang;
13*06c3fb27SDimitry Andric using namespace clang::CodeGen;
14*06c3fb27SDimitry Andric 
15*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
16*06c3fb27SDimitry Andric // Lanai ABI Implementation
17*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
18*06c3fb27SDimitry Andric 
19*06c3fb27SDimitry Andric namespace {
20*06c3fb27SDimitry Andric class LanaiABIInfo : public DefaultABIInfo {
21*06c3fb27SDimitry Andric   struct CCState {
22*06c3fb27SDimitry Andric     unsigned FreeRegs;
23*06c3fb27SDimitry Andric   };
24*06c3fb27SDimitry Andric 
25*06c3fb27SDimitry Andric public:
LanaiABIInfo(CodeGen::CodeGenTypes & CGT)26*06c3fb27SDimitry Andric   LanaiABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
27*06c3fb27SDimitry Andric 
28*06c3fb27SDimitry Andric   bool shouldUseInReg(QualType Ty, CCState &State) const;
29*06c3fb27SDimitry Andric 
computeInfo(CGFunctionInfo & FI) const30*06c3fb27SDimitry Andric   void computeInfo(CGFunctionInfo &FI) const override {
31*06c3fb27SDimitry Andric     CCState State;
32*06c3fb27SDimitry Andric     // Lanai uses 4 registers to pass arguments unless the function has the
33*06c3fb27SDimitry Andric     // regparm attribute set.
34*06c3fb27SDimitry Andric     if (FI.getHasRegParm()) {
35*06c3fb27SDimitry Andric       State.FreeRegs = FI.getRegParm();
36*06c3fb27SDimitry Andric     } else {
37*06c3fb27SDimitry Andric       State.FreeRegs = 4;
38*06c3fb27SDimitry Andric     }
39*06c3fb27SDimitry Andric 
40*06c3fb27SDimitry Andric     if (!getCXXABI().classifyReturnType(FI))
41*06c3fb27SDimitry Andric       FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
42*06c3fb27SDimitry Andric     for (auto &I : FI.arguments())
43*06c3fb27SDimitry Andric       I.info = classifyArgumentType(I.type, State);
44*06c3fb27SDimitry Andric   }
45*06c3fb27SDimitry Andric 
46*06c3fb27SDimitry Andric   ABIArgInfo getIndirectResult(QualType Ty, bool ByVal, CCState &State) const;
47*06c3fb27SDimitry Andric   ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const;
48*06c3fb27SDimitry Andric };
49*06c3fb27SDimitry Andric } // end anonymous namespace
50*06c3fb27SDimitry Andric 
shouldUseInReg(QualType Ty,CCState & State) const51*06c3fb27SDimitry Andric bool LanaiABIInfo::shouldUseInReg(QualType Ty, CCState &State) const {
52*06c3fb27SDimitry Andric   unsigned Size = getContext().getTypeSize(Ty);
53*06c3fb27SDimitry Andric   unsigned SizeInRegs = llvm::alignTo(Size, 32U) / 32U;
54*06c3fb27SDimitry Andric 
55*06c3fb27SDimitry Andric   if (SizeInRegs == 0)
56*06c3fb27SDimitry Andric     return false;
57*06c3fb27SDimitry Andric 
58*06c3fb27SDimitry Andric   if (SizeInRegs > State.FreeRegs) {
59*06c3fb27SDimitry Andric     State.FreeRegs = 0;
60*06c3fb27SDimitry Andric     return false;
61*06c3fb27SDimitry Andric   }
62*06c3fb27SDimitry Andric 
63*06c3fb27SDimitry Andric   State.FreeRegs -= SizeInRegs;
64*06c3fb27SDimitry Andric 
65*06c3fb27SDimitry Andric   return true;
66*06c3fb27SDimitry Andric }
67*06c3fb27SDimitry Andric 
getIndirectResult(QualType Ty,bool ByVal,CCState & State) const68*06c3fb27SDimitry Andric ABIArgInfo LanaiABIInfo::getIndirectResult(QualType Ty, bool ByVal,
69*06c3fb27SDimitry Andric                                            CCState &State) const {
70*06c3fb27SDimitry Andric   if (!ByVal) {
71*06c3fb27SDimitry Andric     if (State.FreeRegs) {
72*06c3fb27SDimitry Andric       --State.FreeRegs; // Non-byval indirects just use one pointer.
73*06c3fb27SDimitry Andric       return getNaturalAlignIndirectInReg(Ty);
74*06c3fb27SDimitry Andric     }
75*06c3fb27SDimitry Andric     return getNaturalAlignIndirect(Ty, false);
76*06c3fb27SDimitry Andric   }
77*06c3fb27SDimitry Andric 
78*06c3fb27SDimitry Andric   // Compute the byval alignment.
79*06c3fb27SDimitry Andric   const unsigned MinABIStackAlignInBytes = 4;
80*06c3fb27SDimitry Andric   unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
81*06c3fb27SDimitry Andric   return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true,
82*06c3fb27SDimitry Andric                                  /*Realign=*/TypeAlign >
83*06c3fb27SDimitry Andric                                      MinABIStackAlignInBytes);
84*06c3fb27SDimitry Andric }
85*06c3fb27SDimitry Andric 
classifyArgumentType(QualType Ty,CCState & State) const86*06c3fb27SDimitry Andric ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty,
87*06c3fb27SDimitry Andric                                               CCState &State) const {
88*06c3fb27SDimitry Andric   // Check with the C++ ABI first.
89*06c3fb27SDimitry Andric   const RecordType *RT = Ty->getAs<RecordType>();
90*06c3fb27SDimitry Andric   if (RT) {
91*06c3fb27SDimitry Andric     CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
92*06c3fb27SDimitry Andric     if (RAA == CGCXXABI::RAA_Indirect) {
93*06c3fb27SDimitry Andric       return getIndirectResult(Ty, /*ByVal=*/false, State);
94*06c3fb27SDimitry Andric     } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
95*06c3fb27SDimitry Andric       return getNaturalAlignIndirect(Ty, /*ByVal=*/true);
96*06c3fb27SDimitry Andric     }
97*06c3fb27SDimitry Andric   }
98*06c3fb27SDimitry Andric 
99*06c3fb27SDimitry Andric   if (isAggregateTypeForABI(Ty)) {
100*06c3fb27SDimitry Andric     // Structures with flexible arrays are always indirect.
101*06c3fb27SDimitry Andric     if (RT && RT->getDecl()->hasFlexibleArrayMember())
102*06c3fb27SDimitry Andric       return getIndirectResult(Ty, /*ByVal=*/true, State);
103*06c3fb27SDimitry Andric 
104*06c3fb27SDimitry Andric     // Ignore empty structs/unions.
105*06c3fb27SDimitry Andric     if (isEmptyRecord(getContext(), Ty, true))
106*06c3fb27SDimitry Andric       return ABIArgInfo::getIgnore();
107*06c3fb27SDimitry Andric 
108*06c3fb27SDimitry Andric     llvm::LLVMContext &LLVMContext = getVMContext();
109*06c3fb27SDimitry Andric     unsigned SizeInRegs = (getContext().getTypeSize(Ty) + 31) / 32;
110*06c3fb27SDimitry Andric     if (SizeInRegs <= State.FreeRegs) {
111*06c3fb27SDimitry Andric       llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
112*06c3fb27SDimitry Andric       SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32);
113*06c3fb27SDimitry Andric       llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
114*06c3fb27SDimitry Andric       State.FreeRegs -= SizeInRegs;
115*06c3fb27SDimitry Andric       return ABIArgInfo::getDirectInReg(Result);
116*06c3fb27SDimitry Andric     } else {
117*06c3fb27SDimitry Andric       State.FreeRegs = 0;
118*06c3fb27SDimitry Andric     }
119*06c3fb27SDimitry Andric     return getIndirectResult(Ty, true, State);
120*06c3fb27SDimitry Andric   }
121*06c3fb27SDimitry Andric 
122*06c3fb27SDimitry Andric   // Treat an enum type as its underlying type.
123*06c3fb27SDimitry Andric   if (const auto *EnumTy = Ty->getAs<EnumType>())
124*06c3fb27SDimitry Andric     Ty = EnumTy->getDecl()->getIntegerType();
125*06c3fb27SDimitry Andric 
126*06c3fb27SDimitry Andric   bool InReg = shouldUseInReg(Ty, State);
127*06c3fb27SDimitry Andric 
128*06c3fb27SDimitry Andric   // Don't pass >64 bit integers in registers.
129*06c3fb27SDimitry Andric   if (const auto *EIT = Ty->getAs<BitIntType>())
130*06c3fb27SDimitry Andric     if (EIT->getNumBits() > 64)
131*06c3fb27SDimitry Andric       return getIndirectResult(Ty, /*ByVal=*/true, State);
132*06c3fb27SDimitry Andric 
133*06c3fb27SDimitry Andric   if (isPromotableIntegerTypeForABI(Ty)) {
134*06c3fb27SDimitry Andric     if (InReg)
135*06c3fb27SDimitry Andric       return ABIArgInfo::getDirectInReg();
136*06c3fb27SDimitry Andric     return ABIArgInfo::getExtend(Ty);
137*06c3fb27SDimitry Andric   }
138*06c3fb27SDimitry Andric   if (InReg)
139*06c3fb27SDimitry Andric     return ABIArgInfo::getDirectInReg();
140*06c3fb27SDimitry Andric   return ABIArgInfo::getDirect();
141*06c3fb27SDimitry Andric }
142*06c3fb27SDimitry Andric 
143*06c3fb27SDimitry Andric namespace {
144*06c3fb27SDimitry Andric class LanaiTargetCodeGenInfo : public TargetCodeGenInfo {
145*06c3fb27SDimitry Andric public:
LanaiTargetCodeGenInfo(CodeGen::CodeGenTypes & CGT)146*06c3fb27SDimitry Andric   LanaiTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
147*06c3fb27SDimitry Andric       : TargetCodeGenInfo(std::make_unique<LanaiABIInfo>(CGT)) {}
148*06c3fb27SDimitry Andric };
149*06c3fb27SDimitry Andric }
150*06c3fb27SDimitry Andric 
151*06c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo>
createLanaiTargetCodeGenInfo(CodeGenModule & CGM)152*06c3fb27SDimitry Andric CodeGen::createLanaiTargetCodeGenInfo(CodeGenModule &CGM) {
153*06c3fb27SDimitry Andric   return std::make_unique<LanaiTargetCodeGenInfo>(CGM.getTypes());
154*06c3fb27SDimitry Andric }
155