Skip to content

Commit eef0734

Browse files
committed
Partially implement zeroing on-drop
1 parent 5147c1f commit eef0734

File tree

6 files changed

+104
-63
lines changed

6 files changed

+104
-63
lines changed

src/librustc_trans/trans/base.rs

+16-9
Original file line numberDiff line numberDiff line change
@@ -1298,22 +1298,29 @@ pub fn init_zero_mem<'blk, 'tcx>(cx: Block<'blk, 'tcx>, llptr: ValueRef, t: Ty<'
12981298
fn memfill<'a, 'tcx>(b: &Builder<'a, 'tcx>, llptr: ValueRef, ty: Ty<'tcx>, byte: u8) {
12991299
let _icx = push_ctxt("memfill");
13001300
let ccx = b.ccx;
1301-
13021301
let llty = type_of::type_of(ccx, ty);
1303-
let ptr_width = &ccx.sess().target.target.target_pointer_width[..];
1304-
let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
1305-
1306-
let llintrinsicfn = ccx.get_intrinsic(&intrinsic_key);
13071302
let llptr = b.pointercast(llptr, Type::i8(ccx).ptr_to());
13081303
let llzeroval = C_u8(ccx, byte);
13091304
let size = machine::llsize_of(ccx, llty);
13101305
let align = C_i32(ccx, type_of::align_of(ccx, ty) as i32);
1311-
let volatile = C_bool(ccx, false);
1312-
b.call(llintrinsicfn,
1313-
&[llptr, llzeroval, size, align, volatile],
1314-
None, None);
1306+
call_memset(b, llptr, llzeroval, size, align, false);
13151307
}
13161308

1309+
pub fn call_memset<'bcx, 'tcx>(b: &Builder<'bcx, 'tcx>,
1310+
ptr: ValueRef,
1311+
fill_byte: ValueRef,
1312+
size: ValueRef,
1313+
align: ValueRef,
1314+
volatile: bool) {
1315+
let ccx = b.ccx;
1316+
let ptr_width = &ccx.sess().target.target.target_pointer_width[..];
1317+
let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
1318+
let llintrinsicfn = ccx.get_intrinsic(&intrinsic_key);
1319+
let volatile = C_bool(ccx, volatile);
1320+
b.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None, None);
1321+
}
1322+
1323+
13171324
/// In general, when we create an scratch value in an alloca, the
13181325
/// creator may not know if the block (that initializes the scratch
13191326
/// with the desired value) actually dominates the cleanup associated

src/librustc_trans/trans/mir/block.rs

+4-33
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use trans::common::{self, Block, LandingPad};
2020
use trans::debuginfo::DebugLoc;
2121
use trans::Disr;
2222
use trans::foreign;
23-
use trans::glue;
2423
use trans::type_of;
2524
use trans::type_::Type;
2625

@@ -96,35 +95,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
9695
}
9796

9897
mir::Terminator::Drop { ref value, target, unwind } => {
99-
let lvalue = self.trans_lvalue(bcx, value);
100-
let ty = lvalue.ty.to_ty(bcx.tcx());
101-
// Double check for necessity to drop
102-
if !glue::type_needs_drop(bcx.tcx(), ty) {
103-
build::Br(bcx, self.llblock(target), DebugLoc::None);
104-
return;
105-
}
106-
let drop_fn = glue::get_drop_glue(bcx.ccx(), ty);
107-
let drop_ty = glue::get_drop_glue_type(bcx.ccx(), ty);
108-
let llvalue = if drop_ty != ty {
109-
build::PointerCast(bcx, lvalue.llval,
110-
type_of::type_of(bcx.ccx(), drop_ty).ptr_to())
111-
} else {
112-
lvalue.llval
113-
};
114-
if let Some(unwind) = unwind {
115-
let uwbcx = self.bcx(unwind);
116-
let unwind = self.make_landing_pad(uwbcx);
117-
build::Invoke(bcx,
118-
drop_fn,
119-
&[llvalue],
120-
self.llblock(target),
121-
unwind.llbb,
122-
None,
123-
DebugLoc::None);
124-
} else {
125-
build::Call(bcx, drop_fn, &[llvalue], None, DebugLoc::None);
126-
build::Br(bcx, self.llblock(target), DebugLoc::None);
127-
}
98+
self.trans_drop(bcx, value, target, unwind);
12899
}
129100

130101
mir::Terminator::Call { ref func, ref args, ref destination, ref cleanup } => {
@@ -287,7 +258,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
287258
}
288259
}
289260

290-
fn make_landing_pad(&mut self, cleanup: Block<'bcx, 'tcx>) -> Block<'bcx, 'tcx> {
261+
pub fn make_landing_pad(&mut self, cleanup: Block<'bcx, 'tcx>) -> Block<'bcx, 'tcx> {
291262
let bcx = cleanup.fcx.new_block("cleanup", None);
292263
// FIXME(#30941) this doesn't handle msvc-style exceptions
293264
*bcx.lpad.borrow_mut() = Some(LandingPad::gnu());
@@ -314,11 +285,11 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
314285
}
315286
}
316287

