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 } ;
@@ -138,7 +139,7 @@ impl<'tcx> ExprVisitor<'tcx> {
138
139
template : & [ InlineAsmTemplatePiece ] ,
139
140
is_input : bool ,
140
141
tied_input : Option < ( & hir:: Expr < ' tcx > , Option < InlineAsmType > ) > ,
141
- target_features : & [ Symbol ] ,
142
+ target_features : & FxHashSet < Symbol > ,
142
143
) -> Option < InlineAsmType > {
143
144
// Check the type against the allowed types for inline asm.
144
145
let ty = self . typeck_results . expr_ty_adjusted ( expr) ;
@@ -285,9 +286,7 @@ impl<'tcx> ExprVisitor<'tcx> {
285
286
// (!). In that case we still need the earlier check to verify that the
286
287
// register class is usable at all.
287
288
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) {
291
290
let msg = & format ! ( "`{}` target feature is not enabled" , feature) ;
292
291
let mut err = self . tcx . sess . struct_span_err ( expr. span , msg) ;
293
292
err. note ( & format ! (
@@ -347,7 +346,8 @@ impl<'tcx> ExprVisitor<'tcx> {
347
346
let hir = self . tcx . hir ( ) ;
348
347
let enclosing_id = hir. enclosing_body_owner ( hir_id) ;
349
348
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 ( ) ;
351
351
for ( idx, ( op, op_sp) ) in asm. operands . iter ( ) . enumerate ( ) {
352
352
// Validate register classes against currently enabled target
353
353
// features. We check that at least one type is available for
@@ -360,16 +360,29 @@ impl<'tcx> ExprVisitor<'tcx> {
360
360
// Note that this is only possible for explicit register
361
361
// operands, which cannot be used in the asm string.
362
362
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
+
363
379
if !op. is_clobber ( ) {
364
380
let mut missing_required_features = vec ! [ ] ;
365
381
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) {
368
383
match feature {
369
384
Some ( feature) => {
370
- if self . tcx . sess . target_features . contains ( & feature)
371
- || attrs. target_features . contains ( & feature)
372
- {
385
+ if target_features. contains ( & feature) {
373
386
missing_required_features. clear ( ) ;
374
387
break ;
375
388
} else {
@@ -425,7 +438,7 @@ impl<'tcx> ExprVisitor<'tcx> {
425
438
asm. template ,
426
439
true ,
427
440
None ,
428
- & attrs . target_features ,
441
+ & target_features,
429
442
) ;
430
443
}
431
444
hir:: InlineAsmOperand :: Out { reg, late : _, ref expr } => {
@@ -437,7 +450,7 @@ impl<'tcx> ExprVisitor<'tcx> {
437
450
asm. template ,
438
451
false ,
439
452
None ,
440
- & attrs . target_features ,
453
+ & target_features,
441
454
) ;
442
455
}
443
456
}
@@ -449,7 +462,7 @@ impl<'tcx> ExprVisitor<'tcx> {
449
462
asm. template ,
450
463
false ,
451
464
None ,
452
- & attrs . target_features ,
465
+ & target_features,
453
466
) ;
454
467
}
455
468
hir:: InlineAsmOperand :: SplitInOut { reg, late : _, ref in_expr, ref out_expr } => {
@@ -460,7 +473,7 @@ impl<'tcx> ExprVisitor<'tcx> {
460
473
asm. template ,
461
474
true ,
462
475
None ,
463
- & attrs . target_features ,
476
+ & target_features,
464
477
) ;
465
478
if let Some ( out_expr) = out_expr {
466
479
self . check_asm_operand_type (
@@ -470,7 +483,7 @@ impl<'tcx> ExprVisitor<'tcx> {
470
483
asm. template ,
471
484
false ,
472
485
Some ( ( in_expr, in_ty) ) ,
473
- & attrs . target_features ,
486
+ & target_features,
474
487
) ;
475
488
}
476
489
}
0 commit comments