1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef MAPLEBE_INCLUDE_CG_X64_X64_CALL_CONV_H
17 #define MAPLEBE_INCLUDE_CG_X64_X64_CALL_CONV_H
18
19 #include "types_def.h"
20 #include "becommon.h"
21 #include "call_conv.h"
22 #include "abi.h"
23 #include "x64_abi.h"
24 #include "x64_isa.h"
25 #include <vector>
26
27 namespace maplebe {
28 using namespace maple;
29 using namespace x64;
30 constexpr const uint32 kMaxStructParamByReg = 4;
31
32 class CallConventionInfo {
33 public:
34 virtual const std::vector<X64reg> &GetIntParamRegs() const = 0;
35 virtual size_t GetIntParamRegsNum() const = 0;
36 virtual const std::vector<X64reg> &GetIntReturnRegs() const = 0;
37 virtual size_t GetIntReturnRegsNum() const = 0;
38 virtual const std::vector<X64reg> &GetFloatParamRegs() const = 0;
39 virtual size_t GetFloatParamRegsNum() const = 0;
40 virtual const std::vector<X64reg> &GetFloatReturnRegs() const = 0;
41 virtual size_t GetFloatReturnRegsNum() const = 0;
42 virtual int32 Classification(const BECommon &be, MIRType &mirType, std::vector<ArgumentClass> &classes) const = 0;
43 };
44
45 #define CALL_CONVENTION_INFO_SUBCLASS_DECLARE_BEGIN(CLASSNAME) \
46 class CLASSNAME : public CallConventionInfo { \
47 public: \
48 const std::vector<X64reg> &GetIntParamRegs() const override \
49 { \
50 return intParmRegs; \
51 } \
52 size_t GetIntParamRegsNum() const override \
53 { \
54 return intParmRegs.size(); \
55 } \
56 const std::vector<X64reg> &GetIntReturnRegs() const override \
57 { \
58 return intReturnRegs; \
59 } \
60 size_t GetIntReturnRegsNum() const override \
61 { \
62 return intReturnRegs.size(); \
63 } \
64 const std::vector<X64reg> &GetFloatParamRegs() const override \
65 { \
66 return floatParmRegs; \
67 } \
68 size_t GetFloatParamRegsNum() const override \
69 { \
70 return floatParmRegs.size(); \
71 } \
72 const std::vector<X64reg> &GetFloatReturnRegs() const override \
73 { \
74 return floatReturnRegs; \
75 } \
76 size_t GetFloatReturnRegsNum() const override \
77 { \
78 return floatReturnRegs.size(); \
79 } \
80 const static CLASSNAME &GetCallConvInfo() \
81 { \
82 static CLASSNAME callConvInfo; \
83 return callConvInfo; \
84 } \
85 int32 Classification(const BECommon &be, MIRType &mirType, \
86 std::vector<ArgumentClass> &classes) const override; \
87 \
88 private: \
89 CLASSNAME() {} \
90 ~CLASSNAME() {} \
91 CLASSNAME &operator=(const CLASSNAME &); \
92 CLASSNAME(const CLASSNAME &);
93
94 #define CALL_CONVENTION_INFO_SUBCLASS_DECLARE_END \
95 } \
96 ;
97
CALL_CONVENTION_INFO_SUBCLASS_DECLARE_BEGIN(WebKitJSCallConventionInfo)98 CALL_CONVENTION_INFO_SUBCLASS_DECLARE_BEGIN(WebKitJSCallConventionInfo)
99
100 const std::vector<X64reg> intParmRegs {
101 RAX};
102 const std::vector<X64reg> intReturnRegs {
103 RAX};
104 const std::vector<X64reg> floatParmRegs{};
105 const std::vector<X64reg> floatReturnRegs{};
106 CALL_CONVENTION_INFO_SUBCLASS_DECLARE_END
107
CALL_CONVENTION_INFO_SUBCLASS_DECLARE_BEGIN(CCallConventionInfo)108 CALL_CONVENTION_INFO_SUBCLASS_DECLARE_BEGIN(CCallConventionInfo)
109 const std::vector<X64reg> intParmRegs {
110 RDI, RSI, RDX, RCX, X64reg::R8, X64reg::R9};
111 const std::vector<X64reg> intReturnRegs {
112 RAX, RDX};
113 const std::vector<X64reg> floatParmRegs = {
114 X64reg::V0, X64reg::V1, X64reg::V2, X64reg::V3, X64reg::V4, X64reg::V5, X64reg::V6, X64reg::V7};
115 const std::vector<X64reg> floatReturnRegs = {
116 X64reg::V0, X64reg::V1 };
117
118 int32 ClassifyAggregate(MIRType &mirType, uint64 sizeOfTy, std::vector<ArgumentClass> &classes) const;
119 CALL_CONVENTION_INFO_SUBCLASS_DECLARE_END
120
CALL_CONVENTION_INFO_SUBCLASS_DECLARE_BEGIN(GHCCallConventionInfo)121 CALL_CONVENTION_INFO_SUBCLASS_DECLARE_BEGIN(GHCCallConventionInfo)
122 const std::vector<X64reg> intParmRegs {
123 X64reg::R13, RBP, X64reg::R12, RBX, X64reg::R14, RSI, RDI, X64reg::R8, X64reg::R9, X64reg::R15};
124 const std::vector<X64reg> intReturnRegs{};
125 const std::vector<X64reg> floatParmRegs{};
126 const std::vector<X64reg> floatReturnRegs{};
127 CALL_CONVENTION_INFO_SUBCLASS_DECLARE_END
128
129 class X64CallConvImpl {
130 public:
X64CallConvImpl(BECommon & be)131 X64CallConvImpl(BECommon &be) : beCommon(be)
132 {
133 convKind = GetCallConvKind(*(be.GetMIRModule().CurFunction()));
134 }
X64CallConvImpl(BECommon & be,CallConvKind convKind)135 X64CallConvImpl(BECommon &be, CallConvKind convKind) : beCommon(be), convKind(convKind) {}
136
137 ~X64CallConvImpl() = default;
138
GetCallConvInfo()139 const CallConventionInfo &GetCallConvInfo() const
140 {
141 return GetCallConvInfo(convKind);
142 }
143
GetCallConvInfo(CallConvKind convKind_)144 static const CallConventionInfo &GetCallConvInfo(CallConvKind convKind_)
145 {
146 switch (convKind_) {
147 case kCCall:
148 return CCallConventionInfo::GetCallConvInfo();
149 case kWebKitJS:
150 return WebKitJSCallConventionInfo::GetCallConvInfo();
151 case kGHC:
152 return GHCCallConventionInfo::GetCallConvInfo();
153 default:
154 return CCallConventionInfo::GetCallConvInfo();
155 }
156 }
157
GetCallConvKind(MIRFunction & mirFunction)158 static CallConvKind GetCallConvKind(MIRFunction &mirFunction)
159 {
160 if (mirFunction.GetAttr(FUNCATTR_ccall)) {
161 return kCCall;
162 } else if (mirFunction.GetAttr(FUNCATTR_webkitjscall)) {
163 return kWebKitJS;
164 } else if (mirFunction.GetAttr(FUNCATTR_ghcall)) {
165 return kGHC;
166 } else {
167 return kCCall;
168 }
169 }
170
GetCallConvKind(StmtNode & node)171 static CallConvKind GetCallConvKind(StmtNode &node)
172 {
173 if (node.GetAttr(STMTATTR_ccall)) {
174 return kCCall;
175 } else if (node.GetAttr(STMTATTR_webkitjscall)) {
176 return kWebKitJS;
177 } else if (node.GetAttr(STMTATTR_ghcall)) {
178 return kGHC;
179 } else {
180 return kCCall;
181 }
182 }
183
184 void InitCCLocInfo(CCLocInfo &pLoc) const;
185
186 /* Passing value related */
187 int32 LocateNextParm(MIRType &mirType, CCLocInfo &pLoc, bool isFirst = false, MIRFunction *func = nullptr);
188
189 /* return value related */
190 int32 LocateRetVal(MIRType &retType, CCLocInfo &ploc);
191
192 private:
AllocateGPParmRegister()193 X64reg AllocateGPParmRegister()
194 {
195 const std::vector<X64reg> &intParamRegs = GetCallConvInfo().GetIntParamRegs();
196 return (nextGeneralParmRegNO < intParamRegs.size()) ? intParamRegs[nextGeneralParmRegNO++] : X64reg::kRinvalid;
197 }
198
AllocateTwoGPParmRegisters(CCLocInfo & pLoc)199 void AllocateTwoGPParmRegisters(CCLocInfo &pLoc)
200 {
201 const std::vector<X64reg> &intParamRegs = GetCallConvInfo().GetIntParamRegs();
202 if ((nextGeneralParmRegNO + 1) < intParamRegs.size()) {
203 pLoc.reg0 = intParamRegs[nextGeneralParmRegNO++];
204 pLoc.reg1 = intParamRegs[nextGeneralParmRegNO++];
205 } else {
206 pLoc.reg0 = X64reg::kRinvalid;
207 }
208 }
209
AllocateSIMDFPRegister()210 X64reg AllocateSIMDFPRegister()
211 {
212 return (nextFloatRegNO < kNumFloatParmRegs) ? kFloatParmRegs[nextFloatRegNO++] : X64reg::kRinvalid;
213 }
214
AllocateGPReturnRegister()215 X64reg AllocateGPReturnRegister()
216 {
217 const std::vector<X64reg> &intReturnRegs = GetCallConvInfo().GetIntReturnRegs();
218 return (nextGeneralReturnRegNO < intReturnRegs.size()) ?
219 intReturnRegs[nextGeneralReturnRegNO++] : X64reg::kRinvalid;
220 }
221
AllocateTwoGPReturnRegisters(CCLocInfo & pLoc)222 void AllocateTwoGPReturnRegisters(CCLocInfo &pLoc)
223 {
224 const std::vector<X64reg> &intReturnRegs = GetCallConvInfo().GetIntReturnRegs();
225 if ((nextGeneralReturnRegNO + 1) < intReturnRegs.size()) {
226 pLoc.reg0 = intReturnRegs[nextGeneralReturnRegNO++];
227 pLoc.reg1 = intReturnRegs[nextGeneralReturnRegNO++];
228 } else {
229 pLoc.reg0 = X64reg::kRinvalid;
230 }
231 }
232
AllocateSIMDFPReturnRegister()233 X64reg AllocateSIMDFPReturnRegister()
234 {
235 return (nextFloatRetRegNO < kNumFloatReturnRegs) ? kFloatReturnRegs[nextFloatRetRegNO++] : X64reg::kRinvalid;
236 }
237
238 BECommon &beCommon;
239 CallConvKind convKind = kCCall;
240 uint64 paramNum = 0; /* number of all types of parameters processed so far */
241 uint32 nextGeneralParmRegNO = 0; /* number of integer parameters processed so far */
242 uint32 nextGeneralReturnRegNO = 0; /* number of integer return processed so far */
243 uint32 nextStackArgAdress = 0;
244 uint32 nextFloatRegNO = 0;
245 uint32 nextFloatRetRegNO = 0;
246 };
247 } /* namespace maplebe */
248
249 #endif /* MAPLEBE_INCLUDE_CG_X64_X64_CALL_CONV_H */
250