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 } ;
@@ -141,7 +142,7 @@ impl<'tcx> ExprVisitor<'tcx> {
141142 template : & [ InlineAsmTemplatePiece ] ,
142143 is_input : bool ,
143144 tied_input : Option < ( & hir:: Expr < ' tcx > , Option < InlineAsmType > ) > ,
144- target_features : & [ Symbol ] ,
145+ target_features : & FxHashSet < Symbol > ,
145146 ) -> Option < InlineAsmType > {
146147 // Check the type against the allowed types for inline asm.
147148 let ty = self . typeck_results . expr_ty_adjusted ( expr) ;
@@ -294,9 +295,7 @@ impl<'tcx> ExprVisitor<'tcx> {
294295 // (!). In that case we still need the earlier check to verify that the
295296 // register class is usable at all.
296297 if let Some ( feature) = feature {
297- if !self . tcx . sess . target_features . contains ( & feature)
298- && !target_features. contains ( & feature)
299- {
298+ if !target_features. contains ( & feature) {
300299 let msg = & format ! ( "`{}` target feature is not enabled" , feature) ;
301300 let mut err = self . tcx . sess . struct_span_err ( expr. span , msg) ;
302301 err. note ( & format ! (
@@ -356,7 +355,8 @@ impl<'tcx> ExprVisitor<'tcx> {
356355 let hir = self . tcx . hir ( ) ;
357356 let enclosing_id = hir. enclosing_body_owner ( hir_id) ;
358357 let enclosing_def_id = hir. local_def_id ( enclosing_id) . to_def_id ( ) ;
359- let attrs = self . tcx . codegen_fn_attrs ( enclosing_def_id) ;
358+ let target_features = self . tcx . asm_target_features ( enclosing_def_id) ;
359+ let asm_arch = self . tcx . sess . asm_arch . unwrap ( ) ;
360360 for ( idx, ( op, op_sp) ) in asm. operands . iter ( ) . enumerate ( ) {
361361 // Validate register classes against currently enabled target
362362 // features. We check that at least one type is available for
@@ -369,16 +369,29 @@ impl<'tcx> ExprVisitor<'tcx> {
369369 // Note that this is only possible for explicit register
370370 // operands, which cannot be used in the asm string.
371371 if let Some ( reg) = op. reg ( ) {
372+ // Some explicit registers cannot be used depending on the
373+ // target. Reject those here.
374+ if let InlineAsmRegOrRegClass :: Reg ( reg) = reg {
375+ if let Err ( msg) = reg. validate (
376+ asm_arch,
377+ self . tcx . sess . relocation_model ( ) ,
378+ & target_features,
379+ & self . tcx . sess . target ,
380+ op. is_clobber ( ) ,
381+ ) {
382+ let msg = format ! ( "cannot use register `{}`: {}" , reg. name( ) , msg) ;
383+ self . tcx . sess . struct_span_err ( * op_sp, & msg) . emit ( ) ;
384+ continue ;
385+ }
386+ }
387+
372388 if !op. is_clobber ( ) {
373389 let mut missing_required_features = vec ! [ ] ;
374390 let reg_class = reg. reg_class ( ) ;
375- for & ( _, feature) in reg_class. supported_types ( self . tcx . sess . asm_arch . unwrap ( ) )
376- {
391+ for & ( _, feature) in reg_class. supported_types ( asm_arch) {
377392 match feature {
378393 Some ( feature) => {
379- if self . tcx . sess . target_features . contains ( & feature)
380- || attrs. target_features . contains ( & feature)
381- {
394+ if target_features. contains ( & feature) {
382395 missing_required_features. clear ( ) ;
383396 break ;
384397 } else {
@@ -434,7 +447,7 @@ impl<'tcx> ExprVisitor<'tcx> {
434447 asm. template ,
435448 true ,
436449 None ,
437- & attrs . target_features ,
450+ & target_features,
438451 ) ;
439452 }
440453 hir:: InlineAsmOperand :: Out { reg, late : _, ref expr } => {
@@ -446,7 +459,7 @@ impl<'tcx> ExprVisitor<'tcx> {
446459 asm. template ,
447460 false ,
448461 None ,
449- & attrs . target_features ,
462+ & target_features,
450463 ) ;
451464 }
452465 }
@@ -458,7 +471,7 @@ impl<'tcx> ExprVisitor<'tcx> {
458471 asm. template ,
459472 false ,
460473 None ,
461- & attrs . target_features ,
474+ & target_features,
462475 ) ;
463476 }
464477 hir:: InlineAsmOperand :: SplitInOut { reg, late : _, ref in_expr, ref out_expr } => {
@@ -469,7 +482,7 @@ impl<'tcx> ExprVisitor<'tcx> {
469482 asm. template ,
470483 true ,
471484 None ,
472- & attrs . target_features ,
485+ & target_features,
473486 ) ;
474487 if let Some ( out_expr) = out_expr {
475488 self . check_asm_operand_type (
@@ -479,7 +492,7 @@ impl<'tcx> ExprVisitor<'tcx> {
479492 asm. template ,
480493 false ,
481494 Some ( ( in_expr, in_ty) ) ,
482- & attrs . target_features ,
495+ & target_features,
483496 ) ;
484497 }
485498 }
0 commit comments