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 #include "aarch64_cgfunc.h"
17 #include "becommon.h"
18
19 namespace maplebe {
20 using namespace maple;
21
22 namespace AArch64Abi {
IsAvailableReg(AArch64reg reg)23 bool IsAvailableReg(AArch64reg reg)
24 {
25 switch (reg) {
26 /* integer registers */
27 #define INT_REG(ID, PREF32, PREF64, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill) \
28 case R##ID: { \
29 return canBeAssigned; \
30 }
31 #define INT_REG_ALIAS(ALIAS, ID, PREF32, PREF64)
32 #include "aarch64_int_regs.def"
33 #undef INT_REG
34 #undef INT_REG_ALIAS
35 /* fp-simd registers */
36 #define FP_SIMD_REG(ID, PV, P8, P16, P32, P64, P128, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill) \
37 case V##ID: { \
38 return canBeAssigned; \
39 }
40 #define FP_SIMD_REG_ALIAS(ID)
41 #include "aarch64_fp_simd_regs.def"
42 #undef FP_SIMD_REG
43 #undef FP_SIMD_REG_ALIAS
44 default:
45 return false;
46 }
47 }
48
IsCallerSaveReg(AArch64reg regNO)49 bool IsCallerSaveReg(AArch64reg regNO)
50 {
51 return (R0 <= regNO && regNO <= R18) || (V0 <= regNO && regNO <= V7) || (V16 <= regNO && regNO <= V31) ||
52 (regNO == kRFLAG);
53 }
54
IsCalleeSavedReg(AArch64reg reg)55 bool IsCalleeSavedReg(AArch64reg reg)
56 {
57 switch (reg) {
58 /* integer registers */
59 #define INT_REG(ID, PREF32, PREF64, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill) \
60 case R##ID: { \
61 return isCalleeSave; \
62 }
63 #define INT_REG_ALIAS(ALIAS, ID, PREF32, PREF64)
64 #include "aarch64_int_regs.def"
65 #undef INT_REG
66 #undef INT_REG_ALIAS
67 /* fp-simd registers */
68 #define FP_SIMD_REG(ID, PV, P8, P16, P32, P64, P128, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill) \
69 case V##ID: { \
70 return isCalleeSave; \
71 }
72 #define FP_SIMD_REG_ALIAS(ID)
73 #include "aarch64_fp_simd_regs.def"
74 #undef FP_SIMD_REG
75 #undef FP_SIMD_REG_ALIAS
76 default:
77 return false;
78 }
79 }
80
IsParamReg(AArch64reg reg)81 bool IsParamReg(AArch64reg reg)
82 {
83 switch (reg) {
84 /* integer registers */
85 #define INT_REG(ID, PREF32, PREF64, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill) \
86 case R##ID: { \
87 return isParam; \
88 }
89 #define INT_REG_ALIAS(ALIAS, ID, PREF32, PREF64)
90 #include "aarch64_int_regs.def"
91 #undef INT_REG
92 #undef INT_REG_ALIAS
93 /* fp-simd registers */
94 #define FP_SIMD_REG(ID, PV, P8, P16, P32, P64, P128, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill) \
95 case V##ID: { \
96 return isParam; \
97 }
98 #define FP_SIMD_REG_ALIAS(ID)
99 #include "aarch64_fp_simd_regs.def"
100 #undef FP_SIMD_REG
101 #undef FP_SIMD_REG_ALIAS
102 default:
103 return false;
104 }
105 }
106
IsSpillReg(AArch64reg reg)107 bool IsSpillReg(AArch64reg reg)
108 {
109 switch (reg) {
110 /* integer registers */
111 #define INT_REG(ID, PREF32, PREF64, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill) \
112 case R##ID: { \
113 return isSpill; \
114 }
115 #define INT_REG_ALIAS(ALIAS, ID, PREF32, PREF64)
116 #include "aarch64_int_regs.def"
117 #undef INT_REG
118 #undef INT_REG_ALIAS
119 /* fp-simd registers */
120 #define FP_SIMD_REG(ID, PV, P8, P16, P32, P64, P128, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill) \
121 case V##ID: { \
122 return isSpill; \
123 }
124 #define FP_SIMD_REG_ALIAS(ID)
125 #include "aarch64_fp_simd_regs.def"
126 #undef FP_SIMD_REG
127 #undef FP_SIMD_REG_ALIAS
128 default:
129 return false;
130 }
131 }
132
IsExtraSpillReg(AArch64reg reg)133 bool IsExtraSpillReg(AArch64reg reg)
134 {
135 switch (reg) {
136 /* integer registers */
137 #define INT_REG(ID, PREF32, PREF64, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill) \
138 case R##ID: { \
139 return isExtraSpill; \
140 }
141 #define INT_REG_ALIAS(ALIAS, ID, PREF32, PREF64)
142 #include "aarch64_int_regs.def"
143 #undef INT_REG
144 #undef INT_REG_ALIAS
145 /* fp-simd registers */
146 #define FP_SIMD_REG(ID, PV, P8, P16, P32, P64, P128, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill) \
147 case V##ID: { \
148 return isExtraSpill; \
149 }
150 #define FP_SIMD_REG_ALIAS(ID)
151 #include "aarch64_fp_simd_regs.def"
152 #undef FP_SIMD_REG
153 #undef FP_SIMD_REG_ALIAS
154 default:
155 return false;
156 }
157 }
158
IsSpillRegInRA(AArch64reg regNO,bool has3RegOpnd)159 bool IsSpillRegInRA(AArch64reg regNO, bool has3RegOpnd)
160 {
161 /* if has 3 RegOpnd, previous reg used to spill. */
162 if (has3RegOpnd) {
163 return AArch64Abi::IsSpillReg(regNO) || AArch64Abi::IsExtraSpillReg(regNO);
164 }
165 return AArch64Abi::IsSpillReg(regNO);
166 }
167
IsVectorArrayType(MIRType * ty,uint32 & arraySize)168 PrimType IsVectorArrayType(MIRType *ty, uint32 &arraySize)
169 {
170 if (ty->GetKind() == kTypeStruct) {
171 MIRStructType *structTy = static_cast<MIRStructType *>(ty);
172 if (structTy->GetFields().size() == 1) {
173 auto fieldPair = structTy->GetFields()[0];
174 MIRType *fieldTy = GlobalTables::GetTypeTable().GetTypeFromTyIdx(fieldPair.second.first);
175 if (fieldTy->GetKind() == kTypeArray) {
176 MIRArrayType *arrayTy = static_cast<MIRArrayType *>(fieldTy);
177 MIRType *arrayElemTy = arrayTy->GetElemType();
178 arraySize = arrayTy->GetSizeArrayItem(0);
179 if (arrayTy->GetDim() == k1BitSize && arraySize <= static_cast<int32>(k4BitSize) &&
180 IsPrimitiveVector(arrayElemTy->GetPrimType())) {
181 return arrayElemTy->GetPrimType();
182 }
183 }
184 }
185 }
186 return PTY_void;
187 }
188 } /* namespace AArch64Abi */
189 } /* namespace maplebe */
190