Skip to content

Commit 30ba978

Browse files
committed
Add asm label support to AST and HIR
1 parent 88d69b7 commit 30ba978

File tree

23 files changed

+134
-12
lines changed

23 files changed

+134
-12
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2272,6 +2272,9 @@ pub enum InlineAsmOperand {
22722272
Sym {
22732273
sym: InlineAsmSym,
22742274
},
2275+
Label {
2276+
block: P<Block>,
2277+
},
22752278
}
22762279

22772280
impl InlineAsmOperand {
@@ -2281,7 +2284,7 @@ impl InlineAsmOperand {
22812284
| Self::Out { reg, .. }
22822285
| Self::InOut { reg, .. }
22832286
| Self::SplitInOut { reg, .. } => Some(reg),
2284-
Self::Const { .. } | Self::Sym { .. } => None,
2287+
Self::Const { .. } | Self::Sym { .. } | Self::Label { .. } => None,
22852288
}
22862289
}
22872290
}

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,6 +1308,7 @@ pub fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
13081308
}
13091309
InlineAsmOperand::Const { anon_const } => vis.visit_anon_const(anon_const),
13101310
InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym),
1311+
InlineAsmOperand::Label { block } => vis.visit_block(block),
13111312
}
13121313
}
13131314
}

compiler/rustc_ast/src/visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,7 @@ pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm)
763763
}
764764
InlineAsmOperand::Const { anon_const, .. } => visitor.visit_anon_const(anon_const),
765765
InlineAsmOperand::Sym { sym } => visitor.visit_inline_asm_sym(sym),
766+
InlineAsmOperand::Label { block } => visitor.visit_block(block),
766767
}
767768
}
768769
}

compiler/rustc_ast_lowering/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ ast_lowering_invalid_abi_suggestion = did you mean
8181
ast_lowering_invalid_asm_template_modifier_const =
8282
asm template modifiers are not allowed for `const` arguments
8383
84+
ast_lowering_invalid_asm_template_modifier_label =
85+
asm template modifiers are not allowed for `label` arguments
86+
8487
ast_lowering_invalid_asm_template_modifier_reg_class =
8588
invalid asm template modifier for this register class
8689

compiler/rustc_ast_lowering/src/asm.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ use crate::{ImplTraitContext, ImplTraitPosition, ParamMode, ResolverAstLoweringE
33
use super::errors::{
44
AbiSpecifiedMultipleTimes, AttSyntaxOnlyX86, ClobberAbiNotSupported,
55
InlineAsmUnsupportedTarget, InvalidAbiClobberAbi, InvalidAsmTemplateModifierConst,
6-
InvalidAsmTemplateModifierRegClass, InvalidAsmTemplateModifierRegClassSub,
7-
InvalidAsmTemplateModifierSym, InvalidRegister, InvalidRegisterClass, RegisterClassOnlyClobber,
8-
RegisterConflict,
6+
InvalidAsmTemplateModifierLabel, InvalidAsmTemplateModifierRegClass,
7+
InvalidAsmTemplateModifierRegClassSub, InvalidAsmTemplateModifierSym, InvalidRegister,
8+
InvalidRegisterClass, RegisterClassOnlyClobber, RegisterConflict,
99
};
1010
use super::LoweringContext;
1111

@@ -241,6 +241,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
241241
}
242242
}
243243
}
244+
InlineAsmOperand::Label { block } => {
245+
if !self.tcx.features().asm_goto {
246+
feature_err(
247+
&sess.parse_sess,
248+
sym::asm_goto,
249+
*op_sp,
250+
"label operands for inline assembly are unstable",
251+
)
252+
.emit();
253+
}
254+
hir::InlineAsmOperand::Label { block: self.lower_block(block, false) }
255+
}
244256
};
245257
(op, self.lower_span(*op_sp))
246258
})
@@ -300,6 +312,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
300312
op_span: op_sp,
301313
});
302314
}
315+
hir::InlineAsmOperand::Label { .. } => {
316+
self.dcx().emit_err(InvalidAsmTemplateModifierLabel {
317+
placeholder_span,
318+
op_span: op_sp,
319+
});
320+
}
303321
}
304322
}
305323
}
@@ -339,7 +357,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
339357

