@@ -17,7 +17,7 @@ use adt;
1717use base;
1818use build;
1919use callee:: { Callee , CalleeData , Fn , Intrinsic , NamedTupleConstructor , Virtual } ;
20- use common:: { self , type_is_fat_ptr , Block , BlockAndBuilder , LandingPad } ;
20+ use common:: { self , Block , BlockAndBuilder , LandingPad } ;
2121use common:: { C_bool , C_str_slice , C_struct , C_u32 , C_undef } ;
2222use consts;
2323use debuginfo:: DebugLoc ;
@@ -36,7 +36,7 @@ use super::analyze::CleanupKind;
3636use super :: constant:: Const ;
3737use super :: lvalue:: { LvalueRef , load_fat_ptr} ;
3838use super :: operand:: OperandRef ;
39- use super :: operand:: OperandValue :: { self , FatPtr , Immediate , Ref } ;
39+ use super :: operand:: OperandValue :: * ;
4040
4141impl < ' bcx , ' tcx > MirContext < ' bcx , ' tcx > {
4242 pub fn trans_block ( & mut self , bb : mir:: BasicBlock ) {
@@ -410,8 +410,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
410410 }
411411 }
412412
413- let val = self . trans_operand ( & bcx, arg) . val ;
414- self . trans_argument ( & bcx, val , & mut llargs, & fn_ty,
413+ let op = self . trans_operand ( & bcx, arg) ;
414+ self . trans_argument ( & bcx, op , & mut llargs, & fn_ty,
415415 & mut idx, & mut callee. data ) ;
416416 }
417417 if let Some ( tup) = untuple {
@@ -449,7 +449,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
449449 if let ReturnDest :: IndirectOperand ( dst, _) = ret_dest {
450450 // Make a fake operand for store_return
451451 let op = OperandRef {
452- val : OperandValue :: Ref ( dst) ,
452+ val : Ref ( dst) ,
453453 ty : sig. output . unwrap ( )
454454 } ;
455455 self . store_return ( & bcx, ret_dest, fn_ty. ret , op) ;
@@ -487,7 +487,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
487487 ret_bcx. at_start ( |ret_bcx| {
488488 debug_loc. apply_to_bcx ( ret_bcx) ;
489489 let op = OperandRef {
490- val : OperandValue :: Immediate ( invokeret) ,
490+ val : Immediate ( invokeret) ,
491491 ty : sig. output . unwrap ( )
492492 } ;
493493 self . store_return ( & ret_bcx, ret_dest, fn_ty. ret , op) ;
@@ -498,7 +498,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
498498 fn_ty. apply_attrs_callsite ( llret) ;
499499 if let Some ( ( _, target) ) = * destination {
500500 let op = OperandRef {
501- val : OperandValue :: Immediate ( llret) ,
501+ val : Immediate ( llret) ,
502502 ty : sig. output . unwrap ( )
503503 } ;
504504 self . store_return ( & bcx, ret_dest, fn_ty. ret , op) ;
@@ -513,25 +513,36 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
513513
514514 fn trans_argument ( & mut self ,
515515 bcx : & BlockAndBuilder < ' bcx , ' tcx > ,
516- val : OperandValue ,
516+ mut op : OperandRef < ' tcx > ,
517517 llargs : & mut Vec < ValueRef > ,
518518 fn_ty : & FnType ,
519519 next_idx : & mut usize ,
520520 callee : & mut CalleeData ) {
521- // Treat the values in a fat pointer separately.
522- if let FatPtr ( ptr, meta) = val {
523- if * next_idx == 0 {
524- if let Virtual ( idx) = * callee {
525- let llfn = bcx. with_block ( |bcx| {
526- meth:: get_virtual_method ( bcx, meta, idx)
527- } ) ;
528- let llty = fn_ty. llvm_type ( bcx. ccx ( ) ) . ptr_to ( ) ;
529- * callee = Fn ( bcx. pointercast ( llfn, llty) ) ;
521+ if let Pair ( a, b) = op. val {
522+ // Treat the values in a fat pointer separately.
523+ if common:: type_is_fat_ptr ( bcx. tcx ( ) , op. ty ) {
524+ let ( ptr, meta) = ( a, b) ;
525+ if * next_idx == 0 {
526+ if let Virtual ( idx) = * callee {
527+ let llfn = bcx. with_block ( |bcx| {
528+ meth:: get_virtual_method ( bcx, meta, idx)
529+ } ) ;
530+ let llty = fn_ty. llvm_type ( bcx. ccx ( ) ) . ptr_to ( ) ;
531+ * callee = Fn ( bcx. pointercast ( llfn, llty) ) ;
532+ }
530533 }
534+
535+ let imm_op = |x| OperandRef {
536+ val : Immediate ( x) ,
537+ // We won't be checking the type again.
538+ ty : bcx. tcx ( ) . types . err
539+ } ;
540+ self . trans_argument ( bcx, imm_op ( ptr) , llargs, fn_ty, next_idx, callee) ;
541+ self . trans_argument ( bcx, imm_op ( meta) , llargs, fn_ty, next_idx, callee) ;
542+ return ;
531543 }
532- self . trans_argument ( bcx, Immediate ( ptr) , llargs, fn_ty, next_idx, callee) ;
533- self . trans_argument ( bcx, Immediate ( meta) , llargs, fn_ty, next_idx, callee) ;
534- return ;
544+
545+ op = op. pack_if_pair ( bcx) ;
535546 }
536547
537548 let arg = & fn_ty. args [ * next_idx] ;
@@ -547,15 +558,15 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
547558 }
548559
549560 // Force by-ref if we have to load through a cast pointer.
550- let ( mut llval, by_ref) = match val {
561+ let ( mut llval, by_ref) = match op . val {
551562 Immediate ( llval) if arg. is_indirect ( ) || arg. cast . is_some ( ) => {
552563 let llscratch = build:: AllocaFcx ( bcx. fcx ( ) , arg. original_ty , "arg" ) ;
553564 bcx. store ( llval, llscratch) ;
554565 ( llscratch, true )
555566 }
556567 Immediate ( llval) => ( llval, false ) ,
557568 Ref ( llval) => ( llval, true ) ,
558- FatPtr ( _ , _ ) => bug ! ( "fat pointers handled above" )
569+ Pair ( .. ) => bug ! ( "pairs handled above" )
559570 } ;
560571
561572 if by_ref && !arg. is_indirect ( ) {
@@ -602,12 +613,16 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
602613 let ptr = adt:: trans_field_ptr_builder ( bcx, & base_repr, base, Disr ( 0 ) , n) ;
603614 let val = if common:: type_is_fat_ptr ( bcx. tcx ( ) , ty) {
604615 let ( lldata, llextra) = load_fat_ptr ( bcx, ptr) ;
605- FatPtr ( lldata, llextra)
616+ Pair ( lldata, llextra)
606617 } else {
607618 // trans_argument will load this if it needs to
608619 Ref ( ptr)
609620 } ;
610- self . trans_argument ( bcx, val, llargs, fn_ty, next_idx, callee) ;
621+ let op = OperandRef {
622+ val : val,
623+ ty : ty
624+ } ;
625+ self . trans_argument ( bcx, op, llargs, fn_ty, next_idx, callee) ;
611626 }
612627
613628 }
@@ -619,11 +634,29 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
619634 elem = bcx. trunc ( elem, Type :: i1 ( bcx. ccx ( ) ) ) ;
620635 }
621636 // If the tuple is immediate, the elements are as well
622- let val = Immediate ( elem) ;
623- self . trans_argument ( bcx, val, llargs, fn_ty, next_idx, callee) ;
637+ let op = OperandRef {
638+ val : Immediate ( elem) ,
639+ ty : ty
640+ } ;
641+ self . trans_argument ( bcx, op, llargs, fn_ty, next_idx, callee) ;
642+ }
643+ }
644+ Pair ( a, b) => {
645+ let elems = [ a, b] ;
646+ for ( n, & ty) in arg_types. iter ( ) . enumerate ( ) {
647+ let mut elem = elems[ n] ;
648+ // Truncate bools to i1, if needed
649+ if ty. is_bool ( ) && common:: val_ty ( elem) != Type :: i1 ( bcx. ccx ( ) ) {
650+ elem = bcx. trunc ( elem, Type :: i1 ( bcx. ccx ( ) ) ) ;
651+ }
652+ // Pair is always made up of immediates
653+ let op = OperandRef {
654+ val : Immediate ( elem) ,
655+ ty : ty
656+ } ;
657+ self . trans_argument ( bcx, op, llargs, fn_ty, next_idx, callee) ;
624658 }
625659 }
626- FatPtr ( _, _) => bug ! ( "tuple is a fat pointer?!" )
627660 }
628661
629662 }
@@ -779,7 +812,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
779812 let f = Callee :: def ( bcx. ccx ( ) , def_id, substs) ;
780813 let datum = f. reify ( bcx. ccx ( ) ) ;
781814 val = OperandRef {
782- val : OperandValue :: Immediate ( datum. val ) ,
815+ val : Immediate ( datum. val ) ,
783816 ty : datum. ty
784817 } ;
785818 }
@@ -806,17 +839,15 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
806839 self . temps [ idx as usize ] = TempRef :: Operand ( Some ( op) ) ;
807840 }
808841 DirectOperand ( idx) => {
809- let op = if type_is_fat_ptr ( bcx. tcx ( ) , op. ty ) {
810- let llval = op. immediate ( ) ;
811- let ptr = bcx. extract_value ( llval, 0 ) ;
812- let meta = bcx. extract_value ( llval, 1 ) ;
813-
814- OperandRef {
815- val : OperandValue :: FatPtr ( ptr, meta) ,
816- ty : op. ty
817- }
842+ // If there is a cast, we have to store and reload.
843+ let op = if ret_ty. cast . is_some ( ) {
844+ let tmp = bcx. with_block ( |bcx| {
845+ base:: alloc_ty ( bcx, op. ty , "tmp_ret" )
846+ } ) ;
847+ ret_ty. store ( bcx, op. immediate ( ) , tmp) ;
848+ self . trans_load ( bcx, tmp, op. ty )
818849 } else {
819- op
850+ op. unpack_if_pair ( bcx )
820851 } ;
821852 self . temps [ idx as usize ] = TempRef :: Operand ( Some ( op) ) ;
822853 }
0 commit comments