Set no-unwind on glue functions that don't drop resources.

This commit is contained in:
Graydon Hoare 2012-04-25 17:18:34 -07:00
parent fa6c68a025
commit 90c1b4645f
2 changed files with 39 additions and 17 deletions

View file

@ -488,6 +488,9 @@ fn declare_generic_glue(ccx: @crate_ctxt, t: ty::t, llfnty: TypeRef,
note_unique_llvm_symbol(ccx, fn_nm);
let llfn = decl_cdecl_fn(ccx.llmod, fn_nm, llfnty);
set_glue_inlining(llfn, t);
if name != "drop" || !ty::type_has_resources(t) {
set_no_unwind(llfn);
}
ret llfn;
}

View file

@ -100,7 +100,8 @@ export ty_uniq, mk_uniq, mk_imm_uniq, type_is_unique_box;
export ty_var, mk_var;
export ty_self, mk_self;
export region, bound_region;
export get, type_has_params, type_has_vars, type_has_regions, type_id;
export get, type_has_params, type_has_vars, type_has_regions;
export type_has_resources, type_id;
export ty_var_id;
export ty_to_def_id;
export ty_fn_args;
@ -235,6 +236,7 @@ type t_box = @{struct: sty,
has_params: bool,
has_vars: bool,
has_regions: bool,
has_resources: bool,
o_def_id: option<ast::def_id>};
// To reduce refcounting cost, we're representing types as unsafe pointers
@ -255,6 +257,7 @@ pure fn get(t: t) -> t_box unsafe {
fn type_has_params(t: t) -> bool { get(t).has_params }
fn type_has_vars(t: t) -> bool { get(t).has_vars }
fn type_has_regions(t: t) -> bool { get(t).has_regions }
fn type_has_resources(t: t) -> bool { get(t).has_resources }
fn type_def_id(t: t) -> option<ast::def_id> { get(t).o_def_id }
fn type_id(t: t) -> uint { get(t).id }
@ -478,13 +481,15 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t {
some(t) { unsafe { ret unsafe::reinterpret_cast(t); } }
_ {}
}
let mut has_params = false, has_vars = false, has_regions = false;
let mut has_params = false, has_vars = false, has_regions = false,
has_resources = false;
fn derive_flags(&has_params: bool, &has_vars: bool, &has_regions: bool,
tt: t) {
&has_resources: bool, tt: t) {
let t = get(tt);
has_params |= t.has_params;
has_vars |= t.has_vars;
has_regions |= t.has_regions;
has_resources |= t.has_resources;
}
fn derive_rflags(&has_vars: bool, &has_regions: bool, r: region) {
has_regions = true;
@ -494,9 +499,10 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t {
}
}
fn derive_sflags(&has_params: bool, &has_vars: bool, &has_regions: bool,
substs: substs) {
&has_resources: bool, substs: substs) {
for substs.tps.each {|tt|
derive_flags(has_params, has_vars, has_regions, tt);
derive_flags(has_params, has_vars, has_regions,
has_resources, tt);
}
substs.self_r.iter { |r| derive_rflags(has_vars, has_regions, r) }
}
@ -506,7 +512,8 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t {
}
ty_evec(mt, vstore_slice(r)) {
derive_rflags(has_vars, has_regions, r);
derive_flags(has_params, has_vars, has_regions, mt.ty);
derive_flags(has_params, has_vars, has_regions,
has_resources, mt.ty);
}
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
ty_str | ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) |
@ -514,41 +521,52 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t {
ty_param(_, _) { has_params = true; }
ty_var(_) | ty_self(_) { has_vars = true; }
ty_enum(_, substs) | ty_class(_, substs) {
derive_sflags(has_params, has_vars, has_regions, substs);
derive_sflags(has_params, has_vars, has_regions,
has_resources, substs);
}
ty_iface(_, tys) {
for tys.each {|tt|
derive_flags(has_params, has_vars, has_regions, tt);
derive_flags(has_params, has_vars, has_regions,
has_resources, tt);
}
}
ty_box(m) | ty_uniq(m) | ty_vec(m) | ty_evec(m, _) | ty_ptr(m) {
derive_flags(has_params, has_vars, has_regions, m.ty);
derive_flags(has_params, has_vars, has_regions,
has_resources, m.ty);
}
ty_rptr(r, m) {
derive_rflags(has_vars, has_regions, r);
derive_flags(has_params, has_vars, has_regions, m.ty);
derive_flags(has_params, has_vars, has_regions,
has_resources, m.ty);
}
ty_rec(flds) {
for flds.each {|f|
derive_flags(has_params, has_vars, has_regions, f.mt.ty);
derive_flags(has_params, has_vars, has_regions,
has_resources, f.mt.ty);
}
}
ty_tup(ts) {
for ts.each {|tt| derive_flags(has_params, has_vars,
has_regions, tt); }
has_regions, has_resources, tt); }
}
ty_fn(f) {
for f.inputs.each {|a|
derive_flags(has_params, has_vars, has_regions, a.ty);
derive_flags(has_params, has_vars, has_regions,
has_resources, a.ty);
}
derive_flags(has_params, has_vars, has_regions, f.output);
derive_flags(has_params, has_vars, has_regions,
has_resources, f.output);
}
ty_res(_, tt, substs) {
derive_flags(has_params, has_vars, has_regions, tt);
derive_sflags(has_params, has_vars, has_regions, substs);
has_resources = true;
derive_flags(has_params, has_vars, has_regions,
has_resources, tt);
derive_sflags(has_params, has_vars, has_regions,
has_resources, substs);
}
ty_constr(tt, _) {
derive_flags(has_params, has_vars, has_regions, tt);
derive_flags(has_params, has_vars, has_regions,
has_resources, tt);
}
}
let t = @{struct: st,
@ -556,6 +574,7 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t {
has_params: has_params,
has_vars: has_vars,
has_regions: has_regions,
has_resources: has_resources,
o_def_id: o_def_id};
cx.interner.insert(key, t);
cx.next_id += 1u;