diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 7bd2653f86990..4637e637cae0d 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1084,6 +1084,28 @@ pub fn with_cond<'a>( next_cx } +pub fn call_lifetime_start(cx: &Block, ptr: ValueRef, llty: Type) { + let _icx = push_ctxt("lifetime_start"); + let ccx = cx.ccx(); + + // let llty = type_of::type_of(ccx, t); + let size = machine::llsize_of(ccx, llty); + let lifetime_start = ccx.intrinsics.get_copy(&("llvm.lifetime.start")); + let ptr = PointerCast(cx, ptr, Type::i8p()); + Call(cx, lifetime_start, [size, ptr], []); +} + +pub fn call_lifetime_end(cx: &Block, ptr: ValueRef, t: ty::t) { + let _icx = push_ctxt("lifetime_end"); + let ccx = cx.ccx(); + + let llty = type_of::type_of(ccx, t); + let size = machine::llsize_of(ccx, llty); + let lifetime_end = ccx.intrinsics.get_copy(&("llvm.lifetime.end")); + let ptr = PointerCast(cx, ptr, Type::i8p()); + Call(cx, lifetime_end, [size, ptr], []); +} + pub fn call_memcpy(cx: &Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) { let _icx = push_ctxt("call_memcpy"); let ccx = cx.ccx(); @@ -1171,6 +1193,8 @@ pub fn alloca_maybe_zeroed(cx: &Block, ty: Type, name: &str, zero: bool) -> Valu let b = cx.fcx.ccx.builder(); b.position_before(cx.fcx.alloca_insert_pt.get().unwrap()); memzero(&b, p, ty); + } else { + call_lifetime_start(cx, p, ty); } p } @@ -1183,7 +1207,9 @@ pub fn arrayalloca(cx: &Block, ty: Type, v: ValueRef) -> ValueRef { } } debuginfo::clear_source_location(cx.fcx); - return ArrayAlloca(cx, ty, v); + let p = ArrayAlloca(cx, ty, v); + call_lifetime_start(cx, p, ty); + p } pub struct BasicBlocks { @@ -2420,6 +2446,9 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<&'static str, ValueRef> { ifn!(intrinsics, "llvm.expect.i1", [Type::i1(), Type::i1()], Type::i1()); + ifn!(intrinsics, "llvm.lifetime.start", [Type::i64(), i8p], Type::void()); + ifn!(intrinsics, "llvm.lifetime.end", [Type::i64(), i8p], Type::void()); + return intrinsics; } diff --git a/src/librustc/middle/trans/cleanup.rs b/src/librustc/middle/trans/cleanup.rs index acbbdf27d1c26..90cb72c9265d8 100644 --- a/src/librustc/middle/trans/cleanup.rs +++ b/src/librustc/middle/trans/cleanup.rs @@ -244,6 +244,11 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> { * instance of `ty` */ + self.schedule_clean(cleanup_scope, ~LifetimeEnd { + val: val, + ty: ty + }); + if !ty::type_needs_drop(self.ccx.tcx, ty) { return; } let drop = ~DropValue { is_immediate: false, @@ -831,6 +836,22 @@ impl Cleanup for DropValue { } } +pub struct LifetimeEnd { + val: ValueRef, + ty: ty::t, +} + +impl Cleanup for LifetimeEnd { + fn clean_on_unwind(&self) -> bool { + false + } + + fn trans<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a> { + base::call_lifetime_end(bcx, self.val, self.ty); + bcx + } +} + pub struct FreeValue { ptr: ValueRef, heap: common::heap, diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index 49f1b073f873e..3c7e91637a861 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -80,6 +80,8 @@ pub fn get_simple_intrinsic(ccx: @CrateContext, item: &ast::ForeignItem) -> Opti "bswap16" => Some(ccx.intrinsics.get_copy(&("llvm.bswap.i16"))), "bswap32" => Some(ccx.intrinsics.get_copy(&("llvm.bswap.i32"))), "bswap64" => Some(ccx.intrinsics.get_copy(&("llvm.bswap.i64"))), + "lifetime_start" => Some(ccx.intrinsics.get_copy(&("llvm.lifetime.start"))), + "lifetime_end" => Some(ccx.intrinsics.get_copy(&("llvm.lifetime.end"))), _ => None } }