From 44c6370e6a8c159c49062d61e51d75b2b52c6954 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 15 Sep 2011 13:18:20 +0200 Subject: [PATCH] Move local numbering into ast_map.rs This further simplifies the alias pass, which is sorely needed. --- src/comp/middle/alias.rs | 56 ++++++++++++++++-------------------- src/comp/middle/ast_map.rs | 59 +++++++++++++++++++++++++++----------- 2 files changed, 67 insertions(+), 48 deletions(-) diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index f3850d977ee..74d9370d4aa 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -17,8 +17,8 @@ tag copied { not_allowed; copied; not_copied; } type binding = @{node_id: node_id, span: span, - local_id: uint, root_var: option::t, + local_id: uint, unsafe_tys: [ty::t], mutable ok: valid, mutable copied: copied}; @@ -26,9 +26,10 @@ type scope = {bs: [binding], ret_style: ast::ret_style}; fn mk_binding(cx: ctx, id: node_id, span: span, root_var: option::t, unsafe: [ty::t]) -> binding { - ret @{node_id: id, span: span, local_id: cx.next_local, - root_var: root_var, unsafe_tys: unsafe, - mutable ok: valid, mutable copied: not_copied}; + ret @{node_id: id, span: span, root_var: root_var, + local_id: local_id_of_node(cx, id), + unsafe_tys: unsafe, mutable ok: valid, + mutable copied: not_copied}; } tag local_info { local(uint); } @@ -36,16 +37,12 @@ tag local_info { local(uint); } type copy_map = std::map::hashmap; type ctx = {tcx: ty::ctxt, - local_map: std::map::hashmap, - mutable next_local: uint, copy_map: copy_map}; fn check_crate(tcx: ty::ctxt, crate: @ast::crate) -> copy_map { // Stores information about object fields and function // arguments that's otherwise not easily available. let cx = @{tcx: tcx, - local_map: std::map::new_int_hash(), - mutable next_local: 0u, copy_map: std::map::new_int_hash()}; let v = @{visit_fn: bind visit_fn(cx, _, _, _, _, _, _, _), visit_expr: bind visit_expr(cx, _, _, _), @@ -133,13 +130,6 @@ fn visit_expr(cx: @ctx, ex: @ast::expr, sc: scope, v: vt) { if !handled { visit::visit_expr(ex, sc, v); } } -fn register_locals(cx: ctx, pat: @ast::pat) { - for each pat in ast_util::pat_bindings(pat) { - cx.local_map.insert(pat.id, local(cx.next_local)); - cx.next_local += 1u; - } -} - fn visit_decl(cx: @ctx, d: @ast::decl, sc: scope, v: vt) { visit::visit_decl(d, sc, v); alt d.node { @@ -154,7 +144,6 @@ fn visit_decl(cx: @ctx, d: @ast::decl, sc: scope, v: vt) { } none. { } } - register_locals(*cx, loc.node.pat); } } _ { } @@ -200,14 +189,17 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] { } } let root_var = path_def_id(cx, root.ex); - let new_bnd = mk_binding(cx, arg.id, arg.span, root_var, - inner_mut(root.ds)); - new_bnd.copied = alt arg_t.mode { - ast::by_move. { copied } - ast::by_ref. { ret_ref ? not_allowed : not_copied } - ast::by_mut_ref. { not_allowed } - }; - bindings += [new_bnd]; + bindings += [@{node_id: arg.id, + span: arg.span, + root_var: root_var, + local_id: 0u, + unsafe_tys: inner_mut(root.ds), + mutable ok: valid, + mutable copied: alt arg_t.mode { + ast::by_move. { copied } + ast::by_ref. { ret_ref ? not_allowed : not_copied } + ast::by_mut_ref. { not_allowed } + }}]; i += 1u; } let f_may_close = @@ -283,7 +275,7 @@ fn check_ret_ref(cx: ctx, sc: scope, mut: bool, expr: @ast::expr) { let cur_node = did.node; while true { alt cx.tcx.items.find(cur_node) { - some(ast_map::node_arg(arg)) { + some(ast_map::node_arg(arg, _)) { if arg.mode == ast::by_move { bad = some("move-mode parameter"); } @@ -358,7 +350,6 @@ fn check_alt(cx: ctx, input: @ast::expr, arms: [ast::arm], sc: scope, new_bs += [mk_binding(cx, info.id, info.span, root_var, copy info.unsafe)]; } - register_locals(cx, a.pats[0]); visit::visit_arm(a, {bs: new_bs with sc}, v); } } @@ -373,7 +364,6 @@ fn check_for_each(cx: ctx, local: @ast::local, call: @ast::expr, new_bs += [mk_binding(cx, proot.id, proot.span, none, inner_mut(proot.ds))]; } - register_locals(cx, local.node.pat); visit::visit_block(blk, {bs: new_bs with sc}, v); } } @@ -401,17 +391,15 @@ fn check_for(cx: ctx, local: @ast::local, seq: @ast::expr, blk: ast::blk, new_bs += [mk_binding(cx, proot.id, proot.span, root_var, inner_mut(proot.ds))]; } - register_locals(cx, local.node.pat); visit::visit_block(blk, {bs: new_bs with sc}, v); } fn check_var(cx: ctx, ex: @ast::expr, p: ast::path, id: ast::node_id, assign: bool, sc: scope) { let def = cx.tcx.def_map.get(id); - if !def_is_local(def, true) { ret; } + if !def_is_local(def, false) { ret; } let my_defnum = ast_util::def_id_of_def(def).node; - let my_local_id = - alt cx.local_map.find(my_defnum) { some(local(id)) { id } _ { 0u } }; + let my_local_id = local_id_of_node(cx, my_defnum); let var_t = ty::expr_ty(cx.tcx, ex); for b in sc.bs { // excludes variables introduced since the alias was made @@ -557,6 +545,12 @@ fn def_is_local(d: ast::def, objfields_count: bool) -> bool { }; } +fn local_id_of_node(cx: ctx, id: node_id) -> uint { + alt cx.tcx.items.get(id) { + ast_map::node_arg(_, id) | ast_map::node_local(id) { id } + } +} + // Heuristic, somewhat random way to decide whether to warn when inserting an // implicit copy. fn copy_is_expensive(tcx: ty::ctxt, ty: ty::t) -> bool { diff --git a/src/comp/middle/ast_map.rs b/src/comp/middle/ast_map.rs index 40e73781126..ce8c983c0f9 100644 --- a/src/comp/middle/ast_map.rs +++ b/src/comp/middle/ast_map.rs @@ -1,5 +1,6 @@ import std::{smallintmap, option}; import syntax::ast::*; +import syntax::ast_util; import syntax::{visit, codemap}; import visit::vt; @@ -8,46 +9,70 @@ tag ast_node { node_obj_ctor(@item); node_native_item(@native_item); node_expr(@expr); - node_arg(arg); + // Locals are numbered, because the alias analysis needs to know in which + // order they are introduced. + node_arg(arg, uint); + node_local(uint); } type map = std::map::hashmap; +type ctx = @{map: map, mutable local_id: uint}; fn map_crate(c: crate) -> map { // FIXME: This is using an adapter to convert the smallintmap // interface to the hashmap interface. It would be better to just // convert everything to use the smallintmap. - let map = new_smallintmap_int_adapter::(); + let cx = @{map: new_smallintmap_int_adapter::(), + mutable local_id: 0u}; let v_map = visit::mk_simple_visitor - (@{visit_item: bind map_item(map, _), - visit_native_item: bind map_native_item(map, _), - visit_expr: bind map_expr(map, _), - visit_fn: bind map_fn(map, _, _, _, _, _) - with *visit::default_simple_visitor()}); + (@{visit_item: bind map_item(cx, _), + visit_native_item: bind map_native_item(cx, _), + visit_expr: bind map_expr(cx, _), + visit_fn: bind map_fn(cx, _, _, _, _, _), + visit_local: bind map_local(cx, _), + visit_arm: bind map_arm(cx, _) + with *visit::default_simple_visitor()}); visit::visit_crate(c, (), v_map); - ret map; + ret cx.map; } -fn map_fn(map: map, f: _fn, _tp: [ty_param], _sp: codemap::span, +fn map_fn(cx: ctx, f: _fn, _tp: [ty_param], _sp: codemap::span, _name: fn_ident, _id: node_id) { - for a in f.decl.inputs { map.insert(a.id, node_arg(a)); } + for a in f.decl.inputs { + cx.map.insert(a.id, node_arg(a, cx.local_id)); + cx.local_id += 1u; + } } -fn map_item(map: map, i: @item) { - map.insert(i.id, node_item(i)); +fn map_local(cx: ctx, loc: @local) { + for each p in ast_util::pat_bindings(loc.node.pat) { + cx.map.insert(p.id, node_local(cx.local_id)); + cx.local_id += 1u; + } +} + +fn map_arm(cx: ctx, arm: arm) { + for each p in ast_util::pat_bindings(arm.pats[0]) { + cx.map.insert(p.id, node_local(cx.local_id)); + cx.local_id += 1u; + } +} + +fn map_item(cx: ctx, i: @item) { + cx.map.insert(i.id, node_item(i)); alt i.node { - item_obj(_, _, ctor_id) { map.insert(ctor_id, node_obj_ctor(i)); } + item_obj(_, _, ctor_id) { cx.map.insert(ctor_id, node_obj_ctor(i)); } _ { } } } -fn map_native_item(map: map, i: @native_item) { - map.insert(i.id, node_native_item(i)); +fn map_native_item(cx: ctx, i: @native_item) { + cx.map.insert(i.id, node_native_item(i)); } -fn map_expr(map: map, ex: @expr) { - map.insert(ex.id, node_expr(ex)); +fn map_expr(cx: ctx, ex: @expr) { + cx.map.insert(ex.id, node_expr(ex)); } fn new_smallintmap_int_adapter<@V>() -> std::map::hashmap {