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