Skip to content

Commit 95dd9f3

Browse files
committed
Get rid of a lot of bind related cruft as part of Issue #2189.
1 parent 40fc173 commit 95dd9f3

File tree

3 files changed

+41
-290
lines changed

3 files changed

+41
-290
lines changed

src/rustc/middle/trans/base.rs

+14-22
Original file line numberDiff line numberDiff line change
@@ -2660,7 +2660,7 @@ fn trans_lval(cx: block, e: @ast::expr) -> lval_result {
26602660
alt e.node {
26612661
ast::expr_path(_) {
26622662
let v = trans_path(cx, e.id);
2663-
ret lval_maybe_callee_to_lval(v, expr_ty(cx, e));
2663+
ret lval_maybe_callee_to_lval(v, e.span);
26642664
}
26652665
ast::expr_field(base, ident, _) {
26662666
ret trans_rec_field(cx, base, ident);
@@ -2711,26 +2711,18 @@ fn non_gc_box_cast(cx: block, val: ValueRef) -> ValueRef {
27112711
PointerCast(cx, val, non_gc_t)
27122712
}
27132713

2714-
fn lval_maybe_callee_to_lval(c: lval_maybe_callee, ty: ty::t) -> lval_result {
2715-
let must_bind = alt c.env { self_env(_, _, _) { true } _ { false } };
2716-
if must_bind {
2717-
let n_args = ty::ty_fn_args(ty).len();
2718-
let args = vec::from_elem(n_args, none);
2719-
let space = alloc_ty(c.bcx, ty);
2720-
let bcx = closure::trans_bind_1(c.bcx, ty, c, args, ty,
2721-
save_in(space));
2722-
add_clean_temp(bcx, space, ty);
2723-
{bcx: bcx, val: space, kind: temporary}
2724-
} else {
2725-
alt check c.env {
2726-
is_closure { {bcx: c.bcx, val: c.val, kind: c.kind} }
2727-
null_env {
2728-
let llfnty = llvm::LLVMGetElementType(val_ty(c.val));
2729-
let llfn = create_real_fn_pair(c.bcx, llfnty, c.val,
2730-
null_env_ptr(c.bcx));
2731-
{bcx: c.bcx, val: llfn, kind: temporary}
2732-
}
2733-
}
2714+
fn lval_maybe_callee_to_lval(c: lval_maybe_callee, sp: span) -> lval_result {
2715+
alt c.env {
2716+
self_env(*) {
2717+
c.bcx.sess().span_bug(sp, "implicitly binding method call");
2718+
}
2719+
is_closure { {bcx: c.bcx, val: c.val, kind: c.kind} }
2720+
null_env {
2721+
let llfnty = llvm::LLVMGetElementType(val_ty(c.val));
2722+
let llfn = create_real_fn_pair(c.bcx, llfnty, c.val,
2723+
null_env_ptr(c.bcx));
2724+
{bcx: c.bcx, val: llfn, kind: temporary}
2725+
}
27342726
}
27352727
}
27362728

@@ -3605,7 +3597,7 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
36053597
ast::expr_field(base, _, _) {
36063598
if dest == ignore { ret trans_expr(bcx, base, ignore); }
36073599
let callee = trans_callee(bcx, e), ty = expr_ty(bcx, e);
3608-
let lv = lval_maybe_callee_to_lval(callee, ty);
3600+
let lv = lval_maybe_callee_to_lval(callee, e.span);
36093601
revoke_clean(lv.bcx, lv.val);
36103602
memmove_ty(lv.bcx, get_dest_addr(dest), lv.val, ty);
36113603
ret lv.bcx;

src/rustc/middle/trans/closure.rs

+3-238
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,6 @@ import dvec::extensions;
9090
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9191

9292
enum environment_value {
93-
// Evaluate expr and store result in env (used for bind).
94-
env_expr(@ast::expr, ty::t),
95-
9693
// Copy the value from this llvm ValueRef into the environment.
9794
env_copy(ValueRef, ty::t, lval_kind),
9895

@@ -105,7 +102,6 @@ enum environment_value {
105102

106103
fn ev_to_str(ccx: @crate_ctxt, ev: environment_value) -> str {
107104
alt ev {
108-
env_expr(ex, _) { expr_to_str(ex) }
109105
env_copy(v, t, lk) { #fmt("copy(%s,%s)", val_str(ccx.tn, v),
110106
ty_to_str(ccx.tcx, t)) }
111107
env_move(v, t, lk) { #fmt("move(%s,%s)", val_str(ccx.tn, v),
@@ -123,7 +119,7 @@ fn mk_tuplified_uniq_cbox_ty(tcx: ty::ctxt, cdata_ty: ty::t) -> ty::t {
123119
// Given a closure ty, emits a corresponding tuple ty
124120
fn mk_closure_tys(tcx: ty::ctxt,
125121
bound_values: ~[environment_value])
126-
-> (ty::t, ~[ty::t]) {
122+
-> ty::t {
127123
let mut bound_tys = ~[];
128124

129125
// Compute the closed over data
@@ -132,15 +128,14 @@ fn mk_closure_tys(tcx: ty::ctxt,
132128
env_copy(_, t, _) { t }
133129
env_move(_, t, _) { t }
134130
env_ref(_, t, _) { t }
135-
env_expr(_, t) { t }
136131
});
137132
}
138133
let bound_data_ty = ty::mk_tup(tcx, bound_tys);
139134
// FIXME[mono] remove tuple of tydescs from closure types (#2531)
140135
let cdata_ty = ty::mk_tup(tcx, ~[ty::mk_tup(tcx, ~[]),
141136
bound_data_ty]);
142137
#debug["cdata_ty=%s", ty_to_str(tcx, cdata_ty)];
143-
ret (cdata_ty, bound_tys);
138+
ret cdata_ty;
144139
}
145140

146141
fn allocate_cbox(bcx: block,
@@ -196,8 +191,7 @@ fn store_environment(bcx: block,
196191
let ccx = bcx.ccx(), tcx = ccx.tcx;
197192

198193
// compute the shape of the closure
199-
let (cdata_ty, bound_tys) =
200-
mk_closure_tys(tcx, bound_values);
194+
let cdata_ty = mk_closure_tys(tcx, bound_values);
201195

202196
// allocate closure in the heap
203197
let llbox = allocate_cbox(bcx, ck, cdata_ty);
@@ -225,11 +219,6 @@ fn store_environment(bcx: block,
225219
let bound_data = GEPi(bcx, llbox,
226220
~[0u, abi::box_field_body, abi::closure_body_bindings, i]);
227221
alt bv {
228-
env_expr(e, _) {
229-
bcx = base::trans_expr_save_in(bcx, e, bound_data);
230-
add_clean_temp_mem(bcx, bound_data, bound_tys[i]);
231-
vec::push(temp_cleanups, bound_data);
232-
}
233222
env_copy(val, ty, owned) {
234223
let val1 = load_if_immediate(bcx, val, ty);
235224
bcx = base::copy_val(bcx, INIT, bound_data, val1, ty);
@@ -415,70 +404,6 @@ fn trans_expr_fn(bcx: block,
415404
ret bcx;
416405
}
417406

418-
fn trans_bind_1(cx: block, outgoing_fty: ty::t,
419-
f_res: lval_maybe_callee,
420-
args: ~[option<@ast::expr>], pair_ty: ty::t,
421-
dest: dest) -> block {
422-
let _icx = cx.insn_ctxt("closure::trans_bind1");
423-
let ccx = cx.ccx();
424-
let mut bound: ~[@ast::expr] = ~[];
425-
for vec::each(args) |argopt| {
426-
alt argopt { none { } some(e) { vec::push(bound, e); } }
427-
}
428-
let mut bcx = f_res.bcx;
429-
if dest == ignore {
430-
for vec::each(bound) |ex| { bcx = trans_expr(bcx, ex, ignore); }
431-
ret bcx;
432-
}
433-
434-
if bound.len() == 0u &&
435-
(f_res.env == null_env || f_res.env == is_closure) {
436-
// Trivial 'binding': just return the closure
437-
let lv = lval_maybe_callee_to_lval(f_res, pair_ty);
438-
memmove_ty(lv.bcx, get_dest_addr(dest), lv.val, pair_ty);
439-
ret lv.bcx;
440-
}
441-
442-
// Arrange for the bound function to live in the first binding spot
443-
// if the function is not statically known.
444-
let (env_vals, target_info) = alt f_res.env {
445-
null_env { (~[], target_static(f_res.val)) }
446-
is_closure {
447-
// Cast the function we are binding to be the type that the
448-
// closure will expect it to have. The type the closure knows
449-
// about has the type parameters substituted with the real types.
450-
let llclosurety = T_ptr(type_of(ccx, outgoing_fty));
451-
let src_loc = PointerCast(bcx, f_res.val, llclosurety);
452-
(~[env_copy(src_loc, pair_ty, owned)], target_closure)
453-
}
454-
self_env(slf, slf_t, none) {
455-
(~[env_copy(slf, slf_t, owned)], target_static_self(f_res.val))
456-
}
457-
self_env(_, slf_t, some(slf)) {
458-
let cast = PointerCast(bcx, f_res.val, T_ptr(T_nil()));
459-
(~[env_copy(cast, ty::mk_nil_ptr(ccx.tcx), owned_imm),
460-
env_copy(slf, slf_t, owned_imm)], target_self)
461-
}
462-
};
463-
464-
// Actually construct the closure
465-
let {llbox, cdata_ty, bcx} = store_environment(
466-
bcx, vec::append(env_vals,
467-
vec::map(bound, |x| {
468-
env_expr(x, expr_ty(bcx, x))
469-
})),
470-
ty::ck_box);
471-
472-
// Make thunk
473-
let llthunk = trans_bind_thunk(
474-
cx.fcx.ccx, cx.fcx.path, pair_ty, outgoing_fty, args,
475-
cdata_ty, target_info);
476-
477-
// Fill the function pair
478-
fill_fn_pair(bcx, get_dest_addr(dest), llthunk.val, llbox);
479-
ret bcx;
480-
}
481-
482407
fn make_fn_glue(
483408
cx: block,
484409
v: ValueRef,
@@ -611,163 +536,3 @@ fn make_opaque_cbox_free_glue(
611536
}
612537
}
613538
}
614-
615-
enum target_info {
616-
target_closure,
617-
target_static(ValueRef),
618-
target_self,
619-
target_static_self(ValueRef),
620-
}
621-
622-
// pth is cx.path
623-
fn trans_bind_thunk(ccx: @crate_ctxt,
624-
path: path,
625-
incoming_fty: ty::t,
626-
outgoing_fty: ty::t,
627-
args: ~[option<@ast::expr>],
628-
cdata_ty: ty::t,
629-
target_info: target_info)
630-
-> {val: ValueRef, ty: TypeRef} {
631-
let _icx = ccx.insn_ctxt("closure::trans_bind_thunk");
632-
let tcx = ccx.tcx;
633-
#debug["trans_bind_thunk[incoming_fty=%s,outgoing_fty=%s,\
634-
cdata_ty=%s]/~",
635-
ty_to_str(tcx, incoming_fty),
636-
ty_to_str(tcx, outgoing_fty),
637-
ty_to_str(tcx, cdata_ty)];
638-
639-
// Here we're not necessarily constructing a thunk in the sense of
640-
// "function with no arguments". The result of compiling 'bind f(foo,
641-
// bar, baz)' would be a thunk that, when called, applies f to those
642-
// arguments and returns the result. But we're stretching the meaning of
643-
// the word "thunk" here to also mean the result of compiling, say, 'bind
644-
// f(foo, _, baz)', or any other bind expression that binds f and leaves
645-
// some (or all) of the arguments unbound.
646-
647-
// Here, 'incoming_fty' is the type of the entire bind expression, while
648-
// 'outgoing_fty' is the type of the function that is having some of its
649-
// arguments bound. If f is a function that takes three arguments of type
650-
// int and returns int, and we're translating, say, 'bind f(3, _, 5)',
651-
// then outgoing_fty is the type of f, which is (int, int, int) -> int,
652-
// and incoming_fty is the type of 'bind f(3, _, 5)', which is int -> int.
653-
654-
// Once translated, the entire bind expression will be the call f(foo,
655-
// bar, baz) wrapped in a (so-called) thunk that takes 'bar' as its
656-
// argument and that has bindings of 'foo' to 3 and 'baz' to 5 and a
657-
// pointer to 'f' all saved in its environment. So, our job is to
658-
// construct and return that thunk.
659-
660-
// Give the thunk a name, type, and value.
661-
let s = mangle_internal_name_by_path_and_seq(ccx, path, @"thunk");
662-
let llthunk_ty = get_pair_fn_ty(type_of(ccx, incoming_fty));
663-
let llthunk = decl_internal_cdecl_fn(ccx.llmod, s, llthunk_ty);
664-
665-
// Create a new function context and block context for the thunk, and hold
666-
// onto a pointer to the first block in the function for later use.
667-
let fcx = new_fn_ctxt(ccx, path, llthunk, none);
668-
let mut bcx = top_scope_block(fcx, none);
669-
let lltop = bcx.llbb;
670-
// Since we might need to construct derived tydescs that depend on
671-
// our bound tydescs, we need to load tydescs out of the environment
672-
// before derived tydescs are constructed. To do this, we load them
673-
// in the load_env block.
674-
let l_bcx = raw_block(fcx, fcx.llloadenv);
675-
676-
// The 'llenv' that will arrive in the thunk we're creating is an
677-
// environment that will contain the values of its arguments and a
678-
// pointer to the original function. This environment is always
679-
// stored like an opaque box (see big comment at the header of the
680-
// file), so we load the body body, which contains the type descr
681-
// and cached data.
682-
let llcdata = base::opaque_box_body(l_bcx, cdata_ty, fcx.llenv);
683-
684-
// "target", in this context, means the function that's having some of its
685-
// arguments bound and that will be called inside the thunk we're
686-
// creating. (In our running example, target is the function f.) Pick
687-
// out the pointer to the target function from the environment. The
688-
// target function lives in the first binding spot.
689-
let (lltargetfn, lltargetenv, starting_idx) = alt target_info {
690-
target_static(fptr) {
691-
(fptr, llvm::LLVMGetUndef(T_opaque_cbox_ptr(ccx)), 0u)
692-
}
693-
target_closure {
694-
let pair = GEPi(bcx, llcdata, ~[0u, abi::closure_body_bindings, 0u]);
695-
let lltargetenv =
696-
Load(bcx, GEPi(bcx, pair, ~[0u, abi::fn_field_box]));
697-
let lltargetfn = Load
698-
(bcx, GEPi(bcx, pair, ~[0u, abi::fn_field_code]));
699-
(lltargetfn, lltargetenv, 1u)
700-
}
701-
target_self {
702-
let fptr = Load(bcx, GEPi(bcx, llcdata,
703-
~[0u, abi::closure_body_bindings, 0u]));
704-
let slfbox =
705-
GEPi(bcx, llcdata, ~[0u, abi::closure_body_bindings, 1u]);
706-
let selfptr =
707-
GEPi(bcx, Load(bcx, slfbox), ~[0u, abi::box_field_body]);
708-
(fptr, PointerCast(bcx, selfptr, T_opaque_cbox_ptr(ccx)), 2u)
709-
}
710-
target_static_self(fptr) {
711-
let slfptr =
712-
GEPi(bcx, llcdata, ~[0u, abi::closure_body_bindings, 0u]);
713-
(fptr, PointerCast(bcx, slfptr, T_opaque_cbox_ptr(ccx)), 1u)
714-
}
715-
};
716-
717-
// And then, pick out the target function's own environment. That's what
718-
// we'll use as the environment the thunk gets.
719-
720-
// Get the types of the arguments to f.
721-
let outgoing_args = ty::ty_fn_args(outgoing_fty);
722-
723-
// Set up the three implicit arguments to the thunk.
724-
let mut llargs: ~[ValueRef] = ~[fcx.llretptr, lltargetenv];
725-
726-
let mut a: uint = first_real_arg; // retptr, env come first
727-
let mut b: uint = starting_idx;
728-
let mut outgoing_arg_index: uint = 0u;
729-
for vec::each(args) |arg| {
730-
let out_arg = outgoing_args[outgoing_arg_index];
731-
alt arg {
732-
// Arg provided at binding time; thunk copies it from
733-
// closure.
734-
some(e) {
735-
let mut val =
736-
GEPi(bcx, llcdata, ~[0u, abi::closure_body_bindings, b]);
737-
738-
alt ty::resolved_mode(tcx, out_arg.mode) {
739-
ast::by_val {
740-
val = Load(bcx, val);
741-
}
742-
ast::by_copy {
743-
let alloc = alloc_ty(bcx, out_arg.ty);
744-
memmove_ty(bcx, alloc, val, out_arg.ty);
745-
bcx = take_ty(bcx, alloc, out_arg.ty);
746-
val = alloc;
747-
}
748-
ast::by_ref | ast::by_mutbl_ref | ast::by_move { }
749-
}
750-
vec::push(llargs, val);
751-
b += 1u;
752-
}
753-
754-
// Arg will be provided when the thunk is invoked.
755-
none {
756-
vec::push(llargs, llvm::LLVMGetParam(llthunk, a as c_uint));
757-
a += 1u;
758-
}
759-
}
760-
outgoing_arg_index += 1u;
761-
}
762-
763-
// Cast the outgoing function to the appropriate type.
764-
// This is necessary because the type of the function that we have
765-
// in the closure does not know how many type descriptors the function
766-
// needs to take.
767-
let lltargetty = type_of_fn_from_ty(ccx, outgoing_fty);
768-
let lltargetfn = PointerCast(bcx, lltargetfn, T_ptr(lltargetty));
769-
Call(bcx, lltargetfn, llargs);
770-
build_return(bcx);
771-
finish_fn(fcx, lltop);
772-
ret {val: llthunk, ty: llthunk_ty};
773-
}

0 commit comments

Comments
 (0)