Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/comp/metadata/tydecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,11 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
ret ty::mk_fn(st.tcx, ast::proto_iter, func._0, func._1, func._2,
func._3);
}
case ('B') {
auto func = parse_ty_fn(st, sd);
ret ty::mk_fn(st.tcx, ast::proto_block, func._0, func._1, func._2,
func._3);
}
case ('N') {
auto abi;
alt (next(st) as char) {
Expand Down
1 change: 1 addition & 0 deletions src/comp/metadata/tyencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ fn enc_proto(&ioivec::writer w, proto proto) {
alt (proto) {
case (proto_iter) { w.write_char('W'); }
case (proto_fn) { w.write_char('F'); }
case (proto_block) { w.write_char('B'); }
}
}

Expand Down
18 changes: 10 additions & 8 deletions src/comp/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export def_map;
tag scope {
scope_crate;
scope_item(@ast::item);
scope_fn(ast::fn_decl, ast::ty_param[]);
scope_fn(ast::fn_decl, ast::proto, ast::ty_param[]);
scope_native_item(@ast::native_item);
scope_loop(@ast::local); // there's only 1 decl per loop.
scope_block(ast::blk);
Expand Down Expand Up @@ -358,7 +358,7 @@ fn visit_fn_with_scope(&@env e, &ast::_fn f, &ast::ty_param[] tp, &span sp,
resolve_constr(e, id, c, sc, v);
}
visit::visit_fn(f, tp, sp, name, id,
cons(scope_fn(f.decl, tp), @sc), v);
cons(scope_fn(f.decl, f.proto, tp), @sc), v);
}

fn visit_block_with_scope(&ast::blk b, &scopes sc, &vt[scopes] v) {
Expand All @@ -375,7 +375,7 @@ fn visit_expr_with_scope(&@ast::expr x, &scopes sc, &vt[scopes] v) {
ast::expr_for(?d, _, _) | ast::expr_for_each(?d, _, _) {
cons[scope](scope_loop(d), @sc)
}
ast::expr_fn(?f) { cons(scope_fn(f.decl, ~[]), @sc) }
ast::expr_fn(?f) { cons(scope_fn(f.decl, f.proto, ~[]), @sc) }
_ { sc }
};
visit::visit_expr(x, new_sc, v);
Expand Down Expand Up @@ -530,7 +530,7 @@ fn unresolved_err(&env e, &scopes sc, &span sp, &ident name, &str kind) {
alt sc {
cons(?cur, ?rest) {
alt cur {
scope_crate | scope_fn(_, _) |
scope_crate | scope_fn(_, _, _) |
scope_item(@{node: ast::item_mod(_), _}) {
ret cur;
}
Expand Down Expand Up @@ -596,9 +596,11 @@ fn lookup_in_scope_strict(&env e, scopes sc, &span sp, &ident name,

fn scope_is_fn(&scope sc) -> bool {
ret alt (sc) {
scope_fn(_, _) | scope_native_item(_) { true }
_ { false }
};
scope_fn(_, ast::proto_iter, _) |
scope_fn(_, ast::proto_fn, _) |
scope_native_item(_) { true }
_ { false }
};
}

fn def_is_local(&def d) -> bool {
Expand Down Expand Up @@ -657,7 +659,7 @@ fn lookup_in_scope(&env e, scopes sc, &span sp, &ident name, namespace ns) ->
}
}
}
case (scope_fn(?decl, ?ty_params)) {
case (scope_fn(?decl, _, ?ty_params)) {
ret lookup_in_fn(name, decl, ty_params, ns);
}
case (scope_loop(?local)) {
Expand Down
58 changes: 50 additions & 8 deletions src/comp/middle/trans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5358,8 +5358,14 @@ fn trans_expr_out(&@block_ctxt cx, &@ast::expr e, out_method output) ->
auto sub_cx = extend_path(cx.fcx.lcx, ccx.names.next("anon"));
auto s = mangle_internal_name_by_path(ccx, sub_cx.path);
auto llfn = decl_internal_fastcall_fn(ccx.llmod, s, llfnty);
trans_fn(sub_cx, e.span, f, llfn, none, ~[], e.id);
ret rslt(cx, create_fn_pair(ccx, s, llfnty, llfn, false));

auto fn_res = trans_closure(some(cx), some(llfnty), sub_cx,
e.span, f, llfn, none, ~[], e.id);
auto fn_pair = alt (fn_res) {
some(?fn_pair) { fn_pair }
none { create_fn_pair(ccx, s, llfnty, llfn, false) }
};
ret rslt(cx, fn_pair);
}
case (ast::expr_block(?blk)) {
auto sub_cx = new_scope_block_ctxt(cx, "block-expr body");
Expand Down Expand Up @@ -6651,10 +6657,16 @@ fn finish_fn(&@fn_ctxt fcx, BasicBlockRef lltop) {
new_builder(fcx.lldynamicallocas).Br(lltop);
}


fn trans_fn_inner(@local_ctxt cx, &span sp, &ast::_fn f, ValueRef llfndecl,
option::t[ty::t] ty_self, &ast::ty_param[] ty_params,
ast::node_id id) {
// trans_closure: Builds an LLVM function out of a source function.
// If the function closes over its environment a closure will be
// returned.
fn trans_closure(&option::t[@block_ctxt] bcx_maybe,
&option::t[TypeRef] llfnty,
@local_ctxt cx,
&span sp, &ast::_fn f, ValueRef llfndecl,
option::t[ty::t] ty_self,
&ast::ty_param[] ty_params, ast::node_id id)
-> option::t[ValueRef] {
set_uwtable(llfndecl);

// Set up arguments to the function.
Expand All @@ -6664,12 +6676,34 @@ fn trans_fn_inner(@local_ctxt cx, &span sp, &ast::_fn f, ValueRef llfndecl,
f.decl.inputs, ty_params);
copy_any_self_to_alloca(fcx);
alt ({ fcx.llself }) {
case (some(?llself)) { populate_fn_ctxt_from_llself(fcx, llself); }
case (_) { }
some(?llself) { populate_fn_ctxt_from_llself(fcx, llself); }
_ { }
}
auto arg_tys = arg_tys_of_fn(fcx.lcx.ccx, id);
copy_args_to_allocas(fcx, f.decl.inputs, arg_tys);

// Figure out if we need to build a closure and act accordingly
auto closure = none;
alt(f.proto) {
ast::proto_block {
auto bcx = option::get(bcx_maybe);
auto upvars = get_freevars(cx.ccx.tcx, id);

auto llenv = build_environment(bcx, upvars);

// Generate code to load the environment out of the
// environment pointer.
load_environment(bcx, fcx, llenv.ptrty, upvars);
// Build the closure.
closure = some(create_real_fn_pair(bcx, option::get(llfnty),
llfndecl, llenv.ptr));
}
ast::proto_closure {
fail "copy capture not implemented yet";
}
_ {}
}

// Create the first basic block in the function and keep a handle on it to
// pass to finish_fn later.
auto bcx = new_top_block_ctxt(fcx);
Expand Down Expand Up @@ -6702,6 +6736,14 @@ fn trans_fn_inner(@local_ctxt cx, &span sp, &ast::_fn f, ValueRef llfndecl,

// Insert the mandatory first few basic blocks before lltop.
finish_fn(fcx, lltop);

ret closure;
}

fn trans_fn_inner(@local_ctxt cx, &span sp, &ast::_fn f, ValueRef llfndecl,
option::t[ty::t] ty_self, &ast::ty_param[] ty_params,
ast::node_id id) {
trans_closure(none, none, cx, sp, f, llfndecl, ty_self, ty_params, id);
}


Expand Down
9 changes: 9 additions & 0 deletions src/comp/middle/tstate/auxiliary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,15 @@ fn constraints_expr(&ty::ctxt cx, @expr e) -> (@ty::constr)[] {
}
}

fn node_id_to_def_upvar_strict(&fn_ctxt cx, node_id id) -> def {
alt (freevars::def_lookup(cx.ccx.tcx, cx.id, id)) {
case (none) {
log_err "node_id_to_def: node_id " + int::str(id) + " has no def";
fail;
}
case (some(?d)) { ret d; }
}
}
fn node_id_to_def_strict(&ty::ctxt cx, node_id id) -> def {
alt (cx.def_map.find(id)) {
case (none) {
Expand Down
33 changes: 21 additions & 12 deletions src/comp/middle/tstate/pre_post_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,18 @@ fn handle_update(&fn_ctxt fcx, &@expr parent,
}
}

fn handle_var(&fn_ctxt fcx, &pre_and_post rslt, node_id id, ident name) {
auto df = node_id_to_def_upvar_strict(fcx, id);
alt (df) {
case (def_local(?d_id)) {
auto i = bit_num(fcx, ninit(d_id._1, name));
use_var(fcx, d_id._1);
require_and_preserve(i, rslt);
}
case (_) {/* nothing to check */ }
}
}

/* Fills in annotations as a side effect. Does not rebuild the expr */
fn find_pre_post_expr(&fn_ctxt fcx, @expr e) {
auto enclosing = fcx.enclosing;
Expand Down Expand Up @@ -338,17 +350,7 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) {
case (expr_path(?p)) {
auto rslt = expr_pp(fcx.ccx, e);
clear_pp(rslt);
auto df = node_id_to_def_strict(fcx.ccx.tcx, e.id);
alt (df) {
case (def_local(?d_id)) {
auto i =
bit_num(fcx,
ninit(d_id._1, path_to_ident(fcx.ccx.tcx, p)));
use_var(fcx, d_id._1);
require_and_preserve(i, rslt);
}
case (_) {/* nothing to check */ }
}
handle_var(fcx, rslt, e.id, path_to_ident(fcx.ccx.tcx, p));
}
case (expr_self_method(?v)) { clear_pp(expr_pp(fcx.ccx, e)); }
case (expr_log(_, ?arg)) {
Expand All @@ -368,7 +370,14 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) {
case (none) { clear_pp(expr_pp(fcx.ccx, e)); }
}
}
case (expr_fn(?f)) { clear_pp(expr_pp(fcx.ccx, e)); }
case (expr_fn(?f)) {
auto rslt = expr_pp(fcx.ccx, e);
clear_pp(rslt);
auto upvars = freevars::get_freevar_uses(fcx.ccx.tcx, e.id);
for (node_id id in *upvars) {
handle_var(fcx, rslt, id, "upvar");
}
}
case (expr_block(?b)) {
find_pre_post_block(fcx, b);
auto p = block_pp(fcx.ccx, b);
Expand Down
2 changes: 1 addition & 1 deletion src/comp/middle/tstate/states.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ fn find_pre_post_state_loop(&fn_ctxt fcx, prestate pres, &@local l,
fn gen_if_local(&fn_ctxt fcx, &poststate p, &@expr e) -> bool {
alt (e.node) {
case (expr_path(?pth)) {
alt (node_id_to_def(fcx.ccx, e.id)) {
alt (freevars::def_lookup(fcx.ccx.tcx, fcx.id, e.id)) {
case (some(def_local(?loc))) {
ret set_in_poststate_ident(fcx, loc._1,
path_to_ident(fcx.ccx.tcx, pth), p);
Expand Down
1 change: 1 addition & 0 deletions src/comp/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,7 @@ fn type_is_structural(&ctxt cx, &t ty) -> bool {
fn type_is_copyable(&ctxt cx, &t ty) -> bool {
ret alt (struct(cx, ty)) {
case (ty_res(_, _, _)) { false }
case (ty_fn(proto_block, _, _, _, _)) { false }
case (_) { true }
};
}
Expand Down
Loading