1
1
use rustc_ast:: InlineAsmTemplatePiece ;
2
+ use rustc_data_structures:: stable_set:: FxHashSet ;
2
3
use rustc_errors:: struct_span_err;
3
4
use rustc_hir as hir;
4
5
use rustc_hir:: def:: { DefKind , Res } ;
@@ -141,7 +142,7 @@ impl<'tcx> ExprVisitor<'tcx> {
141
142
template : & [ InlineAsmTemplatePiece ] ,
142
143
is_input : bool ,
143
144
tied_input : Option < ( & hir:: Expr < ' tcx > , Option < InlineAsmType > ) > ,
144
- target_features : & [ Symbol ] ,
145
+ target_features : & FxHashSet < Symbol > ,
145
146
) -> Option < InlineAsmType > {
146
147
// Check the type against the allowed types for inline asm.
147
148
let ty = self . typeck_results . expr_ty_adjusted ( expr) ;
@@ -294,9 +295,7 @@ impl<'tcx> ExprVisitor<'tcx> {
294
295
// (!). In that case we still need the earlier check to verify that the
295
296
// register class is usable at all.
296
297
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) {
300
299
let msg = & format ! ( "`{}` target feature is not enabled" , feature) ;
301
300
let mut err = self . tcx . sess . struct_span_err ( expr. span , msg) ;
302
301
err. note ( & format ! (
@@ -356,7 +355,8 @@ impl<'tcx> ExprVisitor<'tcx> {
356
355
let hir = self . tcx . hir ( ) ;
357
356
let enclosing_id = hir. enclosing_body_owner ( hir_id) ;
358
357
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 ( ) ;
360
360
for ( idx, ( op, op_sp) ) in asm. operands . iter ( ) . enumerate ( ) {
361
361
// Validate register classes against currently enabled target
362
362
// features. We check that at least one type is available for
@@ -369,16 +369,29 @@ impl<'tcx> ExprVisitor<'tcx> {
369
369
// Note that this is only possible for explicit register
370
370
// operands, which cannot be used in the asm string.
371
371
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
+
372
388
if !op. is_clobber ( ) {
373
389
let mut missing_required_features = vec ! [ ] ;
374
390
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) {
377
392
match feature {
378
393
Some ( feature) => {
379
- if self . tcx . sess . target_features . contains ( & feature)
380
- || attrs. target_features . contains ( & feature)
381
- {
394
+ if target_features. contains ( & feature) {
382
395
missing_required_features. clear ( ) ;
383
396
break ;
384
397
} else {
@@ -434,7 +447,7 @@ impl<'tcx> ExprVisitor<'tcx> {
434
447
asm. template ,
435
448
true ,
436
449
None ,
437
- & attrs . target_features ,
450
+ & target_features,
438
451
) ;
439
452
}
440
453
hir:: InlineAsmOperand :: Out { reg, late : _, ref expr } => {
@@ -446,7 +459,7 @@ impl<'tcx> ExprVisitor<'tcx> {
446
459
asm. template ,
447
460
false ,
448
461
None ,
449
- & attrs . target_features ,
462
+ & target_features,
450
463
) ;
451
464
}
452
465
}
@@ -458,7 +471,7 @@ impl<'tcx> ExprVisitor<'tcx> {
458
471
asm. template ,
459
472
false ,
460
473
None ,
461
- & attrs . target_features ,
474
+ & target_features,
462
475
) ;
463
476
}
464
477
hir:: InlineAsmOperand :: SplitInOut { reg, late : _, ref in_expr, ref out_expr } => {
@@ -469,7 +482,7 @@ impl<'tcx> ExprVisitor<'tcx> {
469
482
asm. template ,
470
483
true ,
471
484
None ,
472
- & attrs . target_features ,
485
+ & target_features,
473
486
) ;
474
487
if let Some ( out_expr) = out_expr {
475
488
self . check_asm_operand_type (
@@ -479,7 +492,7 @@ impl<'tcx> ExprVisitor<'tcx> {
479
492
asm. template ,
480
493
false ,
481
494
Some ( ( in_expr, in_ty) ) ,
482
- & attrs . target_features ,
495
+ & target_features,
483
496
) ;
484
497
}
485
498
}
0 commit comments