Skip to content

Commit ed476a0

Browse files
committed
Apply unwinding support from edef1c#70
1 parent 980890a commit ed476a0

File tree

9 files changed

+506
-153
lines changed

9 files changed

+506
-153
lines changed

src/arch/mod.rs

Lines changed: 96 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,74 +6,109 @@
66
// http://opensource.org/licenses/MIT>, at your option. This file may not be
77
// copied, modified, or distributed except according to those terms.
88

9+
use core::ptr::NonNull;
10+
11+
// #[cfg_attr(target_arch = "x86", path = "x86.rs")]
12+
//#[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")]
13+
// #[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")]
14+
// #[cfg_attr(target_arch = "or1k", path = "or1k.rs")]
15+
//mod imp;
16+
17+
// TEMP FOR RUST-ANALYZER
18+
mod x86_64;
19+
use x86_64 as imp;
20+
921
pub use self::imp::*;
1022

11-
#[cfg_attr(target_arch = "x86", path = "x86.rs")]
12-
#[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")]
13-
#[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")]
14-
#[cfg_attr(target_arch = "or1k", path = "or1k.rs")]
15-
mod imp;
23+
#[derive(Debug, Clone, Copy)]
24+
#[repr(transparent)]
25+
pub struct StackPointer(NonNull<usize>);
26+
27+
impl StackPointer {
28+
#[inline(always)]
29+
pub unsafe fn push(&mut self, val: usize) {
30+
self.0 = NonNull::new_unchecked(self.0.as_ptr().offset(-1));
31+
self.0.as_ptr().write(val);
32+
}
33+
34+
#[inline(always)]
35+
pub const unsafe fn new<T>(sp: *mut T) -> StackPointer {
36+
StackPointer(NonNull::new_unchecked(sp as *mut usize))
37+
}
38+
39+
#[inline(always)]
40+
pub unsafe fn offset(&self, count: isize) -> *mut usize {
41+
self.0.as_ptr().offset(count)
42+
}
43+
}
44+
45+
impl From<NonNull<usize>> for StackPointer {
46+
#[inline(always)]
47+
fn from(val: NonNull<usize>) -> Self {
48+
Self(val)
49+
}
50+
}
1651

