@@ -2514,7 +2514,7 @@ where
2514
2514
extra_args : & [ Ty < ' tcx > ] ,
2515
2515
caller_location : Option < Ty < ' tcx > > ,
2516
2516
codegen_fn_attr_flags : CodegenFnAttrFlags ,
2517
- mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgAbi < ' tcx , Ty < ' tcx > > ,
2517
+ make_self_ptr_thin : bool ,
2518
2518
) -> Self ;
2519
2519
fn adjust_for_abi ( & mut self , cx : & C , abi : SpecAbi ) ;
2520
2520
}
@@ -2574,9 +2574,7 @@ where
2574
2574
// Assume that fn pointers may always unwind
2575
2575
let codegen_fn_attr_flags = CodegenFnAttrFlags :: UNWIND ;
2576
2576
2577
- call:: FnAbi :: new_internal ( cx, sig, extra_args, None , codegen_fn_attr_flags, |ty, _| {
2578
- ArgAbi :: new ( cx. layout_of ( ty) )
2579
- } )
2577
+ call:: FnAbi :: new_internal ( cx, sig, extra_args, None , codegen_fn_attr_flags, false )
2580
2578
}
2581
2579
2582
2580
fn of_instance ( cx : & C , instance : ty:: Instance < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
@@ -2590,55 +2588,14 @@ where
2590
2588
2591
2589
let attrs = cx. tcx ( ) . codegen_fn_attrs ( instance. def_id ( ) ) . flags ;
2592
2590
2593
- call:: FnAbi :: new_internal ( cx, sig, extra_args, caller_location, attrs, |ty, arg_idx| {
2594
- let mut layout = cx. layout_of ( ty) ;
2595
- // Don't pass the vtable, it's not an argument of the virtual fn.
2596
- // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
2597
- // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
2598
- if let ( ty:: InstanceDef :: Virtual ( ..) , Some ( 0 ) ) = ( & instance. def , arg_idx) {
2599
- let fat_pointer_ty = if layout. is_unsized ( ) {
2600
- // unsized `self` is passed as a pointer to `self`
2601
- // FIXME (mikeyhew) change this to use &own if it is ever added to the language
2602
- cx. tcx ( ) . mk_mut_ptr ( layout. ty )
2603
- } else {
2604
- match layout. abi {
2605
- Abi :: ScalarPair ( ..) => ( ) ,
2606
- _ => bug ! ( "receiver type has unsupported layout: {:?}" , layout) ,
2607
- }
2608
-
2609
- // In the case of Rc<Self>, we need to explicitly pass a *mut RcBox<Self>
2610
- // with a Scalar (not ScalarPair) ABI. This is a hack that is understood
2611
- // elsewhere in the compiler as a method on a `dyn Trait`.
2612
- // To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
2613
- // get a built-in pointer type
2614
- let mut fat_pointer_layout = layout;
2615
- ' descend_newtypes: while !fat_pointer_layout. ty . is_unsafe_ptr ( )
2616
- && !fat_pointer_layout. ty . is_region_ptr ( )
2617
- {
2618
- for i in 0 ..fat_pointer_layout. fields . count ( ) {
2619
- let field_layout = fat_pointer_layout. field ( cx, i) ;
2620
-
2621
- if !field_layout. is_zst ( ) {
2622
- fat_pointer_layout = field_layout;
2623
- continue ' descend_newtypes;
2624
- }
2625
- }
2626
-
2627
- bug ! ( "receiver has no non-zero-sized fields {:?}" , fat_pointer_layout) ;
2628
- }
2629
-
2630
- fat_pointer_layout. ty
2631
- } ;
2632
-
2633
- // we now have a type like `*mut RcBox<dyn Trait>`
2634
- // change its layout to that of `*mut ()`, a thin pointer, but keep the same type
2635
- // this is understood as a special case elsewhere in the compiler
2636
- let unit_pointer_ty = cx. tcx ( ) . mk_mut_ptr ( cx. tcx ( ) . mk_unit ( ) ) ;
2637
- layout = cx. layout_of ( unit_pointer_ty) ;
2638
- layout. ty = fat_pointer_ty;
2639
- }
2640
- ArgAbi :: new ( layout)
2641
- } )
2591
+ call:: FnAbi :: new_internal (
2592
+ cx,
2593
+ sig,
2594
+ extra_args,
2595
+ caller_location,
2596
+ attrs,
2597
+ matches ! ( instance. def, ty:: InstanceDef :: Virtual ( ..) ) ,
2598
+ )
2642
2599
}
2643
2600
2644
2601
fn new_internal (
@@ -2647,7 +2604,7 @@ where
2647
2604
extra_args : & [ Ty < ' tcx > ] ,
2648
2605
caller_location : Option < Ty < ' tcx > > ,
2649
2606
codegen_fn_attr_flags : CodegenFnAttrFlags ,
2650
- mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgAbi < ' tcx , Ty < ' tcx > > ,
2607
+ force_thin_self_ptr : bool ,
2651
2608
) -> Self {
2652
2609
debug ! ( "FnAbi::new_internal({:?}, {:?})" , sig, extra_args) ;
2653
2610
@@ -2778,7 +2735,23 @@ where
2778
2735
2779
2736
let arg_of = |ty : Ty < ' tcx > , arg_idx : Option < usize > | {
2780
2737
let is_return = arg_idx. is_none ( ) ;
2781
- let mut arg = mk_arg_type ( ty, arg_idx) ;
2738
+
2739
+ let layout = cx. layout_of ( ty) ;
2740
+ let layout = if force_thin_self_ptr && arg_idx == Some ( 0 ) {
2741
+ // Don't pass the vtable, it's not an argument of the virtual fn.
2742
+ // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
2743
+ // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
2744
+ make_thin_self_ptr ( cx, layout)
2745
+ } else {
2746
+ layout
2747
+ } ;
2748
+
2749
+ let mut arg = ArgAbi :: new ( cx, layout, |layout, scalar, offset| {
2750
+ let mut attrs = ArgAttributes :: new ( ) ;
2751
+ adjust_for_rust_scalar ( & mut attrs, scalar, * layout, offset, is_return) ;
2752
+ attrs
2753
+ } ) ;
2754
+
2782
2755
if arg. layout . is_zst ( ) {
2783
2756
// For some forsaken reason, x86_64-pc-windows-gnu
2784
2757
// doesn't ignore zero-sized struct arguments.
@@ -2794,30 +2767,6 @@ where
2794
2767
}
2795
2768
}
2796
2769
2797
- // FIXME(eddyb) other ABIs don't have logic for scalar pairs.
2798
- if !is_return && rust_abi {
2799
- if let Abi :: ScalarPair ( ref a, ref b) = arg. layout . abi {
2800
- let mut a_attrs = ArgAttributes :: new ( ) ;
2801
- let mut b_attrs = ArgAttributes :: new ( ) ;
2802
- adjust_for_rust_scalar ( & mut a_attrs, a, arg. layout , Size :: ZERO , false ) ;
2803
- adjust_for_rust_scalar (
2804
- & mut b_attrs,
2805
- b,
2806
- arg. layout ,
2807
- a. value . size ( cx) . align_to ( b. value . align ( cx) . abi ) ,
2808
- false ,
2809
- ) ;
2810
- arg. mode = PassMode :: Pair ( a_attrs, b_attrs) ;
2811
- return arg;
2812
- }
2813
- }
2814
-
2815
- if let Abi :: Scalar ( ref scalar) = arg. layout . abi {
2816
- if let PassMode :: Direct ( ref mut attrs) = arg. mode {
2817
- adjust_for_rust_scalar ( attrs, scalar, arg. layout , Size :: ZERO , is_return) ;
2818
- }
2819
- }
2820
-
2821
2770
arg
2822
2771
} ;
2823
2772
@@ -2894,9 +2843,10 @@ where
2894
2843
let max_by_val_size = Pointer . size ( cx) * 2 ;
2895
2844
let size = arg. layout . size ;
2896
2845
2897
- if arg. layout . is_unsized ( ) || size > max_by_val_size {
2898
- arg. make_indirect ( ) ;
2899
- } else {
2846
+ let is_indirect_not_on_stack =
2847
+ matches ! ( arg. mode, PassMode :: Indirect { on_stack: false , .. } ) ;
2848
+ assert ! ( is_indirect_not_on_stack, "{:?}" , arg) ;
2849
+ if !arg. layout . is_unsized ( ) && size <= max_by_val_size {
2900
2850
// We want to pass small aggregates as immediates, but using
2901
2851
// a LLVM aggregate type for this leads to bad optimizations,
2902
2852
// so we pick an appropriately sized integer type instead.
@@ -2915,3 +2865,52 @@ where
2915
2865
}
2916
2866
}
2917
2867
}
2868
+
2869
+ fn make_thin_self_ptr < ' tcx , C > ( cx : & C , mut layout : TyAndLayout < ' tcx > ) -> TyAndLayout < ' tcx >
2870
+ where
2871
+ C : LayoutOf < Ty = Ty < ' tcx > , TyAndLayout = TyAndLayout < ' tcx > >
2872
+ + HasTyCtxt < ' tcx >
2873
+ + HasParamEnv < ' tcx > ,
2874
+ {
2875
+ let fat_pointer_ty = if layout. is_unsized ( ) {
2876
+ // unsized `self` is passed as a pointer to `self`
2877
+ // FIXME (mikeyhew) change this to use &own if it is ever added to the language
2878
+ cx. tcx ( ) . mk_mut_ptr ( layout. ty )
2879
+ } else {
2880
+ match layout. abi {
2881
+ Abi :: ScalarPair ( ..) => ( ) ,
2882
+ _ => bug ! ( "receiver type has unsupported layout: {:?}" , layout) ,
2883
+ }
2884
+
2885
+ // In the case of Rc<Self>, we need to explicitly pass a *mut RcBox<Self>
2886
+ // with a Scalar (not ScalarPair) ABI. This is a hack that is understood
2887
+ // elsewhere in the compiler as a method on a `dyn Trait`.
2888
+ // To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
2889
+ // get a built-in pointer type
2890
+ let mut fat_pointer_layout = layout;
2891
+ ' descend_newtypes: while !fat_pointer_layout. ty . is_unsafe_ptr ( )
2892
+ && !fat_pointer_layout. ty . is_region_ptr ( )
2893
+ {
2894
+ for i in 0 ..fat_pointer_layout. fields . count ( ) {
2895
+ let field_layout = fat_pointer_layout. field ( cx, i) ;
2896
+
2897
+ if !field_layout. is_zst ( ) {
2898
+ fat_pointer_layout = field_layout;
2899
+ continue ' descend_newtypes;
2900
+ }
2901
+ }
2902
+
2903
+ bug ! ( "receiver has no non-zero-sized fields {:?}" , fat_pointer_layout) ;
2904
+ }
2905
+
2906
+ fat_pointer_layout. ty
2907
+ } ;
2908
+
2909
+ // we now have a type like `*mut RcBox<dyn Trait>`
2910
+ // change its layout to that of `*mut ()`, a thin pointer, but keep the same type
2911
+ // this is understood as a special case elsewhere in the compiler
2912
+ let unit_pointer_ty = cx. tcx ( ) . mk_mut_ptr ( cx. tcx ( ) . mk_unit ( ) ) ;
2913
+ layout = cx. layout_of ( unit_pointer_ty) ;
2914
+ layout. ty = fat_pointer_ty;
2915
+ layout
2916
+ }
0 commit comments