wasmtime_internal_unwinder/arch/
x86.rs

1//! x86-specific (also x86-64) definitions of architecture-specific functions in
2//! Wasmtime.
3
4#[inline]
5pub fn get_stack_pointer() -> usize {
6    let stack_pointer: usize;
7    unsafe {
8        core::arch::asm!(
9            "mov {}, rsp",
10            out(reg) stack_pointer,
11            options(nostack,nomem),
12        );
13    }
14    stack_pointer
15}
16
17pub unsafe fn get_next_older_pc_from_fp(fp: usize) -> usize {
18    // The calling convention always pushes the return pointer (aka the PC of
19    // the next older frame) just before this frame.
20    unsafe { *(fp as *mut usize).offset(1) }
21}
22
23pub unsafe fn resume_to_exception_handler(
24    pc: usize,
25    sp: usize,
26    fp: usize,
27    payload1: usize,
28    payload2: usize,
29) -> ! {
30    unsafe {
31        core::arch::asm!(
32            "mov rsp, rcx",
33            "mov rbp, rsi",
34            "jmp rdi",
35            in("rax") payload1,
36            in("rdx") payload2,
37            in("rcx") sp,
38            in("rsi") fp,
39            in("rdi") pc,
40            options(nostack, nomem, noreturn),
41        );
42    }
43}
44
45// And the current frame pointer points to the next older frame pointer.
46pub const NEXT_OLDER_FP_FROM_FP_OFFSET: usize = 0;
47
48// SP of caller is FP in callee plus size of FP/return address pair.
49pub const NEXT_OLDER_SP_FROM_FP_OFFSET: usize = 16;
50
51/// Frame pointers are aligned if they're aligned to twice the size of a
52/// pointer.
53pub fn assert_fp_is_aligned(fp: usize) {
54    let align = 2 * size_of::<usize>();
55    assert_eq!(fp % align, 0, "stack should always be aligned to {align}");
56}