diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 03e12c1c8a7..5a9b4e109a5 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1663,21 +1663,30 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { arg_ty, datum::Lvalue::new("FunctionContext::bind_args")) } else { - unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx, arg_ty, "", - uninit_reason, - arg_scope_id, |bcx, dst| { - debug!("FunctionContext::bind_args: {:?}: {:?}", hir_arg, arg_ty); + let lltmp = if common::type_is_fat_ptr(bcx.tcx(), arg_ty) { + let lltemp = alloc_ty(bcx, arg_ty, ""); let b = &bcx.build(); - if common::type_is_fat_ptr(bcx.tcx(), arg_ty) { - let meta = &self.fn_ty.args[idx]; - idx += 1; - arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, dst)); - meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, dst)); - } else { - arg.store_fn_arg(b, &mut llarg_idx, dst); - } - bcx - })) + // we pass fat pointers as two words, but we want to + // represent them internally as a pointer to two words, + // so make an alloca to store them in. + let meta = &self.fn_ty.args[idx]; + idx += 1; + arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, lltemp)); + meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, lltemp)); + lltemp + } else { + // otherwise, arg is passed by value, so store it into a temporary. + let llarg_ty = arg.cast.unwrap_or(arg.memory_ty(bcx.ccx())); + let lltemp = alloca(bcx, llarg_ty, ""); + let b = &bcx.build(); + arg.store_fn_arg(b, &mut llarg_idx, lltemp); + // And coerce the temporary into the type we expect. + b.pointercast(lltemp, arg.memory_ty(bcx.ccx()).ptr_to()) + }; + + // FIXME: hacky lol? + datum::Datum::new(lltmp, arg_ty, + datum::Lvalue::new("datum::lvalue_scratch_datum")) } } else { // FIXME(pcwalton): Reduce the amount of code bloat this is responsible for. diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index b98e04e51c0..ffc14b4468b 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -327,10 +327,10 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, llarg_idx += 1; llarg } else { - let lltemp = bcx.with_block(|bcx| { - base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index)) - }); if common::type_is_fat_ptr(tcx, arg_ty) { + let lltemp = bcx.with_block(|bcx| { + base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index)) + }); // we pass fat pointers as two words, but we want to // represent them internally as a pointer to two words, // so make an alloca to store them in. @@ -338,12 +338,17 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, idx += 1; arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, lltemp)); meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, lltemp)); + lltemp } else { - // otherwise, arg is passed by value, so make a - // temporary and store it there + // otherwise, arg is passed by value, so store it into a temporary. + let llarg_ty = arg.cast.unwrap_or(arg.memory_ty(bcx.ccx())); + let lltemp = bcx.with_block(|bcx| { + base::alloca(bcx, llarg_ty, &format!("arg{}", arg_index)) + }); arg.store_fn_arg(bcx, &mut llarg_idx, lltemp); + // And coerce the temporary into the type we expect. + bcx.pointercast(lltemp, arg.memory_ty(bcx.ccx()).ptr_to()) } - lltemp }; bcx.with_block(|bcx| arg_scope.map(|scope| { // Is this a regular argument?