From 74262525490262da3b8005db4a252fbb05b5b10a Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Sat, 2 Jul 2011 21:55:38 -0700 Subject: [PATCH] Generate code properly for calls with _|_ - typed arguments The code for translating a fail (for example) would call Unreachable(), which terminates the block; if a fail appeared as an argument, this would cause an LLVM assertion failure. Changed trans_call to handle this situation correctly. --- src/comp/middle/trans.rs | 44 ++++++++++++++++++++--------------- src/test/run-fail/fail-arg.rs | 9 +++++++ 2 files changed, 34 insertions(+), 19 deletions(-) create mode 100644 src/test/run-fail/fail-arg.rs diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 36ab5ed51d3..aaaa54e4779 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -5564,9 +5564,10 @@ fn trans_arg_expr(&@block_ctxt cx, &ty::arg arg, TypeRef lldestty0, val = do_spill(lv.res.bcx, lv.res.val); } } else { auto re = trans_expr(bcx, e); val = re.val; bcx = re.bcx; } + auto is_bot = ty::type_is_bot(cx.fcx.lcx.ccx.tcx, e_ty); // Make a copy here if the type is structural and we're passing by value. - if (arg.mode == ty::mo_val) { + if (arg.mode == ty::mo_val && !is_bot) { if (ty::type_owns_heap_mem(cx.fcx.lcx.ccx.tcx, e_ty)) { auto rslt = alloc_ty(bcx, e_ty); bcx = rslt.bcx; @@ -5579,7 +5580,7 @@ fn trans_arg_expr(&@block_ctxt cx, &ty::arg arg, TypeRef lldestty0, } } - if (ty::type_is_bot(cx.fcx.lcx.ccx.tcx, e_ty)) { + if (is_bot) { // For values of type _|_, we generate an // "undef" value, as such a value should never // be inspected. It's important for the value @@ -5747,25 +5748,30 @@ fn trans_call(&@block_ctxt cx, &@ast::expr f, &option::t[ValueRef] lliterbody, } */ - bcx.build.FastCall(faddr, llargs); + /* If the block is terminated, + then one or more of the args has + type _|_. Since that means it diverges, the code + for the call itself is unreachable. */ auto retval = C_nil(); - alt (lliterbody) { - case (none) { - if (!ty::type_is_nil(cx.fcx.lcx.ccx.tcx, ret_ty)) { - retval = load_if_immediate(bcx, llretslot, ret_ty); - // 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))]; + if (!bcx.build.is_terminated()) { + bcx.build.FastCall(faddr, llargs); + alt (lliterbody) { + case (none) { + if (!ty::type_is_nil(cx.fcx.lcx.ccx.tcx, ret_ty)) { + retval = load_if_immediate(bcx, llretslot, ret_ty); + // 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))]; + } + } + case (some(_)) { + // If there was an lliterbody, it means we were calling an + // iter, and we are *not* the party using its 'output' value, + // we should ignore llretslot. } - } - case (some(_)) { - // If there was an lliterbody, it means we were calling an - // iter, and we are *not* the party using its 'output' value, - // we should ignore llretslot. - } } ret rslt(bcx, retval); diff --git a/src/test/run-fail/fail-arg.rs b/src/test/run-fail/fail-arg.rs new file mode 100644 index 00000000000..59fc8e4bd55 --- /dev/null +++ b/src/test/run-fail/fail-arg.rs @@ -0,0 +1,9 @@ +// xfail-stage0 +// error-pattern:explicit failure +fn f(int a) { + log a; +} + +fn main() { + f(fail); +}