diff --git a/lib/std/debug.zig b/lib/std/debug.zig index ee358be26f..51c0cf24ca 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -623,7 +623,7 @@ pub const StackUnwindOptions = struct { /// the given buffer, so `addr_buf` must have a lifetime at least equal to the `StackTrace`. /// /// See `writeCurrentStackTrace` to immediately print the trace instead of capturing it. -pub fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf: []usize) std.builtin.StackTrace { +pub noinline fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf: []usize) std.builtin.StackTrace { const empty_trace: std.builtin.StackTrace = .{ .index = 0, .instruction_addresses = &.{} }; if (!std.options.allow_stack_tracing) return empty_trace; var it = StackIterator.init(options.context) catch return empty_trace; @@ -661,7 +661,7 @@ pub fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf: []usize) /// Write the current stack trace to `writer`, annotated with source locations. /// /// See `captureCurrentStackTrace` to capture the trace addresses into a buffer instead of printing. -pub fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Writer, tty_config: tty.Config) Writer.Error!void { +pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Writer, tty_config: tty.Config) Writer.Error!void { if (!std.options.allow_stack_tracing) { tty_config.setColor(writer, .dim) catch {}; try writer.print("Cannot print stack trace: stack tracing is disabled\n", .{}); diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index 0134d10e6b..98d7addb32 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -1432,8 +1432,10 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 { .aarch64, .aarch64_be => 32, .arm, .armeb, .thumb, .thumbeb => 15, .hexagon => 76, - .loongarch32, .loongarch64 => 32, - .riscv32, .riscv32be, .riscv64, .riscv64be => 32, + .loongarch32, .loongarch64 => 64, + .mips, .mipsel, .mips64, .mips64el => 66, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => 67, + .riscv32, .riscv32be, .riscv64, .riscv64be => 65, .s390x => 65, .x86 => 8, .x86_64 => 16, @@ -1447,6 +1449,8 @@ pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 { .arm, .armeb, .thumb, .thumbeb => 11, .hexagon => 30, .loongarch32, .loongarch64 => 22, + .mips, .mipsel, .mips64, .mips64el => 30, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => 1, .riscv32, .riscv32be, .riscv64, .riscv64be => 8, .s390x => 11, .x86 => 5, @@ -1461,6 +1465,8 @@ pub fn spRegNum(arch: std.Target.Cpu.Arch) u16 { .arm, .armeb, .thumb, .thumbeb => 13, .hexagon => 29, .loongarch32, .loongarch64 => 3, + .mips, .mipsel, .mips64, .mips64el => 29, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => 1, .riscv32, .riscv32be, .riscv64, .riscv64be => 2, .s390x => 15, .x86 => 4, diff --git a/lib/std/debug/Dwarf/SelfUnwinder.zig b/lib/std/debug/Dwarf/SelfUnwinder.zig index 24afdaba1d..7562a3697f 100644 --- a/lib/std/debug/Dwarf/SelfUnwinder.zig +++ b/lib/std/debug/Dwarf/SelfUnwinder.zig @@ -229,8 +229,10 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE } = switch (rule) { .default => val: { // The default rule is typically equivalent to `.undefined`, but ABIs may override it. - if (builtin.cpu.arch.isAARCH64() and register >= 19 and register <= 28) { - break :val .same; + switch (builtin.target.cpu.arch) { + .aarch64, .aarch64_be => if (register >= 19 and register <= 28) break :val .same, + .s390x => if (register >= 6 and register <= 15) break :val .same, + else => {}, } break :val .undefined; }, diff --git a/lib/std/debug/Dwarf/expression.zig b/lib/std/debug/Dwarf/expression.zig index 4460bd2bc2..62659ec089 100644 --- a/lib/std/debug/Dwarf/expression.zig +++ b/lib/std/debug/Dwarf/expression.zig @@ -1160,22 +1160,19 @@ test "basics" { mem.writeInt(usize, reg_bytes[0..@sizeOf(usize)], 0xee, native_endian); (try regNative(&cpu_context, fp_reg_num)).* = 1; - (try regNative(&cpu_context, sp_reg_num)).* = 2; - (try regNative(&cpu_context, ip_reg_num)).* = 3; + (try regNative(&cpu_context, ip_reg_num)).* = 2; try b.writeBreg(writer, fp_reg_num, @as(usize, 100)); - try b.writeBreg(writer, sp_reg_num, @as(usize, 200)); - try b.writeBregx(writer, ip_reg_num, @as(usize, 300)); - try b.writeRegvalType(writer, @as(u8, 0), @as(usize, 400)); + try b.writeBregx(writer, ip_reg_num, @as(usize, 200)); + try b.writeRegvalType(writer, @as(u8, 0), @as(usize, 300)); _ = try stack_machine.run(program.written(), allocator, context, 0); const regval_type = stack_machine.stack.pop().?.regval_type; - try testing.expectEqual(@as(usize, 400), regval_type.type_offset); + try testing.expectEqual(@as(usize, 300), regval_type.type_offset); try testing.expectEqual(@as(u8, @sizeOf(usize)), regval_type.type_size); try testing.expectEqual(@as(usize, 0xee), regval_type.value); - try testing.expectEqual(@as(usize, 303), stack_machine.stack.pop().?.generic); try testing.expectEqual(@as(usize, 202), stack_machine.stack.pop().?.generic); try testing.expectEqual(@as(usize, 101), stack_machine.stack.pop().?.generic); } diff --git a/lib/std/debug/SelfInfo/Elf.zig b/lib/std/debug/SelfInfo/Elf.zig index 106d2a532f..146f41278d 100644 --- a/lib/std/debug/SelfInfo/Elf.zig +++ b/lib/std/debug/SelfInfo/Elf.zig @@ -99,6 +99,14 @@ pub const can_unwind: bool = s: { .aarch64_be, .hexagon, .loongarch64, + .mips, + .mipsel, + .mips64, + .mips64el, + .powerpc, + .powerpcle, + .powerpc64, + .powerpc64le, .riscv32, .riscv64, .s390x, diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index ae0f0d0e38..b09f36d8ba 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -8,6 +8,8 @@ else switch (native_arch) { .arm, .armeb, .thumb, .thumbeb => Arm, .hexagon => Hexagon, .loongarch32, .loongarch64 => LoongArch, + .mips, .mipsel, .mips64, .mips64el => Mips, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => Powerpc, .riscv32, .riscv32be, .riscv64, .riscv64be => Riscv, .s390x => S390x, .x86 => X86, @@ -196,6 +198,33 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { }, else => null, }, + .mips, .mipsel => switch (builtin.os.tag) { + // The O32 kABI uses 64-bit fields for some reason... + .linux => .{ + .r = s: { + var regs: [32]Mips.Gpr = undefined; + for (uc.mcontext.regs, 0..) |r, i| regs[i] = @truncate(r); // includes r0 (hardwired zero) + break :s regs; + }, + .pc = @truncate(uc.mcontext.pc), + }, + else => null, + }, + .mips64, .mips64el => switch (builtin.os.tag) { + .linux => .{ + .r = uc.mcontext.regs, // includes r0 (hardwired zero) + .pc = uc.mcontext.pc, + }, + else => null, + }, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => switch (builtin.os.tag) { + .linux => .{ + .r = uc.mcontext.gp_regs[0..32].*, + .pc = uc.mcontext.gp_regs[32], + .lr = uc.mcontext.gp_regs[36], + }, + else => null, + }, .riscv32, .riscv64 => switch (builtin.os.tag) { .linux => .{ .r = [1]usize{0} ++ uc.mcontext.gregs[1..].*, // r0 position is used for pc; replace with zero @@ -210,7 +239,6 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { .s390x => switch (builtin.os.tag) { .linux => .{ .r = uc.mcontext.gregs, - .f = uc.mcontext.fregs, .psw = .{ .mask = uc.mcontext.psw.mask, .addr = uc.mcontext.psw.addr, @@ -269,7 +297,7 @@ pub fn fromWindowsContext(ctx: *const std.os.windows.CONTEXT) Native { }; } -pub const X86 = struct { +const X86 = struct { /// The first 8 registers here intentionally match the order of registers in the x86 instruction /// encoding. This order is inherited by the PUSHA instruction and the DWARF register mappings, /// among other things. @@ -313,7 +341,7 @@ pub const X86 = struct { // x86-macos is a deprecated target which is not supported by the Zig Standard Library. 0...8 => return @ptrCast(&ctx.gprs.values[register_num]), - 9 => return error.UnsupportedRegister, // rflags + 9 => return error.UnsupportedRegister, // eflags 11...18 => return error.UnsupportedRegister, // st0 - st7 21...28 => return error.UnsupportedRegister, // xmm0 - xmm7 29...36 => return error.UnsupportedRegister, // mm0 - mm7 @@ -321,14 +349,14 @@ pub const X86 = struct { 40...45 => return error.UnsupportedRegister, // es, cs, ss, ds, fs, gs 48 => return error.UnsupportedRegister, // tr 49 => return error.UnsupportedRegister, // ldtr - 93...94 => return error.UnsupportedRegister, // fs.base, gs.base + 93...100 => return error.UnsupportedRegister, // k0 - k7 (AVX-512) else => return error.InvalidRegister, } } }; -pub const X86_64 = struct { +const X86_64 = struct { /// The order here intentionally matches the order of the DWARF register mappings. It's unclear /// where those mappings actually originated from---the ordering of the first 4 registers seems /// quite unusual---but it is currently convenient for us to match DWARF. @@ -389,13 +417,16 @@ pub const X86_64 = struct { 64 => return error.UnsupportedRegister, // mxcsr 65 => return error.UnsupportedRegister, // fcw 66 => return error.UnsupportedRegister, // fsw + 67...82 => return error.UnsupportedRegister, // xmm16 - xmm31 (AVX-512) + 118...125 => return error.UnsupportedRegister, // k0 - k7 (AVX-512) + 130...145 => return error.UnsupportedRegister, // r16 - r31 (APX) else => return error.InvalidRegister, } } }; -pub const Arm = struct { +const Arm = struct { /// The numbered general-purpose registers R0 - R15. r: [16]u32, @@ -449,7 +480,7 @@ pub const Arm = struct { }; /// This is an `extern struct` so that inline assembly in `current` can use field offsets. -pub const Aarch64 = extern struct { +const Aarch64 = extern struct { /// The numbered general-purpose registers X0 - X30. x: [31]u64, sp: u64, @@ -492,13 +523,13 @@ pub const Aarch64 = extern struct { 31 => return @ptrCast(&ctx.sp), 32 => return @ptrCast(&ctx.pc), - 33 => return error.UnsupportedRegister, // ELF_mode + 33 => return error.UnsupportedRegister, // ELR_mode 34 => return error.UnsupportedRegister, // RA_SIGN_STATE 35 => return error.UnsupportedRegister, // TPIDRRO_ELO - 36 => return error.UnsupportedRegister, // RPIDR_ELO - 37 => return error.UnsupportedRegister, // RPIDR_EL1 - 38 => return error.UnsupportedRegister, // RPIDR_EL2 - 39 => return error.UnsupportedRegister, // RPIDR_EL3 + 36 => return error.UnsupportedRegister, // TPIDR_ELO + 37 => return error.UnsupportedRegister, // TPIDR_EL1 + 38 => return error.UnsupportedRegister, // TPIDR_EL2 + 39 => return error.UnsupportedRegister, // TPIDR_EL3 46 => return error.UnsupportedRegister, // VG 47 => return error.UnsupportedRegister, // FFR 48...63 => return error.UnsupportedRegister, // P0 - P15 @@ -511,7 +542,7 @@ pub const Aarch64 = extern struct { }; /// This is an `extern struct` so that inline assembly in `current` can use field offsets. -pub const Hexagon = extern struct { +const Hexagon = extern struct { /// The numbered general-purpose registers r0 - r31. r: [32]u32, pc: u32, @@ -579,14 +610,16 @@ pub const Hexagon = extern struct { }; /// This is an `extern struct` so that inline assembly in `current` can use field offsets. -pub const LoongArch = extern struct { +const LoongArch = extern struct { /// The numbered general-purpose registers r0 - r31. r0 must be zero. - r: [32]usize, - pc: usize, + r: [32]Gpr, + pc: Gpr, + + pub const Gpr = if (builtin.target.cpu.arch == .loongarch64) u64 else u32; pub inline fn current() LoongArch { var ctx: LoongArch = undefined; - asm volatile (if (@sizeOf(usize) == 8) + asm volatile (if (Gpr == u64) \\ st.d $zero, $t0, 0 \\ st.d $ra, $t0, 8 \\ st.d $tp, $t0, 16 @@ -669,7 +702,9 @@ pub const LoongArch = extern struct { pub fn dwarfRegisterBytes(ctx: *LoongArch, register_num: u16) DwarfRegisterError![]u8 { switch (register_num) { 0...31 => return @ptrCast(&ctx.r[register_num]), - 32 => return @ptrCast(&ctx.pc), + 64 => return @ptrCast(&ctx.pc), + + 32...63 => return error.UnsupportedRegister, // f0 - f31 else => return error.InvalidRegister, } @@ -677,14 +712,294 @@ pub const LoongArch = extern struct { }; /// This is an `extern struct` so that inline assembly in `current` can use field offsets. -pub const Riscv = extern struct { +const Mips = extern struct { /// The numbered general-purpose registers r0 - r31. r0 must be zero. - r: [32]usize, - pc: usize, + r: [32]Gpr, + pc: Gpr, + + pub const Gpr = if (builtin.target.cpu.arch.isMIPS64()) u64 else u32; + + pub inline fn current() Mips { + var ctx: Mips = undefined; + asm volatile (if (Gpr == u64) + \\ .set push + \\ .set noat + \\ .set noreorder + \\ .set nomacro + \\ sd $zero, 0($t0) + \\ sd $at, 8($t0) + \\ sd $v0, 16($t0) + \\ sd $v1, 24($t0) + \\ sd $a0, 32($t0) + \\ sd $a1, 40($t0) + \\ sd $a2, 48($t0) + \\ sd $a3, 56($t0) + \\ sd $a4, 64($t0) + \\ sd $a5, 72($t0) + \\ sd $a6, 80($t0) + \\ sd $a7, 88($t0) + \\ sd $t0, 96($t0) + \\ sd $t1, 104($t0) + \\ sd $t2, 112($t0) + \\ sd $t3, 120($t0) + \\ sd $s0, 128($t0) + \\ sd $s1, 136($t0) + \\ sd $s2, 144($t0) + \\ sd $s3, 152($t0) + \\ sd $s4, 160($t0) + \\ sd $s5, 168($t0) + \\ sd $s6, 176($t0) + \\ sd $s7, 184($t0) + \\ sd $t8, 192($t0) + \\ sd $t9, 200($t0) + \\ sd $k0, 208($t0) + \\ sd $k1, 216($t0) + \\ sd $gp, 224($t0) + \\ sd $sp, 232($t0) + \\ sd $fp, 240($t0) + \\ sd $ra, 248($t0) + \\ bal 1f + \\1: + \\ sd $ra, 256($t0) + \\ ld $ra, 248($t0) + \\ .set pop + else + \\ .set push + \\ .set noat + \\ .set noreorder + \\ .set nomacro + \\ sw $zero, 0($t4) + \\ sw $at, 4($t4) + \\ sw $v0, 8($t4) + \\ sw $v1, 12($t4) + \\ sw $a0, 16($t4) + \\ sw $a1, 20($t4) + \\ sw $a2, 24($t4) + \\ sw $a3, 28($t4) + \\ sw $t0, 32($t4) + \\ sw $t1, 36($t4) + \\ sw $t2, 40($t4) + \\ sw $t3, 44($t4) + \\ sw $t4, 48($t4) + \\ sw $t5, 52($t4) + \\ sw $t6, 56($t4) + \\ sw $t7, 60($t4) + \\ sw $s0, 64($t4) + \\ sw $s1, 68($t4) + \\ sw $s2, 72($t4) + \\ sw $s3, 76($t4) + \\ sw $s4, 80($t4) + \\ sw $s5, 84($t4) + \\ sw $s6, 88($t4) + \\ sw $s7, 92($t4) + \\ sw $t8, 96($t4) + \\ sw $t9, 100($t4) + \\ sw $k0, 104($t4) + \\ sw $k1, 108($t4) + \\ sw $gp, 112($t4) + \\ sw $sp, 116($t4) + \\ sw $fp, 120($t4) + \\ sw $ra, 124($t4) + \\ bal 1f + \\1: + \\ sw $ra, 128($t4) + \\ lw $ra, 124($t4) + \\ .set pop + : + : [gprs] "{$12}" (&ctx), + : .{ .memory = true }); + return ctx; + } + + pub fn dwarfRegisterBytes(ctx: *Mips, register_num: u16) DwarfRegisterError![]u8 { + switch (register_num) { + 0...31 => return @ptrCast(&ctx.r[register_num]), + 66 => return @ptrCast(&ctx.pc), + + // Who the hell knows what numbers exist for this architecture? What's an ABI + // specification anyway? We don't need that nonsense. + 32...63 => return error.UnsupportedRegister, // f0 - f31, w0 - w31 + 64 => return error.UnsupportedRegister, // hi0 (ac0) + 65 => return error.UnsupportedRegister, // lo0 (ac0) + 176 => return error.UnsupportedRegister, // hi1 (ac1) + 177 => return error.UnsupportedRegister, // lo1 (ac1) + 178 => return error.UnsupportedRegister, // hi2 (ac2) + 179 => return error.UnsupportedRegister, // lo2 (ac2) + 180 => return error.UnsupportedRegister, // hi3 (ac3) + 181 => return error.UnsupportedRegister, // lo3 (ac3) + + else => return error.InvalidRegister, + } + } +}; + +/// This is an `extern struct` so that inline assembly in `current` can use field offsets. +const Powerpc = extern struct { + /// The numbered general-purpose registers r0 - r31. + r: [32]Gpr, + pc: Gpr, + lr: Gpr, + + pub const Gpr = if (builtin.target.cpu.arch.isPowerPC64()) u64 else u32; + + pub inline fn current() Powerpc { + var ctx: Powerpc = undefined; + asm volatile (if (Gpr == u64) + \\ std 0, 0(10) + \\ std 1, 8(10) + \\ std 2, 16(10) + \\ std 3, 24(10) + \\ std 4, 32(10) + \\ std 5, 40(10) + \\ std 6, 48(10) + \\ std 7, 56(10) + \\ std 8, 64(10) + \\ std 9, 72(10) + \\ std 10, 80(10) + \\ std 11, 88(10) + \\ std 12, 96(10) + \\ std 13, 104(10) + \\ std 14, 112(10) + \\ std 15, 120(10) + \\ std 16, 128(10) + \\ std 17, 136(10) + \\ std 18, 144(10) + \\ std 19, 152(10) + \\ std 20, 160(10) + \\ std 21, 168(10) + \\ std 22, 176(10) + \\ std 23, 184(10) + \\ std 24, 192(10) + \\ std 25, 200(10) + \\ std 26, 208(10) + \\ std 27, 216(10) + \\ std 28, 224(10) + \\ std 29, 232(10) + \\ std 30, 240(10) + \\ std 31, 248(10) + \\ mflr 8 + \\ std 8, 264(10) + \\ bl 1f + \\1: + \\ mflr 8 + \\ std 8, 256(10) + \\ ld 8, 64(10) + else + \\ stw 0, 0(10) + \\ stw 1, 4(10) + \\ stw 2, 8(10) + \\ stw 3, 12(10) + \\ stw 4, 16(10) + \\ stw 5, 20(10) + \\ stw 6, 24(10) + \\ stw 7, 28(10) + \\ stw 8, 32(10) + \\ stw 9, 36(10) + \\ stw 10, 40(10) + \\ stw 11, 44(10) + \\ stw 12, 48(10) + \\ stw 13, 52(10) + \\ stw 14, 56(10) + \\ stw 15, 60(10) + \\ stw 16, 64(10) + \\ stw 17, 68(10) + \\ stw 18, 72(10) + \\ stw 19, 76(10) + \\ stw 20, 80(10) + \\ stw 21, 84(10) + \\ stw 22, 88(10) + \\ stw 23, 92(10) + \\ stw 24, 96(10) + \\ stw 25, 100(10) + \\ stw 26, 104(10) + \\ stw 27, 108(10) + \\ stw 28, 112(10) + \\ stw 29, 116(10) + \\ stw 30, 120(10) + \\ stw 31, 124(10) + \\ mflr 8 + \\ stw 8, 132(10) + \\ bl 1f + \\1: + \\ mflr 8 + \\ stw 8, 128(10) + \\ lwz 8, 32(10) + : + : [gprs] "{r10}" (&ctx), + : .{ .lr = true, .memory = true }); + return ctx; + } + + pub fn dwarfRegisterBytes(ctx: *Powerpc, register_num: u16) DwarfRegisterError![]u8 { + // References: + // + // * System V Application Binary Interface - PowerPC Processor Supplement §3-46 + // * Power Architecture 32-bit Application Binary Interface Supplement 1.0 - Linux & Embedded §3.4 + // * 64-bit ELF V2 ABI Specification - Power Architecture Revision 1.5 §2.4 + // * ??? AIX? + // + // Are we having fun yet? + + if (Gpr == u64) switch (register_num) { + 65 => return @ptrCast(&ctx.lr), // lr + + 66 => return error.UnsupportedRegister, // ctr + 68...75 => return error.UnsupportedRegister, // cr0 - cr7 + 76 => return error.UnsupportedRegister, // xer + 77...108 => return error.UnsupportedRegister, // vr0 - vr31 + 109 => return error.UnsupportedRegister, // vrsave (LLVM) + 110 => return error.UnsupportedRegister, // vscr + 114 => return error.UnsupportedRegister, // tfhar + 115 => return error.UnsupportedRegister, // tfiar + 116 => return error.UnsupportedRegister, // texasr + + else => {}, + } else switch (register_num) { + 65 => return @ptrCast(&ctx.lr), // fpscr (SVR4 / EABI), or lr if you ask LLVM + 108 => return @ptrCast(&ctx.lr), + + 64 => return error.UnsupportedRegister, // cr + 66 => return error.UnsupportedRegister, // msr (SVR4 / EABI), or ctr if you ask LLVM + 68...75 => return error.UnsupportedRegister, // cr0 - cr7 if you ask LLVM + 76 => return error.UnsupportedRegister, // xer if you ask LLVM + 99 => return error.UnsupportedRegister, // acc + 100 => return error.UnsupportedRegister, // mq + 101 => return error.UnsupportedRegister, // xer + 102...107 => return error.UnsupportedRegister, // SPRs + 109 => return error.UnsupportedRegister, // ctr + 110...111 => return error.UnsupportedRegister, // SPRs + 112 => return error.UnsupportedRegister, // spefscr + 113...1123 => return error.UnsupportedRegister, // SPRs + 1124...1155 => return error.UnsupportedRegister, // SPE v0 - v31 + 1200...1231 => return error.UnsupportedRegister, // SPE upper r0 - r31 + 3072...4095 => return error.UnsupportedRegister, // DCRs + 4096...5120 => return error.UnsupportedRegister, // PMRs + + else => {}, + } + + switch (register_num) { + 0...31 => return @ptrCast(&ctx.r[register_num]), + 67 => return @ptrCast(&ctx.pc), + + 32...63 => return error.UnsupportedRegister, // f0 - f31 + + else => return error.InvalidRegister, + } + } +}; + +/// This is an `extern struct` so that inline assembly in `current` can use field offsets. +const Riscv = extern struct { + /// The numbered general-purpose registers r0 - r31. r0 must be zero. + r: [32]Gpr, + pc: Gpr, + + pub const Gpr = if (builtin.target.cpu.arch.isRiscv64()) u64 else u32; pub inline fn current() Riscv { var ctx: Riscv = undefined; - asm volatile (if (@sizeOf(usize) == 8) + asm volatile (if (Gpr == u64) \\ sd zero, 0(t0) \\ sd ra, 8(t0) \\ sd sp, 16(t0) @@ -767,7 +1082,13 @@ pub const Riscv = extern struct { pub fn dwarfRegisterBytes(ctx: *Riscv, register_num: u16) DwarfRegisterError![]u8 { switch (register_num) { 0...31 => return @ptrCast(&ctx.r[register_num]), - 32 => return @ptrCast(&ctx.pc), + 65 => return @ptrCast(&ctx.pc), + + 32...63 => return error.UnsupportedRegister, // f0 - f31 + 64 => return error.UnsupportedRegister, // Alternate Frame Return Column + 96...127 => return error.UnsupportedRegister, // v0 - v31 + 3072...4095 => return error.UnsupportedRegister, // Custom extensions + 4096...8191 => return error.UnsupportedRegister, // CSRs else => return error.InvalidRegister, } @@ -775,11 +1096,9 @@ pub const Riscv = extern struct { }; /// This is an `extern struct` so that inline assembly in `current` can use field offsets. -pub const S390x = extern struct { +const S390x = extern struct { /// The numbered general-purpose registers r0 - r15. r: [16]u64, - /// The numbered floating-point registers f0 - f15. Yes, really - they can be used in DWARF CFI. - f: [16]f64, /// The program counter. psw: extern struct { mask: u64, @@ -790,26 +1109,10 @@ pub const S390x = extern struct { var ctx: S390x = undefined; asm volatile ( \\ stmg %%r0, %%r15, 0(%%r2) - \\ std %%f0, 128(%%r2) - \\ std %%f1, 136(%%r2) - \\ std %%f2, 144(%%r2) - \\ std %%f3, 152(%%r2) - \\ std %%f4, 160(%%r2) - \\ std %%f5, 168(%%r2) - \\ std %%f6, 176(%%r2) - \\ std %%f7, 184(%%r2) - \\ std %%f8, 192(%%r2) - \\ std %%f9, 200(%%r2) - \\ std %%f10, 208(%%r2) - \\ std %%f11, 216(%%r2) - \\ std %%f12, 224(%%r2) - \\ std %%f13, 232(%%r2) - \\ std %%f14, 240(%%r2) - \\ std %%f15, 248(%%r2) \\ epsw %%r0, %%r1 - \\ stm %%r0, %%r1, 256(%%r2) + \\ stm %%r0, %%r1, 128(%%r2) \\ larl %%r0, . - \\ stg %%r0, 264(%%r2) + \\ stg %%r0, 136(%%r2) \\ lg %%r0, 0(%%r2) \\ lg %%r1, 8(%%r2) : @@ -821,27 +1124,13 @@ pub const S390x = extern struct { pub fn dwarfRegisterBytes(ctx: *S390x, register_num: u16) DwarfRegisterError![]u8 { switch (register_num) { 0...15 => return @ptrCast(&ctx.r[register_num]), - // Why??? - 16 => return @ptrCast(&ctx.f[0]), - 17 => return @ptrCast(&ctx.f[2]), - 18 => return @ptrCast(&ctx.f[4]), - 19 => return @ptrCast(&ctx.f[6]), - 20 => return @ptrCast(&ctx.f[1]), - 21 => return @ptrCast(&ctx.f[3]), - 22 => return @ptrCast(&ctx.f[5]), - 23 => return @ptrCast(&ctx.f[7]), - 24 => return @ptrCast(&ctx.f[8]), - 25 => return @ptrCast(&ctx.f[10]), - 26 => return @ptrCast(&ctx.f[12]), - 27 => return @ptrCast(&ctx.f[14]), - 28 => return @ptrCast(&ctx.f[9]), - 29 => return @ptrCast(&ctx.f[11]), - 30 => return @ptrCast(&ctx.f[13]), - 31 => return @ptrCast(&ctx.f[15]), 64 => return @ptrCast(&ctx.psw.mask), 65 => return @ptrCast(&ctx.psw.addr), + 16...31 => return error.UnsupportedRegister, // f0 - f15 + 32...47 => return error.UnsupportedRegister, // cr0 - cr15 48...63 => return error.UnsupportedRegister, // a0 - a15 + 66...67 => return error.UnsupportedRegister, // z/OS stuff??? 68...83 => return error.UnsupportedRegister, // v16 - v31 else => return error.InvalidRegister, diff --git a/lib/std/os/linux/hexagon.zig b/lib/std/os/linux/hexagon.zig index af3bf81b12..bf6c6cb162 100644 --- a/lib/std/os/linux/hexagon.zig +++ b/lib/std/os/linux/hexagon.zig @@ -254,13 +254,13 @@ pub const mcontext_t = extern struct { badva: u32, cs0: u32, cs1: u32, - _pad2: u32, + _pad1: u32, }; pub const ucontext_t = extern struct { - flags: usize, + flags: u32, link: ?*ucontext_t, stack: stack_t, mcontext: mcontext_t, - sigmask: [2]u32, + sigmask: sigset_t, }; diff --git a/lib/std/os/linux/mips.zig b/lib/std/os/linux/mips.zig index f0a235a598..f34eb0edfb 100644 --- a/lib/std/os/linux/mips.zig +++ b/lib/std/os/linux/mips.zig @@ -9,6 +9,8 @@ const iovec_const = std.posix.iovec_const; const uid_t = linux.uid_t; const gid_t = linux.gid_t; const pid_t = linux.pid_t; +const stack_t = linux.stack_t; +const sigset_t = linux.sigset_t; const sockaddr = linux.sockaddr; const timespec = linux.timespec; @@ -347,5 +349,31 @@ pub const timezone = extern struct { pub const Elf_Symndx = u32; -/// TODO -pub const ucontext_t = void; +pub const mcontext_t = extern struct { + _regmask: u32, + _status: u32, + pc: u64, + regs: [32]u64, + fpregs: [32]f64, + acx: u32, + fpc_csr: u32, + _fpc_eir: u32, + used_math: u32, + dsp: u32, + mdhi: u64, + mdlo: u64, + hi1: u32, + lo1: u32, + hi2: u32, + lo2: u32, + hi3: u32, + lo3: u32, +}; + +pub const ucontext_t = extern struct { + flags: u32, + link: ?*ucontext_t, + stack: stack_t, + mcontext: mcontext_t, + sigmask: sigset_t, +}; diff --git a/lib/std/os/linux/mips64.zig b/lib/std/os/linux/mips64.zig index 11ad102914..4cde9cf15e 100644 --- a/lib/std/os/linux/mips64.zig +++ b/lib/std/os/linux/mips64.zig @@ -9,6 +9,8 @@ const iovec_const = std.posix.iovec_const; const uid_t = linux.uid_t; const gid_t = linux.gid_t; const pid_t = linux.pid_t; +const stack_t = linux.stack_t; +const sigset_t = linux.sigset_t; const sockaddr = linux.sockaddr; const timespec = linux.timespec; @@ -326,5 +328,28 @@ pub const timezone = extern struct { pub const Elf_Symndx = u32; -/// TODO -pub const ucontext_t = void; +pub const mcontext_t = extern struct { + regs: [32]u64, + fpregs: [32]f64, + mdhi: u64, + hi1: u64, + hi2: u64, + hi3: u64, + mdlo: u64, + lo1: u64, + lo2: u64, + lo3: u64, + pc: u64, + fpc_csr: u32, + used_math: u32, + dsp: u32, + _reserved: u32, +}; + +pub const ucontext_t = extern struct { + flags: u32, + link: ?*ucontext_t, + stack: stack_t, + mcontext: mcontext_t, + sigmask: sigset_t, +};