[libunwind] [libunwind][Hexagon] Save/restore full r0-r7 in getcontext/jumpto (PR #208753)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 10 08:20:31 PDT 2026
https://github.com/quic-k created https://github.com/llvm/llvm-project/pull/208753
The Hexagon save and restore routines dropped GPRs, producing an incomplete context.
UnwindRegistersSave.S (__unw_getcontext): save r0-r7 (stores began at __r[8]), drop a dead "r1 = memw(r30)" before the PC store, and return UNW_ESUCCESS instead of a stale non-zero value.
UnwindRegistersRestore.S (jumpto): restore the missing r2-r7 (r0/r1 and r8-r31 were already handled), and fix the stale "pointer is in r2" comment (it is r0).
>From c287986c5fa968624feae8055f9b390229696678 Mon Sep 17 00:00:00 2001
From: Kushal Pal <kushpal at qti.qualcomm.com>
Date: Fri, 10 Jul 2026 20:33:28 +0530
Subject: [PATCH] [libunwind][Hexagon] Save/restore full r0-r7 in
getcontext/jumpto
The Hexagon save and restore routines dropped GPRs, producing an
incomplete context.
UnwindRegistersSave.S (__unw_getcontext): save r0-r7 (stores began at
__r[8]), drop a dead "r1 = memw(r30)" before the PC store, and return
UNW_ESUCCESS instead of a stale non-zero value.
UnwindRegistersRestore.S (jumpto): restore the missing r2-r7 (r0/r1 and
r8-r31 were already handled), and fix the stale "pointer is in r2"
comment (it is r0).
Signed-off-by: Kushal Pal <kushpal at qti.qualcomm.com>
---
libunwind/src/UnwindRegistersRestore.S | 13 ++++++++++++-
libunwind/src/UnwindRegistersSave.S | 24 +++++++++++++++++++++---
2 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S
index 8f84f4d456a35..37e8156408cf2 100644
--- a/libunwind/src/UnwindRegistersRestore.S
+++ b/libunwind/src/UnwindRegistersRestore.S
@@ -947,11 +947,22 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
#elif defined(__hexagon__)
# On entry:
-# thread_state pointer is in r2
+# thread_state pointer is in r0
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind17Registers_hexagon6jumptoEv)
#
# void libunwind::Registers_hexagon::jumpto()
#
+# The context layout is hexagon_thread_state_t: unsigned int __r[35]
+# __r[0..31] = r0..r31, __r[32] = predicates, __r[33] = PC.
+# Offsets: __r[n] is at byte offset n*4. r0 is the context pointer, so
+# it is restored last; r31 is loaded with the saved PC as the jumpr target.
+ r2 = memw(r0+#8)
+ r3 = memw(r0+#12)
+ r4 = memw(r0+#16)
+ r5 = memw(r0+#20)
+ r6 = memw(r0+#24)
+ r7 = memw(r0+#28)
+
r8 = memw(r0+#32)
r9 = memw(r0+#36)
r10 = memw(r0+#40)
diff --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S
index a82ebd1ead23b..f44f6a1331968 100644
--- a/libunwind/src/UnwindRegistersSave.S
+++ b/libunwind/src/UnwindRegistersSave.S
@@ -1103,8 +1103,21 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
# On entry:
# thread_state pointer is in r0
#
+# The context layout is hexagon_thread_state_t: unsigned int __r[35]
+# __r[0..31] = r0..r31, __r[32] = predicates, __r[33] = PC, __r[34] = unused
+# Offsets: __r[n] is at byte offset n*4.
+#
#define OFFSET(offset) (offset/4)
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
+ // Save r1-r7 first (r0 is the context pointer, saved last)
+ memw(r0+#4) = r1
+ memw(r0+#8) = r2
+ memw(r0+#12) = r3
+ memw(r0+#16) = r4
+ memw(r0+#20) = r5
+ memw(r0+#24) = r6
+ memw(r0+#28) = r7
+
memw(r0+#32) = r8
memw(r0+#36) = r9
memw(r0+#40) = r10
@@ -1134,12 +1147,17 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
memw(r0+#116) = r29
memw(r0+#120) = r30
memw(r0+#124) = r31
- r1 = c4 // Predicate register
+
+ r1 = c4 // Predicate register
memw(r0+#128) = r1
- r1 = memw(r30) // *FP == Saved FP
- r1 = r31
+
+ r1 = r31 // Store return address as PC
memw(r0+#132) = r1
+ // Save r0 (the context pointer itself) last
+ memw(r0+#0) = r0
+
+ r0 = #0 // return UNW_ESUCCESS
jumpr r31
#elif defined(__sparc__) && defined(__arch64__)
More information about the cfe-commits
mailing list