Skip to content

Commit dc345d8

Browse files
committed
Reimplement lowering of sym operands for asm! so that it also works with global_asm!
1 parent f9d4d12 commit dc345d8

File tree

28 files changed

+402
-165
lines changed

28 files changed

+402
-165
lines changed

compiler/rustc_ast/src/ast.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -2061,6 +2061,20 @@ impl InlineAsmTemplatePiece {
20612061
}
20622062
}
20632063

2064+
/// Inline assembly symbol operands get their own AST node that is somewhat
2065+
/// similar to `AnonConst`.
2066+
///
2067+
/// The main difference is that we specifically don't assign it `DefId` in
2068+
/// `DefCollector`. Instead this is deferred until AST lowering where we
2069+
/// lower it to an `AnonConst` (for functions) or a `Path` (for statics)
2070+
/// depending on what the path resolves to.
2071+
#[derive(Clone, Encodable, Decodable, Debug)]
2072+
pub struct InlineAsmSym {
2073+
pub id: NodeId,
2074+
pub qself: Option<QSelf>,
2075+
pub path: Path,
2076+
}
2077+
20642078
/// Inline assembly operand.
20652079
///
20662080
/// E.g., `out("eax") result` as in `asm!("mov eax, 2", out("eax") result)`.
@@ -2090,7 +2104,7 @@ pub enum InlineAsmOperand {
20902104
anon_const: AnonConst,
20912105
},
20922106
Sym {
2093-
expr: P<Expr>,
2107+
sym: InlineAsmSym,
20942108
},
20952109
}
20962110

compiler/rustc_ast/src/mut_visit.rs

+23-6
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,14 @@ pub trait MutVisitor: Sized {
280280
fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> {
281281
noop_flat_map_pat_field(fp, self)
282282
}
283+
284+
fn visit_inline_asm(&mut self, asm: &mut InlineAsm) {
285+
noop_visit_inline_asm(asm, self)
286+
}
287+
288+
fn visit_inline_asm_sym(&mut self, sym: &mut InlineAsmSym) {
289+
noop_visit_inline_asm_sym(sym, self)
290+
}
283291
}
284292

285293
/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
@@ -1019,7 +1027,7 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
10191027
}
10201028
}
10211029
ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
1022-
ItemKind::GlobalAsm(asm) => noop_visit_inline_asm(asm, vis),
1030+
ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm),
10231031
ItemKind::TyAlias(box TyAlias {
10241032
defaultness, generics, where_clauses, bounds, ty, ..
10251033
}) => {
@@ -1237,25 +1245,34 @@ pub fn noop_visit_anon_const<T: MutVisitor>(AnonConst { id, value }: &mut AnonCo
12371245
vis.visit_expr(value);
12381246
}
12391247

1240-
fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
1248+
pub fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
12411249
for (op, _) in &mut asm.operands {
12421250
match op {
12431251
InlineAsmOperand::In { expr, .. }
12441252
| InlineAsmOperand::Out { expr: Some(expr), .. }
1245-
| InlineAsmOperand::InOut { expr, .. }
1246-
| InlineAsmOperand::Sym { expr, .. } => vis.visit_expr(expr),
1253+
| InlineAsmOperand::InOut { expr, .. } => vis.visit_expr(expr),
12471254
InlineAsmOperand::Out { expr: None, .. } => {}
12481255
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
12491256
vis.visit_expr(in_expr);
12501257
if let Some(out_expr) = out_expr {
12511258
vis.visit_expr(out_expr);
12521259
}
12531260
}
1254-
InlineAsmOperand::Const { anon_const, .. } => vis.visit_anon_const(anon_const),
1261+
InlineAsmOperand::Const { anon_const } => vis.visit_anon_const(anon_const),
1262+
InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym),
12551263
}
12561264
}
12571265
}
12581266

