diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index c1d05bf39da..7c57c90a5a4 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -5301,6 +5301,7 @@ fn declare_intrinsics(llmod: ModuleRef) -> hashmap { let T_memset64_args: [TypeRef] = [T_ptr(T_i8()), T_i8(), T_i64(), T_i32(), T_i1()]; let T_trap_args: [TypeRef] = []; + let T_frameaddress_args: [TypeRef] = [T_i32()]; let gcroot = decl_cdecl_fn(llmod, "llvm.gcroot", T_fn([T_ptr(T_ptr(T_i8())), T_ptr(T_i8())], T_void())); @@ -5320,6 +5321,9 @@ fn declare_intrinsics(llmod: ModuleRef) -> hashmap { decl_cdecl_fn(llmod, "llvm.memset.p0i8.i64", T_fn(T_memset64_args, T_void())); let trap = decl_cdecl_fn(llmod, "llvm.trap", T_fn(T_trap_args, T_void())); + let frameaddress = decl_cdecl_fn(llmod, "llvm.frameaddress", + T_fn(T_frameaddress_args, + T_ptr(T_i8()))); let intrinsics = str_hash::(); intrinsics.insert("llvm.gcroot", gcroot); intrinsics.insert("llvm.gcread", gcread); @@ -5328,6 +5332,7 @@ fn declare_intrinsics(llmod: ModuleRef) -> hashmap { intrinsics.insert("llvm.memset.p0i8.i32", memset32); intrinsics.insert("llvm.memset.p0i8.i64", memset64); intrinsics.insert("llvm.trap", trap); + intrinsics.insert("llvm.frameaddress", frameaddress); ret intrinsics; } diff --git a/src/rustc/middle/trans/native.rs b/src/rustc/middle/trans/native.rs index 445f300cb02..1f399343f13 100644 --- a/src/rustc/middle/trans/native.rs +++ b/src/rustc/middle/trans/native.rs @@ -755,22 +755,44 @@ fn trans_native_mod(ccx: @crate_ctxt, } let mut cc = alt abi { - ast::native_abi_rust_intrinsic { ret; } + ast::native_abi_rust_intrinsic | ast::native_abi_cdecl { lib::llvm::CCallConv } ast::native_abi_stdcall { lib::llvm::X86StdcallCallConv } }; for vec::each(native_mod.items) {|native_item| alt native_item.node { - ast::native_item_fn(fn_decl, _) { + ast::native_item_fn(fn_decl, typarams) { let id = native_item.id; - let llwrapfn = get_item_val(ccx, id); - let tys = c_stack_tys(ccx, id); - if attr::attrs_contains_name(native_item.attrs, "rust_stack") { - build_direct_fn(ccx, llwrapfn, native_item, tys, cc); + if abi != ast::native_abi_rust_intrinsic { + let llwrapfn = get_item_val(ccx, id); + let tys = c_stack_tys(ccx, id); + if attr::attrs_contains_name(native_item.attrs, "rust_stack") { + build_direct_fn(ccx, llwrapfn, native_item, tys, cc); + } else { + let llshimfn = build_shim_fn(ccx, native_item, tys, cc); + build_wrap_fn(ccx, tys, llshimfn, llwrapfn); + } } else { - let llshimfn = build_shim_fn(ccx, native_item, tys, cc); - build_wrap_fn(ccx, tys, llshimfn, llwrapfn); + // Intrinsics with type parameters are emitted by + // monomorphic_fn, but ones without are emitted here + if typarams.is_empty() { + let llwrapfn = get_item_val(ccx, id); + let path = alt ccx.tcx.items.find(id) { + some(ast_map::node_native_item(_, _, pt)) { pt } + _ { + ccx.sess.span_bug(native_item.span, + "can't find intrinsic path") + } + }; + let psubsts = { + tys: [], + vtables: none, + bounds: @[] + }; + trans_intrinsic(ccx, llwrapfn, native_item, + *path, psubsts, none); + } } } } @@ -783,31 +805,41 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::native_item, let fcx = new_fn_ctxt_w_id(ccx, path, decl, item.id, some(substs), some(item.span)); let mut bcx = top_scope_block(fcx, none), lltop = bcx.llbb; - let tp_ty = substs.tys[0], lltp_ty = type_of::type_of(ccx, tp_ty); alt check item.ident { "size_of" { + let tp_ty = substs.tys[0]; + let lltp_ty = type_of::type_of(ccx, tp_ty); Store(bcx, C_uint(ccx, shape::llsize_of_real(ccx, lltp_ty)), fcx.llretptr); } "min_align_of" { + let tp_ty = substs.tys[0]; + let lltp_ty = type_of::type_of(ccx, tp_ty); Store(bcx, C_uint(ccx, shape::llalign_of_min(ccx, lltp_ty)), fcx.llretptr); } "pref_align_of" { + let tp_ty = substs.tys[0]; + let lltp_ty = type_of::type_of(ccx, tp_ty); Store(bcx, C_uint(ccx, shape::llalign_of_pref(ccx, lltp_ty)), fcx.llretptr); } "get_tydesc" { + let tp_ty = substs.tys[0]; let td = get_tydesc_simple(ccx, tp_ty); Store(bcx, PointerCast(bcx, td, T_ptr(T_nil())), fcx.llretptr); } "init" { + let tp_ty = substs.tys[0]; + let lltp_ty = type_of::type_of(ccx, tp_ty); if !ty::type_is_nil(tp_ty) { Store(bcx, C_null(lltp_ty), fcx.llretptr); } } "forget" {} "reinterpret_cast" { + let tp_ty = substs.tys[0]; + let lltp_ty = type_of::type_of(ccx, tp_ty); let llout_ty = type_of::type_of(ccx, substs.tys[1]); let tp_sz = shape::llsize_of_real(ccx, lltp_ty), out_sz = shape::llsize_of_real(ccx, llout_ty); @@ -831,6 +863,7 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::native_item, Store(bcx, get_param(decl, first_real_arg), fcx.llretptr); } "needs_drop" { + let tp_ty = substs.tys[0]; Store(bcx, C_bool(ty::type_needs_drop(ccx.tcx, tp_ty)), fcx.llretptr); } @@ -839,6 +872,11 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::native_item, let visitor = get_param(decl, first_real_arg); call_tydesc_glue(bcx, visitor, tp_ty, abi::tydesc_field_visit_glue); } + "frame_address" { + let frameaddress = ccx.intrinsics.get("llvm.frameaddress"); + let frameaddress_val = Call(bcx, frameaddress, [C_i32(0i32)]); + Store(bcx, frameaddress_val, fcx.llretptr); + } } build_return(bcx); finish_fn(fcx, lltop); diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index b3f7c5a9388..a6bb333c34e 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -2317,7 +2317,9 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::native_item) { let (_, visitor_iface) = ccx.tcx.intrinsic_ifaces.get("ty_visitor"); (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))) + } other { tcx.sess.span_err(it.span, "unrecognized intrinsic function: `" + other + "`"); diff --git a/src/test/run-pass/intrinsic-frame-address.rs b/src/test/run-pass/intrinsic-frame-address.rs new file mode 100644 index 00000000000..072f5cf8e88 --- /dev/null +++ b/src/test/run-pass/intrinsic-frame-address.rs @@ -0,0 +1,8 @@ +#[abi = "rust-intrinsic"] +native mod rusti { + fn frame_address() -> *u8; +} + +fn main() { + assert rusti::frame_address().is_not_null(); +}