Skip to content

Commit e3a3a03

Browse files
committed
Fix boxed returns.
1 parent 264de9c commit e3a3a03

File tree

1 file changed

+27
-13
lines changed

1 file changed

+27
-13
lines changed

src/comp/middle/trans.rs

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,13 +1395,20 @@ impure fn trans_args(@block_ctxt cx, &vec[@ast.expr] es, @typeck.ty fn_ty)
13951395
}
13961396

13971397
impure fn trans_call(@block_ctxt cx, @ast.expr f,
1398-
vec[@ast.expr] args) -> result {
1398+
vec[@ast.expr] args, &ast.ann ann) -> result {
13991399
auto f_res = trans_lval(cx, f);
14001400
check (! f_res._1);
14011401
auto fn_ty = typeck.expr_ty(f);
1402+
auto ret_ty = typeck.ann_to_type(ann);
14021403
auto args_res = trans_args(f_res._0.bcx, args, fn_ty);
1403-
ret res(args_res._0,
1404-
args_res._0.build.FastCall(f_res._0.val, args_res._1));
1404+
auto retval = args_res._0.build.FastCall(f_res._0.val, args_res._1);
1405+
1406+
// Retval doesn't correspond to anything really tangible in the frame, but
1407+
// it's a ref all the same, so we put a note here to drop it when we're
1408+
// done in this scope.
1409+
find_scope_cx(cx).cleanups += clean(bind drop_ty(_, retval, ret_ty));
1410+
1411+
ret res(args_res._0, retval);
14051412
}
14061413

14071414
impure fn trans_tup(@block_ctxt cx, vec[ast.elt] elts,
@@ -1502,8 +1509,8 @@ impure fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
15021509
ret copy_ty(rhs_res.bcx, false, lhs_res._0.val, v, t);
15031510
}
15041511

1505-
case (ast.expr_call(?f, ?args, _)) {
1506-
ret trans_call(cx, f, args);
1512+
case (ast.expr_call(?f, ?args, ?ann)) {
1513+
ret trans_call(cx, f, args, ann);
15071514
}
15081515

15091516
case (ast.expr_cast(?e, _, ?ann)) {
@@ -1590,7 +1597,21 @@ impure fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result {
15901597
auto r = res(cx, C_nil());
15911598
alt (e) {
15921599
case (some[@ast.expr](?x)) {
1600+
auto t = typeck.expr_ty(x);
15931601
r = trans_expr(cx, x);
1602+
if (typeck.type_is_structural(t)) {
1603+
// We usually treat structurals by-pointer; in particular,
1604+
// trans_expr will have given us a structure pointer. But in
1605+
// this case we're about to return. LLVM wants a first-class
1606+
// value here (which makes sense; the frame is going away!)
1607+
r.val = r.bcx.build.Load(r.val);
1608+
}
1609+
if (typeck.type_is_boxed(t)) {
1610+
// A return is an implicit ++ on the refcount on any boxed
1611+
// value, as it is being newly referenced as the anonymous
1612+
// 'return value' from the function, in the caller frame.
1613+
r.bcx = incr_refcnt(r.bcx, r.val).bcx;
1614+
}
15941615
}
15951616
case (_) { /* fall through */ }
15961617
}
@@ -1611,14 +1632,7 @@ impure fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result {
16111632
}
16121633

16131634
alt (e) {
1614-
case (some[@ast.expr](?e)) {
1615-
if (typeck.type_is_structural(typeck.expr_ty(e))) {
1616-
// We usually treat structurals by-pointer; in particular,
1617-
// trans_expr will have given us a structure pointer. But in
1618-
// this case we're about to return. LLVM wants a first-class
1619-
// value here (which makes sense; the frame is going away!)
1620-
r.val = r.bcx.build.Load(r.val);
1621-
}
1635+
case (some[@ast.expr](_)) {
16221636
r.val = r.bcx.build.Ret(r.val);
16231637
ret r;
16241638
}

0 commit comments

Comments
 (0)