Skip to content

Commit 092ea34

Browse files
committed
---
yaml --- r: 2843 b: refs/heads/master c: 7d68cbd h: refs/heads/master i: 2841: 7dd9c15 2839: e4b0f0f v: v3
1 parent 348f73b commit 092ea34

File tree

2 files changed

+104
-72
lines changed

2 files changed

+104
-72
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 81fc2d8728b622275d55243cbacbc7834641503f
2+
refs/heads/master: 7d68cbdff00d055c1fd5168227803a987a4a4a51

trunk/src/comp/middle/trans.rs

Lines changed: 103 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -3712,14 +3712,28 @@ fn join_results(&@block_ctxt parent_cx,
37123712
ret res(join_cx, phi);
37133713
}
37143714

3715+
fn join_branches(&@block_ctxt parent_cx, &vec[result] ins) -> @block_ctxt {
3716+
auto out = new_sub_block_ctxt(parent_cx, "join");
3717+
for (result r in ins) {
3718+
if (!is_terminated(r.bcx)) {
3719+
r.bcx.build.Br(out.llbb);
3720+
}
3721+
}
3722+
ret out;
3723+
}
3724+
3725+
tag out_method {
3726+
return;
3727+
save_in(ValueRef);
3728+
}
3729+
37153730
fn trans_if(&@block_ctxt cx, &@ast::expr cond,
37163731
&ast::block thn, &option::t[@ast::expr] els,
3717-
&ast::ann ann) -> result {
3718-
3732+
&ast::ann ann, &out_method output) -> result {
37193733
auto cond_res = trans_expr(cx, cond);
37203734

37213735
auto then_cx = new_scope_block_ctxt(cx, "then");
3722-
auto then_res = trans_block(then_cx, thn);
3736+
auto then_res = trans_block(then_cx, thn, output);
37233737

37243738
auto else_cx = new_scope_block_ctxt(cx, "else");
37253739

@@ -3739,14 +3753,14 @@ fn trans_if(&@block_ctxt cx, &@ast::expr cond,
37393753
a = ann);
37403754
auto elseif_blk = rec(node = elseif_blk_,
37413755
span = elexpr.span);
3742-
else_res = trans_block(else_cx, elseif_blk);
3756+
else_res = trans_block(else_cx, elseif_blk, output);
37433757
}
37443758
case (ast::expr_block(?blk, _)) {
37453759
// Calling trans_block directly instead of trans_expr
37463760
// because trans_expr will create another scope block
37473761
// context for the block, but we've already got the
37483762
// 'else' context
3749-
else_res = trans_block(else_cx, blk);
3763+
else_res = trans_block(else_cx, blk, output);
37503764
}
37513765
}
37523766

@@ -3771,9 +3785,7 @@ fn trans_if(&@block_ctxt cx, &@ast::expr cond,
37713785
cond_res.bcx.build.CondBr(cond_res.val,
37723786
then_cx.llbb,
37733787
else_cx.llbb);
3774-
3775-
ret join_results(cx, expr_llty,
3776-
[then_res, else_res]);
3788+
ret res(join_branches(cx, [then_res, else_res]), C_nil());
37773789
}
37783790

