Move local numbering into ast_map.rs

This further simplifies the alias pass, which is sorely needed.
This commit is contained in:
Marijn Haverbeke 2011-09-15 13:18:20 +02:00
parent 1cda74deee
commit 44c6370e6a
2 changed files with 67 additions and 48 deletions

View file

@ -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<node_id>,
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<node_id>,
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<node_id, ()>;
type ctx = {tcx: ty::ctxt,
local_map: std::map::hashmap<node_id, local_info>,
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<scope>) {
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<scope>) {
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<scope>) {
}
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 {

View file

@ -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<node_id, ast_node>;
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::<ast_node>();
let cx = @{map: new_smallintmap_int_adapter::<ast_node>(),
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<int, V> {