340358
hir::InlineAsmOperand::Const { .. }
341359
| hir::InlineAsmOperand::SymFn { .. }
342-
| hir::InlineAsmOperand::SymStatic { .. } => {
360+
| hir::InlineAsmOperand::SymStatic { .. }
361+
| hir::InlineAsmOperand::Label { .. } => {
343362
unreachable!("{op:?} is not a register operand");
344363
}
345364
};

compiler/rustc_ast_lowering/src/errors.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,16 @@ pub struct InvalidAsmTemplateModifierSym {
267267
pub op_span: Span,
268268
}
269269

270+
#[derive(Diagnostic, Clone, Copy)]
271+
#[diag(ast_lowering_invalid_asm_template_modifier_label)]
272+
pub struct InvalidAsmTemplateModifierLabel {
273+
#[primary_span]
274+
#[label(ast_lowering_template_modifier)]
275+
pub placeholder_span: Span,
276+
#[label(ast_lowering_argument)]
277+
pub op_span: Span,
278+
}
279+
270280
#[derive(Diagnostic, Clone, Copy)]
271281
#[diag(ast_lowering_register_class_only_clobber)]
272282
pub struct RegisterClassOnlyClobber {

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,10 @@ impl<'a> State<'a> {
12981298
s.print_path(&sym.path, true, 0);
12991299
}
13001300
}
1301+
InlineAsmOperand::Label { block } => {
1302+
s.head("label");
1303+
s.print_block(block);
1304+
}
13011305
}
13021306
}
13031307
AsmArg::ClobberAbi(abi) => {

compiler/rustc_builtin_macros/src/asm.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ pub fn parse_asm_args<'a>(
166166
path: path.clone(),
167167
};
168168
ast::InlineAsmOperand::Sym { sym }
169+
} else if p.eat_keyword(sym::label) {
170+
let block = p.parse_block()?;
171+
ast::InlineAsmOperand::Label { block }
169172
} else if allow_templates {
170173
let template = p.parse_expr()?;
171174
// If it can't possibly expand to a string, provide diagnostics here to include other

compiler/rustc_codegen_ssa/src/mono_item.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
7676
hir::InlineAsmOperand::In { .. }
7777
| hir::InlineAsmOperand::Out { .. }
7878
| hir::InlineAsmOperand::InOut { .. }
79-
| hir::InlineAsmOperand::SplitInOut { .. } => {
79+
| hir::InlineAsmOperand::SplitInOut { .. }
80+
| hir::InlineAsmOperand::Label { .. } => {
8081
span_bug!(*op_sp, "invalid operand type for global_asm!")
8182
}
8283
})

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,8 @@ declare_features! (
345345
(unstable, asm_const, "1.58.0", Some(93332)),
346346
/// Enables experimental inline assembly support for additional architectures.
347347
(unstable, asm_experimental_arch, "1.58.0", Some(93335)),
348+
/// Allows using `label` operands in inline assembly.
349+
(unstable, asm_goto, "CURRENT_RUSTC_VERSION", Some(119364)),
348350
/// Allows the `may_unwind` option in inline assembly.
349351
(unstable, asm_unwind, "1.58.0", Some(93334)),
350352
/// Allows users to enforce equality of associated constants `TraitImpl<AssocConst=3>`.

compiler/rustc_hir/src/hir.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2631,6 +2631,9 @@ pub enum InlineAsmOperand<'hir> {
26312631
path: QPath<'hir>,
26322632
def_id: DefId,
26332633
},
2634+
Label {
2635+
block: &'hir Block<'hir>,
2636+
},
26342637
}
26352638

26362639
impl<'hir> InlineAsmOperand<'hir> {
@@ -2640,7 +2643,10 @@ impl<'hir> InlineAsmOperand<'hir> {
26402643
| Self::Out { reg, .. }
26412644
| Self::InOut { reg, .. }
26422645
| Self::SplitInOut { reg, .. } => Some(reg),
2643-
Self::Const { .. } | Self::SymFn { .. } | Self::SymStatic { .. } => None,
2646+
Self::Const { .. }
2647+
| Self::SymFn { .. }
2648+
| Self::SymStatic { .. }
2649+
| Self::Label { .. } => None,
26442650
}
26452651
}
26462652

