Fix boxed returns.

This commit is contained in:
Graydon Hoare 2010-12-08 16:20:04 -08:00
parent 264de9c7fc
commit e3a3a03572

View file

@ -1395,13 +1395,20 @@ impure fn trans_args(@block_ctxt cx, &vec[@ast.expr] es, @typeck.ty fn_ty)
}
impure fn trans_call(@block_ctxt cx, @ast.expr f,
vec[@ast.expr] args) -> result {
vec[@ast.expr] args, &ast.ann ann) -> result {
auto f_res = trans_lval(cx, f);
check (! f_res._1);
auto fn_ty = typeck.expr_ty(f);
auto ret_ty = typeck.ann_to_type(ann);
auto args_res = trans_args(f_res._0.bcx, args, fn_ty);
ret res(args_res._0,
args_res._0.build.FastCall(f_res._0.val, args_res._1));
auto retval = args_res._0.build.FastCall(f_res._0.val, args_res._1);
// Retval doesn't correspond to anything really tangible in the frame, but
// it's a ref all the same, so we put a note here to drop it when we're
// done in this scope.
find_scope_cx(cx).cleanups += clean(bind drop_ty(_, retval, ret_ty));
ret res(args_res._0, retval);
}
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 {
ret copy_ty(rhs_res.bcx, false, lhs_res._0.val, v, t);
}
case (ast.expr_call(?f, ?args, _)) {
ret trans_call(cx, f, args);
case (ast.expr_call(?f, ?args, ?ann)) {
ret trans_call(cx, f, args, ann);
}
case (ast.expr_cast(?e, _, ?ann)) {
@ -1590,7 +1597,21 @@ impure fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result {
auto r = res(cx, C_nil());
alt (e) {
case (some[@ast.expr](?x)) {
auto t = typeck.expr_ty(x);
r = trans_expr(cx, x);
if (typeck.type_is_structural(t)) {
// We usually treat structurals by-pointer; in particular,
// trans_expr will have given us a structure pointer. But in
// this case we're about to return. LLVM wants a first-class
// value here (which makes sense; the frame is going away!)
r.val = r.bcx.build.Load(r.val);
}
if (typeck.type_is_boxed(t)) {
// A return is an implicit ++ on the refcount on any boxed
// value, as it is being newly referenced as the anonymous
// 'return value' from the function, in the caller frame.
r.bcx = incr_refcnt(r.bcx, r.val).bcx;
}
}
case (_) { /* fall through */ }
}
@ -1611,14 +1632,7 @@ impure fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result {
}
alt (e) {
case (some[@ast.expr](?e)) {
if (typeck.type_is_structural(typeck.expr_ty(e))) {
// We usually treat structurals by-pointer; in particular,
// trans_expr will have given us a structure pointer. But in
// this case we're about to return. LLVM wants a first-class
// value here (which makes sense; the frame is going away!)
r.val = r.bcx.build.Load(r.val);
}
case (some[@ast.expr](_)) {
r.val = r.bcx.build.Ret(r.val);
ret r;
}