37793791
fn trans_for(&@block_ctxt cx,
@@ -3795,7 +3807,7 @@ fn trans_for(&@block_ctxt cx,
37953807
auto bcx = copy_val(local_res.bcx, INIT, local_res.val, curr, t).bcx;
37963808
scope_cx.cleanups +=
37973809
[clean(bind drop_slot(_, local_res.val, t))];
3798-
bcx = trans_block(bcx, body).bcx;
3810+
bcx = trans_block(bcx, body, return).bcx;
37993811
bcx.build.Br(next_cx.llbb);
38003812
ret res(next_cx, C_nil());
38013813
}
@@ -4053,7 +4065,7 @@ fn trans_for_each(&@block_ctxt cx,
40534065

40544066
auto bcx = new_top_block_ctxt(fcx);
40554067
auto lltop = bcx.llbb;
4056-
auto r = trans_block(bcx, body);
4068+
auto r = trans_block(bcx, body, return);
40574069

40584070
finish_fn(fcx, lltop);
40594071

@@ -4099,7 +4111,7 @@ fn trans_while(&@block_ctxt cx, &@ast::expr cond,
40994111
auto body_cx = new_loop_scope_block_ctxt(cx, option::none[@block_ctxt],
41004112
next_cx, "while loop body");
41014113

4102-
auto body_res = trans_block(body_cx, body);
4114+
auto body_res = trans_block(body_cx, body, return);
41034115
auto cond_res = trans_expr(cond_cx, cond);
41044116

41054117
body_res.bcx.build.Br(cond_cx.llbb);
@@ -4118,7 +4130,7 @@ fn trans_do_while(&@block_ctxt cx, &ast::block body,
41184130
auto body_cx = new_loop_scope_block_ctxt(cx, option::none[@block_ctxt],
41194131
next_cx, "do-while loop body");
41204132

4121-
auto body_res = trans_block(body_cx, body);
4133+
auto body_res = trans_block(body_cx, body, return);
41224134
auto cond_res = trans_expr(body_res.bcx, cond);
41234135

41244136
cond_res.bcx.build.CondBr(cond_res.val,
@@ -4259,7 +4271,8 @@ fn trans_pat_binding(&@block_ctxt cx, &@ast::pat pat,
42594271
}
42604272

42614273
fn trans_alt(&@block_ctxt cx, &@ast::expr expr,
4262-
&vec[ast::arm] arms, &ast::ann ann) -> result {
4274+
&vec[ast::arm] arms, &ast::ann ann,
4275+
&out_method output) -> result {
42634276
auto expr_res = trans_expr(cx, expr);
42644277

42654278
auto this_cx = expr_res.bcx;
@@ -4275,12 +4288,13 @@ fn trans_alt(&@block_ctxt cx, &@ast::expr expr,
42754288
auto binding_res = trans_pat_binding(binding_cx, arm.pat,
42764289
expr_res.val, false);
42774290

4278-
auto block_res = trans_block(binding_res.bcx, arm.block);
4291+
auto block_res = trans_block(binding_res.bcx, arm.block, output);
42794292
arm_results += [block_res];
42804293

42814294
this_cx = next_cx;
42824295
}
42834296

4297+
42844298
auto default_cx = this_cx;
42854299
auto default_res = trans_fail(default_cx, some[common::span](expr.span),
42864300
"non-exhaustive match failure");
@@ -4297,7 +4311,7 @@ fn trans_alt(&@block_ctxt cx, &@ast::expr expr,
42974311
}
42984312
}
42994313

4300-
ret join_results(cx, expr_llty, arm_results);
4314+
ret res(join_branches(cx, arm_results), C_nil());
43014315
}
43024316

43034317
type generic_info = rec(ty::t item_type,
@@ -4454,7 +4468,7 @@ fn trans_path(&@block_ctxt cx, &ast::path p, &ast::ann ann) -> lval_result {
44544468

44554469
auto lltagty;
44564470
if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx,
4457-
tag_ty)) {
4471+
tag_ty)) {
44584472
lltagty = T_opaque_tag(cx.fcx.lcx.ccx.tn);
44594473
} else {
44604474
lltagty = type_of(cx.fcx.lcx.ccx, p.span, tag_ty);
@@ -5428,6 +5442,11 @@ fn trans_rec(&@block_ctxt cx, &vec[ast::field] fields,
54285442
}
54295443

54305444
fn trans_expr(&@block_ctxt cx, &@ast::expr e) -> result {
5445+
be trans_expr_out(cx, e, return);
5446+
}
5447+
5448+
fn trans_expr_out(&@block_ctxt cx, &@ast::expr e, out_method output)
5449+
-> result {
54315450
*cx = rec(sp=e.span with *cx);
54325451
alt (e.node) {
54335452
case (ast::expr_lit(?lit, ?ann)) {
@@ -5445,7 +5464,8 @@ fn trans_expr(&@block_ctxt cx, &@ast::expr e) -> result {
54455464
}
54465465

54475466
case (ast::expr_if(?cond, ?thn, ?els, ?ann)) {
5448-
ret trans_if(cx, cond, thn, els, ann);
5467+
ret with_out_method(bind trans_if(cx, cond, thn, els, ann, _),
5468+
cx, ann, output);
54495469
}
54505470

54515471
case (ast::expr_for(?decl, ?seq, ?body, _)) {
@@ -5465,18 +5485,18 @@ fn trans_expr(&@block_ctxt cx, &@ast::expr e) -> result {
54655485
}
54665486

54675487
case (ast::expr_alt(?expr, ?arms, ?ann)) {
5468-
ret trans_alt(cx, expr, arms, ann);
5488+
ret with_out_method(bind trans_alt(cx, expr, arms, ann, _),
5489+
cx, ann, output);
54695490
}
54705491

5471-
case (ast::expr_block(?blk, _)) {
5492+
case (ast::expr_block(?blk, ?ann)) {
54725493
*cx = rec(sp=blk.span with *cx);
54735494
auto sub_cx = new_scope_block_ctxt(cx, "block-expr body");
54745495
auto next_cx = new_sub_block_ctxt(cx, "next");
5475-
auto sub = trans_block(sub_cx, blk);
5476-
5496+
auto sub = with_out_method(bind trans_block(sub_cx, blk, _),
5497+
cx, ann, output);
54775498
cx.build.Br(sub_cx.llbb);
54785499
sub.bcx.build.Br(next_cx.llbb);
5479-
54805500
ret res(next_cx, sub.val);
54815501
}
54825502

@@ -5617,6 +5637,34 @@ fn trans_expr(&@block_ctxt cx, &@ast::expr e) -> result {
56175637
ret res(sub.res.bcx, load_if_immediate(sub.res.bcx, sub.res.val, t));
56185638
}
56195639

5640+
fn with_out_method(fn(&out_method) -> result work, &@block_ctxt cx,
5641+
&ast::ann ann, &out_method outer_output) -> result {
5642+
auto ccx = cx.fcx.lcx.ccx;
5643+
if (outer_output != return) {
5644+
ret work(outer_output);
5645+
} else {
5646+
auto tp = node_ann_type(ccx, ann);
5647+
if (ty::type_is_nil(ccx.tcx, tp)) {
5648+
ret work(return);
5649+
}
5650+
auto res_alloca = alloc_ty(cx, tp);
5651+
cx = zero_alloca(res_alloca.bcx, res_alloca.val, tp).bcx;
5652+
5653+
fn drop_hoisted_ty(&@block_ctxt cx,
5654+
ValueRef target,
5655+
ty::t t) -> result {
5656+
auto reg_val = load_if_immediate(cx, target, t);
5657+
ret drop_ty(cx, reg_val, t);
5658+
}
5659+
auto cleanup = bind drop_hoisted_ty(_, res_alloca.val, tp);
5660+
find_scope_cx(cx).cleanups += [clean(cleanup)];
5661+
5662+
auto done = work(save_in(res_alloca.val));
5663+
done.val = load_if_immediate(done.bcx, res_alloca.val, tp);
5664+
ret done;
5665+
}
5666+
}
5667+
56205668
// We pass structural values around the compiler "by pointer" and
56215669
// non-structural values (scalars, boxes, pointers) "by value". We call the
56225670
// latter group "immediates" and, in some circumstances when we know we have a
@@ -6472,9 +6520,8 @@ fn alloc_local(&@block_ctxt cx, &@ast::local local) -> result {
64726520
ret r;
64736521
}
64746522

6475-
fn trans_block(&@block_ctxt cx, &ast::block b) -> result {
6523+
fn trans_block(&@block_ctxt cx, &ast::block b, &out_method output) -> result {
64766524
auto bcx = cx;
6477-
64786525
for each (@ast::local local in block_locals(b)) {
64796526
*bcx = rec(sp=local_rhs_span(local, cx.sp) with *bcx);
64806527
bcx = alloc_local(bcx, local).bcx;
@@ -6491,58 +6538,43 @@ fn trans_block(&@block_ctxt cx, &ast::block b) -> result {
64916538
}
64926539
}
64936540

6541+
fn accept_out_method(&@ast::expr expr) -> bool {
6542+
ret alt (expr.node) {
6543+
case (ast::expr_if(_, _, _, _)) { true }
6544+
case (ast::expr_alt(_, _, _)) { true }
6545+
case (ast::expr_block(_, _)) { true }
6546+
case (_) { false }
6547+
};
6548+
}
6549+
64946550
alt (b.node.expr) {
64956551
case (some(?e)) {
6496-
// Hold onto the context for this scope since we'll need it to
6497-
// find the outer scope
6498-
auto scope_bcx = bcx;
6499-
r = trans_expr(bcx, e);
6552+
auto pass = output != return && accept_out_method(e);
6553+
if (pass) {
6554+
r = trans_expr_out(bcx, e, output);
6555+
} else {
6556+
r = trans_expr(bcx, e);
6557+
}
65006558
bcx = r.bcx;
65016559

6502-
if (is_terminated(bcx)) {
6560+
auto ccx = cx.fcx.lcx.ccx;
6561+
auto r_ty = ty::expr_ty(ccx.tcx, e);
6562+
if (is_terminated(bcx) ||
6563+
ty::type_is_bot(ccx.tcx, r_ty)) {
65036564
ret r;
6504-
} else {
6505-
auto r_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, e);
6506-
if (!ty::type_is_nil(cx.fcx.lcx.ccx.tcx, r_ty)
6507-
&& !ty::type_is_bot(cx.fcx.lcx.ccx.tcx, r_ty)) {
6508-
// The value resulting from the block gets copied into an
6509-
// alloca created in an outer scope and its refcount
6510-
// bumped so that it can escape this block. This means
6511-
// that it will definitely live until the end of the
6512-
// enclosing scope, even if nobody uses it, which may be
6513-
// something of a surprise.
6514-
6515-
// It's possible we never hit this block, so the alloca
6516-
// must be initialized to null, then when the potential
6517-
// value finally goes out of scope the drop glue will see
6518-
// that it was never used and ignore it.
6519-
6520-
// NB: Here we're building and initalizing the alloca in
6521-
// the alloca context, not this block's context.
6522-
auto res_alloca = alloc_ty(bcx, r_ty);
6523-
auto llbcx = llallocas_block_ctxt(bcx.fcx);
6524-
zero_alloca(llbcx, res_alloca.val, r_ty);
6525-
6526-
// Now we're working in our own block context again
6527-
auto res_copy = copy_val(bcx, INIT,
6528-
res_alloca.val, r.val, r_ty);
6529-
bcx = res_copy.bcx;
6530-
6531-
fn drop_hoisted_ty(&@block_ctxt cx,
6532-
ValueRef alloca_val,
6533-
ty::t t) -> result {
6534-
auto reg_val = load_if_immediate(cx,
6535-
alloca_val, t);
6536-
ret drop_ty(cx, reg_val, t);
6565+
} else if (!pass) {
6566+
alt (output) {
6567+
case (save_in(?target)) {
6568+
// The output method is to save the value at target,
6569+
// and we didn't pass it to the recursive trans_expr
6570+
// call.
6571+
// FIXME Use move semantics!
6572+
auto res_copy = copy_val(bcx, INIT, target,
6573+
r.val, r_ty);
6574+
bcx = res_copy.bcx;
6575+
r = res(bcx, C_nil());
65376576
}
6538-
6539-
auto cleanup = bind drop_hoisted_ty(_, res_alloca.val,
6540-
r_ty);
6541-
auto outer_scope_cx = find_outer_scope_cx(scope_bcx);
6542-
outer_scope_cx.cleanups += [clean(cleanup)];
6543-
6544-
r = res(bcx, load_if_immediate(bcx,
6545-
res_alloca.val, r_ty));
6577+
case (return) {}
65466578
}
65476579
}
65486580
}
@@ -6860,7 +6892,7 @@ fn trans_fn(@local_ctxt cx, &ast::span sp, &ast::_fn f, ast::def_id fid,
68606892

68616893
auto lltop = bcx.llbb;
68626894

6863-
auto res = trans_block(bcx, f.body);
6895+
auto res = trans_block(bcx, f.body, return);
68646896
if (!is_terminated(res.bcx)) {
68656897
// FIXME: until LLVM has a unit type, we are moving around
68666898
// C_nil values rather than their void type.

0 commit comments

Comments
 (0)