xref: /llvm-project/clang/lib/CodeGen/Targets/CSKY.cpp (revision 6d973b4548e281d0b8e75e85833804bb45b6a0e8)
1992cb984SSergei Barannikov //===- CSKY.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 //===----------------------------------------------------------------------===//
16992cb984SSergei Barannikov // CSKY ABI Implementation
17992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
18992cb984SSergei Barannikov namespace {
19992cb984SSergei Barannikov class CSKYABIInfo : public DefaultABIInfo {
20992cb984SSergei Barannikov   static const int NumArgGPRs = 4;
21992cb984SSergei Barannikov   static const int NumArgFPRs = 4;
22992cb984SSergei Barannikov 
23992cb984SSergei Barannikov   static const unsigned XLen = 32;
24992cb984SSergei Barannikov   unsigned FLen;
25992cb984SSergei Barannikov 
26992cb984SSergei Barannikov public:
CSKYABIInfo(CodeGen::CodeGenTypes & CGT,unsigned FLen)27992cb984SSergei Barannikov   CSKYABIInfo(CodeGen::CodeGenTypes &CGT, unsigned FLen)
28992cb984SSergei Barannikov       : DefaultABIInfo(CGT), FLen(FLen) {}
29992cb984SSergei Barannikov 
30992cb984SSergei Barannikov   void computeInfo(CGFunctionInfo &FI) const override;
31992cb984SSergei Barannikov   ABIArgInfo classifyArgumentType(QualType Ty, int &ArgGPRsLeft,
32992cb984SSergei Barannikov                                   int &ArgFPRsLeft,
33992cb984SSergei Barannikov                                   bool isReturnType = false) const;
34992cb984SSergei Barannikov   ABIArgInfo classifyReturnType(QualType RetTy) const;
35992cb984SSergei Barannikov 
36*6d973b45SMariya Podchishchaeva   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
37*6d973b45SMariya Podchishchaeva                    AggValueSlot Slot) const override;
38992cb984SSergei Barannikov };
39992cb984SSergei Barannikov 
40992cb984SSergei Barannikov } // end anonymous namespace
41992cb984SSergei Barannikov 
computeInfo(CGFunctionInfo & FI) const42992cb984SSergei Barannikov void CSKYABIInfo::computeInfo(CGFunctionInfo &FI) const {
43992cb984SSergei Barannikov   QualType RetTy = FI.getReturnType();
44992cb984SSergei Barannikov   if (!getCXXABI().classifyReturnType(FI))
45992cb984SSergei Barannikov     FI.getReturnInfo() = classifyReturnType(RetTy);
46992cb984SSergei Barannikov 
47992cb984SSergei Barannikov   bool IsRetIndirect = FI.getReturnInfo().getKind() == ABIArgInfo::Indirect;
48992cb984SSergei Barannikov 
49992cb984SSergei Barannikov   // We must track the number of GPRs used in order to conform to the CSKY
50992cb984SSergei Barannikov   // ABI, as integer scalars passed in registers should have signext/zeroext
51992cb984SSergei Barannikov   // when promoted.
52992cb984SSergei Barannikov   int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs;
53992cb984SSergei Barannikov   int ArgFPRsLeft = FLen ? NumArgFPRs : 0;
54992cb984SSergei Barannikov 
55992cb984SSergei Barannikov   for (auto &ArgInfo : FI.arguments()) {
56992cb984SSergei Barannikov     ArgInfo.info = classifyArgumentType(ArgInfo.type, ArgGPRsLeft, ArgFPRsLeft);
57992cb984SSergei Barannikov   }
58992cb984SSergei Barannikov }
59992cb984SSergei Barannikov 
EmitVAArg(CodeGenFunction & CGF,Address VAListAddr,QualType Ty,AggValueSlot Slot) const60*6d973b45SMariya Podchishchaeva RValue CSKYABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
61*6d973b45SMariya Podchishchaeva                               QualType Ty, AggValueSlot Slot) const {
62992cb984SSergei Barannikov   CharUnits SlotSize = CharUnits::fromQuantity(XLen / 8);
63992cb984SSergei Barannikov 
64992cb984SSergei Barannikov   // Empty records are ignored for parameter passing purposes.
65*6d973b45SMariya Podchishchaeva   if (isEmptyRecord(getContext(), Ty, true))
66*6d973b45SMariya Podchishchaeva     return Slot.asRValue();
67992cb984SSergei Barannikov 
68992cb984SSergei Barannikov   auto TInfo = getContext().getTypeInfoInChars(Ty);
69992cb984SSergei Barannikov 
70992cb984SSergei Barannikov   return emitVoidPtrVAArg(CGF, VAListAddr, Ty, false, TInfo, SlotSize,
71*6d973b45SMariya Podchishchaeva                           /*AllowHigherAlign=*/true, Slot);
72992cb984SSergei Barannikov }
73992cb984SSergei Barannikov 
classifyArgumentType(QualType Ty,int & ArgGPRsLeft,int & ArgFPRsLeft,bool isReturnType) const74992cb984SSergei Barannikov ABIArgInfo CSKYABIInfo::classifyArgumentType(QualType Ty, int &ArgGPRsLeft,
75992cb984SSergei Barannikov                                              int &ArgFPRsLeft,
76992cb984SSergei Barannikov                                              bool isReturnType) const {
77992cb984SSergei Barannikov   assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow");
78992cb984SSergei Barannikov   Ty = useFirstFieldIfTransparentUnion(Ty);
79992cb984SSergei Barannikov 
80992cb984SSergei Barannikov   // Structures with either a non-trivial destructor or a non-trivial
81992cb984SSergei Barannikov   // copy constructor are always passed indirectly.
82992cb984SSergei Barannikov   if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
83992cb984SSergei Barannikov     if (ArgGPRsLeft)
84992cb984SSergei Barannikov       ArgGPRsLeft -= 1;
85992cb984SSergei Barannikov     return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA ==
86992cb984SSergei Barannikov                                            CGCXXABI::RAA_DirectInMemory);
87992cb984SSergei Barannikov   }
88992cb984SSergei Barannikov 
89992cb984SSergei Barannikov   // Ignore empty structs/unions.
90992cb984SSergei Barannikov   if (isEmptyRecord(getContext(), Ty, true))
91992cb984SSergei Barannikov     return ABIArgInfo::getIgnore();
92992cb984SSergei Barannikov 
93992cb984SSergei Barannikov   if (!Ty->getAsUnionType())
94992cb984SSergei Barannikov     if (const Type *SeltTy = isSingleElementStruct(Ty, getContext()))
95992cb984SSergei Barannikov       return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));
96992cb984SSergei Barannikov 
97992cb984SSergei Barannikov   uint64_t Size = getContext().getTypeSize(Ty);
98992cb984SSergei Barannikov   // Pass floating point values via FPRs if possible.
99992cb984SSergei Barannikov   if (Ty->isFloatingType() && !Ty->isComplexType() && FLen >= Size &&
100992cb984SSergei Barannikov       ArgFPRsLeft) {
101992cb984SSergei Barannikov     ArgFPRsLeft--;
102992cb984SSergei Barannikov     return ABIArgInfo::getDirect();
103992cb984SSergei Barannikov   }
104992cb984SSergei Barannikov 
105992cb984SSergei Barannikov   // Complex types for the hard float ABI must be passed direct rather than
106992cb984SSergei Barannikov   // using CoerceAndExpand.
107992cb984SSergei Barannikov   if (Ty->isComplexType() && FLen && !isReturnType) {
108992cb984SSergei Barannikov     QualType EltTy = Ty->castAs<ComplexType>()->getElementType();
109992cb984SSergei Barannikov     if (getContext().getTypeSize(EltTy) <= FLen) {
110992cb984SSergei Barannikov       ArgFPRsLeft -= 2;
111992cb984SSergei Barannikov       return ABIArgInfo::getDirect();
112992cb984SSergei Barannikov     }
113992cb984SSergei Barannikov   }
114992cb984SSergei Barannikov 
115992cb984SSergei Barannikov   if (!isAggregateTypeForABI(Ty)) {
116992cb984SSergei Barannikov     // Treat an enum type as its underlying type.
117992cb984SSergei Barannikov     if (const EnumType *EnumTy = Ty->getAs<EnumType>())
118992cb984SSergei Barannikov       Ty = EnumTy->getDecl()->getIntegerType();
119992cb984SSergei Barannikov 
120992cb984SSergei Barannikov     // All integral types are promoted to XLen width, unless passed on the
121992cb984SSergei Barannikov     // stack.
122992cb984SSergei Barannikov     if (Size < XLen && Ty->isIntegralOrEnumerationType())
123992cb984SSergei Barannikov       return ABIArgInfo::getExtend(Ty);
124992cb984SSergei Barannikov 
125992cb984SSergei Barannikov     if (const auto *EIT = Ty->getAs<BitIntType>()) {
126992cb984SSergei Barannikov       if (EIT->getNumBits() < XLen)
127992cb984SSergei Barannikov         return ABIArgInfo::getExtend(Ty);
128992cb984SSergei Barannikov     }
129992cb984SSergei Barannikov 
130992cb984SSergei Barannikov     return ABIArgInfo::getDirect();
131992cb984SSergei Barannikov   }
132992cb984SSergei Barannikov 
133992cb984SSergei Barannikov   // For argument type, the first 4*XLen parts of aggregate will be passed
134992cb984SSergei Barannikov   // in registers, and the rest will be passed in stack.
135992cb984SSergei Barannikov   // So we can coerce to integers directly and let backend handle it correctly.
136992cb984SSergei Barannikov   // For return type, aggregate which <= 2*XLen will be returned in registers.
137992cb984SSergei Barannikov   // Otherwise, aggregate will be returned indirectly.
138992cb984SSergei Barannikov   if (!isReturnType || (isReturnType && Size <= 2 * XLen)) {
139992cb984SSergei Barannikov     if (Size <= XLen) {
140992cb984SSergei Barannikov       return ABIArgInfo::getDirect(
141992cb984SSergei Barannikov           llvm::IntegerType::get(getVMContext(), XLen));
142992cb984SSergei Barannikov     } else {
143992cb984SSergei Barannikov       return ABIArgInfo::getDirect(llvm::ArrayType::get(
144992cb984SSergei Barannikov           llvm::IntegerType::get(getVMContext(), XLen), (Size + 31) / XLen));
145992cb984SSergei Barannikov     }
146992cb984SSergei Barannikov   }
147992cb984SSergei Barannikov   return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
148992cb984SSergei Barannikov }
149992cb984SSergei Barannikov 
classifyReturnType(QualType RetTy) const150992cb984SSergei Barannikov ABIArgInfo CSKYABIInfo::classifyReturnType(QualType RetTy) const {
151992cb984SSergei Barannikov   if (RetTy->isVoidType())
152992cb984SSergei Barannikov     return ABIArgInfo::getIgnore();
153992cb984SSergei Barannikov 
154992cb984SSergei Barannikov   int ArgGPRsLeft = 2;
155992cb984SSergei Barannikov   int ArgFPRsLeft = FLen ? 1 : 0;
156992cb984SSergei Barannikov 
157992cb984SSergei Barannikov   // The rules for return and argument types are the same, so defer to
158992cb984SSergei Barannikov   // classifyArgumentType.
159992cb984SSergei Barannikov   return classifyArgumentType(RetTy, ArgGPRsLeft, ArgFPRsLeft, true);
160992cb984SSergei Barannikov }
161992cb984SSergei Barannikov 
162992cb984SSergei Barannikov namespace {
163992cb984SSergei Barannikov class CSKYTargetCodeGenInfo : public TargetCodeGenInfo {
164992cb984SSergei Barannikov public:
CSKYTargetCodeGenInfo(CodeGen::CodeGenTypes & CGT,unsigned FLen)165992cb984SSergei Barannikov   CSKYTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned FLen)
166992cb984SSergei Barannikov       : TargetCodeGenInfo(std::make_unique<CSKYABIInfo>(CGT, FLen)) {}
167992cb984SSergei Barannikov };
168992cb984SSergei Barannikov } // end anonymous namespace
169992cb984SSergei Barannikov 
170992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo>
createCSKYTargetCodeGenInfo(CodeGenModule & CGM,unsigned FLen)171992cb984SSergei Barannikov CodeGen::createCSKYTargetCodeGenInfo(CodeGenModule &CGM, unsigned FLen) {
172992cb984SSergei Barannikov   return std::make_unique<CSKYTargetCodeGenInfo>(CGM.getTypes(), FLen);
173992cb984SSergei Barannikov }
174