11use rustc_ast:: InlineAsmTemplatePiece ;
2+ use rustc_data_structures:: stable_set:: FxHashSet ;
23use rustc_errors:: struct_span_err;
34use rustc_hir as hir;
45use rustc_hir:: def:: { DefKind , Res } ;
@@ -138,7 +139,7 @@ impl<'tcx> ExprVisitor<'tcx> {
138139 template : & [ InlineAsmTemplatePiece ] ,
139140 is_input : bool ,
140141 tied_input : Option < ( & hir:: Expr < ' tcx > , Option < InlineAsmType > ) > ,
141- target_features : & [ Symbol ] ,
142+ target_features : & FxHashSet < Symbol > ,
142143 ) -> Option < InlineAsmType > {
143144 // Check the type against the allowed types for inline asm.
144145 let ty = self . typeck_results . expr_ty_adjusted ( expr) ;
@@ -285,9 +286,7 @@ impl<'tcx> ExprVisitor<'tcx> {
285286 // (!). In that case we still need the earlier check to verify that the
286287 // register class is usable at all.
287288 if let Some ( feature) = feature {
288- if !self . tcx . sess . target_features . contains ( & feature)
289- && !target_features. contains ( & feature)
290- {
289+ if !target_features. contains ( & feature) {
291290 let msg = & format ! ( "`{}` target feature is not enabled" , feature) ;
292291 let mut err = self . tcx . sess . struct_span_err ( expr. span , msg) ;
293292 err. note ( & format ! (
@@ -347,7 +346,8 @@ impl<'tcx> ExprVisitor<'tcx> {
347346 let hir = self . tcx . hir ( ) ;
348347 let enclosing_id = hir. enclosing_body_owner ( hir_id) ;
349348 let enclosing_def_id = hir. local_def_id ( enclosing_id) . to_def_id ( ) ;
350- let attrs = self . tcx . codegen_fn_attrs ( enclosing_def_id) ;
349+ let target_features = self . tcx . asm_target_features ( enclosing_def_id) ;
350+ let asm_arch = self . tcx . sess . asm_arch . unwrap ( ) ;
351351 for ( idx, ( op, op_sp) ) in asm. operands . iter ( ) . enumerate ( ) {
352352 // Validate register classes against currently enabled target
353353 // features. We check that at least one type is available for
@@ -360,16 +360,29 @@ impl<'tcx> ExprVisitor<'tcx> {
360360 // Note that this is only possible for explicit register
361361 // operands, which cannot be used in the asm string.
362362 if let Some ( reg) = op. reg ( ) {
363+ // Some explicit registers cannot be used depending on the
364+ // target. Reject those here.
365+ if let InlineAsmRegOrRegClass :: Reg ( reg) = reg {
366+ if let Err ( msg) = reg. validate (
367+ asm_arch,
368+ self . tcx . sess . relocation_model ( ) ,
369+ & target_features,
370+ & self . tcx . sess . target ,
371+ op. is_clobber ( ) ,
372+ ) {
373+ let msg = format ! ( "cannot use register `{}`: {}" , reg. name( ) , msg) ;
374+ self . tcx . sess . struct_span_err ( * op_sp, & msg) . emit ( ) ;
375+ continue ;
376+ }
377+ }
378+
363379 if !op. is_clobber ( ) {
364380 let mut missing_required_features = vec ! [ ] ;
365381 let reg_class = reg. reg_class ( ) ;
366- for & ( _, feature) in reg_class. supported_types ( self . tcx . sess . asm_arch . unwrap ( ) )
367- {
382+ for & ( _, feature) in reg_class. supported_types ( asm_arch) {
368383 match feature {
369384 Some ( feature) => {
370- if self . tcx . sess . target_features . contains ( & feature)
371- || attrs. target_features . contains ( & feature)
372- {
385+ if target_features. contains ( & feature) {
373386 missing_required_features. clear ( ) ;
374387 break ;
375388 } else {
@@ -425,7 +438,7 @@ impl<'tcx> ExprVisitor<'tcx> {
425438 asm. template ,
426439 true ,
427440 None ,
428- & attrs . target_features ,
441+ & target_features,
429442 ) ;
430443 }
431444 hir:: InlineAsmOperand :: Out { reg, late : _, ref expr } => {
@@ -437,7 +450,7 @@ impl<'tcx> ExprVisitor<'tcx> {
437450 asm. template ,
438451 false ,
439452 None ,
440- & attrs . target_features ,
453+ & target_features,
441454 ) ;
442455 }
443456 }
@@ -449,7 +462,7 @@ impl<'tcx> ExprVisitor<'tcx> {
449462 asm. template ,
450463 false ,
451464 None ,
452- & attrs . target_features ,
465+ & target_features,
453466 ) ;
454467 }
455468 hir:: InlineAsmOperand :: SplitInOut { reg, late : _, ref in_expr, ref out_expr } => {
@@ -460,7 +473,7 @@ impl<'tcx> ExprVisitor<'tcx> {
460473 asm. template ,
461474 true ,
462475 None ,
463- & attrs . target_features ,
476+ & target_features,
464477 ) ;
465478 if let Some ( out_expr) = out_expr {
466479 self . check_asm_operand_type (
@@ -470,7 +483,7 @@ impl<'tcx> ExprVisitor<'tcx> {
470483 asm. template ,
471484 false ,
472485 Some ( ( in_expr, in_ty) ) ,
473- & attrs . target_features ,
486+ & target_features,
474487 ) ;
475488 }
476489 }
0 commit comments