From 791173fd97c9ea2ad4dd4a497c80b22184c0cd5d Mon Sep 17 00:00:00 2001 From: edef Date: Wed, 24 Dec 2014 06:12:39 +0100 Subject: [PATCH] refactoring! --- src/arch.rs | 119 ++++++++++++++++++++++++++++++++++++ src/arch.s | 2 +- src/context.rs | 95 ++++++---------------------- src/lib.rs | 5 +- src/{debug.c => platform.c} | 0 src/platform.rs | 8 +++ src/stack.rs | 12 ++-- 7 files changed, 153 insertions(+), 88 deletions(-) create mode 100644 src/arch.rs rename src/{debug.c => platform.c} (100%) create mode 100644 src/platform.rs diff --git a/src/arch.rs b/src/arch.rs new file mode 100644 index 0000000..a305e93 --- /dev/null +++ b/src/arch.rs @@ -0,0 +1,119 @@ +use std::simd::u64x2; +use std::mem::{size_of, zeroed}; + +use stack::Stack; + +extern "C" { + #[link_name = "lwut_bootstrap"] + pub fn bootstrap(); + #[link_name = "lwut_swapcontext"] + pub fn swapcontext(save: *mut Registers, restore: *mut Registers); + #[link_name = "lwut_get_sp_limit"] + pub fn get_sp_limit() -> *const u8; + #[link_name = "lwut_set_sp_limit"] + pub fn set_sp_limit(limit: *const u8); + #[link_name = "lwut_abort"] + pub fn abort() -> !; +} + +#[allow(non_camel_case_types)] +pub type uintptr_t = u64; + +#[repr(C)] +#[allow(dead_code)] +pub struct Registers { + rbx: u64, + rsp: u64, + rbp: u64, + rdi: u64, + r12: u64, + r13: u64, + r14: u64, + r15: u64, + ip: u64, + xmm0: u64x2, + xmm1: u64x2, + xmm2: u64x2, + xmm3: u64x2, + xmm4: u64x2, + xmm5: u64x2, +} + +impl Registers { + pub fn new() -> Registers { + unsafe { + Registers { + ip: abort as u64, + .. zeroed() + } + } + } +} + +macro_rules! into_regs_ { + ($regs:ident { $reg:ident } <- $iter:ident) => { + match $iter.next() { + Some(value) => { + $regs.$reg = *value; + Some($iter) + } + None => None + } + }; + ($regs:ident { $reg:ident, $($regs_rest:ident),* } <- $iter:ident) => { + match $iter.next() { + Some(value) => { + $regs.$reg = *value; + into_regs_!($regs { $($regs_rest),* } <- $iter) + } + None => None + } + }; +} + +macro_rules! into_regs { + ($regs:ident { $($regs_rest:ident),* } <- $iter:expr) => { + { + let mut iter = $iter; + into_regs_!($regs { $($regs_rest),* } <- iter) + } + } +} + +pub fn initialise_call_frame(stack: &mut Stack, init: uintptr_t, args: &[uintptr_t]) -> Registers { + let sp = stack.top() as *mut uintptr_t; + let sp = align_down_mut(sp, 16); + let sp = offset_mut(sp, -1); + unsafe { + *sp = 0; + } + + let mut regs = Registers { + rbp: 0, + rsp: sp as uintptr_t, + ip: bootstrap as uintptr_t, + r12: init, + .. Registers::new() + }; + + match into_regs!(regs { rdi, r13, r14, r15 } <- args.iter()) { + Some(mut args) => if args.next().is_some() { + panic!("too many arguments") + }, + None => {} + } + + regs +} + +#[inline] +fn align_down_mut(sp: *mut T, n: uint) -> *mut T { + let sp = (sp as uint) & !(n - 1); + sp as *mut T +} + +// ptr::offset_mmut is positive ints only +#[inline] +pub fn offset_mut(ptr: *mut T, count: int) -> *mut T { + (ptr as int + count * (size_of::() as int)) as *mut T +} diff --git a/src/arch.s b/src/arch.s index 8d228d0..b13a085 100644 --- a/src/arch.s +++ b/src/arch.s @@ -2,7 +2,7 @@ BITS 64 ;; the structure containing every register that is saved on context switches. -;; this needs to match the struct in context.rs, or shit will break badly. +;; this needs to match the struct in arch.rs, or shit will break badly. struc context ctx_rbx resq 1 ctx_rsp resq 1 diff --git a/src/context.rs b/src/context.rs index 66b84e1..8a03f76 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,85 +1,39 @@ use libc; -use stack::Stack; -use std::simd::u64x2; -use std::mem::{zeroed, size_of, transmute}; +use std::mem::transmute; use std::raw; use fn_box::FnBox; +use stack::Stack; +use arch::{mod, Registers}; + pub struct Context { regs: Registers, stack: Stack } -#[repr(C)] -#[allow(dead_code)] -struct Registers { - rbx: u64, - rsp: u64, - rbp: u64, - rdi: u64, - r12: u64, - r13: u64, - r14: u64, - r15: u64, - ip: u64, - xmm0: u64x2, - xmm1: u64x2, - xmm2: u64x2, - xmm3: u64x2, - xmm4: u64x2, - xmm5: u64x2, -} - -impl Registers { - fn zeroed() -> Registers { unsafe { zeroed() } } -} - -extern "C" { - fn lwut_bootstrap(); - fn lwut_swapcontext(save: *mut Registers, restore: *mut Registers); - fn lwut_get_sp_limit() -> *const u8; - fn lwut_set_sp_limit(limit: *const u8); - fn lwut_abort() -> !; -} - pub type BoxedFn = Box + Send + 'static>; pub type StartFn = fn(data: *mut T, f: BoxedFn) -> !; impl Context { pub fn new(init: StartFn, data: *mut T, f: BoxedFn) -> Context { - let stack = Stack::new(4 << 20); - - let sp = stack.top() as *mut uint; - let sp = align_down_mut(sp, 16); - let sp = offset_mut(sp, -1); - unsafe { - *sp = 0; - } - + let mut stack = Stack::new(4 << 20); let f: raw::TraitObject = unsafe { transmute(f) }; Context { - regs: Registers { - rbp: 0, - rsp: sp as libc::uintptr_t, - ip: lwut_bootstrap as libc::uintptr_t, - r12: lwut_init:: as libc::uintptr_t, - rdi: init as libc::uintptr_t, - r13: data as libc::uintptr_t, - r14: f.data as libc::uintptr_t, - r15: f.vtable as libc::uintptr_t, - // r8: …, - // r9: …, - .. Registers::zeroed() - }, + regs: arch::initialise_call_frame(&mut stack, + init_ctx:: as libc::uintptr_t, + &[init as libc::uintptr_t, + data as libc::uintptr_t, + f.data as libc::uintptr_t, + f.vtable as libc::uintptr_t]), stack: stack } } } -unsafe extern "C" fn lwut_init(start: StartFn, data: *mut T, - f_data: *mut (), f_vtable: *mut ()) -> ! { +unsafe extern "C" fn init_ctx(start: StartFn, data: *mut T, + f_data: *mut (), f_vtable: *mut ()) -> ! { let f: BoxedFn = transmute(raw::TraitObject { data: f_data, vtable: f_vtable @@ -91,30 +45,15 @@ unsafe extern "C" fn lwut_init(start: StartFn, data: *mut T, impl Context { pub unsafe fn native() -> Context { Context { - regs: Registers { - ip: lwut_abort as libc::uintptr_t, - .. Registers::zeroed() - }, - stack: Stack::native(lwut_get_sp_limit()) + regs: Registers::new(), + stack: Stack::native(arch::get_sp_limit()) } } #[inline(always)] pub unsafe fn swap(out_context: &mut Context, in_context: &mut Context) { - lwut_set_sp_limit(in_context.stack.limit()); - lwut_swapcontext(&mut out_context.regs, &mut in_context.regs); + arch::set_sp_limit(in_context.stack.limit()); + arch::swapcontext(&mut out_context.regs, &mut in_context.regs); } } - -#[inline] -fn align_down_mut(sp: *mut T, n: uint) -> *mut T { - let sp = (sp as uint) & !(n - 1); - sp as *mut T -} - -// ptr::offset_mmut is positive ints only -#[inline] -pub fn offset_mut(ptr: *mut T, count: int) -> *mut T { - (ptr as int + count * (size_of::() as int)) as *mut T -} diff --git a/src/lib.rs b/src/lib.rs index 2f079a7..474b5bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(default_type_params)] +#![feature(default_type_params, macro_rules)] extern crate libc; extern crate fn_box; @@ -6,3 +6,6 @@ pub use context::Context; mod context; mod stack; + +mod arch; +mod platform; diff --git a/src/debug.c b/src/platform.c similarity index 100% rename from src/debug.c rename to src/platform.c diff --git a/src/platform.rs b/src/platform.rs new file mode 100644 index 0000000..178999b --- /dev/null +++ b/src/platform.rs @@ -0,0 +1,8 @@ +use libc; + +extern "C" { + #[link_name = "lwut_stack_register"] + pub fn stack_register(start: *const u8, end: *const u8) -> libc::c_uint; + #[link_name = "lwut_stack_deregister"] + pub fn stack_deregister(id: libc::c_uint); +} diff --git a/src/stack.rs b/src/stack.rs index b0c057f..c465ba2 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -1,4 +1,5 @@ use libc; +use platform; use std::ptr; use std::os::{errno, page_size, MemoryMap, MapReadable, MapWritable, MapNonStandardFlags}; @@ -17,11 +18,6 @@ pub enum Stack { } } -extern "C" { - fn lwut_stack_register(start: *const u8, end: *const u8) -> libc::c_uint; - fn lwut_stack_deregister(id: libc::c_uint); -} - impl Stack { pub fn new(size: uint) -> Stack { let buf = match MemoryMap::new(size, &[MapReadable, MapWritable, @@ -36,8 +32,8 @@ impl Stack { } let valgrind_id = unsafe { - lwut_stack_register(buf.data().offset(buf.len() as int) as *const _, - buf.data() as *const _) + platform::stack_register(buf.data().offset(buf.len() as int) as *const _, + buf.data() as *const _) }; @@ -91,7 +87,7 @@ impl Drop for Stack { match *self { Stack::Native { .. } => {}, Stack::Managed { valgrind_id, .. } => unsafe { - lwut_stack_deregister(valgrind_id); + platform::stack_deregister(valgrind_id); } } }