@@ -2661,6 +2667,12 @@ pub struct InlineAsm<'hir> {
26612667
pub line_spans: &'hir [Span],
26622668
}
26632669

2670+
impl InlineAsm<'_> {
2671+
pub fn contains_label(&self) -> bool {
2672+
self.operands.iter().any(|x| matches!(x.0, InlineAsmOperand::Label { .. }))
2673+
}
2674+
}
2675+
26642676
/// Represents a parameter in a function header.
26652677
#[derive(Debug, Clone, Copy, HashStable_Generic)]
26662678
pub struct Param<'hir> {

compiler/rustc_hir/src/intravisit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,7 @@ pub fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'
12171217
InlineAsmOperand::Const { anon_const, .. }
12181218
| InlineAsmOperand::SymFn { anon_const, .. } => visitor.visit_anon_const(anon_const),
12191219
InlineAsmOperand::SymStatic { path, .. } => visitor.visit_qpath(path, id, *op_sp),
1220+
InlineAsmOperand::Label { block } => visitor.visit_block(block),
12201221
}
12211222
}
12221223
}

compiler/rustc_hir_analysis/src/check/intrinsicck.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
460460
}
461461
};
462462
}
463+
// No special checking is needed for labels.
464+
hir::InlineAsmOperand::Label { .. } => {}
463465
}
464466
}
465467
}

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,10 @@ impl<'a> State<'a> {
12551255
s.space();
12561256
s.print_qpath(path, true);
12571257
}
1258+
hir::InlineAsmOperand::Label { block } => {
1259+
s.head("label");
1260+
s.print_block(block);
1261+
}
12581262
},
12591263
AsmArg::Options(opts) => {
12601264
s.word("options");

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3243,6 +3243,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32433243
// be well-formed.
32443244
hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {}
32453245
hir::InlineAsmOperand::SymStatic { .. } => {}
3246+
hir::InlineAsmOperand::Label { block } => {
3247+
self.check_block_no_value(block);
3248+
}
32463249
}
32473250
}
32483251
if asm.options.contains(ast::InlineAsmOptions::NORETURN) {

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
293293
| hir::InlineAsmOperand::Const { .. }
294294
| hir::InlineAsmOperand::SymFn { .. }
295295
| hir::InlineAsmOperand::SymStatic { .. } => {}
296+
hir::InlineAsmOperand::Label { block } => {
297+
self.walk_block(block);
298+
}
296299
}
297300
}
298301
}

compiler/rustc_mir_build/src/thir/cx/expr.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,9 @@ impl<'tcx> Cx<'tcx> {
650650
hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
651651
InlineAsmOperand::SymStatic { def_id }
652652
}
653+
hir::InlineAsmOperand::Label { .. } => {
654+
todo!()
655+
}
653656
})
654657
.collect(),
655658
options: asm.options,

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,8 @@ fn collect_items_rec<'tcx>(
446446
hir::InlineAsmOperand::In { .. }
447447
| hir::InlineAsmOperand::Out { .. }
448448
| hir::InlineAsmOperand::InOut { .. }
449-
| hir::InlineAsmOperand::SplitInOut { .. } => {
449+
| hir::InlineAsmOperand::SplitInOut { .. }
450+
| hir::InlineAsmOperand::Label { .. } => {
450451
span_bug!(*op_sp, "invalid operand type for global_asm!")
451452
}
452453
}

compiler/rustc_parse/src/parser/stmt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ impl<'a> Parser<'a> {
427427
}
428428

429429
/// Parses a block. No inner attributes are allowed.
430-
pub(super) fn parse_block(&mut self) -> PResult<'a, P<Block>> {
430+
pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
431431
let (attrs, block) = self.parse_inner_attrs_and_block()?;
432432
if let [.., last] = &*attrs {
433433
self.error_on_forbidden_inner_attr(

compiler/rustc_passes/src/liveness.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,12 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
446446
intravisit::walk_expr(self, expr);
447447
}
448448

449+
// Inline assembly may contain labels.
450+
hir::ExprKind::InlineAsm(asm) if asm.contains_label() => {
451+
self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id));
452+
intravisit::walk_expr(self, expr);
453+
}
454+
449455
// otherwise, live nodes are not required:
450456
hir::ExprKind::Index(..)
451457
| hir::ExprKind::Field(..)
@@ -1074,20 +1080,56 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
10741080
| hir::ExprKind::Repeat(ref e, _) => self.propagate_through_expr(e, succ),
10751081