317-
fn bcx(&self, bb: mir::BasicBlock) -> Block<'bcx, 'tcx> {
288+
pub fn bcx(&self, bb: mir::BasicBlock) -> Block<'bcx, 'tcx> {
318289
self.blocks[bb.index()]
319290
}
320291

321-
fn llblock(&self, bb: mir::BasicBlock) -> BasicBlockRef {
292+
pub fn llblock(&self, bb: mir::BasicBlock) -> BasicBlockRef {
322293
self.blocks[bb.index()].llbb
323294
}
324295
}

src/librustc_trans/trans/mir/drop.rs

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use llvm::ValueRef;
12+
use rustc::middle::ty::Ty;
13+
use rustc::mir::repr as mir;
14+
use trans::adt;
15+
use trans::base;
16+
use trans::build;
17+
use trans::common::{self, Block};
18+
use trans::debuginfo::DebugLoc;
19+
use trans::glue;
20+
use trans::machine;
21+
use trans::type_of;
22+
use trans::type_::Type;
23+
24+
use super::MirContext;
25+
26+
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
27+
pub fn trans_drop(&mut self,
28+
bcx: Block<'bcx, 'tcx>,
29+
value: &mir::Lvalue<'tcx>,
30+
target: mir::BasicBlock,
31+
unwind: Option<mir::BasicBlock>) {
32+
let lvalue = self.trans_lvalue(bcx, value);
33+
let ty = lvalue.ty.to_ty(bcx.tcx());
34+
// Double check for necessity to drop
35+
if !glue::type_needs_drop(bcx.tcx(), ty) {
36+
build::Br(bcx, self.llblock(target), DebugLoc::None);
37+
return;
38+
}
39+
let drop_fn = glue::get_drop_glue(bcx.ccx(), ty);
40+
let drop_ty = glue::get_drop_glue_type(bcx.ccx(), ty);
41+
let llvalue = if drop_ty != ty {
42+
build::PointerCast(bcx, lvalue.llval,
43+
type_of::type_of(bcx.ccx(), drop_ty).ptr_to())
44+
} else {
45+
lvalue.llval
46+
};
47+
if let Some(unwind) = unwind {
48+
// block cannot be cleanup in this case, so a regular block is fine
49+
let intermediate_bcx = bcx.fcx.new_block("", None);
50+
let uwbcx = self.bcx(unwind);
51+
let unwind = self.make_landing_pad(uwbcx);
52+
// FIXME: it could be possible to do zeroing before invoking here if the drop glue
53+
// didn’t code in the checks inside itself.
54+
build::Invoke(bcx,
55+
drop_fn,
56+
&[llvalue],
57+
intermediate_bcx.llbb,
58+
unwind.llbb,
59+
None,
60+
DebugLoc::None);
61+
// FIXME: perhaps we also should fill inside failed branch? We do not want to re-drop a
62+
// failed drop again by mistake. (conflicts with MSVC SEH if we don’t want to introduce
63+
// a heap of hacks)
64+
self.drop_fill(intermediate_bcx, lvalue.llval, ty);
65+
build::Br(intermediate_bcx, self.llblock(target), DebugLoc::None);
66+
} else {
67+
build::Call(bcx, drop_fn, &[llvalue], None, DebugLoc::None);
68+
self.drop_fill(bcx, lvalue.llval, ty);
69+
build::Br(bcx, self.llblock(target), DebugLoc::None);
70+
}
71+
}
72+
73+
pub fn drop_fill(&mut self, bcx: Block<'bcx, 'tcx>, value: ValueRef, ty: Ty<'tcx>) {
74+
let llty = type_of::type_of(bcx.ccx(), ty);
75+
let llptr = build::PointerCast(bcx, value, Type::i8(bcx.ccx()).ptr_to());
76+
let filling = common::C_u8(bcx.ccx(), adt::DTOR_DONE);
77+
let size = machine::llsize_of(bcx.ccx(), llty);
78+
let align = common::C_u32(bcx.ccx(), machine::llalign_of_min(bcx.ccx(), llty));
79+
base::call_memset(&build::B(bcx), llptr, filling, size, align, false);
80+
}
81+
}

src/librustc_trans/trans/mir/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ mod analyze;
196196
mod block;
197197
mod constant;
198198
mod did;
199+
mod drop;
199200
mod lvalue;
200201
mod operand;
201202
mod rvalue;

src/librustc_trans/trans/mir/operand.rs

-16
Original file line numberDiff line numberDiff line change
@@ -147,22 +147,6 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
147147
}
148148
}
149149

150-
pub fn trans_operand_into(&mut self,
151-
bcx: Block<'bcx, 'tcx>,
152-
lldest: ValueRef,
153-
operand: &mir::Operand<'tcx>)
154-
{
155-
debug!("trans_operand_into(lldest={}, operand={:?})",
156-
bcx.val_to_string(lldest),
157-
operand);
158-
159-
// FIXME: consider not copying constants through the
160-
// stack.
161-
162-
let o = self.trans_operand(bcx, operand);
163-
self.store_operand(bcx, lldest, o);
164-
}
165-
166150
pub fn store_operand(&mut self,
167151
bcx: Block<'bcx, 'tcx>,
168152
lldest: ValueRef,

src/librustc_trans/trans/mir/rvalue.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,6 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
4343
rvalue);
4444

4545
match *rvalue {
46-
mir::Rvalue::Use(ref operand) => {
47-
self.trans_operand_into(bcx, dest.llval, operand);
48-
bcx
49-
}
50-
5146
mir::Rvalue::Cast(mir::CastKind::Unsize, ref operand, cast_ty) => {
5247
if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
5348
// into-coerce of a thin pointer to a fat pointer - just
@@ -168,6 +163,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
168163

169164
match *rvalue {
170165
mir::Rvalue::Use(ref operand) => {
166+
// FIXME: consider not copying constants through stack. (fixable by translating
167+
// constants into OperandValue::Ref, why don’t we do that yet if we don’t?)
171168
let operand = self.trans_operand(bcx, operand);
172169
(bcx, operand)
173170
}

0 commit comments

Comments
 (0)