mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Merge pull request #25437 from alexrp/std-debug
`std.debug`: LoongArch and RISC-V unwind support + some minor cleanups
This commit is contained in:
commit
bc4da9a907
@ -61,28 +61,12 @@ pub const cpu_context = @import("debug/cpu_context.zig");
|
|||||||
/// ```
|
/// ```
|
||||||
pub const SelfInfo = if (@hasDecl(root, "debug") and @hasDecl(root.debug, "SelfInfo"))
|
pub const SelfInfo = if (@hasDecl(root, "debug") and @hasDecl(root.debug, "SelfInfo"))
|
||||||
root.debug.SelfInfo
|
root.debug.SelfInfo
|
||||||
else switch (native_os) {
|
else switch (std.Target.ObjectFormat.default(native_os, native_arch)) {
|
||||||
.linux,
|
.coff => if (native_os == .windows) @import("debug/SelfInfo/Windows.zig") else void,
|
||||||
.netbsd,
|
.elf => @import("debug/SelfInfo/Elf.zig"),
|
||||||
.freebsd,
|
.macho => @import("debug/SelfInfo/MachO.zig"),
|
||||||
.dragonfly,
|
.goff, .plan9, .spirv, .wasm, .xcoff => void,
|
||||||
.openbsd,
|
.c, .hex, .raw => unreachable,
|
||||||
.solaris,
|
|
||||||
.illumos,
|
|
||||||
=> @import("debug/SelfInfo/Elf.zig"),
|
|
||||||
|
|
||||||
.macos,
|
|
||||||
.ios,
|
|
||||||
.watchos,
|
|
||||||
.tvos,
|
|
||||||
.visionos,
|
|
||||||
=> @import("debug/SelfInfo/Darwin.zig"),
|
|
||||||
|
|
||||||
.uefi,
|
|
||||||
.windows,
|
|
||||||
=> @import("debug/SelfInfo/Windows.zig"),
|
|
||||||
|
|
||||||
else => void,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const SelfInfoError = error{
|
pub const SelfInfoError = error{
|
||||||
|
|||||||
@ -1429,30 +1429,36 @@ pub fn compactUnwindToDwarfRegNumber(unwind_reg_number: u3) !u16 {
|
|||||||
/// Returns `null` for CPU architectures without an instruction pointer register.
|
/// Returns `null` for CPU architectures without an instruction pointer register.
|
||||||
pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 {
|
pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 {
|
||||||
return switch (arch) {
|
return switch (arch) {
|
||||||
|
.aarch64, .aarch64_be => 32,
|
||||||
|
.arm, .armeb, .thumb, .thumbeb => 15,
|
||||||
|
.loongarch32, .loongarch64 => 32,
|
||||||
|
.riscv32, .riscv32be, .riscv64, .riscv64be => 32,
|
||||||
.x86 => 8,
|
.x86 => 8,
|
||||||
.x86_64 => 16,
|
.x86_64 => 16,
|
||||||
.arm, .armeb, .thumb, .thumbeb => 15,
|
|
||||||
.aarch64, .aarch64_be => 32,
|
|
||||||
else => null,
|
else => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 {
|
pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 {
|
||||||
return switch (arch) {
|
return switch (arch) {
|
||||||
|
.aarch64, .aarch64_be => 29,
|
||||||
|
.arm, .armeb, .thumb, .thumbeb => 11,
|
||||||
|
.loongarch32, .loongarch64 => 22,
|
||||||
|
.riscv32, .riscv32be, .riscv64, .riscv64be => 8,
|
||||||
.x86 => 5,
|
.x86 => 5,
|
||||||
.x86_64 => 6,
|
.x86_64 => 6,
|
||||||
.arm, .armeb, .thumb, .thumbeb => 11,
|
|
||||||
.aarch64, .aarch64_be => 29,
|
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spRegNum(arch: std.Target.Cpu.Arch) u16 {
|
pub fn spRegNum(arch: std.Target.Cpu.Arch) u16 {
|
||||||
return switch (arch) {
|
return switch (arch) {
|
||||||
|
.aarch64, .aarch64_be => 31,
|
||||||
|
.arm, .armeb, .thumb, .thumbeb => 13,
|
||||||
|
.loongarch32, .loongarch64 => 3,
|
||||||
|
.riscv32, .riscv32be, .riscv64, .riscv64be => 2,
|
||||||
.x86 => 4,
|
.x86 => 4,
|
||||||
.x86_64 => 7,
|
.x86_64 => 7,
|
||||||
.arm, .armeb, .thumb, .thumbeb => 13,
|
|
||||||
.aarch64, .aarch64_be => 31,
|
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1470,10 +1476,6 @@ pub fn supportsUnwinding(target: *const std.Target) bool {
|
|||||||
.spirv64,
|
.spirv64,
|
||||||
=> false,
|
=> false,
|
||||||
|
|
||||||
// Enabling this causes relocation errors such as:
|
|
||||||
// error: invalid relocation type R_RISCV_SUB32 at offset 0x20
|
|
||||||
.riscv64, .riscv64be, .riscv32, .riscv32be => false,
|
|
||||||
|
|
||||||
// Conservative guess. Feel free to update this logic with any targets
|
// Conservative guess. Feel free to update this logic with any targets
|
||||||
// that are known to not support Dwarf unwinding.
|
// that are known to not support Dwarf unwinding.
|
||||||
else => true,
|
else => true,
|
||||||
|
|||||||
@ -256,7 +256,18 @@ fn evalInstructions(
|
|||||||
.offset = cfa.offset_sf * cie.data_alignment_factor,
|
.offset = cfa.offset_sf * cie.data_alignment_factor,
|
||||||
} },
|
} },
|
||||||
.def_cfa_reg => |register| switch (vm.current_row.cfa) {
|
.def_cfa_reg => |register| switch (vm.current_row.cfa) {
|
||||||
.none, .expression => return error.InvalidOperation,
|
.none => {
|
||||||
|
// According to the DWARF specification, this is not valid, because this
|
||||||
|
// instruction can only be used to replace the register if the rule is already a
|
||||||
|
// `.reg_off`. However, this is emitted in practice by GNU toolchains for some
|
||||||
|
// targets, and so by convention is interpreted as equivalent to `.def_cfa` with
|
||||||
|
// an offset of 0.
|
||||||
|
vm.current_row.cfa = .{ .reg_off = .{
|
||||||
|
.register = register,
|
||||||
|
.offset = 0,
|
||||||
|
} };
|
||||||
|
},
|
||||||
|
.expression => return error.InvalidOperation,
|
||||||
.reg_off => |*ro| ro.register = register,
|
.reg_off => |*ro| ro.register = register,
|
||||||
},
|
},
|
||||||
.def_cfa_offset => |offset| switch (vm.current_row.cfa) {
|
.def_cfa_offset => |offset| switch (vm.current_row.cfa) {
|
||||||
|
|||||||
@ -84,12 +84,35 @@ pub const can_unwind: bool = s: {
|
|||||||
// Notably, we are yet to support unwinding on ARM. There, unwinding is not done through
|
// Notably, we are yet to support unwinding on ARM. There, unwinding is not done through
|
||||||
// `.eh_frame`, but instead with the `.ARM.exidx` section, which has a different format.
|
// `.eh_frame`, but instead with the `.ARM.exidx` section, which has a different format.
|
||||||
const archs: []const std.Target.Cpu.Arch = switch (builtin.target.os.tag) {
|
const archs: []const std.Target.Cpu.Arch = switch (builtin.target.os.tag) {
|
||||||
.linux => &.{ .x86, .x86_64, .aarch64, .aarch64_be },
|
.linux => &.{
|
||||||
.netbsd => &.{ .x86, .x86_64, .aarch64, .aarch64_be },
|
.aarch64,
|
||||||
.freebsd => &.{ .x86_64, .aarch64, .aarch64_be },
|
.aarch64_be,
|
||||||
.openbsd => &.{.x86_64},
|
.loongarch64,
|
||||||
.solaris => &.{ .x86, .x86_64 },
|
.riscv32,
|
||||||
.illumos => &.{ .x86, .x86_64 },
|
.riscv64,
|
||||||
|
.x86,
|
||||||
|
.x86_64,
|
||||||
|
},
|
||||||
|
.netbsd => &.{
|
||||||
|
.aarch64,
|
||||||
|
.aarch64_be,
|
||||||
|
.x86,
|
||||||
|
.x86_64,
|
||||||
|
},
|
||||||
|
.freebsd => &.{
|
||||||
|
.x86_64,
|
||||||
|
.aarch64,
|
||||||
|
},
|
||||||
|
.openbsd => &.{
|
||||||
|
.x86_64,
|
||||||
|
},
|
||||||
|
.solaris => &.{
|
||||||
|
.x86_64,
|
||||||
|
},
|
||||||
|
.illumos => &.{
|
||||||
|
.x86,
|
||||||
|
.x86_64,
|
||||||
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
for (archs) |a| {
|
for (archs) |a| {
|
||||||
|
|||||||
@ -371,7 +371,7 @@ fn unwindFrameInner(si: *SelfInfo, gpa: Allocator, context: *UnwindContext) !usi
|
|||||||
return context.next(gpa, &rules);
|
return context.next(gpa, &rules);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.aarch64, .aarch64_be => switch (encoding.mode.arm64) {
|
.aarch64 => switch (encoding.mode.arm64) {
|
||||||
.OLD => return error.UnsupportedDebugInfo,
|
.OLD => return error.UnsupportedDebugInfo,
|
||||||
.FRAMELESS => ip: {
|
.FRAMELESS => ip: {
|
||||||
const sp = (try dwarfRegNative(&context.cpu_state, sp_reg_num)).*;
|
const sp = (try dwarfRegNative(&context.cpu_state, sp_reg_num)).*;
|
||||||
@ -88,7 +88,7 @@ pub const UnwindContext = struct {
|
|||||||
.R15 = ctx.gprs.get(.r15),
|
.R15 = ctx.gprs.get(.r15),
|
||||||
.Rip = ctx.gprs.get(.rip),
|
.Rip = ctx.gprs.get(.rip),
|
||||||
}),
|
}),
|
||||||
.aarch64, .aarch64_be => .{
|
.aarch64 => .{
|
||||||
.ContextFlags = 0,
|
.ContextFlags = 0,
|
||||||
.Cpsr = 0,
|
.Cpsr = 0,
|
||||||
.DUMMYUNIONNAME = .{ .X = ctx.x },
|
.DUMMYUNIONNAME = .{ .X = ctx.x },
|
||||||
|
|||||||
@ -4,10 +4,12 @@
|
|||||||
pub const Native = if (@hasDecl(root, "debug") and @hasDecl(root.debug, "CpuContext"))
|
pub const Native = if (@hasDecl(root, "debug") and @hasDecl(root.debug, "CpuContext"))
|
||||||
root.debug.CpuContext
|
root.debug.CpuContext
|
||||||
else switch (native_arch) {
|
else switch (native_arch) {
|
||||||
|
.aarch64, .aarch64_be => Aarch64,
|
||||||
|
.arm, .armeb, .thumb, .thumbeb => Arm,
|
||||||
|
.loongarch32, .loongarch64 => LoongArch,
|
||||||
|
.riscv32, .riscv32be, .riscv64, .riscv64be => Riscv,
|
||||||
.x86 => X86,
|
.x86 => X86,
|
||||||
.x86_64 => X86_64,
|
.x86_64 => X86_64,
|
||||||
.arm, .armeb, .thumb, .thumbeb => Arm,
|
|
||||||
.aarch64, .aarch64_be => Aarch64,
|
|
||||||
else => noreturn,
|
else => noreturn,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -21,7 +23,7 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native {
|
|||||||
const uc: *const signal_ucontext_t = @ptrCast(@alignCast(ctx_ptr));
|
const uc: *const signal_ucontext_t = @ptrCast(@alignCast(ctx_ptr));
|
||||||
return switch (native_arch) {
|
return switch (native_arch) {
|
||||||
.x86 => switch (native_os) {
|
.x86 => switch (native_os) {
|
||||||
.linux, .netbsd, .solaris, .illumos => .{ .gprs = .init(.{
|
.linux, .netbsd, .illumos => .{ .gprs = .init(.{
|
||||||
.eax = uc.mcontext.gregs[std.posix.REG.EAX],
|
.eax = uc.mcontext.gregs[std.posix.REG.EAX],
|
||||||
.ecx = uc.mcontext.gregs[std.posix.REG.ECX],
|
.ecx = uc.mcontext.gregs[std.posix.REG.ECX],
|
||||||
.edx = uc.mcontext.gregs[std.posix.REG.EDX],
|
.edx = uc.mcontext.gregs[std.posix.REG.EDX],
|
||||||
@ -92,7 +94,7 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native {
|
|||||||
.r15 = @bitCast(uc.sc_r15),
|
.r15 = @bitCast(uc.sc_r15),
|
||||||
.rip = @bitCast(uc.sc_rip),
|
.rip = @bitCast(uc.sc_rip),
|
||||||
}) },
|
}) },
|
||||||
.macos, .ios => .{ .gprs = .init(.{
|
.driverkit, .macos, .ios => .{ .gprs = .init(.{
|
||||||
.rax = uc.mcontext.ss.rax,
|
.rax = uc.mcontext.ss.rax,
|
||||||
.rdx = uc.mcontext.ss.rdx,
|
.rdx = uc.mcontext.ss.rdx,
|
||||||
.rcx = uc.mcontext.ss.rcx,
|
.rcx = uc.mcontext.ss.rcx,
|
||||||
@ -137,7 +139,7 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native {
|
|||||||
else => null,
|
else => null,
|
||||||
},
|
},
|
||||||
.aarch64, .aarch64_be => switch (builtin.os.tag) {
|
.aarch64, .aarch64_be => switch (builtin.os.tag) {
|
||||||
.macos, .ios, .tvos, .watchos, .visionos => .{
|
.driverkit, .macos, .ios, .tvos, .watchos, .visionos => .{
|
||||||
.x = uc.mcontext.ss.regs ++ @as([2]u64, .{
|
.x = uc.mcontext.ss.regs ++ @as([2]u64, .{
|
||||||
uc.mcontext.ss.fp, // x29 = fp
|
uc.mcontext.ss.fp, // x29 = fp
|
||||||
uc.mcontext.ss.lr, // x30 = lr
|
uc.mcontext.ss.lr, // x30 = lr
|
||||||
@ -173,6 +175,20 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native {
|
|||||||
},
|
},
|
||||||
else => null,
|
else => null,
|
||||||
},
|
},
|
||||||
|
.loongarch64 => switch (builtin.os.tag) {
|
||||||
|
.linux => .{
|
||||||
|
.r = uc.mcontext.regs, // includes r0 (hardwired zero)
|
||||||
|
.pc = uc.mcontext.pc,
|
||||||
|
},
|
||||||
|
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
|
||||||
|
.pc = uc.mcontext.gregs[0],
|
||||||
|
},
|
||||||
|
else => null,
|
||||||
|
},
|
||||||
else => null,
|
else => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -209,7 +225,7 @@ pub fn fromWindowsContext(ctx: *const std.os.windows.CONTEXT) Native {
|
|||||||
.r15 = ctx.R15,
|
.r15 = ctx.R15,
|
||||||
.rip = ctx.Rip,
|
.rip = ctx.Rip,
|
||||||
}) },
|
}) },
|
||||||
.aarch64, .aarch64_be => .{
|
.aarch64 => .{
|
||||||
.x = ctx.DUMMYUNIONNAME.X[0..31].*,
|
.x = ctx.DUMMYUNIONNAME.X[0..31].*,
|
||||||
.sp = ctx.Sp,
|
.sp = ctx.Sp,
|
||||||
.pc = ctx.Pc,
|
.pc = ctx.Pc,
|
||||||
@ -371,7 +387,6 @@ pub const Arm = struct {
|
|||||||
pub fn dwarfRegisterBytes(ctx: *Arm, register_num: u16) DwarfRegisterError![]u8 {
|
pub fn dwarfRegisterBytes(ctx: *Arm, register_num: u16) DwarfRegisterError![]u8 {
|
||||||
// DWARF for the Arm(r) Architecture § 4.1 "DWARF register names"
|
// DWARF for the Arm(r) Architecture § 4.1 "DWARF register names"
|
||||||
switch (register_num) {
|
switch (register_num) {
|
||||||
// The order of `Gpr` intentionally matches DWARF's mappings.
|
|
||||||
0...15 => return @ptrCast(&ctx.r[register_num]),
|
0...15 => return @ptrCast(&ctx.r[register_num]),
|
||||||
|
|
||||||
64...95 => return error.UnsupportedRegister, // S0 - S31
|
64...95 => return error.UnsupportedRegister, // S0 - S31
|
||||||
@ -444,7 +459,6 @@ pub const Aarch64 = extern struct {
|
|||||||
pub fn dwarfRegisterBytes(ctx: *Aarch64, register_num: u16) DwarfRegisterError![]u8 {
|
pub fn dwarfRegisterBytes(ctx: *Aarch64, register_num: u16) DwarfRegisterError![]u8 {
|
||||||
// DWARF for the Arm(r) 64-bit Architecture (AArch64) § 4.1 "DWARF register names"
|
// DWARF for the Arm(r) 64-bit Architecture (AArch64) § 4.1 "DWARF register names"
|
||||||
switch (register_num) {
|
switch (register_num) {
|
||||||
// The order of `Gpr` intentionally matches DWARF's mappings.
|
|
||||||
0...30 => return @ptrCast(&ctx.x[register_num]),
|
0...30 => return @ptrCast(&ctx.x[register_num]),
|
||||||
31 => return @ptrCast(&ctx.sp),
|
31 => return @ptrCast(&ctx.sp),
|
||||||
32 => return @ptrCast(&ctx.pc),
|
32 => return @ptrCast(&ctx.pc),
|
||||||
@ -467,11 +481,207 @@ pub const Aarch64 = extern struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
|
||||||
|
pub const LoongArch = extern struct {
|
||||||
|
/// The numbered general-purpose registers r0 - r31. r0 must be zero.
|
||||||
|
r: [32]usize,
|
||||||
|
pc: usize,
|
||||||
|
|
||||||
|
pub inline fn current() LoongArch {
|
||||||
|
var ctx: LoongArch = undefined;
|
||||||
|
asm volatile (if (@sizeOf(usize) == 8)
|
||||||
|
\\ st.d $zero, $t0, 0
|
||||||
|
\\ st.d $ra, $t0, 8
|
||||||
|
\\ st.d $tp, $t0, 16
|
||||||
|
\\ st.d $sp, $t0, 24
|
||||||
|
\\ st.d $a0, $t0, 32
|
||||||
|
\\ st.d $a1, $t0, 40
|
||||||
|
\\ st.d $a2, $t0, 48
|
||||||
|
\\ st.d $a3, $t0, 56
|
||||||
|
\\ st.d $a4, $t0, 64
|
||||||
|
\\ st.d $a5, $t0, 72
|
||||||
|
\\ st.d $a6, $t0, 80
|
||||||
|
\\ st.d $a7, $t0, 88
|
||||||
|
\\ st.d $t0, $t0, 96
|
||||||
|
\\ st.d $t1, $t0, 104
|
||||||
|
\\ st.d $t2, $t0, 112
|
||||||
|
\\ st.d $t3, $t0, 120
|
||||||
|
\\ st.d $t4, $t0, 128
|
||||||
|
\\ st.d $t5, $t0, 136
|
||||||
|
\\ st.d $t6, $t0, 144
|
||||||
|
\\ st.d $t7, $t0, 152
|
||||||
|
\\ st.d $t8, $t0, 160
|
||||||
|
\\ st.d $r21, $t0, 168
|
||||||
|
\\ st.d $fp, $t0, 176
|
||||||
|
\\ st.d $s0, $t0, 184
|
||||||
|
\\ st.d $s1, $t0, 192
|
||||||
|
\\ st.d $s2, $t0, 200
|
||||||
|
\\ st.d $s3, $t0, 208
|
||||||
|
\\ st.d $s4, $t0, 216
|
||||||
|
\\ st.d $s5, $t0, 224
|
||||||
|
\\ st.d $s6, $t0, 232
|
||||||
|
\\ st.d $s7, $t0, 240
|
||||||
|
\\ st.d $s8, $t0, 248
|
||||||
|
\\ bl 1f
|
||||||
|
\\1:
|
||||||
|
\\ st.d $ra, $t0, 256
|
||||||
|
\\ ld.d $ra, $t0, 8
|
||||||
|
else
|
||||||
|
\\ st.w $zero, $t0, 0
|
||||||
|
\\ st.w $ra, $t0, 4
|
||||||
|
\\ st.w $tp, $t0, 8
|
||||||
|
\\ st.w $sp, $t0, 12
|
||||||
|
\\ st.w $a0, $t0, 16
|
||||||
|
\\ st.w $a1, $t0, 20
|
||||||
|
\\ st.w $a2, $t0, 24
|
||||||
|
\\ st.w $a3, $t0, 28
|
||||||
|
\\ st.w $a4, $t0, 32
|
||||||
|
\\ st.w $a5, $t0, 36
|
||||||
|
\\ st.w $a6, $t0, 40
|
||||||
|
\\ st.w $a7, $t0, 44
|
||||||
|
\\ st.w $t0, $t0, 48
|
||||||
|
\\ st.w $t1, $t0, 52
|
||||||
|
\\ st.w $t2, $t0, 56
|
||||||
|
\\ st.w $t3, $t0, 60
|
||||||
|
\\ st.w $t4, $t0, 64
|
||||||
|
\\ st.w $t5, $t0, 68
|
||||||
|
\\ st.w $t6, $t0, 72
|
||||||
|
\\ st.w $t7, $t0, 76
|
||||||
|
\\ st.w $t8, $t0, 80
|
||||||
|
\\ st.w $r21, $t0, 84
|
||||||
|
\\ st.w $fp, $t0, 88
|
||||||
|
\\ st.w $s0, $t0, 92
|
||||||
|
\\ st.w $s1, $t0, 96
|
||||||
|
\\ st.w $s2, $t0, 100
|
||||||
|
\\ st.w $s3, $t0, 104
|
||||||
|
\\ st.w $s4, $t0, 108
|
||||||
|
\\ st.w $s5, $t0, 112
|
||||||
|
\\ st.w $s6, $t0, 116
|
||||||
|
\\ st.w $s7, $t0, 120
|
||||||
|
\\ st.w $s8, $t0, 124
|
||||||
|
\\ bl 1f
|
||||||
|
\\1:
|
||||||
|
\\ st.w $ra, $t0, 128
|
||||||
|
\\ ld.w $ra, $t0, 4
|
||||||
|
:
|
||||||
|
: [gprs] "{$r12}" (&ctx),
|
||||||
|
: .{ .memory = true });
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
|
||||||
|
else => return error.InvalidRegister,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
|
||||||
|
pub const Riscv = extern struct {
|
||||||
|
/// The numbered general-purpose registers r0 - r31. r0 must be zero.
|
||||||
|
r: [32]usize,
|
||||||
|
pc: usize,
|
||||||
|
|
||||||
|
pub inline fn current() Riscv {
|
||||||
|
var ctx: Riscv = undefined;
|
||||||
|
asm volatile (if (@sizeOf(usize) == 8)
|
||||||
|
\\ sd zero, 0(t0)
|
||||||
|
\\ sd ra, 8(t0)
|
||||||
|
\\ sd sp, 16(t0)
|
||||||
|
\\ sd gp, 24(t0)
|
||||||
|
\\ sd tp, 32(t0)
|
||||||
|
\\ sd t0, 40(t0)
|
||||||
|
\\ sd t1, 48(t0)
|
||||||
|
\\ sd t2, 56(t0)
|
||||||
|
\\ sd s0, 64(t0)
|
||||||
|
\\ sd s1, 72(t0)
|
||||||
|
\\ sd a0, 80(t0)
|
||||||
|
\\ sd a1, 88(t0)
|
||||||
|
\\ sd a2, 96(t0)
|
||||||
|
\\ sd a3, 104(t0)
|
||||||
|
\\ sd a4, 112(t0)
|
||||||
|
\\ sd a5, 120(t0)
|
||||||
|
\\ sd a6, 128(t0)
|
||||||
|
\\ sd a7, 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 s8, 192(t0)
|
||||||
|
\\ sd s9, 200(t0)
|
||||||
|
\\ sd s10, 208(t0)
|
||||||
|
\\ sd s11, 216(t0)
|
||||||
|
\\ sd t3, 224(t0)
|
||||||
|
\\ sd t4, 232(t0)
|
||||||
|
\\ sd t5, 240(t0)
|
||||||
|
\\ sd t6, 248(t0)
|
||||||
|
\\ jal ra, 1f
|
||||||
|
\\1:
|
||||||
|
\\ sd ra, 256(t0)
|
||||||
|
\\ ld ra, 8(t0)
|
||||||
|
else
|
||||||
|
\\ sw zero, 0(t0)
|
||||||
|
\\ sw ra, 4(t0)
|
||||||
|
\\ sw sp, 8(t0)
|
||||||
|
\\ sw gp, 12(t0)
|
||||||
|
\\ sw tp, 16(t0)
|
||||||
|
\\ sw t0, 20(t0)
|
||||||
|
\\ sw t1, 24(t0)
|
||||||
|
\\ sw t2, 28(t0)
|
||||||
|
\\ sw s0, 32(t0)
|
||||||
|
\\ sw s1, 36(t0)
|
||||||
|
\\ sw a0, 40(t0)
|
||||||
|
\\ sw a1, 44(t0)
|
||||||
|
\\ sw a2, 48(t0)
|
||||||
|
\\ sw a3, 52(t0)
|
||||||
|
\\ sw a4, 56(t0)
|
||||||
|
\\ sw a5, 60(t0)
|
||||||
|
\\ sw a6, 64(t0)
|
||||||
|
\\ sw a7, 68(t0)
|
||||||
|
\\ sw s2, 72(t0)
|
||||||
|
\\ sw s3, 76(t0)
|
||||||
|
\\ sw s4, 80(t0)
|
||||||
|
\\ sw s5, 84(t0)
|
||||||
|
\\ sw s6, 88(t0)
|
||||||
|
\\ sw s7, 92(t0)
|
||||||
|
\\ sw s8, 96(t0)
|
||||||
|
\\ sw s9, 100(t0)
|
||||||
|
\\ sw s10, 104(t0)
|
||||||
|
\\ sw s11, 108(t0)
|
||||||
|
\\ sw t3, 112(t0)
|
||||||
|
\\ sw t4, 116(t0)
|
||||||
|
\\ sw t5, 120(t0)
|
||||||
|
\\ sw t6, 124(t0)
|
||||||
|
\\ jal ra, 1f
|
||||||
|
\\1:
|
||||||
|
\\ sw ra, 128(t0)
|
||||||
|
\\ lw ra, 4(t0)
|
||||||
|
:
|
||||||
|
: [gprs] "{t0}" (&ctx),
|
||||||
|
: .{ .memory = true });
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
|
||||||
|
else => return error.InvalidRegister,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const signal_ucontext_t = switch (native_os) {
|
const signal_ucontext_t = switch (native_os) {
|
||||||
.linux => std.os.linux.ucontext_t,
|
.linux => std.os.linux.ucontext_t,
|
||||||
.emscripten => std.os.emscripten.ucontext_t,
|
.emscripten => std.os.emscripten.ucontext_t,
|
||||||
.freebsd => std.os.freebsd.ucontext_t,
|
.freebsd => std.os.freebsd.ucontext_t,
|
||||||
.macos, .ios, .tvos, .watchos, .visionos => extern struct {
|
.driverkit, .macos, .ios, .tvos, .watchos, .visionos => extern struct {
|
||||||
onstack: c_int,
|
onstack: c_int,
|
||||||
sigmask: std.c.sigset_t,
|
sigmask: std.c.sigset_t,
|
||||||
stack: std.c.stack_t,
|
stack: std.c.stack_t,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user