cranelift_codegen/isa/x64/inst/stack_switch.rs
1use crate::{isa::x64::inst::regs, machinst::Reg};
2
3/// The `stack_switch` instruction loads information about the stack to switch
4/// to and stores information about the current stack by receiving pointers to
5/// memory laid out as in the struct `ControlContext` below.
6///
7/// The instruction is only supported on x64 Linux at the moment.
8///
9/// ```
10/// #[repr(C)]
11/// pub struct ControlContext {
12/// pub stack_pointer: *mut u8,
13/// pub frame_pointer: *mut u8,
14/// pub instruction_pointer: *mut u8,
15/// }
16/// ```
17///
18/// Note that this layout is deliberately chosen to make frame pointer walking
19/// possible, if desired: The layout enables stack layouts where a
20/// `ControlContext` is part of a frame pointer chain, putting the frame pointer
21/// next to the corresponding IP.
22///
23/// We never actually interact with values of that type in Cranelift, but are
24/// only interested in its layout for the purposes of generating code.
25#[allow(dead_code)]
26pub struct ControlContextLayout {
27 pub size: usize,
28 pub stack_pointer_offset: usize,
29 pub frame_pointer_offset: usize,
30 pub ip_offset: usize,
31}
32
33pub fn control_context_layout() -> ControlContextLayout {
34 ControlContextLayout {
35 size: 24,
36 stack_pointer_offset: 0,
37 frame_pointer_offset: 8,
38 ip_offset: 16,
39 }
40}
41
42/// The register used for handing over the payload when switching stacks.
43///
44/// We must use a fixed register for sending and receiving the payload: When
45/// switching from one stack to another using two matching``stack_switch``
46/// instructions, they must agree on the register where the payload is, similar
47/// to a calling convention. The same holds when `stack_switch`-ing to a newly
48/// initialized stack, where the entry trampoline must know which register the
49/// payload is in.
50pub fn payload_register() -> Reg {
51 regs::rdi()
52}