@@ -436,47 +436,47 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
436
436
fn_ty : & FnType ,
437
437
next_idx : & mut usize ,
438
438
callee : & mut CalleeData ) {
439
- // FIXME: consider having some optimization to avoid tupling/untupling
440
- // (and storing/loading in the case of immediates)
441
-
442
- // avoid trans_operand for pointless copying
443
- let lv = match * operand {
444
- mir:: Operand :: Consume ( ref lvalue) => self . trans_lvalue ( bcx, lvalue) ,
445
- mir:: Operand :: Constant ( ref constant) => {
446
- // FIXME: consider being less pessimized
447
- if constant. ty . is_nil ( ) {
448
- return ;
449
- }
450
-
451
- let ty = bcx. monomorphize ( & constant. ty ) ;
452
- let lv = LvalueRef :: alloca ( bcx, ty, "__untuple_alloca" ) ;
453
- let constant = self . trans_constant ( bcx, constant) ;
454
- self . store_operand ( bcx, lv. llval , constant) ;
455
- lv
456
- }
457
- } ;
439
+ let tuple = self . trans_operand ( bcx, operand) ;
458
440
459
- let lv_ty = lv. ty . to_ty ( bcx. tcx ( ) ) ;
460
- let result_types = match lv_ty. sty {
441
+ let arg_types = match tuple. ty . sty {
461
442
ty:: TyTuple ( ref tys) => tys,
462
- _ => span_bug ! (
463
- self . mir. span,
464
- "bad final argument to \" rust-call\" fn {:?}" , lv_ty)
443
+ _ => span_bug ! ( self . mir. span,
444
+ "bad final argument to \" rust-call\" fn {:?}" , tuple. ty)
465
445
} ;
466
446
467
- let base_repr = adt:: represent_type ( bcx. ccx ( ) , lv_ty) ;
468
- let base = adt:: MaybeSizedValue :: sized ( lv. llval ) ;
469
- for ( n, & ty) in result_types. iter ( ) . enumerate ( ) {
470
- let ptr = adt:: trans_field_ptr_builder ( bcx, & base_repr, base, Disr ( 0 ) , n) ;
471
- let val = if common:: type_is_fat_ptr ( bcx. tcx ( ) , ty) {
472
- let ( lldata, llextra) = load_fat_ptr ( bcx, ptr) ;
473
- FatPtr ( lldata, llextra)
474
- } else {
475
- // Don't bother loading the value, trans_argument will.
476
- Ref ( ptr)
477
- } ;
478
- self . trans_argument ( bcx, val, llargs, fn_ty, next_idx, callee) ;
447
+ // Handle both by-ref and immediate tuples. This gives us the option of
448
+ match tuple. val {
449
+ Ref ( llval) => {
450
+ let base_repr = adt:: represent_type ( bcx. ccx ( ) , tuple. ty ) ;
451
+ let base = adt:: MaybeSizedValue :: sized ( llval) ;
452
+ for ( n, & ty) in arg_types. iter ( ) . enumerate ( ) {
453
+ let ptr = adt:: trans_field_ptr_builder ( bcx, & base_repr, base, Disr ( 0 ) , n) ;
454
+ let val = if common:: type_is_fat_ptr ( bcx. tcx ( ) , ty) {
455
+ let ( lldata, llextra) = load_fat_ptr ( bcx, ptr) ;
456
+ FatPtr ( lldata, llextra)
457
+ } else {
458
+ // trans_argument will load this if it needs to
459
+ Ref ( ptr)
460
+ } ;
461
+ self . trans_argument ( bcx, val, llargs, fn_ty, next_idx, callee) ;
462
+ }
463
+
464
+ }
465
+ Immediate ( llval) => {
466
+ for ( n, & ty) in arg_types. iter ( ) . enumerate ( ) {
467
+ let mut elem = bcx. extract_value ( llval, n) ;
468
+ // Truncate bools to i1, if needed
469
+ if ty. is_bool ( ) && common:: val_ty ( elem) != Type :: i1 ( bcx. ccx ( ) ) {
470
+ elem = bcx. trunc ( elem, Type :: i1 ( bcx. ccx ( ) ) ) ;
471
+ }
472
+ // If the tuple is immediate, the elements are as well
473
+ let val = Immediate ( elem) ;
474
+ self . trans_argument ( bcx, val, llargs, fn_ty, next_idx, callee) ;
475
+ }
476
+ }
477
+ FatPtr ( _, _) => bug ! ( "tuple is a fat pointer?!" )
479
478
}
479
+
480
480
}
481
481
482
482
fn get_personality_slot ( & mut self , bcx : & BlockAndBuilder < ' bcx , ' tcx > ) -> ValueRef {
0 commit comments