1267+
pub fn noop_visit_inline_asm_sym<T: MutVisitor>(
1268+
InlineAsmSym { id, qself, path }: &mut InlineAsmSym,
1269+
vis: &mut T,
1270+
) {
1271+
vis.visit_id(id);
1272+
vis.visit_qself(qself);
1273+
vis.visit_path(path);
1274+
}
1275+
12591276
pub fn noop_visit_expr<T: MutVisitor>(
12601277
Expr { kind, id, span, attrs, tokens }: &mut Expr,
12611278
vis: &mut T,
@@ -1374,7 +1391,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
13741391
ExprKind::Ret(expr) => {
13751392
visit_opt(expr, |expr| vis.visit_expr(expr));
13761393
}
1377-
ExprKind::InlineAsm(asm) => noop_visit_inline_asm(asm, vis),
1394+
ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm),
13781395
ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
13791396
ExprKind::Struct(se) => {
13801397
let StructExpr { qself, path, fields, rest } = se.deref_mut();

compiler/rustc_ast/src/visit.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,12 @@ pub trait Visitor<'ast>: Sized {
214214
fn visit_crate(&mut self, krate: &'ast Crate) {
215215
walk_crate(self, krate)
216216
}
217+
fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) {
218+
walk_inline_asm(self, asm)
219+
}
220+
fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
221+
walk_inline_asm_sym(self, sym)
222+
}
217223
}
218224

219225
#[macro_export]
@@ -717,13 +723,12 @@ pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonCo
717723
visitor.visit_expr(&constant.value);
718724
}
719725

720-
fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) {
726+
pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) {
721727
for (op, _) in &asm.operands {
722728
match op {
723729
InlineAsmOperand::In { expr, .. }
724730
| InlineAsmOperand::Out { expr: Some(expr), .. }
725-
| InlineAsmOperand::InOut { expr, .. }
726-
| InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr),
731+
| InlineAsmOperand::InOut { expr, .. } => visitor.visit_expr(expr),
727732
InlineAsmOperand::Out { expr: None, .. } => {}
728733
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
729734
visitor.visit_expr(in_expr);
@@ -732,10 +737,18 @@ fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) {
732737
}
733738
}
734739
InlineAsmOperand::Const { anon_const, .. } => visitor.visit_anon_const(anon_const),
740+
InlineAsmOperand::Sym { sym } => visitor.visit_inline_asm_sym(sym),
735741
}
736742
}
737743
}
738744

745+
pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(visitor: &mut V, sym: &'a InlineAsmSym) {
746+
if let Some(ref qself) = sym.qself {
747+
visitor.visit_ty(&qself.ty);
748+
}
749+
visitor.visit_path(&sym.path, sym.id);
750+
}
751+
739752
pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
740753
walk_list!(visitor, visit_attribute, expression.attrs.iter());
741754

compiler/rustc_ast_lowering/src/asm.rs

+60-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1+
use crate::{ImplTraitContext, ImplTraitPosition, ParamMode};
2+
13
use super::LoweringContext;
24

