diff --git a/src/libcore/core.rc b/src/libcore/core.rc index efcd424024a..5997c1d0632 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -201,7 +201,7 @@ mod extfmt; mod unicode; mod priv; mod cmath; - +mod stackwalk; // Local Variables: // mode: rust; diff --git a/src/libcore/stackwalk.rs b/src/libcore/stackwalk.rs new file mode 100644 index 00000000000..f1072d79a3a --- /dev/null +++ b/src/libcore/stackwalk.rs @@ -0,0 +1,54 @@ +import libc::uintptr_t; + +class frame { + let fp: uintptr_t; + + new(fp: uintptr_t) { + self.fp = fp; + } +} + +fn walk_stack(visit: fn(frame) -> bool) { + frame_address { |frame_pointer| + let frame_address = unsafe { + unsafe::reinterpret_cast(frame_pointer) + }; + visit(frame(frame_address)); + } +} + +#[test] +fn test() { + for walk_stack { |frame| + #debug("frame: %x", frame.fp); + // breakpoint(); + } +} + +fn breakpoint() { + rustrt::rust_dbg_breakpoint() +} + +fn frame_address(f: fn(*u8)) { + rusti::frame_address(f) +} + +native mod rustrt { + fn rust_dbg_breakpoint(); +} + +// FIXME: Unconditionalize after snapshot +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +#[abi = "rust-intrinsic"] +native mod rusti { + fn frame_address(f: fn(*u8)); +} + +#[cfg(stage0)] +mod rusti { + fn frame_address(_f: fn(*u8)) { + fail; + } +} diff --git a/src/rustc/middle/trans/native.rs b/src/rustc/middle/trans/native.rs index 1f399343f13..60b25410212 100644 --- a/src/rustc/middle/trans/native.rs +++ b/src/rustc/middle/trans/native.rs @@ -875,7 +875,27 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::native_item, "frame_address" { let frameaddress = ccx.intrinsics.get("llvm.frameaddress"); let frameaddress_val = Call(bcx, frameaddress, [C_i32(0i32)]); - Store(bcx, frameaddress_val, fcx.llretptr); + let fty = ty::mk_fn(bcx.tcx(), { + purity: ast::impure_fn, + proto: ast::proto_any, + inputs: [{ + mode: ast::expl(ast::by_val), + ty: ty::mk_imm_ptr( + bcx.tcx(), + ty::mk_mach_uint(bcx.tcx(), ast::ty_u8)) + }], + output: ty::mk_nil(bcx.tcx()), + ret_style: ast::return_val, + constraints: [] + }); + bcx = trans_call_inner(bcx, none, fty, ty::mk_nil(bcx.tcx()), + { |bcx| + lval_no_env( + bcx, + get_param(decl, first_real_arg), + temporary) + }, + arg_vals([frameaddress_val]), ignore); } } build_return(bcx); diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index a6bb333c34e..22d31a8fe72 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -2318,7 +2318,20 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::native_item) { (1u, [arg(ast::by_ref, visitor_iface)], ty::mk_nil(tcx)) } "frame_address" { - (0u, [], ty::mk_imm_ptr(tcx, ty::mk_mach_uint(tcx, ast::ty_u8))) + let fty = ty::mk_fn(ccx.tcx, { + purity: ast::impure_fn, + proto: ast::proto_any, + inputs: [{ + mode: ast::expl(ast::by_val), + ty: ty::mk_imm_ptr( + ccx.tcx, + ty::mk_mach_uint(ccx.tcx, ast::ty_u8)) + }], + output: ty::mk_nil(ccx.tcx), + ret_style: ast::return_val, + constraints: [] + }); + (0u, [arg(ast::by_ref, fty)], ty::mk_nil(tcx)) } other { tcx.sess.span_err(it.span, "unrecognized intrinsic function: `" + diff --git a/src/test/run-pass/intrinsic-frame-address.rs b/src/test/run-pass/intrinsic-frame-address.rs index 072f5cf8e88..84b2a1c995d 100644 --- a/src/test/run-pass/intrinsic-frame-address.rs +++ b/src/test/run-pass/intrinsic-frame-address.rs @@ -1,8 +1,10 @@ #[abi = "rust-intrinsic"] native mod rusti { - fn frame_address() -> *u8; + fn frame_address(f: fn(*u8)); } fn main() { - assert rusti::frame_address().is_not_null(); + rusti::frame_address {|addr| + assert addr.is_not_null(); + } }