auto merge of #11723 : eddyb/rust/more-trans-cleanup, r=pcwalton
This commit is contained in:
commit
760ddb3081
8 changed files with 62 additions and 146 deletions
|
|
@ -42,11 +42,10 @@ pub static general_code_alignment: uint = 16u;
|
|||
|
||||
pub static tydesc_field_size: uint = 0u;
|
||||
pub static tydesc_field_align: uint = 1u;
|
||||
pub static tydesc_field_take_glue: uint = 2u;
|
||||
pub static tydesc_field_drop_glue: uint = 3u;
|
||||
pub static tydesc_field_visit_glue: uint = 4u;
|
||||
pub static tydesc_field_name_offset: uint = 5u;
|
||||
pub static n_tydesc_fields: uint = 6u;
|
||||
pub static tydesc_field_drop_glue: uint = 2u;
|
||||
pub static tydesc_field_visit_glue: uint = 3u;
|
||||
pub static tydesc_field_name_offset: uint = 4u;
|
||||
pub static n_tydesc_fields: uint = 5u;
|
||||
|
||||
// The two halves of a closure: code and environment.
|
||||
pub static fn_field_code: uint = 0u;
|
||||
|
|
|
|||
|
|
@ -777,9 +777,6 @@ pub fn iter_structural_ty<'r,
|
|||
let variant_cx =
|
||||
fcx.new_temp_block(~"enum-iter-variant-" +
|
||||
variant.disr_val.to_str());
|
||||
let variant_cx =
|
||||
iter_variant(variant_cx, repr, av, *variant,
|
||||
substs.tps, |x,y,z| f(x,y,z));
|
||||
match adt::trans_case(cx, repr, variant.disr_val) {
|
||||
_match::single_result(r) => {
|
||||
AddCase(llswitch, r.val, variant_cx.llbb)
|
||||
|
|
@ -787,6 +784,9 @@ pub fn iter_structural_ty<'r,
|
|||
_ => ccx.sess.unimpl("value from adt::trans_case \
|
||||
in iter_structural_ty")
|
||||
}
|
||||
let variant_cx =
|
||||
iter_variant(variant_cx, repr, av, *variant,
|
||||
substs.tps, |x,y,z| f(x,y,z));
|
||||
Br(variant_cx, next_cx.llbb);
|
||||
}
|
||||
cx = next_cx;
|
||||
|
|
@ -1458,16 +1458,16 @@ pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block) {
|
|||
// trans_closure: Builds an LLVM function out of a source function.
|
||||
// If the function closes over its environment a closure will be
|
||||
// returned.
|
||||
pub fn trans_closure(ccx: @CrateContext,
|
||||
path: ast_map::Path,
|
||||
decl: &ast::FnDecl,
|
||||
body: &ast::Block,
|
||||
llfndecl: ValueRef,
|
||||
param_substs: Option<@param_substs>,
|
||||
id: ast::NodeId,
|
||||
_attributes: &[ast::Attribute],
|
||||
output_type: ty::t,
|
||||
maybe_load_env: |&FunctionContext|) {
|
||||
pub fn trans_closure<'a>(ccx: @CrateContext,
|
||||
path: ast_map::Path,
|
||||
decl: &ast::FnDecl,
|
||||
body: &ast::Block,
|
||||
llfndecl: ValueRef,
|
||||
param_substs: Option<@param_substs>,
|
||||
id: ast::NodeId,
|
||||
_attributes: &[ast::Attribute],
|
||||
output_type: ty::t,
|
||||
maybe_load_env: |&'a Block<'a>| -> &'a Block<'a>) {
|
||||
ccx.stats.n_closures.set(ccx.stats.n_closures.get() + 1);
|
||||
|
||||
let _icx = push_ctxt("trans_closure");
|
||||
|
|
@ -1500,7 +1500,7 @@ pub fn trans_closure(ccx: @CrateContext,
|
|||
|
||||
bcx = copy_args_to_allocas(&fcx, arg_scope, bcx, decl.inputs, arg_datums);
|
||||
|
||||
maybe_load_env(&fcx);
|
||||
bcx = maybe_load_env(bcx);
|
||||
|
||||
// Up until here, IR instructions for this function have explicitly not been annotated with
|
||||
// source code location, so we don't step into call setup code. From here on, source location
|
||||
|
|
@ -1558,16 +1558,8 @@ pub fn trans_fn(ccx: @CrateContext,
|
|||
debug!("trans_fn(param_substs={})", param_substs.repr(ccx.tcx));
|
||||
let _icx = push_ctxt("trans_fn");
|
||||
let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, id));
|
||||
trans_closure(ccx,
|
||||
path.clone(),
|
||||
decl,
|
||||
body,
|
||||
llfndecl,
|
||||
param_substs,
|
||||
id,
|
||||
attrs,
|
||||
output_type,
|
||||
|_fcx| { });
|
||||
trans_closure(ccx, path.clone(), decl, body, llfndecl,
|
||||
param_substs, id, attrs, output_type, |bcx| bcx);
|
||||
}
|
||||
|
||||
pub fn trans_enum_variant(ccx: @CrateContext,
|
||||
|
|
|
|||
|
|
@ -282,23 +282,22 @@ fn build_closure<'a>(bcx0: &'a Block<'a>,
|
|||
// Given an enclosing block context, a new function context, a closure type,
|
||||
// and a list of upvars, generate code to load and populate the environment
|
||||
// with the upvars and type descriptors.
|
||||
fn load_environment(fcx: &FunctionContext, cdata_ty: ty::t,
|
||||
cap_vars: &[moves::CaptureVar], sigil: ast::Sigil) {
|
||||
fn load_environment<'a>(bcx: &'a Block<'a>, cdata_ty: ty::t,
|
||||
cap_vars: &[moves::CaptureVar],
|
||||
sigil: ast::Sigil) -> &'a Block<'a> {
|
||||
let _icx = push_ctxt("closure::load_environment");
|
||||
|
||||
// Don't bother to create the block if there's nothing to load
|
||||
if cap_vars.len() == 0 {
|
||||
return;
|
||||
return bcx;
|
||||
}
|
||||
|
||||
let bcx = fcx.entry_bcx.get().unwrap();
|
||||
|
||||
// Load a pointer to the closure data, skipping over the box header:
|
||||
let llcdata = at_box_body(bcx, cdata_ty, fcx.llenv.unwrap());
|
||||
let llcdata = at_box_body(bcx, cdata_ty, bcx.fcx.llenv.unwrap());
|
||||
|
||||
// Store the pointer to closure data in an alloca for debug info because that's what the
|
||||
// llvm.dbg.declare intrinsic expects
|
||||
let env_pointer_alloca = if fcx.ccx.sess.opts.extra_debuginfo {
|
||||
let env_pointer_alloca = if bcx.ccx().sess.opts.extra_debuginfo {
|
||||
let alloc = alloc_ty(bcx, ty::mk_mut_ptr(bcx.tcx(), cdata_ty), "__debuginfo_env_ptr");
|
||||
Store(bcx, llcdata, alloc);
|
||||
Some(alloc)
|
||||
|
|
@ -317,7 +316,7 @@ fn load_environment(fcx: &FunctionContext, cdata_ty: ty::t,
|
|||
let def_id = ast_util::def_id_of_def(cap_var.def);
|
||||
|
||||
{
|
||||
let mut llupvars = fcx.llupvars.borrow_mut();
|
||||
let mut llupvars = bcx.fcx.llupvars.borrow_mut();
|
||||
llupvars.get().insert(def_id.node, upvarptr);
|
||||
}
|
||||
|
||||
|
|
@ -334,6 +333,8 @@ fn load_environment(fcx: &FunctionContext, cdata_ty: ty::t,
|
|||
|
||||
i += 1u;
|
||||
}
|
||||
|
||||
bcx
|
||||
}
|
||||
|
||||
fn fill_fn_pair(bcx: &Block, pair: ValueRef, llfn: ValueRef, llenvptr: ValueRef) {
|
||||
|
|
@ -405,7 +406,7 @@ pub fn trans_expr_fn<'a>(
|
|||
trans_closure(ccx, sub_path, decl, body, llfn,
|
||||
bcx.fcx.param_substs, user_id,
|
||||
[], ty::ty_fn_ret(fty),
|
||||
|fcx| load_environment(fcx, cdata_ty, cap_vars, sigil));
|
||||
|bcx| load_environment(bcx, cdata_ty, cap_vars, sigil));
|
||||
fill_fn_pair(bcx, dest_addr, llfn, llbox);
|
||||
|
||||
bcx
|
||||
|
|
|
|||
|
|
@ -114,7 +114,6 @@ pub struct tydesc_info {
|
|||
size: ValueRef,
|
||||
align: ValueRef,
|
||||
name: ValueRef,
|
||||
take_glue: Cell<Option<ValueRef>>,
|
||||
drop_glue: Cell<Option<ValueRef>>,
|
||||
visit_glue: Cell<Option<ValueRef>>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -491,7 +491,7 @@ impl Datum<Expr> {
|
|||
}
|
||||
ByValue => {
|
||||
let v = load(bcx, l.val, l.ty);
|
||||
l.kind.post_store(bcx, l.val, l.ty);
|
||||
bcx = l.kind.post_store(bcx, l.val, l.ty);
|
||||
DatumBlock(bcx, Datum(v, l.ty, Rvalue(ByValue)))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,14 +58,24 @@ pub fn trans_exchange_free<'a>(cx: &'a Block<'a>, v: ValueRef)
|
|||
Some(expr::Ignore)).bcx
|
||||
}
|
||||
|
||||
pub fn take_ty<'a>(cx: &'a Block<'a>, v: ValueRef, t: ty::t)
|
||||
pub fn take_ty<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
|
||||
-> &'a Block<'a> {
|
||||
// NB: v is an *alias* of type t here, not a direct value.
|
||||
let _icx = push_ctxt("take_ty");
|
||||
if ty::type_needs_drop(cx.tcx(), t) {
|
||||
return call_tydesc_glue(cx, v, t, abi::tydesc_field_take_glue);
|
||||
match ty::get(t).sty {
|
||||
ty::ty_box(_) |
|
||||
ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) => {
|
||||
incr_refcnt_of_boxed(bcx, v)
|
||||
}
|
||||
ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => {
|
||||
incr_refcnt_of_boxed(bcx, GEPi(bcx, v, [0u, abi::trt_field_box]))
|
||||
}
|
||||
_ if ty::type_is_structural(t)
|
||||
&& ty::type_needs_drop(bcx.tcx(), t) => {
|
||||
iter_structural_ty(bcx, v, t, take_ty)
|
||||
}
|
||||
_ => bcx
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
pub fn drop_ty<'a>(cx: &'a Block<'a>, v: ValueRef, t: ty::t)
|
||||
|
|
@ -88,30 +98,15 @@ pub fn drop_ty_immediate<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
|
|||
|
||||
pub fn lazily_emit_all_tydesc_glue(ccx: @CrateContext,
|
||||
static_ti: @tydesc_info) {
|
||||
lazily_emit_tydesc_glue(ccx, abi::tydesc_field_take_glue, static_ti);
|
||||
lazily_emit_tydesc_glue(ccx, abi::tydesc_field_drop_glue, static_ti);
|
||||
lazily_emit_tydesc_glue(ccx, abi::tydesc_field_visit_glue, static_ti);
|
||||
}
|
||||
|
||||
fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t {
|
||||
if (field == abi::tydesc_field_take_glue || field == abi::tydesc_field_drop_glue)
|
||||
&& !ty::type_needs_drop(tcx, t) {
|
||||
return ty::mk_nil();
|
||||
}
|
||||
|
||||
if field == abi::tydesc_field_take_glue {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_str(ty::vstore_uniq) | ty::ty_vec(_, ty::vstore_uniq) |
|
||||
ty::ty_unboxed_vec(..) | ty::ty_uniq(..) => return ty::mk_nil(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if field == abi::tydesc_field_take_glue && ty::type_is_boxed(t) {
|
||||
return ty::mk_box(tcx, ty::mk_nil());
|
||||
}
|
||||
|
||||
if field == abi::tydesc_field_drop_glue {
|
||||
if !ty::type_needs_drop(tcx, t) {
|
||||
return ty::mk_nil();
|
||||
}
|
||||
match ty::get(t).sty {
|
||||
ty::ty_box(typ)
|
||||
if !ty::type_needs_drop(tcx, typ) =>
|
||||
|
|
@ -145,9 +140,7 @@ fn lazily_emit_tydesc_glue(ccx: @CrateContext, field: uint, ti: @tydesc_info) {
|
|||
let simpl_ti = get_tydesc(ccx, simpl);
|
||||
lazily_emit_tydesc_glue(ccx, field, simpl_ti);
|
||||
|
||||
if field == abi::tydesc_field_take_glue {
|
||||
ti.take_glue.set(simpl_ti.take_glue.get());
|
||||
} else if field == abi::tydesc_field_drop_glue {
|
||||
if field == abi::tydesc_field_drop_glue {
|
||||
ti.drop_glue.set(simpl_ti.drop_glue.get());
|
||||
} else if field == abi::tydesc_field_visit_glue {
|
||||
ti.visit_glue.set(simpl_ti.visit_glue.get());
|
||||
|
|
@ -158,20 +151,7 @@ fn lazily_emit_tydesc_glue(ccx: @CrateContext, field: uint, ti: @tydesc_info) {
|
|||
|
||||
let llfnty = Type::glue_fn(type_of(ccx, ti.ty).ptr_to());
|
||||
|
||||
if field == abi::tydesc_field_take_glue {
|
||||
match ti.take_glue.get() {
|
||||
Some(_) => (),
|
||||
None => {
|
||||
debug!("+++ lazily_emit_tydesc_glue TAKE {}",
|
||||
ppaux::ty_to_str(ccx.tcx, ti.ty));
|
||||
let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "take");
|
||||
ti.take_glue.set(Some(glue_fn));
|
||||
make_generic_glue(ccx, ti.ty, glue_fn, make_take_glue, "take");
|
||||
debug!("--- lazily_emit_tydesc_glue TAKE {}",
|
||||
ppaux::ty_to_str(ccx.tcx, ti.ty));
|
||||
}
|
||||
}
|
||||
} else if field == abi::tydesc_field_drop_glue {
|
||||
if field == abi::tydesc_field_drop_glue {
|
||||
match ti.drop_glue.get() {
|
||||
Some(_) => (),
|
||||
None => {
|
||||
|
|
@ -213,9 +193,7 @@ pub fn call_tydesc_glue_full(bcx: &Block, v: ValueRef, tydesc: ValueRef,
|
|||
None => None,
|
||||
Some(sti) => {
|
||||
lazily_emit_tydesc_glue(ccx, field, sti);
|
||||
if field == abi::tydesc_field_take_glue {
|
||||
sti.take_glue.get()
|
||||
} else if field == abi::tydesc_field_drop_glue {
|
||||
if field == abi::tydesc_field_drop_glue {
|
||||
sti.drop_glue.get()
|
||||
} else if field == abi::tydesc_field_visit_glue {
|
||||
sti.visit_glue.get()
|
||||
|
|
@ -472,53 +450,16 @@ fn decr_refcnt_maybe_free<'a>(bcx: &'a Block<'a>, box_ptr_ptr: ValueRef,
|
|||
next_bcx
|
||||
}
|
||||
|
||||
fn make_take_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) -> &'a Block<'a> {
|
||||
let _icx = push_ctxt("make_take_glue");
|
||||
// NB: v is a *pointer* to type t here, not a direct value.
|
||||
match ty::get(t).sty {
|
||||
ty::ty_box(_) |
|
||||
ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) => {
|
||||
incr_refcnt_of_boxed(bcx, Load(bcx, v)); bcx
|
||||
}
|
||||
ty::ty_vec(_, ty::vstore_slice(_))
|
||||
| ty::ty_str(ty::vstore_slice(_)) => {
|
||||
bcx
|
||||
}
|
||||
ty::ty_closure(_) => bcx,
|
||||
ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => {
|
||||
let llbox = Load(bcx, GEPi(bcx, v, [0u, abi::trt_field_box]));
|
||||
incr_refcnt_of_boxed(bcx, llbox);
|
||||
bcx
|
||||
}
|
||||
ty::ty_trait(_, _, ty::UniqTraitStore, _, _) => {
|
||||
let lluniquevalue = GEPi(bcx, v, [0, abi::trt_field_box]);
|
||||
let llvtable = Load(bcx, GEPi(bcx, v, [0, abi::trt_field_vtable]));
|
||||
|
||||
// Cast the vtable to a pointer to a pointer to a tydesc.
|
||||
let llvtable = PointerCast(bcx, llvtable,
|
||||
bcx.ccx().tydesc_type.ptr_to().ptr_to());
|
||||
let lltydesc = Load(bcx, llvtable);
|
||||
call_tydesc_glue_full(bcx,
|
||||
lluniquevalue,
|
||||
lltydesc,
|
||||
abi::tydesc_field_take_glue,
|
||||
None);
|
||||
bcx
|
||||
}
|
||||
_ if ty::type_is_structural(t) => {
|
||||
iter_structural_ty(bcx, v, t, take_ty)
|
||||
}
|
||||
_ => bcx
|
||||
}
|
||||
}
|
||||
|
||||
fn incr_refcnt_of_boxed(cx: &Block, box_ptr: ValueRef) {
|
||||
fn incr_refcnt_of_boxed<'a>(bcx: &'a Block<'a>,
|
||||
box_ptr_ptr: ValueRef) -> &'a Block<'a> {
|
||||
let _icx = push_ctxt("incr_refcnt_of_boxed");
|
||||
let ccx = cx.ccx();
|
||||
let rc_ptr = GEPi(cx, box_ptr, [0u, abi::box_field_refcnt]);
|
||||
let rc = Load(cx, rc_ptr);
|
||||
let rc = Add(cx, rc, C_int(ccx, 1));
|
||||
Store(cx, rc, rc_ptr);
|
||||
let ccx = bcx.ccx();
|
||||
let box_ptr = Load(bcx, box_ptr_ptr);
|
||||
let rc_ptr = GEPi(bcx, box_ptr, [0u, abi::box_field_refcnt]);
|
||||
let rc = Load(bcx, rc_ptr);
|
||||
let rc = Add(bcx, rc, C_int(ccx, 1));
|
||||
Store(bcx, rc, rc_ptr);
|
||||
bcx
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -554,7 +495,6 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
|
|||
size: llsize,
|
||||
align: llalign,
|
||||
name: ty_name,
|
||||
take_glue: Cell::new(None),
|
||||
drop_glue: Cell::new(None),
|
||||
visit_glue: Cell::new(None),
|
||||
};
|
||||
|
|
@ -616,21 +556,6 @@ pub fn emit_tydescs(ccx: &CrateContext) {
|
|||
// before being put into the tydesc because we only have a singleton
|
||||
// tydesc type. Then we'll recast each function to its real type when
|
||||
// calling it.
|
||||
let take_glue =
|
||||
match ti.take_glue.get() {
|
||||
None => {
|
||||
ccx.stats.n_null_glues.set(ccx.stats.n_null_glues.get() +
|
||||
1);
|
||||
C_null(glue_fn_ty)
|
||||
}
|
||||
Some(v) => {
|
||||
unsafe {
|
||||
ccx.stats.n_real_glues.set(ccx.stats.n_real_glues.get() +
|
||||
1);
|
||||
llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref())
|
||||
}
|
||||
}
|
||||
};
|
||||
let drop_glue =
|
||||
match ti.drop_glue.get() {
|
||||
None => {
|
||||
|
|
@ -665,7 +590,6 @@ pub fn emit_tydescs(ccx: &CrateContext) {
|
|||
let tydesc = C_named_struct(ccx.tydesc_type,
|
||||
[ti.size, // size
|
||||
ti.align, // align
|
||||
take_glue, // take_glue
|
||||
drop_glue, // drop_glue
|
||||
visit_glue, // visit_glue
|
||||
ti.name]); // name
|
||||
|
|
|
|||
|
|
@ -211,7 +211,6 @@ impl Type {
|
|||
|
||||
let elems = [int_ty, // size
|
||||
int_ty, // align
|
||||
glue_fn_ty, // take
|
||||
glue_fn_ty, // drop
|
||||
glue_fn_ty, // visit
|
||||
Type::struct_([Type::i8p(), Type::int(arch)], false)]; // name
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ pub struct TyDesc {
|
|||
align: uint,
|
||||
|
||||
// Called on a copy of a value of type `T` *after* memcpy
|
||||
// NOTE remove after next snapshot
|
||||
#[cfg(stage0)]
|
||||
take_glue: GlueFn,
|
||||
|
||||
// Called when a value of type `T` is no longer needed
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue