authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-10-01 23:24:43+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-10-01 23:47:47+02:00
log8520e9312eed3b3b8d7f95d4844c83105c91ead1
treead03355e6ae4c011458712168f7eec97f5b9d0a7
parentb46867848e4a2e8ba9965d579d4474fba1ab3b10
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.debug: add loongarch64-linux unwind support


3 files changed, 118 insertions(+), 8 deletions(-)

lib/std/debug/Dwarf.zig+9-6
......@@ -1429,30 +1429,33 @@ pub fn compactUnwindToDwarfRegNumber(unwind_reg_number: u3) !u16 {
14291429/// Returns `null` for CPU architectures without an instruction pointer register.
14301430pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 {
14311431 return switch (arch) {
1432 .aarch64, .aarch64_be => 32,
1433 .arm, .armeb, .thumb, .thumbeb => 15,
1434 .loongarch32, .loongarch64 => 32,
14321435 .x86 => 8,
14331436 .x86_64 => 16,
1434 .arm, .armeb, .thumb, .thumbeb => 15,
1435 .aarch64, .aarch64_be => 32,
14361437 else => null,
14371438 };
14381439}
14391440
14401441pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 {
14411442 return switch (arch) {
1443 .aarch64, .aarch64_be => 29,
1444 .arm, .armeb, .thumb, .thumbeb => 11,
1445 .loongarch32, .loongarch64 => 22,
14421446 .x86 => 5,
14431447 .x86_64 => 6,
1444 .arm, .armeb, .thumb, .thumbeb => 11,
1445 .aarch64, .aarch64_be => 29,
14461448 else => unreachable,
14471449 };
14481450}
14491451
14501452pub fn spRegNum(arch: std.Target.Cpu.Arch) u16 {
14511453 return switch (arch) {
1454 .aarch64, .aarch64_be => 31,
1455 .arm, .armeb, .thumb, .thumbeb => 13,
1456 .loongarch32, .loongarch64 => 3,
14521457 .x86 => 4,
14531458 .x86_64 => 7,
1454 .arm, .armeb, .thumb, .thumbeb => 13,
1455 .aarch64, .aarch64_be => 31,
14561459 else => unreachable,
14571460 };
14581461}
lib/std/debug/SelfInfo/Elf.zig+1
......@@ -87,6 +87,7 @@ pub const can_unwind: bool = s: {
8787 .linux => &.{
8888 .aarch64,
8989 .aarch64_be,
90 .loongarch64,
9091 .x86,
9192 .x86_64,
9293 },
lib/std/debug/cpu_context.zig+108-2
......@@ -4,10 +4,11 @@
44pub const Native = if (@hasDecl(root, "debug") and @hasDecl(root.debug, "CpuContext"))
55 root.debug.CpuContext
66else switch (native_arch) {
7 .aarch64, .aarch64_be => Aarch64,
8 .arm, .armeb, .thumb, .thumbeb => Arm,
9 .loongarch32, .loongarch64 => LoongArch,
710 .x86 => X86,
811 .x86_64 => X86_64,
9 .arm, .armeb, .thumb, .thumbeb => Arm,
10 .aarch64, .aarch64_be => Aarch64,
1112 else => noreturn,
1213};
1314
......@@ -173,6 +174,13 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native {
173174 },
174175 else => null,
175176 },
177 .loongarch64 => switch (builtin.os.tag) {
178 .linux => .{
179 .r = uc.mcontext.regs, // includes r0 (hardwired zero)
180 .pc = uc.mcontext.pc,
181 },
182 else => null,
183 },
176184 else => null,
177185 };
178186}
......@@ -465,6 +473,104 @@ pub const Aarch64 = extern struct {
465473 }
466474};
467475
476/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
477pub const LoongArch = extern struct {
478 /// The numbered general-purpose registers r0 - r31. r0 must be zero.
479 r: [32]usize,
480 pc: usize,
481
482 pub inline fn current() LoongArch {
483 var ctx: LoongArch = undefined;
484 asm volatile (if (@sizeOf(usize) == 8)
485 \\ st.d $zero, $t0, 0
486 \\ st.d $ra, $t0, 8
487 \\ st.d $tp, $t0, 16
488 \\ st.d $sp, $t0, 24
489 \\ st.d $a0, $t0, 32
490 \\ st.d $a1, $t0, 40
491 \\ st.d $a2, $t0, 48
492 \\ st.d $a3, $t0, 56
493 \\ st.d $a4, $t0, 64
494 \\ st.d $a5, $t0, 72
495 \\ st.d $a6, $t0, 80
496 \\ st.d $a7, $t0, 88
497 \\ st.d $t0, $t0, 96
498 \\ st.d $t1, $t0, 104
499 \\ st.d $t2, $t0, 112
500 \\ st.d $t3, $t0, 120
501 \\ st.d $t4, $t0, 128
502 \\ st.d $t5, $t0, 136
503 \\ st.d $t6, $t0, 144
504 \\ st.d $t7, $t0, 152
505 \\ st.d $t8, $t0, 160
506 \\ st.d $r21, $t0, 168
507 \\ st.d $fp, $t0, 176
508 \\ st.d $s0, $t0, 184
509 \\ st.d $s1, $t0, 192
510 \\ st.d $s2, $t0, 200
511 \\ st.d $s3, $t0, 208
512 \\ st.d $s4, $t0, 216
513 \\ st.d $s5, $t0, 224
514 \\ st.d $s6, $t0, 232
515 \\ st.d $s7, $t0, 240
516 \\ st.d $s8, $t0, 248
517 \\ bl 1f
518 \\1:
519 \\ st.d $ra, $t0, 256
520 \\ ld.d $ra, $t0, 8
521 else
522 \\ st.w $zero, $t0, 0
523 \\ st.w $ra, $t0, 4
524 \\ st.w $tp, $t0, 8
525 \\ st.w $sp, $t0, 12
526 \\ st.w $a0, $t0, 16
527 \\ st.w $a1, $t0, 20
528 \\ st.w $a2, $t0, 24
529 \\ st.w $a3, $t0, 28
530 \\ st.w $a4, $t0, 32
531 \\ st.w $a5, $t0, 36
532 \\ st.w $a6, $t0, 40
533 \\ st.w $a7, $t0, 44
534 \\ st.w $t0, $t0, 48
535 \\ st.w $t1, $t0, 52
536 \\ st.w $t2, $t0, 56
537 \\ st.w $t3, $t0, 60
538 \\ st.w $t4, $t0, 64
539 \\ st.w $t5, $t0, 68
540 \\ st.w $t6, $t0, 72
541 \\ st.w $t7, $t0, 76
542 \\ st.w $t8, $t0, 80
543 \\ st.w $r21, $t0, 84
544 \\ st.w $fp, $t0, 88
545 \\ st.w $s0, $t0, 92
546 \\ st.w $s1, $t0, 96
547 \\ st.w $s2, $t0, 100
548 \\ st.w $s3, $t0, 104
549 \\ st.w $s4, $t0, 108
550 \\ st.w $s5, $t0, 112
551 \\ st.w $s6, $t0, 116
552 \\ st.w $s7, $t0, 120
553 \\ st.w $s8, $t0, 124
554 \\ bl 1f
555 \\1:
556 \\ st.w $ra, $t0, 128
557 \\ ld.w $ra, $t0, 4
558 :
559 : [gprs] "{$r12}" (&ctx),
560 : .{ .memory = true });
561 return ctx;
562 }
563
564 pub fn dwarfRegisterBytes(ctx: *LoongArch, register_num: u16) DwarfRegisterError![]u8 {
565 switch (register_num) {
566 0...31 => return @ptrCast(&ctx.r[register_num]),
567 32 => return @ptrCast(&ctx.pc),
568
569 else => return error.InvalidRegister,
570 }
571 }
572};
573
468574const signal_ucontext_t = switch (native_os) {
469575 .linux => std.os.linux.ucontext_t,
470576 .emscripten => std.os.emscripten.ucontext_t,