• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 PANDA_TARGET_H
17 #define PANDA_TARGET_H
18 
19 #include "operands.h"
20 #include "arch_info_gen.h"
21 #include <string>
22 
23 namespace ark::compiler {
24 
25 // There is a problem with callee/caller register numbers with amd64.
26 // For example, take a look at
27 // caller reg mask: 0000111111000111 and
28 // callee reg mask: 1111000000001000
29 // Stack walker requires this mask to be densed, so the decision is to
30 // rename regs number 3, 4, 5 to 11, 10, 9 (and vice versa).
31 // Resulting
32 // caller mask is 0000000111111111 and
33 // callee mask is 1111100000000000.
34 
ConvertRegNumberX86(size_t regId)35 constexpr size_t ConvertRegNumberX86(size_t regId)
36 {
37     constexpr size_t RENAMING_MASK_3_5_OR_9_11 {0xE38};
38     constexpr size_t RENAMING_CONST {14U};
39 
40     ASSERT(regId < MAX_NUM_REGS);
41     // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult)
42     if ((RENAMING_MASK_3_5_OR_9_11 & (size_t(1) << regId)) != 0) {
43         return RENAMING_CONST - regId;
44     }
45     return regId;
46 }
47 
48 // CC-OFFNXT(G.PRE.06) list generation
49 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
50 #define DEFINE_NUMERIC_REGISTERS(REG) \
51     REG(0)                            \
52     REG(1)                            \
53     REG(2)                            \
54     REG(3)                            \
55     REG(4)                            \
56     REG(5)                            \
57     REG(6)                            \
58     REG(7)                            \
59     REG(8)                            \
60     REG(9)                            \
61     REG(10)                           \
62     REG(11)                           \
63     REG(12)                           \
64     REG(13)                           \
65     REG(14)                           \
66     REG(15)                           \
67     REG(16)                           \
68     REG(17)                           \
69     REG(18)                           \
70     REG(19)                           \
71     REG(20)                           \
72     REG(21)                           \
73     REG(22)                           \
74     REG(23)                           \
75     REG(24)                           \
76     REG(25)                           \
77     REG(26)                           \
78     REG(27)                           \
79     REG(28)                           \
80     REG(29)                           \
81     REG(30)                           \
82     REG(31)
83 
84 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
85 #define DEFINE_REG(name, reg) static constexpr uint8_t name = (reg)
86 
87 struct ArchCallingConventionX8664 {
88     // Following registers are swapped (see comment above for ConvertRegNumberX86):
89     // BX, SP, BP <==> R9, R10, R11
90 // CC-OFFNXT(G.PRE.06) solid logic
91 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
92 #define X86_64_REGISTER_LIST(REG) \
93     REG(rax) /* 0 */              \
94     REG(rcx) /* 1 */              \
95     REG(rdx) /* 2 */              \
96     REG(r11) /* 3 */              \
97     REG(r10) /* 4 */              \
98     REG(r9)  /* 5 */              \
99     REG(rsi) /* 6 */              \
100     REG(rdi) /* 7 */              \
101     REG(r8)  /* 8 */              \
102     REG(rbp) /* 9 */              \
103     REG(rsp) /* 10 */             \
104     REG(rbx) /* 11 */             \
105     REG(r12) /* 12 */             \
106     REG(r13) /* 13 */             \
107     REG(r14) /* 14 */             \
108     REG(r15) /* 15 */
109 
110 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
111 #define DEF_ENUM(r) id_##r,
112     enum Id : uint8_t { X86_64_REGISTER_LIST(DEF_ENUM) ID_COUNT };
113 #undef DEF_ENUM
114 
115     DEFINE_REG(SP_REG, id_rsp);
116     DEFINE_REG(FP_REG, id_rbp);
117     DEFINE_REG(LR_REG, INVALID_REG_ID);
118     DEFINE_REG(RETURN_REG, id_rax);
119     DEFINE_REG(FP_RETURN_REG, 0);
120     DEFINE_REG(ZERO_REG, INVALID_REG_ID);
121     static constexpr std::array<size_t, 6> CALL_PARAMS_REGS = {id_rdi, id_rsi, id_rdx, id_rcx, id_r8, id_r9};
122     static constexpr uint32_t TEMP_REGS_MASK = arch_info::x86_64::TEMP_REGS.to_ulong();
123     static constexpr uint32_t TEMP_VREGS_MASK = arch_info::x86_64::TEMP_FP_REGS.to_ulong();
124     static constexpr uint32_t GENERAL_REGS_MASK = MakeMaskByExcluding(ID_COUNT, SP_REG, FP_REG);
125     static constexpr uint32_t SP_ALIGNMENT = 16;
126 
127 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
128 #define DEF_REG_NAME(r) #r,
129     static constexpr std::array<const char *, ID_COUNT> REG_NAMES = {X86_64_REGISTER_LIST(DEF_REG_NAME)};
130 #undef DEF_REG_NAME
131 
132 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
133 #define DEF_FP_REG_NAME_X86(r) "xmm" #r,
134     static constexpr std::array<const char *, 32> FP_REG_NAMES = {DEFINE_NUMERIC_REGISTERS(DEF_FP_REG_NAME_X86)};
135 #undef DEF_FP_REG_NAME_X86
GetRegNameArchCallingConventionX8664136     static constexpr const char *GetRegName(size_t reg, bool isFp)
137     {
138         ASSERT(reg < REG_NAMES.size() || isFp);
139         ASSERT(reg < FP_REG_NAMES.size() || !isFp);
140         return isFp ? FP_REG_NAMES[reg] : REG_NAMES[reg];
141     }
142 };
143 
144 struct ArchCallingConventionAarch64 {
145     DEFINE_REG(SP_REG, 63);
146     DEFINE_REG(FP_REG, 29);
147     DEFINE_REG(LR_REG, 30);
148     DEFINE_REG(RETURN_REG, 0);
149     DEFINE_REG(FP_RETURN_REG, 0);
150     DEFINE_REG(ZERO_REG, 31);
151     static constexpr std::array CALL_PARAMS_REGS = {0, 1, 2, 3, 4, 5, 6, 7};
152     static constexpr uint32_t TEMP_REGS_MASK = arch_info::arm64::TEMP_REGS.to_ulong();
153     static constexpr uint32_t TEMP_VREGS_MASK = arch_info::arm64::TEMP_FP_REGS.to_ulong();
154     static constexpr uint32_t GENERAL_REGS_MASK = MakeMaskByExcluding(32, SP_REG, FP_REG, ZERO_REG, LR_REG);
155     static constexpr uint32_t SP_ALIGNMENT = 16;
156 
157 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
158 #define DEF_FP_REG_NAME_AARCH_64(r) "r" #r,
159     static constexpr std::array<const char *, 32> REG_NAMES = {DEFINE_NUMERIC_REGISTERS(DEF_FP_REG_NAME_AARCH_64)};
160 #undef DEF_FP_REG_NAME_AARCH_64
161 
162 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
163 #define DEF_FP_REG_NAME_AARCH_64(r) "d" #r,
164     static constexpr std::array<const char *, 32> FP_REG_NAMES = {DEFINE_NUMERIC_REGISTERS(DEF_FP_REG_NAME_AARCH_64)};
165 #undef DEF_FP_REG_NAME_AARCH_64
166 
GetRegNameArchCallingConventionAarch64167     static constexpr const char *GetRegName(size_t reg, bool isFp)
168     {
169         ASSERT(reg < REG_NAMES.size() || isFp);
170         ASSERT(reg < FP_REG_NAMES.size() || !isFp);
171         return isFp ? FP_REG_NAMES[reg] : REG_NAMES[reg];
172     }
173 };
174 
175 struct ArchCallingConventionAarch32 {
176     DEFINE_REG(SP_REG, 13);
177     DEFINE_REG(FP_REG, 11);
178     DEFINE_REG(LR_REG, 14);
179     DEFINE_REG(RETURN_REG, 0);
180     DEFINE_REG(FP_RETURN_REG, 0);
181     DEFINE_REG(ZERO_REG, INVALID_REG_ID);
182     static constexpr std::array CALL_PARAMS_REGS = {0, 1, 2, 3};
183     static constexpr uint32_t TEMP_REGS_MASK = arch_info::arm32::TEMP_REGS.to_ulong();
184     static constexpr uint32_t TEMP_VREGS_MASK = arch_info::arm32::TEMP_FP_REGS.to_ulong();
185     static constexpr uint32_t GENERAL_REGS_MASK = MakeMaskByExcluding(16, SP_REG, FP_REG, LR_REG);
186     static constexpr uint32_t SP_ALIGNMENT = 8;
187 
188 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
189 #define DEF_FP_REG_NAME_AARCH_32(r) "r" #r,
190     static constexpr std::array<const char *, 32> REG_NAMES = {DEFINE_NUMERIC_REGISTERS(DEF_FP_REG_NAME_AARCH_32)};
191 #undef DEF_FP_REG_NAME_AARCH_32
192 
193 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
194 #define DEF_FP_REG_NAME_AARCH_32(r) "d" #r,
195     static constexpr std::array<const char *, 32> FP_REG_NAMES = {DEFINE_NUMERIC_REGISTERS(DEF_FP_REG_NAME_AARCH_32)};
196 #undef DEF_FP_REG_NAME_AARCH_32
197 
GetRegNameArchCallingConventionAarch32198     static constexpr const char *GetRegName(size_t reg, bool isFp)
199     {
200         ASSERT(reg < REG_NAMES.size() || isFp);
201         ASSERT(reg < FP_REG_NAMES.size() || !isFp);
202         return isFp ? FP_REG_NAMES[reg] : REG_NAMES[reg];
203     }
204 };
205 
206 struct ArchCallingConventionX86 {
207     DEFINE_REG(SP_REG, 0);
208     DEFINE_REG(FP_REG, 0);
209     DEFINE_REG(LR_REG, 0);
210     DEFINE_REG(RETURN_REG, 0);
211     DEFINE_REG(FP_RETURN_REG, 0);
212     DEFINE_REG(ZERO_REG, 0);
213     static constexpr std::array CALL_PARAMS_REGS = {0, 1, 2, 3, 4, 5, 6, 7};
214     static constexpr uint32_t TEMP_REGS_MASK = MakeMask(0);
215     static constexpr uint32_t TEMP_VREGS_MASK = MakeMask(0);
216     static constexpr uint32_t GENERAL_REGS_MASK = MakeMaskByExcluding(16, 0);
217     static constexpr uint32_t SP_ALIGNMENT = 8;
218 
GetRegNameArchCallingConventionX86219     static constexpr const char *GetRegName([[maybe_unused]] size_t reg, [[maybe_unused]] bool isFp)
220     {
221         return "not supported";
222     }
223 };
224 
225 template <Arch ARCH>
226 struct ArchCallingConvention {
227     using Target = std::conditional_t<
228         ARCH == Arch::X86_64, ArchCallingConventionX8664,
229         std::conditional_t<
230             ARCH == Arch::X86, ArchCallingConventionX86,
231             std::conditional_t<ARCH == Arch::AARCH64, ArchCallingConventionAarch64,
232                                std::conditional_t<ARCH == Arch::AARCH32, ArchCallingConventionAarch32, void>>>>;
233 
WordSizeArchCallingConvention234     static constexpr size_t WordSize()
235     {
236         return ArchTraits<ARCH>::IS_64_BITS ? sizeof(uint64_t) : sizeof(uint32_t);
237     }
GetReturnRegIdArchCallingConvention238     static constexpr size_t GetReturnRegId()
239     {
240         return Target::RETURN_REG;
241     }
GetReturnFpRegIdArchCallingConvention242     static constexpr size_t GetReturnFpRegId()
243     {
244         return Target::FP_RETURN_REG;
245     }
GetReturnRegArchCallingConvention246     static constexpr Reg GetReturnReg(TypeInfo type)
247     {
248         // NOLINTNEXTLINE(readability-braces-around-statements,bugprone-suspicious-semicolon)
249         if constexpr (ARCH == Arch::AARCH32) {
250             if (type.IsFloat()) {
251 #if PANDA_TARGET_ARM32_ABI_HARD
252                 return Reg(GetReturnFpRegId(), (type == FLOAT64_TYPE) ? FLOAT64_TYPE : FLOAT32_TYPE);
253 #else
254                 return Reg(GetReturnRegId(), (type == FLOAT64_TYPE) ? INT64_TYPE : INT32_TYPE);
255 #endif
256             }
257             return Reg(GetReturnRegId(), type);
258         }
259         return type.IsFloat() ? Reg(GetReturnFpRegId(), type) : Reg(GetReturnRegId(), type);
260     }
GetStackRegArchCallingConvention261     static constexpr Reg GetStackReg()
262     {
263         return Reg(Target::SP_REG, ArchTraits<ARCH>::IS_64_BITS ? INT64_TYPE : INT32_TYPE);
264     }
GetFrameRegArchCallingConvention265     static constexpr Reg GetFrameReg()
266     {
267         return Reg(Target::FP_REG, ArchTraits<ARCH>::IS_64_BITS ? INT64_TYPE : INT32_TYPE);
268     }
GetLinkRegArchCallingConvention269     static constexpr Reg GetLinkReg()
270     {
271         return Reg(Target::LR_REG, ArchTraits<ARCH>::IS_64_BITS ? INT64_TYPE : INT32_TYPE);
272     }
GetZeroRegArchCallingConvention273     static constexpr Reg GetZeroReg()
274     {
275         return Reg(Target::ZERO_REG, ArchTraits<ARCH>::IS_64_BITS ? INT64_TYPE : INT32_TYPE);
276     }
SupportLinkRegArchCallingConvention277     static constexpr bool SupportLinkReg()
278     {
279         return Target::LR_REG != INVALID_REG_ID;
280     }
SupportZeroRegArchCallingConvention281     static constexpr bool SupportZeroReg()
282     {
283         return Target::ZERO_REG != INVALID_REG_ID;
284     }
GetParamRegsCountArchCallingConvention285     static constexpr size_t GetParamRegsCount()
286     {
287         return Target::CALL_PARAMS_REGS.size();
288     }
GetParamRegIdArchCallingConvention289     static constexpr size_t GetParamRegId(size_t index)
290     {
291         ASSERT(index < GetParamRegsCount());
292         return Target::CALL_PARAMS_REGS[index];
293     }
GetSpAlignmentArchCallingConvention294     static constexpr size_t GetSpAlignment()
295     {
296         return Target::SP_ALIGNMENT;
297     }
GetParamRegsMaskArchCallingConvention298     static constexpr RegMask GetParamRegsMask()
299     {
300         return MakeMask(Target::CALL_PARAMS_REGS);
301     }
302 
GetTempRegsMaskArchCallingConvention303     static constexpr RegMask GetTempRegsMask()
304     {
305         return RegMask(Target::TEMP_REGS_MASK);
306     }
GetTempVRegsMaskArchCallingConvention307     static constexpr RegMask GetTempVRegsMask()
308     {
309         return Target::TEMP_VREGS_MASK;
310     }
GetGeneralRegsMaskArchCallingConvention311     static constexpr RegMask GetGeneralRegsMask()
312     {
313         return Target::GENERAL_REGS_MASK;
314     }
GetGeneralVRegsMaskArchCallingConvention315     static constexpr RegMask GetGeneralVRegsMask()
316     {
317         return Target::GENERAL_REGS_MASK;
318     }
GetAvailableRegsMaskArchCallingConvention319     static constexpr RegMask GetAvailableRegsMask()
320     {
321         return GetGeneralRegsMask() & (~GetTempRegsMask());
322     }
GetAvailableVRegsMaskArchCallingConvention323     static constexpr RegMask GetAvailableVRegsMask()
324     {
325         return RegMask(ArchTraits<ARCH>::CALLEE_FP_REG_MASK | ArchTraits<ARCH>::CALLER_FP_REG_MASK) &
326                ~GetTempVRegsMask();
327     }
328 };
329 
330 class Target {
331 public:
Target(Arch arch)332     constexpr explicit Target(Arch arch) : arch_(arch) {}
333     ~Target() = default;
334     DEFAULT_MOVE_CTOR(Target);
335     DEFAULT_COPY_CTOR(Target);
336     NO_MOVE_OPERATOR(Target);
337     NO_COPY_OPERATOR(Target);
338 
GetArch()339     constexpr Arch GetArch() const
340     {
341         return arch_;
342     }
343 
Current()344     static constexpr Target Current()
345     {
346         return Target(RUNTIME_ARCH);
347     }
348 
349 #undef TARGET_DEFINE_GETTER
350 // CC-OFFNXT(G.PRE.06) solid logic
351 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
352 #define TARGET_DEFINE_GETTER(name)                                   \
353     constexpr auto name() const                                      \
354     {                                                                \
355         switch (arch_) {                                             \
356             case Arch::X86_64:                                       \
357                 /* CC-OFFNXT(G.PRE.05) function gen */               \
358                 return ArchCallingConvention<Arch::X86_64>::name();  \
359             case Arch::X86:                                          \
360                 /* CC-OFFNXT(G.PRE.05) function gen */               \
361                 return ArchCallingConvention<Arch::X86>::name();     \
362             case Arch::AARCH64:                                      \
363                 /* CC-OFFNXT(G.PRE.05) function gen */               \
364                 return ArchCallingConvention<Arch::AARCH64>::name(); \
365             case Arch::AARCH32:                                      \
366                 /* CC-OFFNXT(G.PRE.05) function gen */               \
367                 return ArchCallingConvention<Arch::AARCH32>::name(); \
368             default:                                                 \
369                 UNREACHABLE();                                       \
370         }                                                            \
371     }
372 
373     TARGET_DEFINE_GETTER(WordSize);
374     TARGET_DEFINE_GETTER(GetReturnRegId);
375     TARGET_DEFINE_GETTER(GetReturnFpRegId);
376     TARGET_DEFINE_GETTER(GetStackReg);
377     TARGET_DEFINE_GETTER(GetFrameReg);
378     TARGET_DEFINE_GETTER(GetLinkReg);
379     TARGET_DEFINE_GETTER(SupportLinkReg);
380     TARGET_DEFINE_GETTER(GetZeroReg);
381     TARGET_DEFINE_GETTER(SupportZeroReg);
382     TARGET_DEFINE_GETTER(GetTempRegsMask);
383     TARGET_DEFINE_GETTER(GetTempVRegsMask);
384     TARGET_DEFINE_GETTER(GetGeneralRegsMask);
385     TARGET_DEFINE_GETTER(GetAvailableRegsMask);
386     TARGET_DEFINE_GETTER(GetAvailableVRegsMask);
387     TARGET_DEFINE_GETTER(GetParamRegsCount);
388     TARGET_DEFINE_GETTER(GetParamRegsMask);
389     TARGET_DEFINE_GETTER(GetSpAlignment);
390 
391 #undef TARGET_DEFINE_GETTER_1_ARG
392 // CC-OFFNXT(G.PRE.06) solid logic
393 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
394 #define TARGET_DEFINE_GETTER_1_ARG(name, arg_type)                      \
395     constexpr auto name(arg_type arg) const                             \
396     {                                                                   \
397         switch (arch_) {                                                \
398             case Arch::X86_64:                                          \
399                 /* CC-OFFNXT(G.PRE.05) function gen */                  \
400                 return ArchCallingConvention<Arch::X86_64>::name(arg);  \
401             case Arch::X86:                                             \
402                 /* CC-OFFNXT(G.PRE.05) function gen */                  \
403                 return ArchCallingConvention<Arch::X86>::name(arg);     \
404             case Arch::AARCH64:                                         \
405                 /* CC-OFFNXT(G.PRE.05) function gen */                  \
406                 return ArchCallingConvention<Arch::AARCH64>::name(arg); \
407             case Arch::AARCH32:                                         \
408                 /* CC-OFFNXT(G.PRE.05) function gen */                  \
409                 return ArchCallingConvention<Arch::AARCH32>::name(arg); \
410             default:                                                    \
411                 UNREACHABLE();                                          \
412         }                                                               \
413     }
414 
415     TARGET_DEFINE_GETTER_1_ARG(GetReturnReg, TypeInfo);
416     TARGET_DEFINE_GETTER_1_ARG(GetParamRegId, size_t);
417 
GetFpParamRegId(size_t index)418     constexpr size_t GetFpParamRegId(size_t index) const
419     {
420         switch (arch_) {
421             case Arch::X86_64:
422             case Arch::AARCH64:
423             case Arch::AARCH32:
424                 return index;
425             default:
426                 UNREACHABLE();
427         }
428     }
429 
GetReturnReg()430     constexpr Reg GetReturnReg() const
431     {
432         return GetReturnReg(GetPtrRegType());
433     }
434 
GetReturnFpReg()435     constexpr Reg GetReturnFpReg() const
436     {
437         return GetReturnReg(Is64BitsArch(GetArch()) ? FLOAT64_TYPE : FLOAT32_TYPE);
438     }
439 
GetPtrRegType()440     constexpr TypeInfo GetPtrRegType() const
441     {
442         return Is64BitsArch(GetArch()) ? INT64_TYPE : INT32_TYPE;
443     }
444 
GetParamReg(size_t index,TypeInfo type)445     constexpr Reg GetParamReg(size_t index, TypeInfo type) const
446     {
447         auto regId {type.IsScalar() ? GetParamRegId(index) : GetFpParamRegId(index)};
448         return Reg(regId, type);
449     }
450 
GetParamReg(size_t index)451     constexpr Reg GetParamReg(size_t index) const
452     {
453         return Reg(GetParamRegId(index), GetPtrRegType());
454     }
455 
GetParamRegsMask(size_t limit)456     constexpr RegMask GetParamRegsMask(size_t limit) const
457     {
458         size_t mask = 0;
459         for (size_t i = 0; i < limit; i++) {
460             mask |= 1UL << GetParamRegId(i);
461         }
462         return RegMask(mask);
463     }
464 
465     // NOTE(msherstennikov): Take into account register size
GetRegName(size_t reg,bool isFp)466     std::string GetRegName(size_t reg, bool isFp) const
467     {
468         switch (arch_) {
469             case Arch::X86_64:
470                 return ArchCallingConventionX8664::GetRegName(reg, isFp);
471             case Arch::X86:
472                 return ArchCallingConventionX86::GetRegName(reg, isFp);
473             case Arch::AARCH64:
474                 return ArchCallingConventionAarch64::GetRegName(reg, isFp);
475             case Arch::AARCH32:
476                 return ArchCallingConventionAarch32::GetRegName(reg, isFp);
477             case Arch::NONE:
478                 return "r" + std::to_string(reg);
479             default:
480                 UNREACHABLE();
481         }
482     }
483 
484 private:
485     const Arch arch_;
486 };
487 
488 // Check that all getters can be evaluated in compile time.
489 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
490 #define VERIFY_GETTER(name)                                                    \
491     static_assert(Target(Arch::X86_64).name() == Target(Arch::X86_64).name()); \
492     static_assert(Target(Arch::AARCH64).name() == Target(Arch::AARCH64).name())
493 VERIFY_GETTER(WordSize);
494 VERIFY_GETTER(GetReturnRegId);
495 VERIFY_GETTER(GetReturnFpRegId);
496 VERIFY_GETTER(GetStackReg);
497 VERIFY_GETTER(GetFrameReg);
498 VERIFY_GETTER(GetLinkReg);
499 VERIFY_GETTER(SupportLinkReg);
500 VERIFY_GETTER(GetZeroReg);
501 VERIFY_GETTER(SupportZeroReg);
502 VERIFY_GETTER(GetTempRegsMask);
503 VERIFY_GETTER(GetTempVRegsMask);
504 VERIFY_GETTER(GetGeneralRegsMask);
505 VERIFY_GETTER(GetAvailableRegsMask);
506 VERIFY_GETTER(GetAvailableVRegsMask);
507 VERIFY_GETTER(GetParamRegsCount);
508 VERIFY_GETTER(GetParamRegsMask);
509 VERIFY_GETTER(GetSpAlignment);
510 static_assert(Target(Arch::X86_64).GetParamReg(0) == Target(Arch::X86_64).GetParamReg(0));
511 static_assert(Target(Arch::AARCH64).GetParamReg(0) == Target(Arch::AARCH64).GetParamReg(0));
512 
513 }  // namespace ark::compiler
514 
515 #endif  // PANDA_TARGET_H
516