11use std:: borrow:: Cow ;
2- use std:: iter;
32
4- use rustc:: hir;
53use rustc:: ty:: layout:: { FloatTy , Integer , Primitive , Scalar } ;
64use rustc_target:: spec:: abi:: Abi ;
75
@@ -44,26 +42,16 @@ pub fn scalar_to_clif_type(tcx: TyCtxt, scalar: Scalar) -> Type {
4442fn get_pass_mode < ' a , ' tcx : ' a > (
4543 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
4644 ty : Ty < ' tcx > ,
47- is_return : bool ,
4845) -> PassMode {
4946 let layout = tcx. layout_of ( ParamEnv :: reveal_all ( ) . and ( ty) ) . unwrap ( ) ;
5047 assert ! ( !layout. is_unsized( ) ) ;
5148
52- if layout. size . bytes ( ) == 0 {
53- if is_return {
54- PassMode :: NoPass
55- } else {
56- PassMode :: ByRef
57- }
49+ if layout. is_zst ( ) {
50+ // WARNING zst arguments must never be passed, as that will break CastKind::ClosureFnPointer
51+ PassMode :: NoPass
5852 } else {
5953 match & layout. abi {
60- layout:: Abi :: Uninhabited => {
61- if is_return {
62- PassMode :: NoPass
63- } else {
64- PassMode :: ByRef
65- }
66- }
54+ layout:: Abi :: Uninhabited => PassMode :: NoPass ,
6755 layout:: Abi :: Scalar ( scalar) => {
6856 PassMode :: ByVal ( scalar_to_clif_type ( tcx, scalar. clone ( ) ) )
6957 }
@@ -80,11 +68,11 @@ fn get_pass_mode<'a, 'tcx: 'a>(
8068fn adjust_arg_for_abi < ' a , ' tcx : ' a > (
8169 fx : & mut FunctionCx < ' a , ' tcx , impl Backend > ,
8270 arg : CValue < ' tcx > ,
83- ) -> Value {
84- match get_pass_mode ( fx. tcx , arg. layout ( ) . ty , false ) {
85- PassMode :: NoPass => unimplemented ! ( "pass mode nopass" ) ,
86- PassMode :: ByVal ( _) => arg. load_scalar ( fx) ,
87- PassMode :: ByRef => arg. force_stack ( fx) ,
71+ ) -> Option < Value > {
72+ match get_pass_mode ( fx. tcx , arg. layout ( ) . ty ) {
73+ PassMode :: NoPass => None ,
74+ PassMode :: ByVal ( _) => Some ( arg. load_scalar ( fx) ) ,
75+ PassMode :: ByRef => Some ( arg. force_stack ( fx) ) ,
8876 }
8977}
9078
@@ -109,13 +97,13 @@ fn clif_sig_from_fn_sig<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sig: FnSig<'t
10997
11098 let inputs = inputs
11199 . into_iter ( )
112- . filter_map ( |ty| match get_pass_mode ( tcx, ty, false ) {
100+ . filter_map ( |ty| match get_pass_mode ( tcx, ty) {
101+ PassMode :: NoPass => None ,
113102 PassMode :: ByVal ( clif_ty) => Some ( clif_ty) ,
114- PassMode :: NoPass => unimplemented ! ( "pass mode nopass" ) ,
115103 PassMode :: ByRef => Some ( pointer_ty ( tcx) ) ,
116104 } ) ;
117105
118- let ( params, returns) = match get_pass_mode ( tcx, output, true ) {
106+ let ( params, returns) = match get_pass_mode ( tcx, output) {
119107 PassMode :: NoPass => ( inputs. map ( AbiParam :: new) . collect ( ) , vec ! [ ] ) ,
120108 PassMode :: ByVal ( ret_ty) => (
121109 inputs. map ( AbiParam :: new) . collect ( ) ,
@@ -140,59 +128,13 @@ fn clif_sig_from_fn_sig<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sig: FnSig<'t
140128 }
141129}
142130
143- pub fn ty_fn_sig < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , ty : Ty < ' tcx > ) -> ty:: FnSig < ' tcx > {
144- let sig = match ty. sty {
145- ty:: FnDef ( ..) |
146- // Shims currently have type TyFnPtr. Not sure this should remain.
147- ty:: FnPtr ( _) => ty. fn_sig ( tcx) ,
148- ty:: Closure ( def_id, substs) => {
149- let sig = substs. closure_sig ( def_id, tcx) ;
150-
151- let env_ty = tcx. closure_env_ty ( def_id, substs) . unwrap ( ) ;
152- sig. map_bound ( |sig| tcx. mk_fn_sig (
153- iter:: once ( * env_ty. skip_binder ( ) ) . chain ( sig. inputs ( ) . iter ( ) . cloned ( ) ) ,
154- sig. output ( ) ,
155- sig. c_variadic ,
156- sig. unsafety ,
157- sig. abi
158- ) )
159- }
160- ty:: Generator ( def_id, substs, _) => {
161- let sig = substs. poly_sig ( def_id, tcx) ;
162-
163- let env_region = ty:: ReLateBound ( ty:: INNERMOST , ty:: BrEnv ) ;
164- let env_ty = tcx. mk_mut_ref ( tcx. mk_region ( env_region) , ty) ;
165-
166- sig. map_bound ( |sig| {
167- let state_did = tcx. lang_items ( ) . gen_state ( ) . unwrap ( ) ;
168- let state_adt_ref = tcx. adt_def ( state_did) ;
169- let state_substs = tcx. intern_substs ( & [
170- sig. yield_ty . into ( ) ,
171- sig. return_ty . into ( ) ,
172- ] ) ;
173- let ret_ty = tcx. mk_adt ( state_adt_ref, state_substs) ;
174-
175- tcx. mk_fn_sig ( iter:: once ( env_ty) ,
176- ret_ty,
177- false ,
178- hir:: Unsafety :: Normal ,
179- Abi :: Rust
180- )
181- } )
182- }
183- _ => bug ! ( "unexpected type {:?} to ty_fn_sig" , ty)
184- } ;
185- tcx. normalize_erasing_late_bound_regions ( ParamEnv :: reveal_all ( ) , & sig)
186- }
187-
188131pub fn get_function_name_and_sig < ' a , ' tcx > (
189132 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
190133 inst : Instance < ' tcx > ,
191134 support_vararg : bool ,
192135) -> ( String , Signature ) {
193136 assert ! ( !inst. substs. needs_infer( ) && !inst. substs. has_param_types( ) ) ;
194- let fn_ty = inst. ty ( tcx) ;
195- let fn_sig = ty_fn_sig ( tcx, fn_ty) ;
137+ let fn_sig = tcx. normalize_erasing_late_bound_regions ( ParamEnv :: reveal_all ( ) , & inst. fn_sig ( tcx) ) ;
196138 if fn_sig. c_variadic && !support_vararg {
197139 unimpl ! ( "Variadic function definitions are not yet supported" ) ;
198140 }
@@ -293,7 +235,7 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
293235 }
294236
295237 fn self_sig ( & self ) -> FnSig < ' tcx > {
296- ty_fn_sig ( self . tcx , self . instance . ty ( self . tcx ) )
238+ self . tcx . normalize_erasing_late_bound_regions ( ParamEnv :: reveal_all ( ) , & self . instance . fn_sig ( self . tcx ) )
297239 }
298240
299241 fn return_type ( & self ) -> Ty < ' tcx > {
@@ -405,9 +347,14 @@ fn cvalue_for_param<'a, 'tcx: 'a>(
405347 local_field : Option < usize > ,
406348 arg_ty : Ty < ' tcx > ,
407349 ssa_flags : crate :: analyze:: Flags ,
408- ) -> CValue < ' tcx > {
350+ ) -> Option < CValue < ' tcx > > {
409351 let layout = fx. layout_of ( arg_ty) ;
410- let pass_mode = get_pass_mode ( fx. tcx , arg_ty, false ) ;
352+ let pass_mode = get_pass_mode ( fx. tcx , arg_ty) ;
353+
354+ if let PassMode :: NoPass = pass_mode {
355+ return None ;
356+ }
357+
411358 let clif_type = pass_mode. get_param_ty ( fx) ;
412359 let ebb_param = fx. bcx . append_ebb_param ( start_ebb, clif_type) ;
413360
@@ -424,9 +371,9 @@ fn cvalue_for_param<'a, 'tcx: 'a>(
424371 ) ;
425372
426373 match pass_mode {
427- PassMode :: NoPass => unimplemented ! ( "pass mode nopass" ) ,
428- PassMode :: ByVal ( _) => CValue :: ByVal ( ebb_param, layout) ,
429- PassMode :: ByRef => CValue :: ByRef ( ebb_param, layout) ,
374+ PassMode :: NoPass => unreachable ! ( ) ,
375+ PassMode :: ByVal ( _) => Some ( CValue :: ByVal ( ebb_param, layout) ) ,
376+ PassMode :: ByRef => Some ( CValue :: ByRef ( ebb_param, layout) ) ,
430377 }
431378}
432379
@@ -440,7 +387,7 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
440387 fx. add_global_comment ( format ! ( "ssa {:?}" , ssa_analyzed) ) ;
441388
442389 let ret_layout = fx. layout_of ( fx. return_type ( ) ) ;
443- let output_pass_mode = get_pass_mode ( fx. tcx , fx. return_type ( ) , true ) ;
390+ let output_pass_mode = get_pass_mode ( fx. tcx , fx. return_type ( ) ) ;
444391 let ret_param = match output_pass_mode {
445392 PassMode :: NoPass => None ,
446393 PassMode :: ByVal ( _) => None ,
@@ -462,9 +409,10 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
462409 ) ;
463410 }
464411
412+ // None means pass_mode == NoPass
465413 enum ArgKind < ' tcx > {
466- Normal ( CValue < ' tcx > ) ,
467- Spread ( Vec < CValue < ' tcx > > ) ,
414+ Normal ( Option < CValue < ' tcx > > ) ,
415+ Spread ( Vec < Option < CValue < ' tcx > > > ) ,
468416 }
469417
470418 let func_params = fx
@@ -542,13 +490,17 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
542490
543491 match arg_kind {
544492 ArgKind :: Normal ( param) => {
545- place. write_cvalue ( fx, param) ;
493+ if let Some ( param) = param {
494+ place. write_cvalue ( fx, param) ;
495+ }
546496 }
547497 ArgKind :: Spread ( params) => {
548498 for ( i, param) in params. into_iter ( ) . enumerate ( ) {
549- place
550- . place_field ( fx, mir:: Field :: new ( i) )
551- . write_cvalue ( fx, param) ;
499+ if let Some ( param) = param {
500+ place
501+ . place_field ( fx, mir:: Field :: new ( i) )
502+ . write_cvalue ( fx, param) ;
503+ }
552504 }
553505 }
554506 }
@@ -578,7 +530,7 @@ pub fn codegen_terminator_call<'a, 'tcx: 'a>(
578530 destination : & Option < ( Place < ' tcx > , BasicBlock ) > ,
579531) {
580532 let fn_ty = fx. monomorphize ( & func. ty ( fx. mir , fx. tcx ) ) ;
581- let sig = ty_fn_sig ( fx. tcx , fn_ty) ;
533+ let sig = fx. tcx . normalize_erasing_late_bound_regions ( ParamEnv :: reveal_all ( ) , & fn_ty. fn_sig ( fx . tcx ) ) ;
582534
583535 // Unpack arguments tuple for closures
584536 let args = if sig. abi == Abi :: RustCall {
@@ -649,11 +601,11 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
649601 args : Vec < CValue < ' tcx > > ,
650602 ret_place : Option < CPlace < ' tcx > > ,
651603) {
652- let fn_sig = ty_fn_sig ( fx. tcx , fn_ty) ;
604+ let fn_sig = fx. tcx . normalize_erasing_late_bound_regions ( ParamEnv :: reveal_all ( ) , & fn_ty. fn_sig ( fx . tcx ) ) ;
653605
654606 let ret_layout = fx. layout_of ( fn_sig. output ( ) ) ;
655607
656- let output_pass_mode = get_pass_mode ( fx. tcx , fn_sig. output ( ) , true ) ;
608+ let output_pass_mode = get_pass_mode ( fx. tcx , fn_sig. output ( ) ) ;
657609 let return_ptr = match output_pass_mode {
658610 PassMode :: NoPass => None ,
659611 PassMode :: ByRef => match ret_place {
@@ -683,15 +635,15 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
683635 }
684636
685637 // Normal call
686- Some ( _) => ( None , args. get ( 0 ) . map ( |arg| adjust_arg_for_abi ( fx, * arg) ) ) ,
638+ Some ( _) => ( None , args. get ( 0 ) . and_then ( |arg| adjust_arg_for_abi ( fx, * arg) ) ) ,
687639
688640 // Indirect call
689641 None => {
690642 let func = trans_operand ( fx, func. expect ( "indirect call without func Operand" ) )
691643 . load_scalar ( fx) ;
692644 (
693645 Some ( func) ,
694- args. get ( 0 ) . map ( |arg| adjust_arg_for_abi ( fx, * arg) ) ,
646+ args. get ( 0 ) . and_then ( |arg| adjust_arg_for_abi ( fx, * arg) ) ,
695647 )
696648 }
697649 } ;
@@ -702,7 +654,7 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
702654 . chain (
703655 args. into_iter ( )
704656 . skip ( 1 )
705- . map ( |arg| adjust_arg_for_abi ( fx, arg) ) ,
657+ . filter_map ( |arg| adjust_arg_for_abi ( fx, arg) ) ,
706658 )
707659 . collect :: < Vec < _ > > ( ) ;
708660
@@ -756,9 +708,9 @@ pub fn codegen_drop<'a, 'tcx: 'a>(
756708 let ( ptr, vtable) = drop_place. to_addr_maybe_unsized ( fx) ;
757709 let drop_fn = crate :: vtable:: drop_fn_of_obj ( fx, vtable. unwrap ( ) ) ;
758710
759- let fn_sig = ty_fn_sig ( fx. tcx , drop_fn_ty) ;
711+ let fn_sig = fx. tcx . normalize_erasing_late_bound_regions ( ParamEnv :: reveal_all ( ) , & drop_fn_ty. fn_sig ( fx . tcx ) ) ;
760712
761- match get_pass_mode ( fx. tcx , fn_sig. output ( ) , true ) {
713+ match get_pass_mode ( fx. tcx , fn_sig. output ( ) ) {
762714 PassMode :: NoPass => { }
763715 _ => unreachable ! ( ) ,
764716 } ;
@@ -770,7 +722,7 @@ pub fn codegen_drop<'a, 'tcx: 'a>(
770722}
771723
772724pub fn codegen_return ( fx : & mut FunctionCx < impl Backend > ) {
773- match get_pass_mode ( fx. tcx , fx. return_type ( ) , true ) {
725+ match get_pass_mode ( fx. tcx , fx. return_type ( ) ) {
774726 PassMode :: NoPass | PassMode :: ByRef => {
775727 fx. bcx . ins ( ) . return_ ( & [ ] ) ;
776728 }
0 commit comments