authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-02-13 22:16:22+07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-13 17:16:22+02:00
log55fa349ad946aaa4e2ff5a5dc2a3f0d6bce64282
treefbd8365132d929851ec418d048a90aaafd1d575e
parentb5f8fb85e64022ed1ee59ff70753577839ad41b6
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Import SPARCv9 libunwind

Import LLVM's D32450/D116857 patch to enable unwinding support on SPARCv9 systems.

9 files changed, 367 insertions(+), 10 deletions(-)

lib/libunwind/include/__libunwind_config.h+7
......@@ -23,6 +23,7 @@
2323#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 32
2424#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS 65
2525#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC 31
26#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64 31
2627#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON 34
2728#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64
2829#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE 143
......@@ -125,6 +126,11 @@
125126# error "Unsupported MIPS ABI and/or environment"
126127# endif
127128# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS
129# elif defined(__sparc__) && defined(__arch64__)
130# define _LIBUNWIND_TARGET_SPARC64 1
131# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64
132# define _LIBUNWIND_CONTEXT_SIZE 33
133# define _LIBUNWIND_CURSOR_SIZE 45
128134# elif defined(__sparc__)
129135 #define _LIBUNWIND_TARGET_SPARC 1
130136 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC
......@@ -165,6 +171,7 @@
165171# define _LIBUNWIND_TARGET_MIPS_O32 1
166172# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
167173# define _LIBUNWIND_TARGET_SPARC 1
174# define _LIBUNWIND_TARGET_SPARC64 1
168175# define _LIBUNWIND_TARGET_HEXAGON 1
169176# define _LIBUNWIND_TARGET_RISCV 1
170177# define _LIBUNWIND_TARGET_VE 1
lib/libunwind/src/DwarfInstructions.hpp+21-1
......@@ -67,7 +67,7 @@ private:
6767 return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
6868 prolog.cfaRegisterOffset);
6969 if (prolog.cfaExpression != 0)
70 return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
70 return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
7171 registers, 0);
7272 assert(0 && "getCFA(): unknown location");
7373 __builtin_unreachable();
......@@ -75,6 +75,14 @@ private:
7575};
7676
7777
78template <typename R>
79auto getSparcWCookie(const R &r, int) -> decltype(r.getWCookie()) {
80 return r.getWCookie();
81}
82template <typename R> uint64_t getSparcWCookie(const R &, long) {
83 return 0;
84}
85
7886template <typename A, typename R>
7987typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
8088 A &addressSpace, const R &registers, pint_t cfa,
......@@ -83,6 +91,10 @@ typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
8391 case CFI_Parser<A>::kRegisterInCFA:
8492 return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value);
8593
94 case CFI_Parser<A>::kRegisterInCFADecrypt: // sparc64 specific
95 return addressSpace.getP(cfa + (pint_t)savedReg.value) ^
96 getSparcWCookie(registers, 0);
97
8698 case CFI_Parser<A>::kRegisterAtExpression:
8799 return (pint_t)addressSpace.getRegister(evaluateExpression(
88100 (pint_t)savedReg.value, addressSpace, registers, cfa));
......@@ -121,6 +133,7 @@ double DwarfInstructions<A, R>::getSavedFloatRegister(
121133 case CFI_Parser<A>::kRegisterUndefined:
122134 case CFI_Parser<A>::kRegisterOffsetFromCFA:
123135 case CFI_Parser<A>::kRegisterInRegister:
136 case CFI_Parser<A>::kRegisterInCFADecrypt:
124137 // FIX ME
125138 break;
126139 }
......@@ -145,6 +158,7 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister(
145158 case CFI_Parser<A>::kRegisterUndefined:
146159 case CFI_Parser<A>::kRegisterOffsetFromCFA:
147160 case CFI_Parser<A>::kRegisterInRegister:
161 case CFI_Parser<A>::kRegisterInCFADecrypt:
148162 // FIX ME
149163 break;
150164 }
......@@ -249,6 +263,12 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
249263 }
250264#endif
251265
266#if defined(_LIBUNWIND_TARGET_SPARC64)
267 // Skip call site instruction and delay slot
268 if (R::getArch() == REGISTERS_SPARC64)
269 returnAddress += 8;
270#endif
271
252272#if defined(_LIBUNWIND_TARGET_PPC64)
253273#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)
254274#define PPC64_ELFV1_R2_OFFSET 40
lib/libunwind/src/DwarfParser.hpp+24-1
......@@ -71,6 +71,7 @@ public:
7171 kRegisterUnused,
7272 kRegisterUndefined,
7373 kRegisterInCFA,
74 kRegisterInCFADecrypt, // sparc64 specific
7475 kRegisterOffsetFromCFA,
7576 kRegisterInRegister,
7677 kRegisterAtExpression,
......@@ -723,7 +724,8 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
723724 "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset);
724725 break;
725726
726#if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC)
727#if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC) || \
728 defined(_LIBUNWIND_TARGET_SPARC64)
727729 // The same constant is used to represent different instructions on
728730 // AArch64 (negate_ra_state) and SPARC (window_save).
729731 static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save,
......@@ -757,8 +759,29 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
757759 }
758760 break;
759761#endif
762
763#if defined(_LIBUNWIND_TARGET_SPARC64)
764 // case DW_CFA_GNU_window_save:
765 case REGISTERS_SPARC64:
766 // Don't save %o0-%o7 on sparc64.
767 // https://reviews.llvm.org/D32450#736405
768
769 for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) {
770 if (reg == UNW_SPARC_I7)
771 results->setRegister(
772 reg, kRegisterInCFADecrypt,
773 ((int64_t)reg - UNW_SPARC_L0) * sizeof(pint_t), initialState);
774 else
775 results->setRegister(
776 reg, kRegisterInCFA,
777 ((int64_t)reg - UNW_SPARC_L0) * sizeof(pint_t), initialState);
778 }
779 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save\n");
780 break;
781#endif
760782 }
761783 break;
784
762785#else
763786 (void)arch;
764787#endif
lib/libunwind/src/Registers.hpp+187
......@@ -34,6 +34,7 @@ enum {
3434 REGISTERS_MIPS_O32,
3535 REGISTERS_MIPS_NEWABI,
3636 REGISTERS_SPARC,
37 REGISTERS_SPARC64,
3738 REGISTERS_HEXAGON,
3839 REGISTERS_RISCV,
3940 REGISTERS_VE,
......@@ -3546,6 +3547,192 @@ inline const char *Registers_sparc::getRegisterName(int regNum) {
35463547}
35473548#endif // _LIBUNWIND_TARGET_SPARC
35483549
3550
3551#if defined(_LIBUNWIND_TARGET_SPARC64)
3552/// Registers_sparc64 holds the register state of a thread in a 64-bit
3553/// sparc process.
3554class _LIBUNWIND_HIDDEN Registers_sparc64 {
3555public:
3556 Registers_sparc64() = default;
3557 Registers_sparc64(const void *registers);
3558
3559 bool validRegister(int num) const;
3560 uint64_t getRegister(int num) const;
3561 void setRegister(int num, uint64_t value);
3562 bool validFloatRegister(int num) const;
3563 double getFloatRegister(int num) const;
3564 void setFloatRegister(int num, double value);
3565 bool validVectorRegister(int num) const;
3566 v128 getVectorRegister(int num) const;
3567 void setVectorRegister(int num, v128 value);
3568 const char *getRegisterName(int num);
3569 void jumpto();
3570 static int lastDwarfRegNum() {
3571 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64;
3572 }
3573 static int getArch() { return REGISTERS_SPARC64; }
3574
3575 uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6] + 2047; }
3576 void setSP(uint64_t value) { _registers.__regs[UNW_SPARC_O6] = value - 2047; }
3577 uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }
3578 void setIP(uint64_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
3579 uint64_t getWCookie() const { return _wcookie; }
3580
3581private:
3582 struct sparc64_thread_state_t {
3583 uint64_t __regs[32];
3584 };
3585
3586 sparc64_thread_state_t _registers{};
3587 uint64_t _wcookie = 0;
3588};
3589
3590inline Registers_sparc64::Registers_sparc64(const void *registers) {
3591 static_assert((check_fit<Registers_sparc64, unw_context_t>::does_fit),
3592 "sparc64 registers do not fit into unw_context_t");
3593 memcpy(&_registers, registers, sizeof(_registers));
3594 memcpy(&_wcookie,
3595 static_cast<const uint8_t *>(registers) + sizeof(_registers),
3596 sizeof(_wcookie));
3597}
3598
3599inline bool Registers_sparc64::validRegister(int regNum) const {
3600 if (regNum == UNW_REG_IP)
3601 return true;
3602 if (regNum == UNW_REG_SP)
3603 return true;
3604 if (regNum < 0)
3605 return false;
3606 if (regNum <= UNW_SPARC_I7)
3607 return true;
3608 return false;
3609}
3610
3611inline uint64_t Registers_sparc64::getRegister(int regNum) const {
3612 if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7)
3613 return _registers.__regs[regNum];
3614
3615 switch (regNum) {
3616 case UNW_REG_IP:
3617 return _registers.__regs[UNW_SPARC_O7];
3618 case UNW_REG_SP:
3619 return _registers.__regs[UNW_SPARC_O6] + 2047;
3620 }
3621 _LIBUNWIND_ABORT("unsupported sparc64 register");
3622}
3623
3624inline void Registers_sparc64::setRegister(int regNum, uint64_t value) {
3625 if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7) {
3626 _registers.__regs[regNum] = value;
3627 return;
3628 }
3629
3630 switch (regNum) {
3631 case UNW_REG_IP:
3632 _registers.__regs[UNW_SPARC_O7] = value;
3633 return;
3634 case UNW_REG_SP:
3635 _registers.__regs[UNW_SPARC_O6] = value - 2047;
3636 return;
3637 }
3638 _LIBUNWIND_ABORT("unsupported sparc64 register");
3639}
3640
3641inline bool Registers_sparc64::validFloatRegister(int) const { return false; }
3642
3643inline double Registers_sparc64::getFloatRegister(int) const {
3644 _LIBUNWIND_ABORT("no sparc64 float registers");
3645}
3646
3647inline void Registers_sparc64::setFloatRegister(int, double) {
3648 _LIBUNWIND_ABORT("no sparc64 float registers");
3649}
3650
3651inline bool Registers_sparc64::validVectorRegister(int) const { return false; }
3652
3653inline v128 Registers_sparc64::getVectorRegister(int) const {
3654 _LIBUNWIND_ABORT("no sparc64 vector registers");
3655}
3656
3657inline void Registers_sparc64::setVectorRegister(int, v128) {
3658 _LIBUNWIND_ABORT("no sparc64 vector registers");
3659}
3660
3661inline const char *Registers_sparc64::getRegisterName(int regNum) {
3662 switch (regNum) {
3663 case UNW_REG_IP:
3664 return "pc";
3665 case UNW_SPARC_G0:
3666 return "g0";
3667 case UNW_SPARC_G1:
3668 return "g1";
3669 case UNW_SPARC_G2:
3670 return "g2";
3671 case UNW_SPARC_G3:
3672 return "g3";
3673 case UNW_SPARC_G4:
3674 return "g4";
3675 case UNW_SPARC_G5:
3676 return "g5";
3677 case UNW_SPARC_G6:
3678 return "g6";
3679 case UNW_SPARC_G7:
3680 return "g7";
3681 case UNW_SPARC_O0:
3682 return "o0";
3683 case UNW_SPARC_O1:
3684 return "o1";
3685 case UNW_SPARC_O2:
3686 return "o2";
3687 case UNW_SPARC_O3:
3688 return "o3";
3689 case UNW_SPARC_O4:
3690 return "o4";
3691 case UNW_SPARC_O5:
3692 return "o5";
3693 case UNW_REG_SP:
3694 case UNW_SPARC_O6:
3695 return "o6";
3696 case UNW_SPARC_O7:
3697 return "o7";
3698 case UNW_SPARC_L0:
3699 return "l0";
3700 case UNW_SPARC_L1:
3701 return "l1";
3702 case UNW_SPARC_L2:
3703 return "l2";
3704 case UNW_SPARC_L3:
3705 return "l3";
3706 case UNW_SPARC_L4:
3707 return "l4";
3708 case UNW_SPARC_L5:
3709 return "l5";
3710 case UNW_SPARC_L6:
3711 return "l6";
3712 case UNW_SPARC_L7:
3713 return "l7";
3714 case UNW_SPARC_I0:
3715 return "i0";
3716 case UNW_SPARC_I1:
3717 return "i1";
3718 case UNW_SPARC_I2:
3719 return "i2";
3720 case UNW_SPARC_I3:
3721 return "i3";
3722 case UNW_SPARC_I4:
3723 return "i4";
3724 case UNW_SPARC_I5:
3725 return "i5";
3726 case UNW_SPARC_I6:
3727 return "i6";
3728 case UNW_SPARC_I7:
3729 return "i7";
3730 default:
3731 return "unknown register";
3732 }
3733}
3734#endif // _LIBUNWIND_TARGET_SPARC64
3735
35493736#if defined(_LIBUNWIND_TARGET_HEXAGON)
35503737/// Registers_hexagon holds the register state of a thread in a Hexagon QDSP6
35513738/// process.
lib/libunwind/src/UnwindCursor.hpp+16
......@@ -1020,6 +1020,10 @@ private:
10201020 int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; }
10211021#endif
10221022
1023#if defined(_LIBUNWIND_TARGET_SPARC64)
1024 int stepWithCompactEncoding(Registers_sparc64 &) { return UNW_EINVAL; }
1025#endif
1026
10231027#if defined (_LIBUNWIND_TARGET_RISCV)
10241028 int stepWithCompactEncoding(Registers_riscv &) {
10251029 return UNW_EINVAL;
......@@ -1092,6 +1096,12 @@ private:
10921096 bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; }
10931097#endif
10941098
1099#if defined(_LIBUNWIND_TARGET_SPARC64)
1100 bool compactSaysUseDwarf(Registers_sparc64 &, uint32_t *) const {
1101 return true;
1102 }
1103#endif
1104
10951105#if defined (_LIBUNWIND_TARGET_RISCV)
10961106 bool compactSaysUseDwarf(Registers_riscv &, uint32_t *) const {
10971107 return true;
......@@ -1170,6 +1180,12 @@ private:
11701180 compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; }
11711181#endif
11721182
1183#if defined(_LIBUNWIND_TARGET_SPARC64)
1184 compact_unwind_encoding_t dwarfEncoding(Registers_sparc64 &) const {
1185 return 0;
1186 }
1187#endif
1188
11731189#if defined (_LIBUNWIND_TARGET_RISCV)
11741190 compact_unwind_encoding_t dwarfEncoding(Registers_riscv &) const {
11751191 return 0;
lib/libunwind/src/UnwindRegistersRestore.S+47
......@@ -1050,6 +1050,53 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv)
10501050 ld $4, (8 * 4)($4)
10511051 .set pop
10521052
1053#elif defined(__sparc__) && defined(__arch64__)
1054
1055DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind17Registers_sparc646jumptoEv)
1056//
1057// void libunwind::Registers_sparc64::jumpto()
1058//
1059// On entry:
1060// thread_state pointer is in %o0
1061//
1062 .register %g2, #scratch
1063 .register %g3, #scratch
1064 .register %g6, #scratch
1065 .register %g7, #scratch
1066 flushw
1067 ldx [%o0 + 0x08], %g1
1068 ldx [%o0 + 0x10], %g2
1069 ldx [%o0 + 0x18], %g3
1070 ldx [%o0 + 0x20], %g4
1071 ldx [%o0 + 0x28], %g5
1072 ldx [%o0 + 0x30], %g6
1073 ldx [%o0 + 0x38], %g7
1074 ldx [%o0 + 0x48], %o1
1075 ldx [%o0 + 0x50], %o2
1076 ldx [%o0 + 0x58], %o3
1077 ldx [%o0 + 0x60], %o4
1078 ldx [%o0 + 0x68], %o5
1079 ldx [%o0 + 0x70], %o6
1080 ldx [%o0 + 0x78], %o7
1081 ldx [%o0 + 0x80], %l0
1082 ldx [%o0 + 0x88], %l1
1083 ldx [%o0 + 0x90], %l2
1084 ldx [%o0 + 0x98], %l3
1085 ldx [%o0 + 0xa0], %l4
1086 ldx [%o0 + 0xa8], %l5
1087 ldx [%o0 + 0xb0], %l6
1088 ldx [%o0 + 0xb8], %l7
1089 ldx [%o0 + 0xc0], %i0
1090 ldx [%o0 + 0xc8], %i1
1091 ldx [%o0 + 0xd0], %i2
1092 ldx [%o0 + 0xd8], %i3
1093 ldx [%o0 + 0xe0], %i4
1094 ldx [%o0 + 0xe8], %i5
1095 ldx [%o0 + 0xf0], %i6
1096 ldx [%o0 + 0xf8], %i7
1097 jmp %o7
1098 ldx [%o0 + 0x40], %o0
1099
10531100#elif defined(__sparc__)
10541101
10551102//
lib/libunwind/src/UnwindRegistersSave.S+59-1
......@@ -766,7 +766,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
766766@
767767@ On entry:
768768@ thread_state pointer is in r0
769@
769@
770770@ Per EHABI #4.7 this only saves the core integer registers.
771771@ EHABI #7.4.5 notes that in general all VRS registers should be restored
772772@ however this is very hard to do for VFP registers because it is unknown
......@@ -996,6 +996,64 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
996996
997997 jumpr r31
998998
999#elif defined(__sparc__) && defined(__arch64__)
1000
1001#
1002# extern int __unw_getcontext(unw_context_t* thread_state)
1003#
1004# On entry:
1005# thread_state pointer is in %o0
1006#
1007DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1008 .register %g2, #scratch
1009 .register %g3, #scratch
1010 .register %g6, #scratch
1011 .register %g7, #scratch
1012 stx %g1, [%o0 + 0x08]
1013 stx %g2, [%o0 + 0x10]
1014 stx %g3, [%o0 + 0x18]
1015 stx %g4, [%o0 + 0x20]
1016 stx %g5, [%o0 + 0x28]
1017 stx %g6, [%o0 + 0x30]
1018 stx %g7, [%o0 + 0x38]
1019 stx %o0, [%o0 + 0x40]
1020 stx %o1, [%o0 + 0x48]
1021 stx %o2, [%o0 + 0x50]
1022 stx %o3, [%o0 + 0x58]
1023 stx %o4, [%o0 + 0x60]
1024 stx %o5, [%o0 + 0x68]
1025 stx %o6, [%o0 + 0x70]
1026 stx %o7, [%o0 + 0x78]
1027 stx %l0, [%o0 + 0x80]
1028 stx %l1, [%o0 + 0x88]
1029 stx %l2, [%o0 + 0x90]
1030 stx %l3, [%o0 + 0x98]
1031 stx %l4, [%o0 + 0xa0]
1032 stx %l5, [%o0 + 0xa8]
1033 stx %l6, [%o0 + 0xb0]
1034 stx %l7, [%o0 + 0xb8]
1035 stx %i0, [%o0 + 0xc0]
1036 stx %i1, [%o0 + 0xc8]
1037 stx %i2, [%o0 + 0xd0]
1038 stx %i3, [%o0 + 0xd8]
1039 stx %i4, [%o0 + 0xe0]
1040 stx %i5, [%o0 + 0xe8]
1041 stx %i6, [%o0 + 0xf0]
1042 stx %i7, [%o0 + 0xf8]
1043
1044 # save StackGhost cookie
1045 mov %i7, %g4
1046 save %sp, -176, %sp
1047 # register window flush necessary even without StackGhost
1048 flushw
1049 restore
1050 ldx [%sp + 2047 + 0x78], %g5
1051 xor %g4, %g5, %g4
1052 stx %g4, [%o0 + 0x100]
1053 retl
1054 # return UNW_ESUCCESS
1055 clr %o0
1056
9991057#elif defined(__sparc__)
10001058
10011059#
lib/libunwind/src/config.h+4-7
......@@ -109,13 +109,10 @@
109109#define _LIBUNWIND_SUPPORT_FRAME_APIS
110110#endif
111111
112#if defined(__i386__) || defined(__x86_64__) || \
113 defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) || \
114 (!defined(__APPLE__) && defined(__arm__)) || \
115 defined(__aarch64__) || \
116 defined(__mips__) || \
117 defined(__riscv) || \
118 defined(__hexagon__)
112#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \
113 (!defined(__APPLE__) && defined(__arm__)) || defined(__aarch64__) || \
114 defined(__mips__) || defined(__riscv) || defined(__hexagon__) || \
115 defined(__sparc__)
119116#if !defined(_LIBUNWIND_BUILD_SJLJ_APIS)
120117#define _LIBUNWIND_BUILD_ZERO_COST_APIS
121118#endif
lib/libunwind/src/libunwind.cpp+2
......@@ -69,6 +69,8 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor,
6969# define REGISTER_KIND Registers_mips_newabi
7070#elif defined(__mips__)
7171# warning The MIPS architecture is not supported with this ABI and environment!
72#elif defined(__sparc__) && defined(__arch64__)
73# define REGISTER_KIND Registers_sparc64
7274#elif defined(__sparc__)
7375# define REGISTER_KIND Registers_sparc
7476#elif defined(__riscv)