separate out write_guard code into its own module

This commit is contained in:
Niko Matsakis 2013-05-04 14:29:32 -04:00
parent ccf2f7b979
commit 989d008124
6 changed files with 41 additions and 204 deletions

View File

@ -110,6 +110,9 @@ endif
ifdef SAVE_TEMPS
CFG_RUSTC_FLAGS += --save-temps
endif
ifdef ASM_COMMENTS
CFG_RUSTC_FLAGS += -z asm-comments
endif
ifdef TIME_PASSES
CFG_RUSTC_FLAGS += -Z time-passes
endif

View File

@ -969,30 +969,17 @@ pub fn pats_require_rooting(bcx: block,
})
}
pub fn root_pats_as_necessary(bcx: block,
pub fn root_pats_as_necessary(mut bcx: block,
m: &[@Match],
col: uint,
val: ValueRef)
-> block {
let mut bcx = bcx;
for vec::each(m) |br| {
let pat_id = br.pats[col].id;
let key = root_map_key {id: pat_id, derefs: 0u };
match bcx.ccx().maps.root_map.find(&key) {
None => (),
Some(&root_info) => {
// Note: the scope_id will always be the id of the match. See
// the extended comment in rustc::middle::borrowck::preserve()
// for details (look for the case covering cat_discr).
let datum = Datum {val: val, ty: node_id_type(bcx, pat_id),
mode: ByRef, source: ZeroMem};
bcx = datum.root(bcx, br.pats[col].span, key, root_info);
// If we kept going, we'd only re-root the same value, so
// return now.
return bcx;
}
if pat_id != 0 {
let datum = Datum {val: val, ty: node_id_type(bcx, pat_id),
mode: ByRef, source: ZeroMem};
bcx = datum.root_and_write_guard(bcx, br.pats[col].span, pat_id, 0);
}
}
return bcx;

View File

@ -27,18 +27,18 @@ use middle::resolve;
use middle::trans::adt;
use middle::trans::base;
use middle::trans::build;
use middle::trans::callee;
use middle::trans::datum;
use middle::trans::debuginfo;
use middle::trans::expr;
use middle::trans::glue;
use middle::trans::reachable;
use middle::trans::shape;
use middle::trans::type_of;
use middle::trans::type_use;
use middle::trans::write_guard;
use middle::ty::substs;
use middle::ty;
use middle::typeck;
use middle::borrowck::root_map_key;
use util::ppaux::{Repr};
use core::cast::transmute;
@ -468,6 +468,7 @@ pub fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) {
}
}
pub fn add_clean_return_to_mut(bcx: block,
root_key: root_map_key,
frozen_val_ref: ValueRef,
bits_val_ref: ValueRef,
filename_val: ValueRef,
@ -488,44 +489,12 @@ pub fn add_clean_return_to_mut(bcx: block,
scope_info.cleanups.push(
clean_temp(
frozen_val_ref,
|bcx| {
let mut bcx = bcx;
let box_ptr =
build::Load(bcx,
build::PointerCast(bcx,
frozen_val_ref,
T_ptr(T_ptr(T_i8()))));
let bits_val =
build::Load(bcx,
bits_val_ref);
if bcx.tcx().sess.opts.optimize == session::No {
bcx = callee::trans_lang_call(
bcx,
bcx.tcx().lang_items.unrecord_borrow_fn(),
~[
box_ptr,
bits_val,
filename_val,
line_val
],
expr::Ignore);
}
callee::trans_lang_call(
bcx,
bcx.tcx().lang_items.return_to_mut_fn(),
~[
box_ptr,
bits_val,
filename_val,
line_val
],
expr::Ignore
)
},
|bcx| write_guard::return_to_mut(bcx,
root_key,
frozen_val_ref,
bits_val_ref,
filename_val,
line_val),
normal_exit_only));
scope_clean_changed(scope_info);
}
@ -1563,6 +1532,15 @@ pub fn dummy_substs(tps: ~[ty::t]) -> ty::substs {
}
}
pub fn filename_and_line_num_from_span(bcx: block,
span: span) -> (ValueRef, ValueRef) {
let loc = bcx.sess().parse_sess.cm.lookup_char_pos(span.lo);
let filename_cstr = C_cstr(bcx.ccx(), @/*bad*/copy loc.file.name);
let filename = build::PointerCast(bcx, filename_cstr, T_ptr(T_i8()));
let line = C_int(bcx.ccx(), loc.line as int);
(filename, line)
}
// Casts a Rust bool value to an i1.
pub fn bool_to_i1(bcx: block, llval: ValueRef) -> ValueRef {
build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(false))

View File

@ -385,13 +385,7 @@ fn trans_fail_value(bcx: block,
pub fn trans_fail_bounds_check(bcx: block, sp: span,
index: ValueRef, len: ValueRef) -> block {
let _icx = bcx.insn_ctxt("trans_fail_bounds_check");
let ccx = bcx.ccx();
let loc = bcx.sess().parse_sess.cm.lookup_char_pos(sp.lo);
let line = C_int(ccx, loc.line as int);
let filename_cstr = C_cstr(bcx.ccx(), @/*bad*/copy loc.file.name);
let filename = PointerCast(bcx, filename_cstr, T_ptr(T_i8()));
let (filename, line) = filename_and_line_num_from_span(bcx, sp);
let args = ~[filename, line, index, len];
let bcx = callee::trans_lang_call(
bcx, bcx.tcx().lang_items.fail_bounds_check_fn(), args, expr::Ignore);

View File

@ -87,21 +87,19 @@
use lib;
use lib::llvm::ValueRef;
use middle::borrowck::{RootInfo, root_map_key, DynaImm, DynaMut};
use middle::trans::adt;
use middle::trans::base::*;
use middle::trans::build::*;
use middle::trans::callee;
use middle::trans::common::*;
use middle::trans::common;
use middle::trans::expr;
use middle::trans::glue;
use middle::trans::tvec;
use middle::trans::type_of;
use middle::trans::write_guard;
use middle::ty;
use util::common::indenter;
use util::ppaux::ty_to_str;
use driver::session;
use core::container::Set; // XXX: this should not be necessary
use core::to_bytes;
@ -518,113 +516,6 @@ pub impl Datum {
}
}
fn root(&self, mut bcx: block, span: span,
root_key: root_map_key, root_info: RootInfo) -> block {
/*!
*
* In some cases, borrowck will decide that an @T/@[]/@str
* value must be rooted for the program to be safe. In that
* case, we will call this function, which will stash a copy
* away until we exit the scope `scope_id`. */
debug!("root(root_map_key=%?, root_info=%?, self=%?)",
root_key, root_info, self.to_str(bcx.ccx()));
if bcx.sess().trace() {
trans_trace(
bcx, None,
@fmt!("preserving until end of scope %d",
root_info.scope));
}
// First, root the datum. Note that we must zero this value,
// because sometimes we root on one path but not another.
// See e.g. #4904.
let scratch = scratch_datum(bcx, self.ty, true);
self.copy_to_datum(bcx, INIT, scratch);
let cleanup_bcx = find_bcx_for_scope(bcx, root_info.scope);
add_clean_temp_mem(cleanup_bcx, scratch.val, scratch.ty);
// Now, consider also freezing it.
match root_info.freeze {
None => {}
Some(freeze_kind) => {
let loc = bcx.sess().parse_sess.cm.lookup_char_pos(span.lo);
let line = C_int(bcx.ccx(), loc.line as int);
let filename_cstr = C_cstr(bcx.ccx(), @/*bad*/copy loc.file.name);
let filename = PointerCast(bcx, filename_cstr, T_ptr(T_i8()));
// in this case, we don't have to zero, because
// scratch.val will be NULL should the cleanup get
// called without the freezing actually occurring, and
// return_to_mut checks for this condition.
let scratch_bits = scratch_datum(bcx, ty::mk_uint(), false);
let freeze_did = match freeze_kind {
DynaImm => bcx.tcx().lang_items.borrow_as_imm_fn(),
DynaMut => bcx.tcx().lang_items.borrow_as_mut_fn(),
};
let box_ptr = Load(bcx,
PointerCast(bcx,
scratch.val,
T_ptr(T_ptr(T_i8()))));
bcx = callee::trans_lang_call(
bcx,
freeze_did,
~[
box_ptr,
filename,
line
],
expr::SaveIn(scratch_bits.val));
if bcx.tcx().sess.opts.optimize == session::No {
bcx = callee::trans_lang_call(
bcx,
bcx.tcx().lang_items.record_borrow_fn(),
~[
box_ptr,
Load(bcx, scratch_bits.val),
filename,
line
],
expr::Ignore);
}
add_clean_return_to_mut(
cleanup_bcx, scratch.val, scratch_bits.val,
filename, line);
}
}
bcx
}
fn perform_write_guard(&self, bcx: block, span: span) -> block {
debug!("perform_write_guard");
// Create scratch space, but do not root it.
let llval = match self.mode {
ByValue => self.val,
ByRef => Load(bcx, self.val),
};
let loc = bcx.sess().parse_sess.cm.lookup_char_pos(span.lo);
let line = C_int(bcx.ccx(), loc.line as int);
let filename_cstr = C_cstr(bcx.ccx(), @/*bad*/copy loc.file.name);
let filename = PointerCast(bcx, filename_cstr, T_ptr(T_i8()));
callee::trans_lang_call(
bcx,
bcx.tcx().lang_items.check_not_borrowed_fn(),
~[PointerCast(bcx, llval, T_ptr(T_i8())),
filename,
line],
expr::Ignore)
}
fn drop_val(&self, bcx: block) -> block {
if !ty::type_needs_drop(bcx.tcx(), self.ty) {
return bcx;
@ -687,7 +578,9 @@ pub impl Datum {
debug!("try_deref(expr_id=%?, derefs=%?, is_auto=%b, self=%?)",
expr_id, derefs, is_auto, self.to_str(bcx.ccx()));
let bcx = self.root_and_write_guard(bcx, span, expr_id, derefs);
let bcx =
write_guard::root_and_write_guard(
self, bcx, span, expr_id, derefs);
match ty::get(self.ty).sty {
ty::ty_box(_) | ty::ty_uniq(_) => {
@ -841,33 +734,6 @@ pub impl Datum {
DatumBlock { bcx: bcx, datum: datum }
}
fn root_and_write_guard(&self,
mut bcx: block,
span: span,
expr_id: ast::node_id,
derefs: uint) -> block {
let key = root_map_key { id: expr_id, derefs: derefs };
debug!("root_and_write_guard(key=%?)", key);
// root the autoderef'd value, if necessary:
//
// (Note: root'd values are always boxes)
let ccx = bcx.ccx();
bcx = match ccx.maps.root_map.find(&key) {
None => bcx,
Some(&root_info) => self.root(bcx, span, key, root_info)
};
// Perform the write guard, if necessary.
//
// (Note: write-guarded values are always boxes)
if ccx.maps.write_guard_map.contains(&key) {
self.perform_write_guard(bcx, span)
} else {
bcx
}
}
fn get_vec_base_and_len(&self,
mut bcx: block,
span: span,
@ -877,7 +743,7 @@ pub impl Datum {
//! and write guards checks.
// only imp't for @[] and @str, but harmless
bcx = self.root_and_write_guard(bcx, span, expr_id, 0);
bcx = write_guard::root_and_write_guard(self, bcx, span, expr_id, 0);
let (base, len) = self.get_vec_base_and_len_no_root(bcx);
(bcx, base, len)
}
@ -890,6 +756,14 @@ pub impl Datum {
tvec::get_base_and_len(bcx, llval, self.ty)
}
fn root_and_write_guard(&self,
bcx: block,
span: span,
expr_id: ast::node_id,
derefs: uint) -> block {
write_guard::root_and_write_guard(self, bcx, span, expr_id, derefs)
}
fn to_result(&self, bcx: block) -> common::Result {
rslt(bcx, self.to_appropriate_llval(bcx))
}

View File

@ -47,6 +47,7 @@ pub mod middle {
pub mod controlflow;
pub mod glue;
pub mod datum;
pub mod write_guard;
pub mod callee;
pub mod expr;
pub mod common;