5+
use rustc_ast::ptr::P;
36
use rustc_ast::*;
47
use rustc_data_structures::fx::FxHashMap;
58
use rustc_data_structures::stable_set::FxHashSet;
69
use rustc_errors::struct_span_err;
710
use rustc_hir as hir;
11+
use rustc_hir::def::{DefKind, Res};
12+
use rustc_hir::definitions::DefPathData;
813
use rustc_session::parse::feature_err;
9-
use rustc_span::{sym, Span};
14+
use rustc_span::{sym, ExpnId, Span};
1015
use rustc_target::asm;
1116
use std::collections::hash_map::Entry;
1217
use std::fmt::Write;
@@ -188,7 +193,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
188193
anon_const: self.lower_anon_const(anon_const),
189194
}
190195
}
191-
InlineAsmOperand::Sym { ref expr } => {
196+
InlineAsmOperand::Sym { ref sym } => {
192197
if !self.sess.features_untracked().asm_sym {
193198
feature_err(
194199
&self.sess.parse_sess,
@@ -198,7 +203,54 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
198203
)
199204
.emit();
200205
}
201-
hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
206+
207+
let static_def_id = self
208+
.resolver
209+
.get_partial_res(sym.id)
210+
.filter(|res| res.unresolved_segments() == 0)
211+
.and_then(|res| {
212+
if let Res::Def(DefKind::Static(_), def_id) = res.base_res() {
213+
Some(def_id)
214+
} else {
215+
None
216+
}
217+
});
218+
219+
if let Some(def_id) = static_def_id {
220+
let path = self.lower_qpath(
221+
sym.id,
222+
&sym.qself,
223+
&sym.path,
224+
ParamMode::Optional,
225+
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
226+
);
227+
hir::InlineAsmOperand::SymStatic { path, def_id }
228+
} else {
229+
// Replace the InlineAsmSym AST node with an
230+
// Expr using the name node id.
231+
let expr = Expr {
232+
id: sym.id,
233+
kind: ExprKind::Path(sym.qself.clone(), sym.path.clone()),
234+
span: *op_sp,
235+
attrs: AttrVec::new(),
236+
tokens: None,
237+
};
238+
239+
// Wrap the expression in an AnonConst.
240+
let parent_def_id = self.current_hir_id_owner;
241+
let node_id = self.resolver.next_node_id();
242+
self.resolver.create_def(
243+
parent_def_id,
244+
node_id,
245+
DefPathData::AnonConst,
246+
ExpnId::root(),
247+
*op_sp,
248+
);
249+
let anon_const = AnonConst { id: node_id, value: P(expr) };
250+
hir::InlineAsmOperand::SymFn {
251+
anon_const: self.lower_anon_const(&anon_const),
252+
}
253+
}
202254
}
203255
};
204256
(op, self.lower_span(*op_sp))
@@ -260,7 +312,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
260312
err.span_label(op_sp, "argument");
261313
err.emit();
262314
}
263-
hir::InlineAsmOperand::Sym { .. } => {
315+
hir::InlineAsmOperand::SymFn { .. }
316+
| hir::InlineAsmOperand::SymStatic { .. } => {
264317
let mut err = sess.struct_span_err(
265318
placeholder_span,
266319
"asm template modifiers are not allowed for `sym` arguments",
@@ -308,7 +361,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
308361
hir::InlineAsmOperand::InOut { .. }
309362
| hir::InlineAsmOperand::SplitInOut { .. } => (true, true),
310363

311-
hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::Sym { .. } => {
364+
hir::InlineAsmOperand::Const { .. }
365+
| hir::InlineAsmOperand::SymFn { .. }
366+
| hir::InlineAsmOperand::SymStatic { .. } => {
312367
unreachable!()
313368
}
314369
};

compiler/rustc_ast_pretty/src/pprust/state.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1266,10 +1266,14 @@ impl<'a> State<'a> {
12661266
s.space();
12671267
s.print_expr(&anon_const.value);
12681268
}
1269-
InlineAsmOperand::Sym { expr } => {
1269+
InlineAsmOperand::Sym { sym } => {
12701270
s.word("sym");
12711271
s.space();
1272-
s.print_expr(expr);
1272+
if let Some(qself) = &sym.qself {
1273+
s.print_qpath(&sym.path, qself, true);
1274+
} else {
1275+
s.print_path(&sym.path, true, 0);
1276+
}
12731277
}
12741278
}
12751279
}

compiler/rustc_builtin_macros/src/asm.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -154,17 +154,19 @@ pub fn parse_asm_args<'a>(
154154
} else if p.eat_keyword(kw::Const) {
155155
let anon_const = p.parse_anon_const_expr()?;
156156
ast::InlineAsmOperand::Const { anon_const }
157-
} else if !is_global_asm && p.eat_keyword(sym::sym) {
157+
} else if p.eat_keyword(sym::sym) {
158158
let expr = p.parse_expr()?;
159-
match expr.kind {
160-
ast::ExprKind::Path(..) => {}
161-
_ => {
162-
let err = diag
163-
.struct_span_err(expr.span, "argument to `sym` must be a path expression");
164-
return Err(err);
165-
}
166-
}
167-
ast::InlineAsmOperand::Sym { expr }
159+
let ast::ExprKind::Path(qself, path) = &expr.kind else {
160+
let err = diag
161+
.struct_span_err(expr.span, "expected a path for argument to `sym`");
162+
return Err(err);
163+
};
164+
let sym = ast::InlineAsmSym {
165+
id: ast::DUMMY_NODE_ID,
166+
qself: qself.clone(),
167+
path: path.clone(),
168+
};
169+
ast::InlineAsmOperand::Sym { sym }
168170
} else if allow_templates {
169171
let template = p.parse_expr()?;
170172
// If it can't possibly expand to a string, provide diagnostics here to include other

compiler/rustc_hir/src/hir.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -2425,8 +2425,12 @@ pub enum InlineAsmOperand<'hir> {
24252425
Const {
24262426
anon_const: AnonConst,
24272427
},
2428-
Sym {
2429-
expr: Expr<'hir>,
2428+
SymFn {
2429+
anon_const: AnonConst,
2430+
},
2431+
SymStatic {
2432+
path: QPath<'hir>,
2433+
def_id: DefId,
24302434
},
24312435
}
24322436

@@ -2437,7 +2441,7 @@ impl<'hir> InlineAsmOperand<'hir> {
24372441
| Self::Out { reg, .. }
24382442
| Self::InOut { reg, .. }
24392443
| Self::SplitInOut { reg, .. } => Some(reg),
2440-
Self::Const { .. } | Self::Sym { .. } => None,
2444+
Self::Const { .. } | Self::SymFn { .. } | Self::SymStatic { .. } => None,
24412445
}
24422446
}
24432447

compiler/rustc_hir/src/intravisit.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,9 @@ pub trait Visitor<'v>: Sized {
484484
fn visit_defaultness(&mut self, defaultness: &'v Defaultness) {
485485
walk_defaultness(self, defaultness);
486486
}
487+
fn visit_inline_asm(&mut self, asm: &'v InlineAsm<'v>, id: HirId) {
488+
walk_inline_asm(self, asm, id);
489+
}
487490
}
488491

