authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-10-06 17:45:31+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-10-07 16:47:57+02:00
logca73d697b9b11b579b2fefb40e68ec637bea5050
tree4e6f6964e9e7191e25b5212f00dae8b3cfc8a482
parenta5a9ffb90b9427efbad40404a9a830ddb42b88b6
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.debug: add unwind support for mips*-linux


3 files changed, 137 insertions(+), 0 deletions(-)

lib/std/debug/Dwarf.zig+3
...@@ -1433,6 +1433,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 {...@@ -1433,6 +1433,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 {
1433 .arm, .armeb, .thumb, .thumbeb => 15,1433 .arm, .armeb, .thumb, .thumbeb => 15,
1434 .hexagon => 76,1434 .hexagon => 76,
1435 .loongarch32, .loongarch64 => 32,1435 .loongarch32, .loongarch64 => 32,
1436 .mips, .mipsel, .mips64, .mips64el => 37,
1436 .riscv32, .riscv32be, .riscv64, .riscv64be => 32,1437 .riscv32, .riscv32be, .riscv64, .riscv64be => 32,
1437 .s390x => 65,1438 .s390x => 65,
1438 .x86 => 8,1439 .x86 => 8,
...@@ -1447,6 +1448,7 @@ pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 {...@@ -1447,6 +1448,7 @@ pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 {
1447 .arm, .armeb, .thumb, .thumbeb => 11,1448 .arm, .armeb, .thumb, .thumbeb => 11,
1448 .hexagon => 30,1449 .hexagon => 30,
1449 .loongarch32, .loongarch64 => 22,1450 .loongarch32, .loongarch64 => 22,
1451 .mips, .mipsel, .mips64, .mips64el => 30,
1450 .riscv32, .riscv32be, .riscv64, .riscv64be => 8,1452 .riscv32, .riscv32be, .riscv64, .riscv64be => 8,
1451 .s390x => 11,1453 .s390x => 11,
1452 .x86 => 5,1454 .x86 => 5,
...@@ -1461,6 +1463,7 @@ pub fn spRegNum(arch: std.Target.Cpu.Arch) u16 {...@@ -1461,6 +1463,7 @@ pub fn spRegNum(arch: std.Target.Cpu.Arch) u16 {
1461 .arm, .armeb, .thumb, .thumbeb => 13,1463 .arm, .armeb, .thumb, .thumbeb => 13,
1462 .hexagon => 29,1464 .hexagon => 29,
1463 .loongarch32, .loongarch64 => 3,1465 .loongarch32, .loongarch64 => 3,
1466 .mips, .mipsel, .mips64, .mips64el => 29,
1464 .riscv32, .riscv32be, .riscv64, .riscv64be => 2,1467 .riscv32, .riscv32be, .riscv64, .riscv64be => 2,
1465 .s390x => 15,1468 .s390x => 15,
1466 .x86 => 4,1469 .x86 => 4,
lib/std/debug/SelfInfo/Elf.zig+4
...@@ -99,6 +99,10 @@ pub const can_unwind: bool = s: {...@@ -99,6 +99,10 @@ pub const can_unwind: bool = s: {
99 .aarch64_be,99 .aarch64_be,
100 .hexagon,100 .hexagon,
101 .loongarch64,101 .loongarch64,
102 .mips,
103 .mipsel,
104 .mips64,
105 .mips64el,
102 .riscv32,106 .riscv32,
103 .riscv64,107 .riscv64,
104 .s390x,108 .s390x,
lib/std/debug/cpu_context.zig+130
...@@ -8,6 +8,7 @@ else switch (native_arch) {...@@ -8,6 +8,7 @@ else switch (native_arch) {
8 .arm, .armeb, .thumb, .thumbeb => Arm,8 .arm, .armeb, .thumb, .thumbeb => Arm,
9 .hexagon => Hexagon,9 .hexagon => Hexagon,
10 .loongarch32, .loongarch64 => LoongArch,10 .loongarch32, .loongarch64 => LoongArch,
11 .mips, .mipsel, .mips64, .mips64el => Mips,
11 .riscv32, .riscv32be, .riscv64, .riscv64be => Riscv,12 .riscv32, .riscv32be, .riscv64, .riscv64be => Riscv,
12 .s390x => S390x,13 .s390x => S390x,
13 .x86 => X86,14 .x86 => X86,
...@@ -196,6 +197,25 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native {...@@ -196,6 +197,25 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native {
196 },197 },
197 else => null,198 else => null,
198 },199 },
200 .mips, .mipsel => switch (builtin.os.tag) {
201 // The O32 kABI uses 64-bit fields for some reason...
202 .linux => .{
203 .r = s: {
204 var regs: [32]Mips.Gpr = undefined;
205 for (uc.mcontext.regs, 0..) |r, i| regs[i] = @truncate(r); // includes r0 (hardwired zero)
206 break :s regs;
207 },
208 .pc = @truncate(uc.mcontext.pc),
209 },
210 else => null,
211 },
212 .mips64, .mips64el => switch (builtin.os.tag) {
213 .linux => .{
214 .r = uc.mcontext.regs, // includes r0 (hardwired zero)
215 .pc = uc.mcontext.pc,
216 },
217 else => null,
218 },
199 .riscv32, .riscv64 => switch (builtin.os.tag) {219 .riscv32, .riscv64 => switch (builtin.os.tag) {
200 .linux => .{220 .linux => .{
201 .r = [1]usize{0} ++ uc.mcontext.gregs[1..].*, // r0 position is used for pc; replace with zero221 .r = [1]usize{0} ++ uc.mcontext.gregs[1..].*, // r0 position is used for pc; replace with zero
...@@ -678,6 +698,116 @@ pub const LoongArch = extern struct {...@@ -678,6 +698,116 @@ pub const LoongArch = extern struct {
678 }698 }
679};699};
680700
701/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
702pub const Mips = extern struct {
703 /// The numbered general-purpose registers r0 - r31. r0 must be zero.
704 r: [32]Gpr,
705 pc: Gpr,
706
707 pub const Gpr = if (builtin.target.cpu.arch.isMIPS64()) u64 else u32;
708
709 pub inline fn current() Mips {
710 var ctx: Mips = undefined;
711 asm volatile (if (Gpr == u64)
712 \\ .set push
713 \\ .set noat
714 \\ .set noreorder
715 \\ .set nomacro
716 \\ sd $zero, 0($t0)
717 \\ sd $at, 8($t0)
718 \\ sd $v0, 16($t0)
719 \\ sd $v1, 24($t0)
720 \\ sd $a0, 32($t0)
721 \\ sd $a1, 40($t0)
722 \\ sd $a2, 48($t0)
723 \\ sd $a3, 56($t0)
724 \\ sd $a4, 64($t0)
725 \\ sd $a5, 72($t0)
726 \\ sd $a6, 80($t0)
727 \\ sd $a7, 88($t0)
728 \\ sd $t0, 96($t0)
729 \\ sd $t1, 104($t0)
730 \\ sd $t2, 112($t0)
731 \\ sd $t3, 120($t0)
732 \\ sd $s0, 128($t0)
733 \\ sd $s1, 136($t0)
734 \\ sd $s2, 144($t0)
735 \\ sd $s3, 152($t0)
736 \\ sd $s4, 160($t0)
737 \\ sd $s5, 168($t0)
738 \\ sd $s6, 176($t0)
739 \\ sd $s7, 184($t0)
740 \\ sd $t8, 192($t0)
741 \\ sd $t9, 200($t0)
742 \\ sd $k0, 208($t0)
743 \\ sd $k1, 216($t0)
744 \\ sd $gp, 224($t0)
745 \\ sd $sp, 232($t0)
746 \\ sd $fp, 240($t0)
747 \\ sd $ra, 248($t0)
748 \\ bal 1f
749 \\1:
750 \\ sd $ra, 256($t0)
751 \\ ld $ra, 248($t0)
752 \\ .set pop
753 else
754 \\ .set push
755 \\ .set noat
756 \\ .set noreorder
757 \\ .set nomacro
758 \\ sw $zero, 0($t4)
759 \\ sw $at, 4($t4)
760 \\ sw $v0, 8($t4)
761 \\ sw $v1, 12($t4)
762 \\ sw $a0, 16($t4)
763 \\ sw $a1, 20($t4)
764 \\ sw $a2, 24($t4)
765 \\ sw $a3, 28($t4)
766 \\ sw $t0, 32($t4)
767 \\ sw $t1, 36($t4)
768 \\ sw $t2, 40($t4)
769 \\ sw $t3, 44($t4)
770 \\ sw $t4, 48($t4)
771 \\ sw $t5, 52($t4)
772 \\ sw $t6, 56($t4)
773 \\ sw $t7, 60($t4)
774 \\ sw $s0, 64($t4)
775 \\ sw $s1, 68($t4)
776 \\ sw $s2, 72($t4)
777 \\ sw $s3, 76($t4)
778 \\ sw $s4, 80($t4)
779 \\ sw $s5, 84($t4)
780 \\ sw $s6, 88($t4)
781 \\ sw $s7, 92($t4)
782 \\ sw $t8, 96($t4)
783 \\ sw $t9, 100($t4)
784 \\ sw $k0, 104($t4)
785 \\ sw $k1, 108($t4)
786 \\ sw $gp, 112($t4)
787 \\ sw $sp, 116($t4)
788 \\ sw $fp, 120($t4)
789 \\ sw $ra, 124($t4)
790 \\ bal 1f
791 \\1:
792 \\ sw $ra, 128($t4)
793 \\ lw $ra, 124($t4)
794 \\ .set pop
795 :
796 : [gprs] "{$12}" (&ctx),
797 : .{ .memory = true });
798 return ctx;
799 }
800
801 pub fn dwarfRegisterBytes(ctx: *Mips, register_num: u16) DwarfRegisterError![]u8 {
802 switch (register_num) {
803 0...31 => return @ptrCast(&ctx.r[register_num]),
804 37 => return @ptrCast(&ctx.pc),
805
806 else => return error.InvalidRegister,
807 }
808 }
809};
810
681/// This is an `extern struct` so that inline assembly in `current` can use field offsets.811/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
682pub const Riscv = extern struct {812pub const Riscv = extern struct {
683 /// The numbered general-purpose registers r0 - r31. r0 must be zero.813 /// The numbered general-purpose registers r0 - r31. r0 must be zero.