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