diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs index 2bbce0e2cb510..61432715d3a86 100644 --- a/src/rustc/driver/driver.rs +++ b/src/rustc/driver/driver.rs @@ -169,7 +169,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, let (copy_map, ref_map) = time(time_passes, "alias checking", bind middle::alias::check_crate(ty_cx, crate)); - let last_uses = time(time_passes, "last use finding", + let (last_uses, spill_map) = time(time_passes, "last use finding", bind last_use::find_last_uses(crate, def_map, ref_map, ty_cx)); time(time_passes, "kind checking", bind kind::check_crate(ty_cx, method_map, last_uses, crate)); @@ -181,7 +181,8 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, let maps = {mutbl_map: mutbl_map, copy_map: copy_map, last_uses: last_uses, impl_map: impl_map, - method_map: method_map, vtable_map: vtable_map}; + method_map: method_map, vtable_map: vtable_map, + spill_map: spill_map}; let (llmod, link_meta) = time(time_passes, "translation", diff --git a/src/rustc/metadata/astencode.rs b/src/rustc/metadata/astencode.rs index 9f9b0c986f88f..4e445bb3d4f84 100644 --- a/src/rustc/metadata/astencode.rs +++ b/src/rustc/metadata/astencode.rs @@ -512,7 +512,7 @@ impl of tr for method_origin { impl of tr for last_use::is_last_use { fn tr(xcx: extended_decode_ctxt) -> last_use::is_last_use { alt self { - last_use::is_last_use | last_use::has_last_use { self } + last_use::is_last_use { self } last_use::closes_over(ids) { last_use::closes_over(vec::map(ids, {|id| xcx.tr_id(id)})) } @@ -780,6 +780,12 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt, } } + option::may(ccx.maps.spill_map.find(id)) {|_m| + ebml_w.tag(c::tag_table_spill) {|| + ebml_w.id(id); + } + } + option::may(ccx.maps.last_uses.find(id)) {|m| ebml_w.tag(c::tag_table_last_use) {|| ebml_w.id(id); @@ -869,6 +875,8 @@ fn decode_side_tables(xcx: extended_decode_ctxt, dcx.maps.mutbl_map.insert(id, ()); } else if tag == (c::tag_table_copy as uint) { dcx.maps.copy_map.insert(id, ()); + } else if tag == (c::tag_table_spill as uint) { + dcx.maps.spill_map.insert(id, ()); } else { let val_doc = entry_doc[c::tag_table_val]; let val_dsr = ebml::ebml_deserializer(val_doc); diff --git a/src/rustc/metadata/common.rs b/src/rustc/metadata/common.rs index 8a6b0eb30b2f2..a446d5ba90b1d 100644 --- a/src/rustc/metadata/common.rs +++ b/src/rustc/metadata/common.rs @@ -100,6 +100,7 @@ enum astencode_tag { // Reserves 0x50 -- 0x6f tag_table_mutbl, tag_table_copy, tag_table_last_use, + tag_table_spill, tag_table_method_map, tag_table_vtable_map } diff --git a/src/rustc/middle/last_use.rs b/src/rustc/middle/last_use.rs index 36a8047cdfb3e..6c9e61c0fa564 100644 --- a/src/rustc/middle/last_use.rs +++ b/src/rustc/middle/last_use.rs @@ -28,10 +28,10 @@ import std::map::hashmap; #[auto_serialize] enum is_last_use { is_last_use, - has_last_use, closes_over([node_id]), } type last_uses = std::map::hashmap; +type spill_map = std::map::hashmap; enum seen { unset, seen(node_id), } enum block_type { func, lp, } @@ -46,6 +46,7 @@ fn hash_use_id(id: use_id) -> uint { } type ctx = {last_uses: std::map::hashmap, + spill_map: std::map::hashmap, def_map: resolve::def_map, ref_map: alias::ref_map, tcx: ty::ctxt, @@ -54,12 +55,14 @@ type ctx = {last_uses: std::map::hashmap, mutable blocks: list}; fn find_last_uses(c: @crate, def_map: resolve::def_map, - ref_map: alias::ref_map, tcx: ty::ctxt) -> last_uses { + ref_map: alias::ref_map, tcx: ty::ctxt) + -> (last_uses, spill_map) { let v = visit::mk_vt(@{visit_expr: visit_expr, visit_stmt: visit_stmt, visit_fn: visit_fn with *visit::default_visitor()}); let cx = {last_uses: std::map::hashmap(hash_use_id, {|a, b| a == b}), + spill_map: std::map::int_hash(), def_map: def_map, ref_map: ref_map, tcx: tcx, @@ -73,10 +76,10 @@ fn find_last_uses(c: @crate, def_map: resolve::def_map, path(id) { mini_table.insert(id, is_last_use); let def_node = ast_util::def_id_of_def(def_map.get(id)).node; - mini_table.insert(def_node, has_last_use); + cx.spill_map.insert(def_node, ()); } close(fn_id, local_id) { - mini_table.insert(local_id, has_last_use); + cx.spill_map.insert(local_id, ()); let known = alt check mini_table.find(fn_id) { some(closes_over(ids)) { ids } none { [] } @@ -85,7 +88,7 @@ fn find_last_uses(c: @crate, def_map: resolve::def_map, } } } - ret mini_table; + ret (mini_table, cx.spill_map); } fn visit_expr(ex: @expr, cx: ctx, v: visit::vt) { @@ -187,7 +190,11 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt) { expr_path(_) { alt ty::arg_mode(cx.tcx, arg_t) { by_ref | by_val | by_mutbl_ref { - clear_if_path(cx, arg, v, false); + let def = cx.def_map.get(arg.id); + option::may(def_is_owned_local(cx, def)) {|id| + clear_in_current(cx, id, false); + cx.spill_map.insert(id, ()); + } } _ {} } diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 54050e6210111..6548975801a21 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -3687,7 +3687,7 @@ fn alloc_local(cx: block, local: @ast::local) -> block { let ccx = cx.ccx(); if option::is_some(simple_name) && !ccx.maps.mutbl_map.contains_key(local.node.pat.id) && - !ccx.maps.last_uses.contains_key(local.node.pat.id) && + !ccx.maps.spill_map.contains_key(local.node.pat.id) && ty::type_is_immediate(t) { alt local.node.init { some({op: ast::init_assign, _}) { ret cx; } diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 58d11cebee22a..cee8508dc58ec 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -69,7 +69,8 @@ type maps = { last_uses: middle::last_use::last_uses, impl_map: middle::resolve::impl_map, method_map: middle::typeck::method_map, - vtable_map: middle::typeck::vtable_map + vtable_map: middle::typeck::vtable_map, + spill_map: last_use::spill_map }; // Crate context. Every crate we compile has one of these. diff --git a/src/test/run-pass/stable-addr-of.rs b/src/test/run-pass/stable-addr-of.rs new file mode 100644 index 0000000000000..060994ed48f0a --- /dev/null +++ b/src/test/run-pass/stable-addr-of.rs @@ -0,0 +1,6 @@ +// Issue #2040 + +fn main() { + let foo = 1; + assert ptr::addr_of(foo) == ptr::addr_of(foo); +}