@@ -113,14 +113,17 @@ pub enum Candidate {
113
113
/// the attribute currently provides the semantic requirement that arguments
114
114
/// must be constant.
115
115
Argument { bb : BasicBlock , index : usize } ,
116
+
117
+ /// `const` operand in asm!.
118
+ InlineAsm { bb : BasicBlock , index : usize } ,
116
119
}
117
120
118
121
impl Candidate {
119
122
/// Returns `true` if we should use the "explicit" rules for promotability for this `Candidate`.
120
123
fn forces_explicit_promotion ( & self ) -> bool {
121
124
match self {
122
125
Candidate :: Ref ( _) | Candidate :: Repeat ( _) => false ,
123
- Candidate :: Argument { .. } => true ,
126
+ Candidate :: Argument { .. } | Candidate :: InlineAsm { .. } => true ,
124
127
}
125
128
}
126
129
}
@@ -216,25 +219,39 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
216
219
fn visit_terminator_kind ( & mut self , kind : & TerminatorKind < ' tcx > , location : Location ) {
217
220
self . super_terminator_kind ( kind, location) ;
218
221
219
- if let TerminatorKind :: Call { ref func, .. } = * kind {
220
- if let ty:: FnDef ( def_id, _) = func. ty ( self . ccx . body , self . ccx . tcx ) . kind {
221
- let fn_sig = self . ccx . tcx . fn_sig ( def_id) ;
222
- if let Abi :: RustIntrinsic | Abi :: PlatformIntrinsic = fn_sig. abi ( ) {
223
- let name = self . ccx . tcx . item_name ( def_id) ;
224
- // FIXME(eddyb) use `#[rustc_args_required_const(2)]` for shuffles.
225
- if name. as_str ( ) . starts_with ( "simd_shuffle" ) {
226
- self . candidates . push ( Candidate :: Argument { bb : location. block , index : 2 } ) ;
222
+ match * kind {
223
+ TerminatorKind :: Call { ref func, .. } => {
224
+ if let ty:: FnDef ( def_id, _) = func. ty ( self . ccx . body , self . ccx . tcx ) . kind {
225
+ let fn_sig = self . ccx . tcx . fn_sig ( def_id) ;
226
+ if let Abi :: RustIntrinsic | Abi :: PlatformIntrinsic = fn_sig. abi ( ) {
227
+ let name = self . ccx . tcx . item_name ( def_id) ;
228
+ // FIXME(eddyb) use `#[rustc_args_required_const(2)]` for shuffles.
229
+ if name. as_str ( ) . starts_with ( "simd_shuffle" ) {
230
+ self . candidates
231
+ . push ( Candidate :: Argument { bb : location. block , index : 2 } ) ;
232
+
233
+ return ; // Don't double count `simd_shuffle` candidates
234
+ }
235
+ }
227
236
228
- return ; // Don't double count `simd_shuffle` candidates
237
+ if let Some ( constant_args) = args_required_const ( self . ccx . tcx , def_id) {
238
+ for index in constant_args {
239
+ self . candidates . push ( Candidate :: Argument { bb : location. block , index } ) ;
240
+ }
229
241
}
230
242
}
231
-
232
- if let Some ( constant_args) = args_required_const ( self . ccx . tcx , def_id) {
233
- for index in constant_args {
234
- self . candidates . push ( Candidate :: Argument { bb : location. block , index } ) ;
243
+ }
244
+ TerminatorKind :: InlineAsm { ref operands, .. } => {
245
+ for ( index, op) in operands. iter ( ) . enumerate ( ) {
246
+ match op {
247
+ InlineAsmOperand :: Const { .. } => {
248
+ self . candidates . push ( Candidate :: InlineAsm { bb : location. block , index } )
249
+ }
250
+ _ => { }
235
251
}
236
252
}
237
253
}
254
+ _ => { }
238
255
}
239
256
}
240
257
@@ -402,6 +419,18 @@ impl<'tcx> Validator<'_, 'tcx> {
402
419
_ => bug ! ( ) ,
403
420
}
404
421
}
422
+ Candidate :: InlineAsm { bb, index } => {
423
+ assert ! ( self . explicit) ;
424
+
425
+ let terminator = self . body [ bb] . terminator ( ) ;
426
+ match & terminator. kind {
427
+ TerminatorKind :: InlineAsm { operands, .. } => match & operands[ index] {
428
+ InlineAsmOperand :: Const { value } => self . validate_operand ( value) ,
429
+ _ => bug ! ( ) ,
430
+ } ,
431
+ _ => bug ! ( ) ,
432
+ }
433
+ }
405
434
}
406
435
}
407
436
@@ -747,7 +776,9 @@ pub fn validate_candidates(
747
776
}
748
777
749
778
match candidate {
750
- Candidate :: Argument { bb, index } if !is_promotable => {
779
+ Candidate :: Argument { bb, index } | Candidate :: InlineAsm { bb, index }
780
+ if !is_promotable =>
781
+ {
751
782
let span = ccx. body [ bb] . terminator ( ) . source_info . span ;
752
783
let msg = format ! ( "argument {} is required to be a constant" , index + 1 ) ;
753
784
ccx. tcx . sess . span_err ( span, & msg) ;
@@ -1024,6 +1055,24 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
1024
1055
_ => bug ! ( ) ,
1025
1056
}
1026
1057
}
1058
+ Candidate :: InlineAsm { bb, index } => {
1059
+ let terminator = blocks[ bb] . terminator_mut ( ) ;
1060
+ match terminator. kind {
1061
+ TerminatorKind :: InlineAsm { ref mut operands, .. } => {
1062
+ match & mut operands[ index] {
1063
+ InlineAsmOperand :: Const { ref mut value } => {
1064
+ let ty = value. ty ( local_decls, self . tcx ) ;
1065
+ let span = terminator. source_info . span ;
1066
+
1067
+ Rvalue :: Use ( mem:: replace ( value, promoted_operand ( ty, span) ) )
1068
+ }
1069
+ _ => bug ! ( ) ,
1070
+ }
1071
+ }
1072
+
1073
+ _ => bug ! ( ) ,
1074
+ }
1075
+ }
1027
1076
}
1028
1077
} ;
1029
1078
@@ -1080,7 +1129,7 @@ pub fn promote_candidates<'tcx>(
1080
1129
}
1081
1130
}
1082
1131
}
1083
- Candidate :: Argument { .. } => { }
1132
+ Candidate :: Argument { .. } | Candidate :: InlineAsm { .. } => { }
1084
1133
}
1085
1134
1086
1135
// Declare return place local so that `mir::Body::new` doesn't complain.
0 commit comments