489492
pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) {
@@ -588,7 +591,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
588591
}
589592
ItemKind::GlobalAsm(asm) => {
590593
visitor.visit_id(item.hir_id());
591-
walk_inline_asm(visitor, asm);
594+
visitor.visit_inline_asm(asm, item.hir_id());
592595
}
593596
ItemKind::TyAlias(ref ty, ref generics) => {
594597
visitor.visit_id(item.hir_id());
@@ -648,12 +651,12 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
648651
}
649652
}
650653

651-
fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'v>) {
652-
for (op, _op_sp) in asm.operands {
654+
pub fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'v>, id: HirId) {
655+
for (op, op_sp) in asm.operands {
653656
match op {
654-
InlineAsmOperand::In { expr, .. }
655-
| InlineAsmOperand::InOut { expr, .. }
656-
| InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr),
657+
InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => {
658+
visitor.visit_expr(expr)
659+
}
657660
InlineAsmOperand::Out { expr, .. } => {
658661
if let Some(expr) = expr {
659662
visitor.visit_expr(expr);
@@ -665,7 +668,9 @@ fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'v>)
665668
visitor.visit_expr(out_expr);
666669
}
667670
}
668-
InlineAsmOperand::Const { anon_const } => visitor.visit_anon_const(anon_const),
671+
InlineAsmOperand::Const { anon_const, .. }
672+
| InlineAsmOperand::SymFn { anon_const, .. } => visitor.visit_anon_const(anon_const),
673+
InlineAsmOperand::SymStatic { path, .. } => visitor.visit_qpath(path, id, *op_sp),
669674
}
670675
}
671676
}
@@ -1221,7 +1226,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
12211226
walk_list!(visitor, visit_expr, optional_expression);
12221227
}
12231228
ExprKind::InlineAsm(ref asm) => {
1224-
walk_inline_asm(visitor, asm);
1229+
visitor.visit_inline_asm(asm, expression.hir_id);
12251230
}
12261231
ExprKind::Yield(ref subexpression, _) => {
12271232
visitor.visit_expr(subexpression);

0 commit comments

Comments
 (0)