1752
#[cfg(test)]
1853
mod tests {
1954
extern crate test;
2055

2156
use crate::{
2257
arch::{self, StackPointer},
23-
OsStack,
58+
OsStack, Stack,
2459
};
2560

2661
#[test]
2762
fn context() {
28-
unsafe extern "C" fn adder(arg: usize, stack_ptr: StackPointer) -> ! {
63+
unsafe fn adder(arg: usize, stack_ptr: StackPointer) {
2964
println!("it's alive! arg: {}", arg);
30-
let (arg, stack_ptr) = arch::swap(arg + 1, stack_ptr, None);
65+
let (arg, stack_ptr) = arch::swap(arg + 1, stack_ptr);
3166
println!("still alive! arg: {}", arg);
32-
arch::swap(arg + 1, stack_ptr, None);
67+
arch::swap(arg + 1, stack_ptr);
3368
panic!("i should be dead");
3469
}
3570

3671
unsafe {
3772
let stack = OsStack::new(4 << 20).unwrap();
38-
let stack_ptr = arch::init(&stack, adder);
73+
let stack_ptr = arch::init(stack.base(), adder);
3974

40-
let (ret, stack_ptr) = arch::swap(10, stack_ptr, Some(&stack));
75+
let (ret, stack_ptr) = arch::swap_link(10, stack_ptr, stack.base());
4176
assert_eq!(ret, 11);
42-
let (ret, _) = arch::swap(50, stack_ptr, Some(&stack));
77+
let (ret, _) = arch::swap_link(50, stack_ptr.unwrap(), stack.base());
4378
assert_eq!(ret, 51);
4479
}
4580
}
4681

47-
#[test]
48-
fn context_simd() {
49-
unsafe extern "C" fn permuter(arg: usize, stack_ptr: StackPointer) -> ! {
50-
// This will crash if the stack is not aligned properly.
51-
let x = packed_simd::i32x4::splat(arg as i32);
52-
let y = x * x;
53-
println!("simd result: {:?}", y);
54-
let (_, stack_ptr) = arch::swap(0, stack_ptr, None);
55-
// And try again after a context switch.
56-
let x = packed_simd::i32x4::splat(arg as i32);
57-
let y = x * x;
58-
println!("simd result: {:?}", y);
59-
arch::swap(0, stack_ptr, None);
60-
panic!("i should be dead");
61-
}
62-
63-
unsafe {
64-
let stack = OsStack::new(4 << 20).unwrap();
65-
let stack_ptr = arch::init(&stack, permuter);
66-
67-
let (_, stack_ptr) = arch::swap(10, stack_ptr, Some(&stack));
68-
arch::swap(20, stack_ptr, Some(&stack));
69-
}
70-
}
71-
72-
unsafe extern "C" fn do_panic(arg: usize, stack_ptr: StackPointer) -> ! {
82+
// #[test]
83+
// fn context_simd() {
84+
// unsafe fn permuter(arg: usize, stack_ptr: StackPointer) {
85+
// // This will crash if the stack is not aligned properly.
86+
// let x = packed_simd::i32x4::splat(arg as i32);
87+
// let y = x * x;
88+
// println!("simd result: {:?}", y);
89+
// let (_, stack_ptr) = arch::swap(0, stack_ptr);
90+
// // And try again after a context switch.
91+
// let x = packed_simd::i32x4::splat(arg as i32);
92+
// let y = x * x;
93+
// println!("simd result: {:?}", y);
94+
// arch::swap(0, stack_ptr);
95+
// panic!("i should be dead");
96+
// }
97+
98+
// unsafe {
99+
// let stack = OsStack::new(4 << 20).unwrap();
100+
// let stack_ptr = arch::init(stack.base(), permuter);
101+
102+
// let (_, stack_ptr) = arch::swap_link(10, stack_ptr, stack.base());
103+
// arch::swap_link(20, stack_ptr.unwrap(), stack.base());
104+
// }
105+
// }
106+
107+
unsafe fn do_panic(arg: usize, stack_ptr: StackPointer) {
73108
match arg {
74109
0 => panic!("arg=0"),
75110
1 => {
76-
arch::swap(0, stack_ptr, None);
111+
arch::swap(0, stack_ptr);
77112
panic!("arg=1");
78113
}
79114
_ => unreachable!(),
@@ -85,9 +120,9 @@ mod tests {
85120
fn panic_after_start() {
86121
unsafe {
87122
let stack = OsStack::new(4 << 20).unwrap();
88-
let stack_ptr = arch::init(&stack, do_panic);
123+
let stack_ptr = arch::init(stack.base(), do_panic);
89124

90-
arch::swap(0, stack_ptr, Some(&stack));
125+
arch::swap_link(0, stack_ptr, stack.base());
91126
}
92127
}
93128

@@ -96,32 +131,45 @@ mod tests {
96131
fn panic_after_swap() {
97132
unsafe {
98133
let stack = OsStack::new(4 << 20).unwrap();
99-
let stack_ptr = arch::init(&stack, do_panic);
134+
let stack_ptr = arch::init(stack.base(), do_panic);
135+
136+
let (_, stack_ptr) = arch::swap_link(1, stack_ptr, stack.base());
137+
arch::swap_link(0, stack_ptr.unwrap(), stack.base());
138+
}
139+
}
140+
141+
#[test]
142+
fn ret() {
143+
unsafe fn ret2(_: usize, _: StackPointer) {}
144+
145+
unsafe {
146+
let stack = OsStack::new(4 << 20).unwrap();
147+
let stack_ptr = arch::init(stack.base(), ret2);
100148

101-
let (_, stack_ptr) = arch::swap(1, stack_ptr, Some(&stack));
102-
arch::swap(0, stack_ptr, Some(&stack));
149+
let (_, stack_ptr) = arch::swap_link(0, stack_ptr, stack.base());
150+
assert!(stack_ptr.is_none());
103151
}
104152
}
105153

106154
#[bench]
107155
fn swap(b: &mut test::Bencher) {
108-
unsafe extern "C" fn loopback(mut arg: usize, mut stack_ptr: StackPointer) -> ! {
156+
unsafe fn loopback(mut arg: usize, mut stack_ptr: StackPointer) {
109157
// This deliberately does not ignore arg, to measure the time it takes
110158
// to move the return value between registers.
111159
loop {
112-
let data = arch::swap(arg, stack_ptr, None);
160+
let data = arch::swap(arg, stack_ptr);
113161
arg = data.0;
114162
stack_ptr = data.1;
115163
}
116164
}
117165

118166
unsafe {
119167
let stack = OsStack::new(4 << 20).unwrap();
120-
let mut stack_ptr = arch::init(&stack, loopback);
168+
let mut stack_ptr = arch::init(stack.base(), loopback);
121169

122170
b.iter(|| {
123171
for _ in 0..10 {
124-
stack_ptr = arch::swap(0, stack_ptr, Some(&stack)).1;
172+
stack_ptr = arch::swap_link(0, stack_ptr, stack.base()).1.unwrap();
125173
}
126174
});
127175
}

0 commit comments

Comments
 (0)