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_AARCH64_AARCH64_CALL_CONV_H 17 #define MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_CALL_CONV_H 18 19 #include "types_def.h" 20 #include "becommon.h" 21 #include "call_conv.h" 22 #include "aarch64_abi.h" 23 #include "abi.h" 24 25 namespace maplebe { 26 using namespace maple; 27 28 /* 29 * We use the names used in ARM IHI 0055C_beta. $ 5.4.2. 30 * nextGeneralRegNO (= _int_parm_num) : Next General-purpose Register number 31 * nextFloatRegNO (= _float_parm_num): Next SIMD and Floating-point Register Number 32 * nextStackArgAdress (= _last_memOffset): Next Stacked Argument Address 33 * for processing an incoming or outgoing parameter list 34 */ 35 36 class AArch64CallConvImpl : public CCImpl { 37 public: AArch64CallConvImpl(BECommon & be)38 explicit AArch64CallConvImpl(BECommon &be) : CCImpl(), beCommon(be) {} 39 40 ~AArch64CallConvImpl() = default; 41 42 /* Return size of aggregate structure copy on stack. */ 43 int32 LocateNextParm(MIRType &mirType, CCLocInfo &pLoc, bool isFirst = false, MIRFunction *func = nullptr) override; 44 45 int32 LocateRetVal(MIRType &retType, CCLocInfo &ploc) override; 46 47 /* for lmbc */ 48 uint32 FloatParamRegRequired(MIRStructType &structType, uint32 &fpSize); 49 50 /* return value related */ 51 void InitReturnInfo(MIRType &retTy, CCLocInfo &pLoc) override; 52 53 void SetupSecondRetReg(const MIRType &retTy2, CCLocInfo &pLoc) const override; 54 SetupToReturnThroughMemory(CCLocInfo & pLoc)55 void SetupToReturnThroughMemory(CCLocInfo &pLoc) const 56 { 57 pLoc.regCount = 1; 58 pLoc.reg0 = R8; 59 pLoc.primTypeOfReg0 = PTY_u64; 60 } 61 Init()62 void Init() override 63 { 64 paramNum = 0; 65 nextGeneralRegNO = 0; 66 nextFloatRegNO = 0; 67 nextStackArgAdress = 0; 68 } 69 70 private: 71 BECommon &beCommon; 72 uint64 paramNum = 0; /* number of all types of parameters processed so far */ 73 int32 nextGeneralRegNO = 0; /* number of integer parameters processed so far */ 74 uint32 nextFloatRegNO = 0; /* number of float parameters processed so far */ 75 AllocateGPRegister()76 AArch64reg AllocateGPRegister() 77 { 78 DEBUG_ASSERT(nextGeneralRegNO >= 0, "nextGeneralRegNO can not be neg"); 79 return (nextGeneralRegNO < AArch64Abi::kNumIntParmRegs) ? AArch64Abi::intParmRegs[nextGeneralRegNO++] 80 : kRinvalid; 81 } 82 AllocateTwoGPRegisters(CCLocInfo & pLoc)83 void AllocateTwoGPRegisters(CCLocInfo &pLoc) 84 { 85 if ((nextGeneralRegNO + 1) < AArch64Abi::kNumIntParmRegs) { 86 pLoc.reg0 = AArch64Abi::intParmRegs[nextGeneralRegNO++]; 87 pLoc.reg1 = AArch64Abi::intParmRegs[nextGeneralRegNO++]; 88 } else { 89 pLoc.reg0 = kRinvalid; 90 } 91 } 92 AllocateSIMDFPRegister()93 AArch64reg AllocateSIMDFPRegister() 94 { 95 return (nextFloatRegNO < AArch64Abi::kNumFloatParmRegs) ? AArch64Abi::floatParmRegs[nextFloatRegNO++] 96 : kRinvalid; 97 } 98 AllocateNSIMDFPRegisters(CCLocInfo & ploc,uint32 num)99 void AllocateNSIMDFPRegisters(CCLocInfo &ploc, uint32 num) 100 { 101 if ((nextFloatRegNO + num - 1) < AArch64Abi::kNumFloatParmRegs) { 102 switch (num) { 103 case kOneRegister: 104 ploc.reg0 = AArch64Abi::floatParmRegs[nextFloatRegNO++]; 105 break; 106 case kTwoRegister: 107 ploc.reg0 = AArch64Abi::floatParmRegs[nextFloatRegNO++]; 108 ploc.reg1 = AArch64Abi::floatParmRegs[nextFloatRegNO++]; 109 break; 110 case kThreeRegister: 111 ploc.reg0 = AArch64Abi::floatParmRegs[nextFloatRegNO++]; 112 ploc.reg1 = AArch64Abi::floatParmRegs[nextFloatRegNO++]; 113 ploc.reg2 = AArch64Abi::floatParmRegs[nextFloatRegNO++]; 114 break; 115 case kFourRegister: 116 ploc.reg0 = AArch64Abi::floatParmRegs[nextFloatRegNO++]; 117 ploc.reg1 = AArch64Abi::floatParmRegs[nextFloatRegNO++]; 118 ploc.reg2 = AArch64Abi::floatParmRegs[nextFloatRegNO++]; 119 ploc.reg3 = AArch64Abi::floatParmRegs[nextFloatRegNO++]; 120 break; 121 default: 122 CHECK_FATAL(0, "AllocateNSIMDFPRegisters: unsupported"); 123 } 124 } else { 125 ploc.reg0 = kRinvalid; 126 } 127 } 128 RoundNGRNUpToNextEven()129 void RoundNGRNUpToNextEven() 130 { 131 nextGeneralRegNO = static_cast<int32>((nextGeneralRegNO + 1) & ~static_cast<int32>(1)); 132 } 133 134 int32 ProcessPtyAggWhenLocateNextParm(MIRType &mirType, CCLocInfo &pLoc, uint64 &typeSize, int32 typeAlign); 135 }; 136 137 class AArch64WebKitJSCC : public CCImpl { 138 public: AArch64WebKitJSCC(BECommon & be)139 explicit AArch64WebKitJSCC(BECommon &be) : CCImpl(), beCommon(be) {} 140 141 ~AArch64WebKitJSCC() = default; 142 143 /* Return size of aggregate structure copy on stack. */ 144 int32 LocateNextParm(MIRType &mirType, CCLocInfo &pLoc, bool isFirst = false, MIRFunction *func = nullptr) override; 145 146 int32 LocateRetVal(MIRType &retType, CCLocInfo &ploc) override; 147 148 /* return value related */ 149 void InitReturnInfo(MIRType &retTy, CCLocInfo &pLoc) override; 150 151 // invalid interface 152 void SetupSecondRetReg(const MIRType &retTy2, CCLocInfo &pLoc) const override; 153 Init()154 void Init() override 155 { 156 nextGeneralRegNO = 0; 157 nextFloatRegNO = 0; 158 nextStackArgAdress = 0; 159 } 160 161 private: 162 BECommon &beCommon; 163 int32 nextGeneralRegNO = 0; /* number of integer parameters processed so far */ 164 uint32 nextFloatRegNO = 0; /* number of float parameters processed so far */ 165 static constexpr int32 kNumIntRetRegs = 8; 166 static constexpr int32 kNumFloatRetRegs = 8; 167 static constexpr int32 kNumIntParmRegs = 1; 168 static constexpr int32 kNumFloatParmRegs = 0; 169 static constexpr AArch64reg intReturnRegs[kNumIntRetRegs] = {R0, R1, R2, R3, R4, R5, R6, R7}; 170 static constexpr AArch64reg floatReturnRegs[kNumFloatRetRegs] = {V0, V1, V2, V3, V4, V5, V6, V7}; 171 static constexpr AArch64reg intParmRegs[kNumIntParmRegs] = {R0}; 172 static constexpr AArch64reg floatParmRegs[kNumFloatParmRegs] = {}; 173 174 int32 ClassificationArg(const BECommon &be, MIRType &mirType, std::vector<ArgumentClass> &classes) const; 175 176 int32 ClassificationRet(const BECommon &be, MIRType &mirType, std::vector<ArgumentClass> &classes) const; 177 AllocateGPParmRegister()178 AArch64reg AllocateGPParmRegister() 179 { 180 DEBUG_ASSERT(nextGeneralRegNO >= 0, "nextGeneralRegNO can not be neg"); 181 return (nextGeneralRegNO < AArch64WebKitJSCC::kNumIntParmRegs) 182 ? AArch64WebKitJSCC::intParmRegs[nextGeneralRegNO++] 183 : kRinvalid; 184 } 185 AllocateGPRetRegister()186 AArch64reg AllocateGPRetRegister() 187 { 188 DEBUG_ASSERT(nextGeneralRegNO >= 0, "nextGeneralRegNO can not be neg"); 189 return (nextGeneralRegNO < AArch64WebKitJSCC::kNumIntRetRegs) 190 ? AArch64WebKitJSCC::intReturnRegs[nextGeneralRegNO++] 191 : kRinvalid; 192 } 193 AllocateSIMDFPRetRegister()194 AArch64reg AllocateSIMDFPRetRegister() 195 { 196 return (nextFloatRegNO < AArch64WebKitJSCC::kNumFloatParmRegs) 197 ? AArch64WebKitJSCC::floatReturnRegs[nextFloatRegNO++] 198 : kRinvalid; 199 } 200 }; 201 202 class GHCCC : public CCImpl { 203 public: GHCCC(BECommon & be)204 explicit GHCCC(BECommon &be) : CCImpl(), beCommon(be) {} 205 206 ~GHCCC() = default; 207 208 /* Return size of aggregate structure copy on stack. */ 209 int32 LocateNextParm(MIRType &mirType, CCLocInfo &pLoc, bool isFirst = false, MIRFunction *func = nullptr) override; 210 211 int32 LocateRetVal(MIRType &retType, CCLocInfo &ploc) override; 212 213 /* return value related */ 214 void InitReturnInfo(MIRType &retTy, CCLocInfo &pLoc) override; 215 216 // invalid interface 217 void SetupSecondRetReg(const MIRType &retTy2, CCLocInfo &pLoc) const override; 218 Init()219 void Init() override 220 { 221 nextGeneralRegNO = 0; 222 nextFloatRegNOF32 = 0; 223 nextFloatRegNOF64 = 0; 224 nextFloatRegNOF128 = 0; 225 nextStackArgAdress = 0; 226 } 227 228 private: 229 BECommon &beCommon; 230 int32 nextGeneralRegNO = 0; /* number of integer parameters processed so far */ 231 uint32 nextFloatRegNOF32 = 0; 232 uint32 nextFloatRegNOF64 = 0; 233 uint32 nextFloatRegNOF128 = 0; 234 static constexpr int32 kNumIntParmRegs = 8; 235 static constexpr int32 kNumFloatParmRegsF32 = 4; 236 static constexpr int32 kNumFloatParmRegsF64 = 4; 237 static constexpr int32 kNumFloatParmRegsF128 = 2; 238 static constexpr AArch64reg intParmRegs[kNumIntParmRegs] = {R19, R20, R21, R22, R23, R24, R25, R26}; 239 static constexpr AArch64reg floatParmRegsF32[kNumFloatParmRegsF32] = {V8, V9, V10, V11}; 240 static constexpr AArch64reg floatParmRegsF64[kNumFloatParmRegsF64] = {V12, V13, V14, V15}; 241 static constexpr AArch64reg floatParmRegsF128[kNumFloatParmRegsF128] = {V4, V5}; 242 243 int32 ClassificationArg(const BECommon &be, MIRType &mirType, std::vector<ArgumentClass> &classes) const; 244 AllocateGPParmRegister()245 AArch64reg AllocateGPParmRegister() 246 { 247 DEBUG_ASSERT(nextGeneralRegNO >= 0, "nextGeneralRegNO can not be neg"); 248 return (nextGeneralRegNO < GHCCC::kNumIntParmRegs) ? GHCCC::intParmRegs[nextGeneralRegNO++] : kRinvalid; 249 } 250 AllocateSIMDFPParmRegisterF32()251 AArch64reg AllocateSIMDFPParmRegisterF32() 252 { 253 return (nextFloatRegNOF32 < GHCCC::kNumFloatParmRegsF32) ? GHCCC::floatParmRegsF32[nextFloatRegNOF32++] 254 : kRinvalid; 255 } 256 AllocateSIMDFPParmRegisterF64()257 AArch64reg AllocateSIMDFPParmRegisterF64() 258 { 259 return (nextFloatRegNOF64 < GHCCC::kNumFloatParmRegsF64) ? GHCCC::floatParmRegsF64[nextFloatRegNOF64++] 260 : kRinvalid; 261 } 262 AllocateSIMDFPParmRegisterF128()263 AArch64reg AllocateSIMDFPParmRegisterF128() 264 { 265 return (nextFloatRegNOF128 < GHCCC::kNumFloatParmRegsF128) ? GHCCC::floatParmRegsF128[nextFloatRegNOF128++] 266 : kRinvalid; 267 } 268 }; 269 270 } /* namespace maplebe */ 271 272 #endif /* MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_CALL_CONV_H */ 273