@@ -54,7 +54,7 @@ use trans::callee;
54
54
use trans:: cleanup:: { self , CleanupMethods , DropHint } ;
55
55
use trans:: closure;
56
56
use trans:: common:: { Block , C_bool , C_bytes_in_context , C_i32 , C_int , C_integral } ;
57
- use trans:: common:: { C_null , C_struct_in_context , C_u64 , C_u8 , C_undef } ;
57
+ use trans:: common:: { C_null , C_struct_in_context , C_u64 , C_u8 , C_undef , C_nil } ;
58
58
use trans:: common:: { CrateContext , DropFlagHintsMap , Field , FunctionContext } ;
59
59
use trans:: common:: { Result , NodeIdAndSpan , VariantInfo } ;
60
60
use trans:: common:: { node_id_type, return_type_is_void} ;
@@ -699,8 +699,22 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
699
699
debug_loc : DebugLoc )
700
700
-> ( ValueRef , Block < ' blk , ' tcx > ) {
701
701
let _icx = push_ctxt ( "invoke_" ) ;
702
+
703
+ let ret_ty = match fn_ty. sty {
704
+ ty:: TyBareFn ( _, ref f) => {
705
+ let output = bcx. tcx ( ) . erase_late_bound_regions ( & f. sig . output ( ) ) ;
706
+ output
707
+ }
708
+ _ => panic ! ( "expected bare rust fn or closure in trans_call_inner" )
709
+ } ;
710
+
702
711
if bcx. unreachable . get ( ) {
703
- return ( C_null ( Type :: i8 ( bcx. ccx ( ) ) ) , bcx) ;
712
+ if let ty:: FnConverging ( ty) = ret_ty {
713
+ let llty = type_of:: arg_type_of ( bcx. ccx ( ) , ty) ;
714
+ return ( C_undef ( llty) , bcx) ;
715
+ } else {
716
+ return ( C_nil ( bcx. ccx ( ) ) , bcx) ;
717
+ }
704
718
}
705
719
706
720
let attributes = attributes:: from_fn_type ( bcx. ccx ( ) , fn_ty) ;
@@ -722,25 +736,39 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
722
736
let normal_bcx = bcx. fcx . new_temp_block ( "normal-return" ) ;
723
737
let landing_pad = bcx. fcx . get_landing_pad ( ) ;
724
738
725
- let llresult = Invoke ( bcx,
739
+ let mut llresult = Invoke ( bcx,
726
740
llfn,
727
741
& llargs[ ..] ,
728
742
normal_bcx. llbb ,
729
743
landing_pad,
730
744
Some ( attributes) ,
731
745
debug_loc) ;
746
+ if let ty:: FnConverging ( ty) = ret_ty {
747
+ if return_type_is_void ( bcx. ccx ( ) , ty) {
748
+ llresult = C_nil ( bcx. ccx ( ) ) ;
749
+ }
750
+ } else {
751
+ llresult = C_nil ( bcx. ccx ( ) ) ;
752
+ }
732
753
return ( llresult, normal_bcx) ;
733
754
} else {
734
755
debug ! ( "calling {} at {:?}" , bcx. val_to_string( llfn) , bcx. llbb) ;
735
756
for & llarg in llargs {
736
757
debug ! ( "arg: {}" , bcx. val_to_string( llarg) ) ;
737
758
}
738
759
739
- let llresult = Call ( bcx,
740
- llfn,
741
- & llargs[ ..] ,
742
- Some ( attributes) ,
743
- debug_loc) ;
760
+ let mut llresult = Call ( bcx,
761
+ llfn,
762
+ & llargs[ ..] ,
763
+ Some ( attributes) ,
764
+ debug_loc) ;
765
+ if let ty:: FnConverging ( ty) = ret_ty {
766
+ if return_type_is_void ( bcx. ccx ( ) , ty) {
767
+ llresult = C_nil ( bcx. ccx ( ) ) ;
768
+ }
769
+ } else {
770
+ llresult = C_nil ( bcx. ccx ( ) ) ;
771
+ }
744
772
return ( llresult, bcx) ;
745
773
}
746
774
}
@@ -775,23 +803,41 @@ pub fn load_if_immediate<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
775
803
/// gives us better information about what we are loading.
776
804
pub fn load_ty < ' blk , ' tcx > ( cx : Block < ' blk , ' tcx > ,
777
805
ptr : ValueRef , t : Ty < ' tcx > ) -> ValueRef {
806
+ use trans:: basic_block:: BasicBlock ;
807
+
778
808
if cx. unreachable . get ( ) || type_is_zero_size ( cx. ccx ( ) , t) {
779
809
return C_undef ( type_of:: type_of ( cx. ccx ( ) , t) ) ;
780
810
}
781
811
782
812
let ptr = to_arg_ty_ptr ( cx, ptr, t) ;
813
+ let ptr = Value ( ptr) ;
783
814
let align = type_of:: align_of ( cx. ccx ( ) , t) ;
784
815
816
+ let bb = BasicBlock ( cx. llbb ) ;
817
+
785
818
if type_is_immediate ( cx. ccx ( ) , t) && type_of:: type_of ( cx. ccx ( ) , t) . is_aggregate ( ) {
786
- let load = Load ( cx, ptr) ;
819
+ if let Some ( val) = ptr. get_dominating_store ( cx) {
820
+ let valbb = val. get_parent ( ) ;
821
+
822
+ if Some ( bb) == valbb {
823
+ if let Some ( val) = val. get_operand ( 0 ) {
824
+ debug ! ( "Eliding load from {}" , cx. ccx( ) . tn( ) . val_to_string( ptr. get( ) ) ) ;
825
+ debug ! ( " Using previous stored value: {}" ,
826
+ cx. ccx( ) . tn( ) . val_to_string( val. get( ) ) ) ;
827
+ return val. get ( ) ;
828
+ }
829
+ }
830
+ }
831
+
832
+ let load = Load ( cx, ptr. get ( ) ) ;
787
833
unsafe {
788
834
llvm:: LLVMSetAlignment ( load, align) ;
789
835
}
790
836
return load;
791
837
}
792
838
793
839
unsafe {
794
- let global = llvm:: LLVMIsAGlobalVariable ( ptr) ;
840
+ let global = llvm:: LLVMIsAGlobalVariable ( ptr. get ( ) ) ;
795
841
if !global. is_null ( ) && llvm:: LLVMIsGlobalConstant ( global) == llvm:: True {
796
842
let val = llvm:: LLVMGetInitializer ( global) ;
797
843
if !val. is_null ( ) {
@@ -800,17 +846,30 @@ pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
800
846
}
801
847
}
802
848
849
+ if let Some ( val) = ptr. get_dominating_store ( cx) {
850
+ let valbb = val. get_parent ( ) ;
851
+
852
+ if Some ( bb) == valbb {
853
+ if let Some ( val) = val. get_operand ( 0 ) {
854
+ debug ! ( "Eliding load from {}" , cx. ccx( ) . tn( ) . val_to_string( ptr. get( ) ) ) ;
855
+ debug ! ( " Using previous stored value: {}" ,
856
+ cx. ccx( ) . tn( ) . val_to_string( val. get( ) ) ) ;
857
+ return to_arg_ty ( cx, val. get ( ) , t) ;
858
+ }
859
+ }
860
+ }
861
+
803
862
let val = if t. is_bool ( ) {
804
- LoadRangeAssert ( cx, ptr, 0 , 2 , llvm:: False )
863
+ LoadRangeAssert ( cx, ptr. get ( ) , 0 , 2 , llvm:: False )
805
864
} else if t. is_char ( ) {
806
865
// a char is a Unicode codepoint, and so takes values from 0
807
866
// to 0x10FFFF inclusive only.
808
- LoadRangeAssert ( cx, ptr, 0 , 0x10FFFF + 1 , llvm:: False )
867
+ LoadRangeAssert ( cx, ptr. get ( ) , 0 , 0x10FFFF + 1 , llvm:: False )
809
868
} else if ( t. is_region_ptr ( ) || t. is_unique ( ) )
810
869
&& !common:: type_is_fat_ptr ( cx. tcx ( ) , t) {
811
- LoadNonNull ( cx, ptr)
870
+ LoadNonNull ( cx, ptr. get ( ) )
812
871
} else {
813
- Load ( cx, ptr)
872
+ Load ( cx, ptr. get ( ) )
814
873
} ;
815
874
816
875
unsafe {
@@ -831,7 +890,18 @@ pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t
831
890
Store ( cx, ExtractValue ( cx, v, abi:: FAT_PTR_ADDR ) , expr:: get_dataptr ( cx, dst) ) ;
832
891
Store ( cx, ExtractValue ( cx, v, abi:: FAT_PTR_EXTRA ) , expr:: get_len ( cx, dst) ) ;
833
892
} else {
834
- let store = Store ( cx, from_arg_ty ( cx, v, t) , to_arg_ty_ptr ( cx, dst, t) ) ;
893
+ let vty = val_ty ( v) ;
894
+ let dstty = val_ty ( dst) . element_type ( ) ;
895
+
896
+ // If the source and destination have the same type, then don't try any conversion,
897
+ // this can happen with the return values of functions, as they don't touch an alloca
898
+ let ( v, dst) = if vty == dstty {
899
+ ( v, dst)
900
+ } else {
901
+ ( from_arg_ty ( cx, v, t) , to_arg_ty_ptr ( cx, dst, t) )
902
+ } ;
903
+
904
+ let store = Store ( cx, v, dst) ;
835
905
unsafe {
836
906
llvm:: LLVMSetAlignment ( store, type_of:: align_of ( cx. ccx ( ) , t) ) ;
837
907
}
@@ -848,7 +918,16 @@ pub fn from_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
848
918
849
919
pub fn to_arg_ty ( bcx : Block , val : ValueRef , ty : Ty ) -> ValueRef {
850
920
if ty. is_bool ( ) {
851
- Trunc ( bcx, val, Type :: i1 ( bcx. ccx ( ) ) )
921
+ let val = Value ( val) ;
922
+ if let Some ( zext) = val. as_zext_inst ( ) {
923
+ if let Some ( val) = zext. get_operand ( 0 ) {
924
+ let valty = val_ty ( val. get ( ) ) ;
925
+ if valty == Type :: i1 ( bcx. ccx ( ) ) {
926
+ return val. get ( ) ;
927
+ }
928
+ }
929
+ }
930
+ Trunc ( bcx, val. get ( ) , Type :: i1 ( bcx. ccx ( ) ) )
852
931
} else {
853
932
val
854
933
}
@@ -1709,8 +1788,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
1709
1788
disr : ty:: Disr ,
1710
1789
args : callee:: CallArgs ,
1711
1790
dest : expr:: Dest ,
1712
- debug_loc : DebugLoc )
1713
- -> Result < ' blk , ' tcx > {
1791
+ debug_loc : DebugLoc ) -> Result < ' blk , ' tcx > {
1714
1792
1715
1793
let ccx = bcx. fcx . ccx ;
1716
1794
@@ -1753,6 +1831,12 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
1753
1831
}
1754
1832
}
1755
1833
1834
+ let llretval = if type_is_immediate ( bcx. ccx ( ) , result_ty) {
1835
+ load_ty ( bcx, llresult, result_ty)
1836
+ } else {
1837
+ C_undef ( type_of:: type_of ( bcx. ccx ( ) , result_ty) )
1838
+ } ;
1839
+
1756
1840
// If the caller doesn't care about the result
1757
1841
// drop the temporary we made
1758
1842
let bcx = match dest {
@@ -1766,7 +1850,8 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
1766
1850
}
1767
1851
} ;
1768
1852
1769
- Result :: new ( bcx, llresult)
1853
+
1854
+ Result :: new ( bcx, llretval)
1770
1855
}
1771
1856
1772
1857
pub fn trans_tuple_struct < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
0 commit comments