1 use 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 pub struct ControlContextLayout {
26 pub stack_pointer_offset: usize,
27 pub frame_pointer_offset: usize,
28 pub ip_offset: usize,
29 }
30
control_context_layout() -> ControlContextLayout31 pub fn control_context_layout() -> ControlContextLayout {
32 ControlContextLayout {
33 stack_pointer_offset: 0,
34 frame_pointer_offset: 8,
35 ip_offset: 16,
36 }
37 }
38
39 /// The register used for handing over the payload when switching stacks.
40 ///
41 /// We must use a fixed register for sending and receiving the payload: When
42 /// switching from one stack to another using two matching``stack_switch``
43 /// instructions, they must agree on the register where the payload is, similar
44 /// to a calling convention. The same holds when `stack_switch`-ing to a newly
45 /// initialized stack, where the entry trampoline must know which register the
46 /// payload is in.
payload_register() -> Reg47 pub fn payload_register() -> Reg {
48 regs::rdi()
49 }
50