@@ -211,70 +211,13 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
211211 let mut llargs = Vec :: with_capacity ( arg_count) ;
212212
213213 // Prepare the return value destination
214- let ret_dest = if let Some ( ( ref d, _) ) = * destination {
215- match * d {
216- // Handle temporary lvalues, specifically Operand ones, as
217- // they don't have allocas
218- mir:: Lvalue :: Temp ( idx) => {
219- let lvalue_ty = self . mir . lvalue_ty ( bcx. tcx ( ) , d) ;
220- let ret_ty = lvalue_ty. to_ty ( bcx. tcx ( ) ) ;
221- match self . temps [ idx as usize ] {
222- TempRef :: Lvalue ( dest) => {
223- if fn_ty. ret . is_indirect ( ) {
224- llargs. push ( dest. llval ) ;
225- ReturnDest :: Nothing
226- } else if fn_ty. ret . is_ignore ( ) {
227- ReturnDest :: Nothing
228- } else {
229- ReturnDest :: Store ( dest. llval )
230- }
231- }
232- TempRef :: Operand ( None ) => {
233- let is_intrinsic = if let Intrinsic = callee. data {
234- true
235- } else {
236- false
237- } ;
238-
239- if fn_ty. ret . is_indirect ( ) {
240- // Odd, but possible, case, we have an operand temporary,
241- // but the calling convention has an indirect return.
242- let tmp = bcx. with_block ( |bcx| {
243- base:: alloc_ty ( bcx, ret_ty, "tmp_ret" )
244- } ) ;
245- llargs. push ( tmp) ;
246- ReturnDest :: IndirectOperand ( tmp, idx)
247- } else if is_intrinsic {
248- // Currently, intrinsics always need a location to store
249- // the result. so we create a temporary alloca for the
250- // result
251- let tmp = bcx. with_block ( |bcx| {
252- base:: alloc_ty ( bcx, ret_ty, "tmp_ret" )
253- } ) ;
254- ReturnDest :: IndirectOperand ( tmp, idx)
255- } else if fn_ty. ret . is_ignore ( ) {
256- ReturnDest :: Nothing
257- } else {
258- ReturnDest :: DirectOperand ( idx)
259- }
260- }
261- TempRef :: Operand ( Some ( _) ) => {
262- bug ! ( "lvalue temp already assigned to" ) ;
263- }
264- }
265- }
266- _ => {
267- let dest = self . trans_lvalue ( & bcx, d) ;
268- if fn_ty. ret . is_indirect ( ) {
269- llargs. push ( dest. llval ) ;
270- ReturnDest :: Nothing
271- } else if fn_ty. ret . is_ignore ( ) {
272- ReturnDest :: Nothing
273- } else {
274- ReturnDest :: Store ( dest. llval )
275- }
276- }
277- }
214+ let ret_dest = if let Some ( ( ref dest, _) ) = * destination {
215+ let is_intrinsic = if let Intrinsic = callee. data {
216+ true
217+ } else {
218+ false
219+ } ;
220+ self . make_return_dest ( & bcx, dest, & fn_ty. ret , & mut llargs, is_intrinsic)
278221 } else {
279222 ReturnDest :: Nothing
280223 } ;
@@ -601,6 +544,57 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
601544 self . blocks [ bb. index ( ) ] . llbb
602545 }
603546
547+ fn make_return_dest ( & mut self , bcx : & BlockAndBuilder < ' bcx , ' tcx > ,
548+ dest : & mir:: Lvalue < ' tcx > , fn_ret_ty : & ArgType ,
549+ llargs : & mut Vec < ValueRef > , is_intrinsic : bool ) -> ReturnDest {
550+ // If the return is ignored, we can just return a do-nothing ReturnDest
551+ if fn_ret_ty. is_ignore ( ) {
552+ return ReturnDest :: Nothing ;
553+ }
554+ let dest = match * dest {
555+ mir:: Lvalue :: Temp ( idx) => {
556+ let lvalue_ty = self . mir . lvalue_ty ( bcx. tcx ( ) , dest) ;
557+ let ret_ty = lvalue_ty. to_ty ( bcx. tcx ( ) ) ;
558+ match self . temps [ idx as usize ] {
559+ TempRef :: Lvalue ( dest) => dest,
560+ TempRef :: Operand ( None ) => {
561+ // Handle temporary lvalues, specifically Operand ones, as
562+ // they don't have allocas
563+ return if fn_ret_ty. is_indirect ( ) {
564+ // Odd, but possible, case, we have an operand temporary,
565+ // but the calling convention has an indirect return.
566+ let tmp = bcx. with_block ( |bcx| {
567+ base:: alloc_ty ( bcx, ret_ty, "tmp_ret" )
568+ } ) ;
569+ llargs. push ( tmp) ;
570+ ReturnDest :: IndirectOperand ( tmp, idx)
571+ } else if is_intrinsic {
572+ // Currently, intrinsics always need a location to store
573+ // the result. so we create a temporary alloca for the
574+ // result
575+ let tmp = bcx. with_block ( |bcx| {
576+ base:: alloc_ty ( bcx, ret_ty, "tmp_ret" )
577+ } ) ;
578+ ReturnDest :: IndirectOperand ( tmp, idx)
579+ } else {
580+ ReturnDest :: DirectOperand ( idx)
581+ } ;
582+ }
583+ TempRef :: Operand ( Some ( _) ) => {
584+ bug ! ( "lvalue temp already assigned to" ) ;
585+ }
586+ }
587+ }
588+ _ => self . trans_lvalue ( bcx, dest)
589+ } ;
590+ if fn_ret_ty. is_indirect ( ) {
591+ llargs. push ( dest. llval ) ;
592+ ReturnDest :: Nothing
593+ } else {
594+ ReturnDest :: Store ( dest. llval )
595+ }
596+ }
597+
604598 fn trans_transmute ( & mut self , bcx : & BlockAndBuilder < ' bcx , ' tcx > ,
605599 src : & mir:: Operand < ' tcx > , dst : LvalueRef < ' tcx > ) {
606600 let mut val = self . trans_operand ( bcx, src) ;
0 commit comments