10761082
hir::ExprKind::InlineAsm(asm) => {
1083+
//
1084+
// (inputs)
1085+
// |
1086+
// v
1087+
// (outputs)
1088+
// / \
1089+
// | |
1090+
// v v
1091+
// (labels)(fallthrough)
1092+
// | |
1093+
// v v
1094+
// ( succ / exit_ln )
1095+
10771096
// Handle non-returning asm
10781097
let mut succ = if asm.options.contains(InlineAsmOptions::NORETURN) {
10791098
self.exit_ln
10801099
} else {
10811100
succ
10821101
};
10831102

1103+
// Do a first pass for labels only
1104+
if asm.contains_label() {
1105+
let ln = self.live_node(expr.hir_id, expr.span);
1106+
self.init_from_succ(ln, succ);
1107+
for (op, _op_sp) in asm.operands.iter().rev() {
1108+
match op {
1109+
hir::InlineAsmOperand::Label { block } => {
1110+
let label_ln = self.propagate_through_block(block, succ);
1111+
self.merge_from_succ(ln, label_ln);
1112+
}
1113+
hir::InlineAsmOperand::In { .. }
1114+
| hir::InlineAsmOperand::Out { .. }
1115+
| hir::InlineAsmOperand::InOut { .. }
1116+
| hir::InlineAsmOperand::SplitInOut { .. }
1117+
| hir::InlineAsmOperand::Const { .. }
1118+
| hir::InlineAsmOperand::SymFn { .. }
1119+
| hir::InlineAsmOperand::SymStatic { .. } => {}
1120+
}
1121+
}
1122+
succ = ln;
1123+
}
1124+
10841125
// Do a first pass for writing outputs only
10851126
for (op, _op_sp) in asm.operands.iter().rev() {
10861127
match op {
10871128
hir::InlineAsmOperand::In { .. }
10881129
| hir::InlineAsmOperand::Const { .. }
10891130
| hir::InlineAsmOperand::SymFn { .. }
1090-
| hir::InlineAsmOperand::SymStatic { .. } => {}
1131+
| hir::InlineAsmOperand::SymStatic { .. }
1132+
| hir::InlineAsmOperand::Label { .. } => {}
10911133
hir::InlineAsmOperand::Out { expr, .. } => {
10921134
if let Some(expr) = expr {
10931135
succ = self.write_place(expr, succ, ACC_WRITE);
@@ -1126,7 +1168,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
11261168
}
11271169
hir::InlineAsmOperand::Const { .. }
11281170
| hir::InlineAsmOperand::SymFn { .. }
1129-
| hir::InlineAsmOperand::SymStatic { .. } => {}
1171+
| hir::InlineAsmOperand::SymStatic { .. }
1172+
| hir::InlineAsmOperand::Label { .. } => {}
11301173
}
11311174
}
11321175
succ

compiler/rustc_passes/src/naked_functions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
237237
InlineAsmOperand::In { .. }
238238
| InlineAsmOperand::Out { .. }
239239
| InlineAsmOperand::InOut { .. }
240-
| InlineAsmOperand::SplitInOut { .. } => Some(op_sp),
240+
| InlineAsmOperand::SplitInOut { .. }
241+
| InlineAsmOperand::Label { .. } => Some(op_sp),
241242
})
242243
.collect();
243244
if !unsupported_operands.is_empty() {

compiler/rustc_resolve/src/late.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,6 +1235,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
12351235
self.resolve_anon_const(anon_const, AnonConstKind::InlineConst);
12361236
}
12371237
InlineAsmOperand::Sym { sym } => self.visit_inline_asm_sym(sym),
1238+
InlineAsmOperand::Label { block } => self.visit_block(block),
12381239
}
12391240
}
12401241
}

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ symbols! {
403403
asm,
404404
asm_const,
405405
asm_experimental_arch,
406+
asm_goto,
406407
asm_sym,
407408
asm_unwind,
408409
assert,

0 commit comments

Comments
 (0)