Skip to content

Commit 2c0f4d5

Browse files
committed
Change the way freevars stores its information again.
1 parent 5068ae4 commit 2c0f4d5

File tree

3 files changed

+37
-46
lines changed

3 files changed

+37
-46
lines changed

src/comp/middle/freevars.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,19 @@ export freevar_set;
1818
export freevar_map;
1919
export get_freevar_info;
2020
export get_freevars;
21-
export get_freevar_uses;
21+
export get_freevar_refs;
2222
export has_freevars;
2323
export is_freevar_of;
2424
export def_lookup;
2525

26+
// Throughout the compiler, variables are generally dealt with using the
27+
// node_ids of the reference sites and not the def_id of the definition
28+
// site. Thus we store a set are the definitions along with a vec of one
29+
// referencing node_id per free variable. The set is useful for testing
30+
// membership, the list of referencing sites is what you want for most
31+
// other things.
2632
type freevar_set = hashset[ast::node_id];
27-
type freevar_info = {defs: freevar_set, uses: @ast::node_id[]};
33+
type freevar_info = {defs: freevar_set, refs: @ast::node_id[]};
2834
type freevar_map = hashmap[ast::node_id, freevar_info];
2935

3036
// Searches through part of the AST for all references to locals or
@@ -83,17 +89,17 @@ fn collect_freevars(def_map: &resolve::def_map, sess: &session::session,
8389
// Calculate (refs - decls). This is the set of captured upvars.
8490
// We build a vec of the node ids of the uses and a set of the
8591
// node ids of the definitions.
86-
let uses = ~[];
92+
let refs = ~[];
8793
let defs = new_int_hash();
8894
for ref_id_: ast::node_id in e.refs {
8995
let ref_id = ref_id_;
9096
let def_id = ast::def_id_of_def(def_map.get(ref_id)).node;
91-
if !decls.contains_key(def_id) {
92-
uses += ~[ref_id];
97+
if !decls.contains_key(def_id) && !defs.contains_key(def_id) {
98+
refs += ~[ref_id];
9399
set_add(defs, def_id);
94100
}
95101
}
96-
ret {defs: defs, uses: @uses};
102+
ret {defs: defs, refs: @refs};
97103
}
98104

99105
// Build a map from every function and for-each body to a set of the
@@ -150,17 +156,17 @@ fn get_freevar_info(tcx: &ty::ctxt, fid: ast::node_id) -> freevar_info {
150156
some(d) { ret d; }
151157
}
152158
}
153-
fn get_freevars(tcx: &ty::ctxt, fid: ast::node_id) -> freevar_set {
159+
fn get_freevar_refs(tcx: &ty::ctxt, fid: ast::node_id) -> freevar_set {
154160
ret get_freevar_info(tcx, fid).defs;
155161
}
156-
fn get_freevar_uses(tcx: &ty::ctxt, fid: ast::node_id) -> @ast::node_id[] {
157-
ret get_freevar_info(tcx, fid).uses;
162+
fn get_freevars(tcx: &ty::ctxt, fid: ast::node_id) -> @ast::node_id[] {
163+
ret get_freevar_info(tcx, fid).refs;
158164
}
159165
fn has_freevars(tcx: &ty::ctxt, fid: ast::node_id) -> bool {
160-
ret get_freevars(tcx, fid).size() != 0u;
166+
ret get_freevar_refs(tcx, fid).size() != 0u;
161167
}
162-
fn is_freevar_of(tcx: &ty::ctxt, var: ast::node_id, f: ast::node_id) -> bool {
163-
ret get_freevars(tcx, f).contains_key(var);
168+
fn is_freevar_of(tcx: &ty::ctxt, def: ast::node_id, f: ast::node_id) -> bool {
169+
ret get_freevar_refs(tcx, f).contains_key(def);
164170
}
165171
fn def_lookup(tcx: &ty::ctxt, f: ast::node_id, id: ast::node_id) ->
166172
option::t[ast::def] {

src/comp/middle/trans.rs

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3677,30 +3677,6 @@ fn trans_for(cx: &@block_ctxt, local: &@ast::local, seq: &@ast::expr,
36773677

36783678
// Iterator translation
36793679

3680-
// Finds the ValueRef associated with a variable in a function
3681-
// context. It checks locals, upvars, and args.
3682-
fn find_variable(cx: &@block_ctxt, nid: ast::node_id) -> lval_result {
3683-
let fcx = cx.fcx;
3684-
let llval = alt fcx.lllocals.find(nid) {
3685-
none. {
3686-
alt fcx.llupvars.find(nid) {
3687-
none. {
3688-
alt fcx.llargs.find(nid) {
3689-
some(llval) { llval }
3690-
_ {
3691-
fcx.lcx.ccx.sess.bug("unbound var in build_environment "
3692-
+ int::str(nid))
3693-
}
3694-
}
3695-
}
3696-
some(llval) { llval }
3697-
}
3698-
}
3699-
some(llval) { llval }
3700-
};
3701-
ret lval_mem(cx, llval);
3702-
}
3703-
37043680
// build_environment_heap and build_environment are very similar. It
37053681
// would be nice to unify them.
37063682

@@ -3781,21 +3757,21 @@ fn build_environment_heap(bcx: @block_ctxt, lltydescs: ValueRef[],
37813757
// Given a block context and a list of upvars, construct a closure that
37823758
// contains pointers to all of the upvars and all of the tydescs in
37833759
// scope. Return the ValueRef and TypeRef corresponding to the closure.
3784-
fn build_environment(cx: &@block_ctxt, upvars: &freevar_set) ->
3760+
fn build_environment(cx: &@block_ctxt, upvars: &@ast::node_id[]) ->
37853761
{ptr: ValueRef, ptrty: TypeRef} {
37863762
let has_iterbody = !option::is_none(cx.fcx.lliterbody);
37873763
let llbindingsptr;
37883764

3789-
if upvars.size() > 0u || has_iterbody {
3765+
if std::ivec::len(*upvars) > 0u || has_iterbody {
37903766
// Gather up the upvars.
37913767
let llbindings: ValueRef[] = ~[];
37923768
let llbindingtys: TypeRef[] = ~[];
37933769
if has_iterbody {
37943770
llbindings += ~[option::get(cx.fcx.lliterbody)];
37953771
llbindingtys += ~[val_ty(llbindings.(0))];
37963772
}
3797-
for each nid: ast::node_id in upvars.keys() {
3798-
let llbinding = find_variable(cx, nid).res.val;
3773+
for nid: ast::node_id in *upvars {
3774+
let llbinding = trans_var(cx, cx.sp, nid).res.val;
37993775
llbindings += ~[llbinding];
38003776
llbindingtys += ~[val_ty(llbinding)];
38013777
}
@@ -3847,7 +3823,7 @@ fn build_environment(cx: &@block_ctxt, upvars: &freevar_set) ->
38473823
// and a list of upvars, generate code to load and populate the environment
38483824
// with the upvars and type descriptors.
38493825
fn load_environment(cx: &@block_ctxt, fcx: &@fn_ctxt, llenvptrty: TypeRef,
3850-
upvars: &freevar_set) {
3826+
upvars: &@ast::node_id[]) {
38513827
let copy_args_bcx = new_raw_block_ctxt(fcx, fcx.llcopyargs);
38523828

38533829
// Populate the upvars from the environment.
@@ -3869,12 +3845,13 @@ fn load_environment(cx: &@block_ctxt, fcx: &@fn_ctxt, llenvptrty: TypeRef,
38693845
let lliterbody = copy_args_bcx.build.Load(lliterbodyptr);
38703846
fcx.lliterbody = some(lliterbody);
38713847
}
3872-
for each upvar_id: ast::node_id in upvars.keys() {
3848+
for upvar_id: ast::node_id in *upvars {
38733849
let llupvarptrptr =
38743850
copy_args_bcx.build.GEP(llremotebindingsptr,
38753851
~[C_int(0), C_int(i as int)]);
38763852
let llupvarptr = copy_args_bcx.build.Load(llupvarptrptr);
3877-
fcx.llupvars.insert(upvar_id, llupvarptr);
3853+
let def_id = ast::def_id_of_def(bcx_tcx(cx).def_map.get(upvar_id));
3854+
fcx.llupvars.insert(def_id.node, llupvarptr);
38783855
i += 1u;
38793856
}
38803857

@@ -4092,9 +4069,12 @@ fn lookup_discriminant(lcx: &@local_ctxt, tid: &ast::def_id,
40924069
}
40934070
}
40944071

4095-
fn trans_path(cx: &@block_ctxt, p: &ast::path, id: ast::node_id) ->
4072+
fn trans_var(cx: &@block_ctxt, sp: &span, id: ast::node_id) ->
40964073
lval_result {
40974074
let ccx = bcx_ccx(cx);
4075+
// If we had a good way to get at the node_id for the function we
4076+
// are in, we could do a freevars::def_lookup and avoid having to
4077+
// check the llupvars case in all of the other cases...
40984078
alt bcx_tcx(cx).def_map.find(id) {
40994079
some(ast::def_arg(did)) {
41004080
alt cx.fcx.llargs.find(did.node) {
@@ -4144,7 +4124,7 @@ fn trans_path(cx: &@block_ctxt, p: &ast::path, id: ast::node_id) ->
41444124
let tag_ty = node_id_type(ccx, id);
41454125
let alloc_result = alloc_ty(cx, tag_ty);
41464126
let lltagblob = alloc_result.val;
4147-
let lltagty = type_of_tag(ccx, p.span, tid, tag_ty);
4127+
let lltagty = type_of_tag(ccx, sp, tid, tag_ty);
41484128
let bcx = alloc_result.bcx;
41494129
let lltagptr = bcx.build.PointerCast(lltagblob, T_ptr(lltagty));
41504130
if std::ivec::len(ty::tag_variants(ccx.tcx, tid)) != 1u {
@@ -4180,6 +4160,11 @@ fn trans_path(cx: &@block_ctxt, p: &ast::path, id: ast::node_id) ->
41804160
}
41814161
}
41824162

4163+
fn trans_path(cx: &@block_ctxt, p: &ast::path, id: ast::node_id) ->
4164+
lval_result {
4165+
ret trans_var(cx, p.span, id);
4166+
}
4167+
41834168
fn trans_field(cx: &@block_ctxt, sp: &span, v: ValueRef, t0: &ty::t,
41844169
field: &ast::ident, id: ast::node_id) -> lval_result {
41854170
let r = autoderef(cx, v, t0);

src/comp/middle/tstate/pre_post_conditions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ fn find_pre_post_expr(fcx: &fn_ctxt, e: @expr) {
371371
expr_fn(f) {
372372
let rslt = expr_pp(fcx.ccx, e);
373373
clear_pp(rslt);
374-
let upvars = freevars::get_freevar_uses(fcx.ccx.tcx, e.id);
374+
let upvars = freevars::get_freevars(fcx.ccx.tcx, e.id);
375375
for id: node_id in *upvars { handle_var(fcx, rslt, id, "upvar"); }
376376
}
377377
expr_block(b) {

0 commit comments

Comments
 (0)