@@ -1331,84 +1331,83 @@ impl<'hir> LoweringContext<'_, 'hir> {
1331
1331
}
1332
1332
1333
1333
fn lower_expr_asm ( & mut self , sp : Span , asm : & InlineAsm ) -> hir:: ExprKind < ' hir > {
1334
- if self . sess . asm_arch . is_none ( ) {
1334
+ // Rustdoc needs to support asm! from foriegn architectures: don't try
1335
+ // lowering the register contraints in this case.
1336
+ let asm_arch = if self . sess . opts . actually_rustdoc { None } else { self . sess . asm_arch } ;
1337
+ if asm_arch. is_none ( ) && !self . sess . opts . actually_rustdoc {
1335
1338
struct_span_err ! ( self . sess, sp, E0472 , "asm! is unsupported on this target" ) . emit ( ) ;
1336
1339
}
1337
1340
if asm. options . contains ( InlineAsmOptions :: ATT_SYNTAX )
1338
- && !matches ! (
1339
- self . sess. asm_arch,
1340
- Some ( asm:: InlineAsmArch :: X86 | asm:: InlineAsmArch :: X86_64 )
1341
- )
1341
+ && !matches ! ( asm_arch, Some ( asm:: InlineAsmArch :: X86 | asm:: InlineAsmArch :: X86_64 ) )
1342
+ && !self . sess . opts . actually_rustdoc
1342
1343
{
1343
1344
self . sess
1344
1345
. struct_span_err ( sp, "the `att_syntax` option is only supported on x86" )
1345
1346
. emit ( ) ;
1346
1347
}
1347
1348
1348
- // Lower operands to HIR, filter_map skips any operands with invalid
1349
- // register classes.
1349
+ // Lower operands to HIR. We use dummy register classes if an error
1350
+ // occurs during lowering because we still need to be able to produce a
1351
+ // valid HIR.
1350
1352
let sess = self . sess ;
1351
1353
let operands: Vec < _ > = asm
1352
1354
. operands
1353
1355
. iter ( )
1354
- . filter_map ( |( op, op_sp) | {
1355
- let lower_reg = |reg| {
1356
- Some ( match reg {
1357
- InlineAsmRegOrRegClass :: Reg ( s ) => asm :: InlineAsmRegOrRegClass :: Reg (
1356
+ . map ( |( op, op_sp) | {
1357
+ let lower_reg = |reg| match reg {
1358
+ InlineAsmRegOrRegClass :: Reg ( s ) => {
1359
+ asm :: InlineAsmRegOrRegClass :: Reg ( if let Some ( asm_arch ) = asm_arch {
1358
1360
asm:: InlineAsmReg :: parse (
1359
- sess . asm_arch ? ,
1361
+ asm_arch,
1360
1362
|feature| sess. target_features . contains ( & Symbol :: intern ( feature) ) ,
1361
1363
& sess. target ,
1362
1364
s,
1363
1365
)
1364
- . map_err ( |e| {
1366
+ . unwrap_or_else ( |e| {
1365
1367
let msg = format ! ( "invalid register `{}`: {}" , s. as_str( ) , e) ;
1366
1368
sess. struct_span_err ( * op_sp, & msg) . emit ( ) ;
1369
+ asm:: InlineAsmReg :: Err
1367
1370
} )
1368
- . ok ( ) ?,
1369
- ) ,
1370
- InlineAsmRegOrRegClass :: RegClass ( s) => {
1371
- asm:: InlineAsmRegOrRegClass :: RegClass (
1372
- asm:: InlineAsmRegClass :: parse ( sess. asm_arch ?, s)
1373
- . map_err ( |e| {
1374
- let msg = format ! (
1375
- "invalid register class `{}`: {}" ,
1376
- s. as_str( ) ,
1377
- e
1378
- ) ;
1379
- sess. struct_span_err ( * op_sp, & msg) . emit ( ) ;
1380
- } )
1381
- . ok ( ) ?,
1382
- )
1383
- }
1384
- } )
1371
+ } else {
1372
+ asm:: InlineAsmReg :: Err
1373
+ } )
1374
+ }
1375
+ InlineAsmRegOrRegClass :: RegClass ( s) => {
1376
+ asm:: InlineAsmRegOrRegClass :: RegClass ( if let Some ( asm_arch) = asm_arch {
1377
+ asm:: InlineAsmRegClass :: parse ( asm_arch, s) . unwrap_or_else ( |e| {
1378
+ let msg = format ! ( "invalid register class `{}`: {}" , s. as_str( ) , e) ;
1379
+ sess. struct_span_err ( * op_sp, & msg) . emit ( ) ;
1380
+ asm:: InlineAsmRegClass :: Err
1381
+ } )
1382
+ } else {
1383
+ asm:: InlineAsmRegClass :: Err
1384
+ } )
1385
+ }
1385
1386
} ;
1386
1387
1387
- // lower_reg is executed last because we need to lower all
1388
- // sub-expressions even if we throw them away later.
1389
1388
let op = match * op {
1390
1389
InlineAsmOperand :: In { reg, ref expr } => hir:: InlineAsmOperand :: In {
1390
+ reg : lower_reg ( reg) ,
1391
1391
expr : self . lower_expr_mut ( expr) ,
1392
- reg : lower_reg ( reg) ?,
1393
1392
} ,
1394
1393
InlineAsmOperand :: Out { reg, late, ref expr } => hir:: InlineAsmOperand :: Out {
1394
+ reg : lower_reg ( reg) ,
1395
1395
late,
1396
1396
expr : expr. as_ref ( ) . map ( |expr| self . lower_expr_mut ( expr) ) ,
1397
- reg : lower_reg ( reg) ?,
1398
1397
} ,
1399
1398
InlineAsmOperand :: InOut { reg, late, ref expr } => {
1400
1399
hir:: InlineAsmOperand :: InOut {
1400
+ reg : lower_reg ( reg) ,
1401
1401
late,
1402
1402
expr : self . lower_expr_mut ( expr) ,
1403
- reg : lower_reg ( reg) ?,
1404
1403
}
1405
1404
}
1406
1405
InlineAsmOperand :: SplitInOut { reg, late, ref in_expr, ref out_expr } => {
1407
1406
hir:: InlineAsmOperand :: SplitInOut {
1407
+ reg : lower_reg ( reg) ,
1408
1408
late,
1409
1409
in_expr : self . lower_expr_mut ( in_expr) ,
1410
1410
out_expr : out_expr. as_ref ( ) . map ( |expr| self . lower_expr_mut ( expr) ) ,
1411
- reg : lower_reg ( reg) ?,
1412
1411
}
1413
1412
}
1414
1413
InlineAsmOperand :: Const { ref expr } => {
@@ -1418,17 +1417,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
1418
1417
hir:: InlineAsmOperand :: Sym { expr : self . lower_expr_mut ( expr) }
1419
1418
}
1420
1419
} ;
1421
- Some ( ( op, * op_sp) )
1420
+ ( op, * op_sp)
1422
1421
} )
1423
1422
. collect ( ) ;
1424
1423
1425
- // Stop if there were any errors when lowering the register classes
1426
- if operands. len ( ) != asm. operands . len ( ) || sess. asm_arch . is_none ( ) {
1427
- return hir:: ExprKind :: Err ;
1428
- }
1429
-
1430
1424
// Validate template modifiers against the register classes for the operands
1431
- let asm_arch = sess. asm_arch . unwrap ( ) ;
1432
1425
for p in & asm. template {
1433
1426
if let InlineAsmTemplatePiece :: Placeholder {
1434
1427
operand_idx,
@@ -1443,7 +1436,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
1443
1436
| hir:: InlineAsmOperand :: InOut { reg, .. }
1444
1437
| hir:: InlineAsmOperand :: SplitInOut { reg, .. } => {
1445
1438
let class = reg. reg_class ( ) ;
1446
- let valid_modifiers = class. valid_modifiers ( asm_arch) ;
1439
+ if class == asm:: InlineAsmRegClass :: Err {
1440
+ continue ;
1441
+ }
1442
+ let valid_modifiers = class. valid_modifiers ( asm_arch. unwrap ( ) ) ;
1447
1443
if !valid_modifiers. contains ( & modifier) {
1448
1444
let mut err = sess. struct_span_err (
1449
1445
placeholder_span,
@@ -1506,7 +1502,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
1506
1502
// features. We check that at least one type is available for
1507
1503
// the current target.
1508
1504
let reg_class = reg. reg_class ( ) ;
1509
- for & ( _, feature) in reg_class. supported_types ( asm_arch) {
1505
+ if reg_class == asm:: InlineAsmRegClass :: Err {
1506
+ continue ;
1507
+ }
1508
+ for & ( _, feature) in reg_class. supported_types ( asm_arch. unwrap ( ) ) {
1510
1509
if let Some ( feature) = feature {
1511
1510
if self . sess . target_features . contains ( & Symbol :: intern ( feature) ) {
1512
1511
required_features. clear ( ) ;
0 commit comments