@@ -2514,7 +2514,7 @@ where
25142514 extra_args : & [ Ty < ' tcx > ] ,
25152515 caller_location : Option < Ty < ' tcx > > ,
25162516 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 ,
25182518 ) -> Self ;
25192519 fn adjust_for_abi ( & mut self , cx : & C , abi : SpecAbi ) ;
25202520}
@@ -2574,9 +2574,7 @@ where
25742574 // Assume that fn pointers may always unwind
25752575 let codegen_fn_attr_flags = CodegenFnAttrFlags :: UNWIND ;
25762576
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 )
25802578 }
25812579
25822580 fn of_instance ( cx : & C , instance : ty:: Instance < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
@@ -2590,55 +2588,14 @@ where
25902588
25912589 let attrs = cx. tcx ( ) . codegen_fn_attrs ( instance. def_id ( ) ) . flags ;
25922590
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+ )
26422599 }
26432600
26442601 fn new_internal (
@@ -2647,7 +2604,7 @@ where
26472604 extra_args : & [ Ty < ' tcx > ] ,
26482605 caller_location : Option < Ty < ' tcx > > ,
26492606 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 ,
26512608 ) -> Self {
26522609 debug ! ( "FnAbi::new_internal({:?}, {:?})" , sig, extra_args) ;
26532610
@@ -2778,7 +2735,23 @@ where
27782735
27792736 let arg_of = |ty : Ty < ' tcx > , arg_idx : Option < usize > | {
27802737 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+
27822755 if arg. layout . is_zst ( ) {
27832756 // For some forsaken reason, x86_64-pc-windows-gnu
27842757 // doesn't ignore zero-sized struct arguments.
@@ -2794,30 +2767,6 @@ where
27942767 }
27952768 }
27962769
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-
28212770 arg
28222771 } ;
28232772
@@ -2894,9 +2843,10 @@ where
28942843 let max_by_val_size = Pointer . size ( cx) * 2 ;
28952844 let size = arg. layout . size ;
28962845
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 {
29002850 // We want to pass small aggregates as immediates, but using
29012851 // a LLVM aggregate type for this leads to bad optimizations,
29022852 // so we pick an appropriately sized integer type instead.
@@ -2915,3 +2865,52 @@ where
29152865 }
29162866 }
29172867}
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