1
1
use std:: borrow:: Cow ;
2
- use std:: iter;
3
2
4
- use rustc:: hir;
5
3
use rustc:: ty:: layout:: { FloatTy , Integer , Primitive , Scalar } ;
6
4
use rustc_target:: spec:: abi:: Abi ;
7
5
@@ -44,26 +42,16 @@ pub fn scalar_to_clif_type(tcx: TyCtxt, scalar: Scalar) -> Type {
44
42
fn get_pass_mode < ' a , ' tcx : ' a > (
45
43
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
46
44
ty : Ty < ' tcx > ,
47
- is_return : bool ,
48
45
) -> PassMode {
49
46
let layout = tcx. layout_of ( ParamEnv :: reveal_all ( ) . and ( ty) ) . unwrap ( ) ;
50
47
assert ! ( !layout. is_unsized( ) ) ;
51
48
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
58
52
} else {
59
53
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 ,
67
55
layout:: Abi :: Scalar ( scalar) => {
68
56
PassMode :: ByVal ( scalar_to_clif_type ( tcx, scalar. clone ( ) ) )
69
57
}
@@ -80,11 +68,11 @@ fn get_pass_mode<'a, 'tcx: 'a>(
80
68
fn adjust_arg_for_abi < ' a , ' tcx : ' a > (
81
69
fx : & mut FunctionCx < ' a , ' tcx , impl Backend > ,
82
70
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) ) ,
88
76
}
89
77
}
90
78
@@ -109,13 +97,13 @@ fn clif_sig_from_fn_sig<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sig: FnSig<'t
109
97
110
98
let inputs = inputs
111
99
. 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 ,
113
102
PassMode :: ByVal ( clif_ty) => Some ( clif_ty) ,
114
- PassMode :: NoPass => unimplemented ! ( "pass mode nopass" ) ,
115
103
PassMode :: ByRef => Some ( pointer_ty ( tcx) ) ,
116
104
} ) ;
117
105
118
- let ( params, returns) = match get_pass_mode ( tcx, output, true ) {
106
+ let ( params, returns) = match get_pass_mode ( tcx, output) {
119
107
PassMode :: NoPass => ( inputs. map ( AbiParam :: new) . collect ( ) , vec ! [ ] ) ,
120
108
PassMode :: ByVal ( ret_ty) => (
121
109
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
140
128
}
141
129
}
142
130
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
-
188
131
pub fn get_function_name_and_sig < ' a , ' tcx > (
189
132
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
190
133
inst : Instance < ' tcx > ,
191
134
support_vararg : bool ,
192
135
) -> ( String , Signature ) {
193
136
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) ) ;
196
138
if fn_sig. c_variadic && !support_vararg {
197
139
unimpl ! ( "Variadic function definitions are not yet supported" ) ;
198
140
}
@@ -293,7 +235,7 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
293
235
}
294
236
295
237
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 ) )
297
239
}
298
240
299
241
fn return_type ( & self ) -> Ty < ' tcx > {
@@ -405,9 +347,14 @@ fn cvalue_for_param<'a, 'tcx: 'a>(
405
347
local_field : Option < usize > ,
406
348
arg_ty : Ty < ' tcx > ,
407
349
ssa_flags : crate :: analyze:: Flags ,
408
- ) -> CValue < ' tcx > {
350
+ ) -> Option < CValue < ' tcx > > {
409
351
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
+
411
358
let clif_type = pass_mode. get_param_ty ( fx) ;
412
359
let ebb_param = fx. bcx . append_ebb_param ( start_ebb, clif_type) ;
413
360
@@ -424,9 +371,9 @@ fn cvalue_for_param<'a, 'tcx: 'a>(
424
371
) ;
425
372
426
373
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) ) ,
430
377
}
431
378
}
432
379
@@ -440,7 +387,7 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
440
387
fx. add_global_comment ( format ! ( "ssa {:?}" , ssa_analyzed) ) ;
441
388
442
389
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 ( ) ) ;
444
391
let ret_param = match output_pass_mode {
445
392
PassMode :: NoPass => None ,
446
393
PassMode :: ByVal ( _) => None ,
@@ -462,9 +409,10 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
462
409
) ;
463
410
}
464
411
412
+ // None means pass_mode == NoPass
465
413
enum ArgKind < ' tcx > {
466
- Normal ( CValue < ' tcx > ) ,
467
- Spread ( Vec < CValue < ' tcx > > ) ,
414
+ Normal ( Option < CValue < ' tcx > > ) ,
415
+ Spread ( Vec < Option < CValue < ' tcx > > > ) ,
468
416
}
469
417
470
418
let func_params = fx
@@ -542,13 +490,17 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
542
490
543
491
match arg_kind {
544
492
ArgKind :: Normal ( param) => {
545
- place. write_cvalue ( fx, param) ;
493
+ if let Some ( param) = param {
494
+ place. write_cvalue ( fx, param) ;
495
+ }
546
496
}
547
497
ArgKind :: Spread ( params) => {
548
498
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
+ }
552
504
}
553
505
}
554
506
}
@@ -578,7 +530,7 @@ pub fn codegen_terminator_call<'a, 'tcx: 'a>(
578
530
destination : & Option < ( Place < ' tcx > , BasicBlock ) > ,
579
531
) {
580
532
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 ) ) ;
582
534
583
535
// Unpack arguments tuple for closures
584
536
let args = if sig. abi == Abi :: RustCall {
@@ -649,11 +601,11 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
649
601
args : Vec < CValue < ' tcx > > ,
650
602
ret_place : Option < CPlace < ' tcx > > ,
651
603
) {
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 ) ) ;
653
605
654
606
let ret_layout = fx. layout_of ( fn_sig. output ( ) ) ;
655
607
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 ( ) ) ;
657
609
let return_ptr = match output_pass_mode {
658
610
PassMode :: NoPass => None ,
659
611
PassMode :: ByRef => match ret_place {
@@ -683,15 +635,15 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
683
635
}
684
636
685
637
// 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) ) ) ,
687
639
688
640
// Indirect call
689
641
None => {
690
642
let func = trans_operand ( fx, func. expect ( "indirect call without func Operand" ) )
691
643
. load_scalar ( fx) ;
692
644
(
693
645
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) ) ,
695
647
)
696
648
}
697
649
} ;
@@ -702,7 +654,7 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
702
654
. chain (
703
655
args. into_iter ( )
704
656
. skip ( 1 )
705
- . map ( |arg| adjust_arg_for_abi ( fx, arg) ) ,
657
+ . filter_map ( |arg| adjust_arg_for_abi ( fx, arg) ) ,
706
658
)
707
659
. collect :: < Vec < _ > > ( ) ;
708
660
@@ -756,9 +708,9 @@ pub fn codegen_drop<'a, 'tcx: 'a>(
756
708
let ( ptr, vtable) = drop_place. to_addr_maybe_unsized ( fx) ;
757
709
let drop_fn = crate :: vtable:: drop_fn_of_obj ( fx, vtable. unwrap ( ) ) ;
758
710
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 ) ) ;
760
712
761
- match get_pass_mode ( fx. tcx , fn_sig. output ( ) , true ) {
713
+ match get_pass_mode ( fx. tcx , fn_sig. output ( ) ) {
762
714
PassMode :: NoPass => { }
763
715
_ => unreachable ! ( ) ,
764
716
} ;
@@ -770,7 +722,7 @@ pub fn codegen_drop<'a, 'tcx: 'a>(
770
722
}
771
723
772
724
pub 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 ( ) ) {
774
726
PassMode :: NoPass | PassMode :: ByRef => {
775
727
fx. bcx . ins ( ) . return_ ( & [ ] ) ;
776
728
}
0 commit comments