Skip to content

Commit 97d5dfd

Browse files
Handle lifetimes correctly in in sym in line-asm
1 parent f6bbc80 commit 97d5dfd

File tree

23 files changed

+211
-90
lines changed

23 files changed

+211
-90
lines changed

compiler/rustc_ast_lowering/src/asm.rs

+23-14
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
2626
&mut self,
2727
sp: Span,
2828
asm: &InlineAsm,
29+
is_global: bool,
2930
) -> &'hir hir::InlineAsm<'hir> {
3031
// Rustdoc needs to support asm! from foreign architectures: don't try
3132
// lowering the register constraints in this case.
@@ -221,18 +222,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
221222
tokens: None,
222223
};
223224

224-
// Wrap the expression in an AnonConst.
225-
let parent_def_id = self.current_hir_id_owner;
226-
let node_id = self.next_node_id();
227-
self.create_def(
228-
parent_def_id.def_id,
229-
node_id,
230-
DefPathData::AnonConst,
231-
*op_sp,
232-
);
233-
let anon_const = AnonConst { id: node_id, value: P(expr) };
234-
hir::InlineAsmOperand::SymFn {
235-
anon_const: self.lower_anon_const(&anon_const),
225+
if is_global {
226+
// Wrap the expression in an AnonConst.
227+
let parent_def_id = self.current_hir_id_owner;
228+
let node_id = self.next_node_id();
229+
self.create_def(
230+
parent_def_id.def_id,
231+
node_id,
232+
DefPathData::AnonConst,
233+
*op_sp,
234+
);
235+
let anon_const = AnonConst { id: node_id, value: P(expr) };
236+
hir::InlineAsmOperand::SymFnInGlobal {
237+
anon_const: self.lower_anon_const(&anon_const),
238+
}
239+
} else {
240+
hir::InlineAsmOperand::SymFnInInline {
241+
expr: self.lower_expr(&expr),
242+
}
236243
}
237244
}
238245
}
@@ -288,7 +295,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
288295
op_span: op_sp,
289296
});
290297
}
291-
hir::InlineAsmOperand::SymFn { .. }
298+
hir::InlineAsmOperand::SymFnInGlobal { .. }
299+
| hir::InlineAsmOperand::SymFnInInline { .. }
292300
| hir::InlineAsmOperand::SymStatic { .. } => {
293301
sess.emit_err(InvalidAsmTemplateModifierSym {
294302
placeholder_span,
@@ -333,7 +341,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
333341
| hir::InlineAsmOperand::SplitInOut { .. } => (true, true),
334342

335343
hir::InlineAsmOperand::Const { .. }
336-
| hir::InlineAsmOperand::SymFn { .. }
344+
| hir::InlineAsmOperand::SymFnInGlobal { .. }
345+
| hir::InlineAsmOperand::SymFnInInline { .. }
337346
| hir::InlineAsmOperand::SymStatic { .. } => {
338347
unreachable!()
339348
}

compiler/rustc_ast_lowering/src/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
283283
hir::ExprKind::Become(sub_expr)
284284
}
285285
ExprKind::InlineAsm(asm) => {
286-
hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm))
286+
hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm, false))
287287
}
288288
ExprKind::FormatArgs(fmt) => self.lower_format_args(e.span, fmt),
289289
ExprKind::OffsetOf(container, fields) => hir::ExprKind::OffsetOf(

compiler/rustc_ast_lowering/src/item.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
311311
.arena
312312
.alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
313313
},
314-
ItemKind::GlobalAsm(asm) => hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm)),
314+
ItemKind::GlobalAsm(asm) => {
315+
hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm, true))
316+
}
315317
ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
316318
// We lower
317319
//

compiler/rustc_codegen_ssa/src/mono_item.rs

+48-45
Original file line numberDiff line numberDiff line change
@@ -35,52 +35,55 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
3535
MonoItem::GlobalAsm(item_id) => {
3636
let item = cx.tcx().hir().item(item_id);
3737
if let hir::ItemKind::GlobalAsm(ref asm) = item.kind {
38-
let operands: Vec<_> = asm
39-
.operands
40-
.iter()
41-
.map(|(op, op_sp)| match *op {
42-
hir::InlineAsmOperand::Const { ref anon_const } => {
43-
let const_value = cx
44-
.tcx()
45-
.const_eval_poly(anon_const.def_id.to_def_id())
46-
.unwrap_or_else(|_| {
47-
span_bug!(*op_sp, "asm const cannot be resolved")
48-
});
49-
let ty = cx
50-
.tcx()
51-
.typeck_body(anon_const.body)
52-
.node_type(anon_const.hir_id);
53-
let string = common::asm_const_to_str(
54-
cx.tcx(),
55-
*op_sp,
56-
const_value,
57-
cx.layout_of(ty),
58-
);
59-
GlobalAsmOperandRef::Const { string }
60-
}
61-
hir::InlineAsmOperand::SymFn { ref anon_const } => {
62-
let ty = cx
63-
.tcx()
64-
.typeck_body(anon_const.body)
65-
.node_type(anon_const.hir_id);
66-
let instance = match ty.kind() {
67-
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
68-
_ => span_bug!(*op_sp, "asm sym is not a function"),
69-
};
38+
let operands: Vec<_> =
39+
asm.operands
40+
.iter()
41+
.map(|(op, op_sp)| match *op {
42+
hir::InlineAsmOperand::Const { ref anon_const } => {
43+
let const_value = cx
44+
.tcx()
45+
.const_eval_poly(anon_const.def_id.to_def_id())
46+
.unwrap_or_else(|_| {
47+
span_bug!(*op_sp, "asm const cannot be resolved")
48+
});
49+
let ty = cx
50+
.tcx()
51+
.typeck_body(anon_const.body)
52+
.node_type(anon_const.hir_id);
53+
let string = common::asm_const_to_str(
54+
cx.tcx(),
55+
*op_sp,
56+
const_value,
57+
cx.layout_of(ty),
58+
);
59+
GlobalAsmOperandRef::Const { string }
60+
}
61+
hir::InlineAsmOperand::SymFnInGlobal { ref anon_const } => {
62+
let fn_ty =
63+
cx.tcx().type_of(anon_const.def_id).no_bound_vars().expect(
64+
"`sym` in `global_asm!` should not have generics",
65+
);
66+
let instance = match fn_ty.kind() {
67+
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
68+
_ => span_bug!(*op_sp, "asm sym is not a function"),
69+
};
7070

71-
GlobalAsmOperandRef::SymFn { instance }
72-
}
73-
hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
74-
GlobalAsmOperandRef::SymStatic { def_id }
75-
}
76-
hir::InlineAsmOperand::In { .. }
77-
| hir::InlineAsmOperand::Out { .. }
78-
| hir::InlineAsmOperand::InOut { .. }
79-
| hir::InlineAsmOperand::SplitInOut { .. } => {
80-
span_bug!(*op_sp, "invalid operand type for global_asm!")
81-
}
82-
})
83-
.collect();
71+
GlobalAsmOperandRef::SymFn { instance }
72+
}
73+
hir::InlineAsmOperand::SymFnInInline { .. } => {
74+
bug!("should not encounter `SymFnInInline` in `global_asm!`");
75+
}
76+
hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
77+
GlobalAsmOperandRef::SymStatic { def_id }
78+
}
79+
hir::InlineAsmOperand::In { .. }
80+
| hir::InlineAsmOperand::Out { .. }
81+
| hir::InlineAsmOperand::InOut { .. }
82+
| hir::InlineAsmOperand::SplitInOut { .. } => {
83+
span_bug!(*op_sp, "invalid operand type for global_asm!")
84+
}
85+
})
86+
.collect();
8487

8588
cx.codegen_global_asm(asm.template, &operands, asm.options, asm.line_spans);
8689
} else {

compiler/rustc_hir/src/hir.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -2766,9 +2766,12 @@ pub enum InlineAsmOperand<'hir> {
27662766
Const {
27672767
anon_const: AnonConst,
27682768
},
2769-
SymFn {
2769+
SymFnInGlobal {
27702770
anon_const: AnonConst,
27712771
},
2772+
SymFnInInline {
2773+
expr: &'hir Expr<'hir>,
2774+
},
27722775
SymStatic {
27732776
path: QPath<'hir>,
27742777
def_id: DefId,
@@ -2782,7 +2785,10 @@ impl<'hir> InlineAsmOperand<'hir> {
27822785
| Self::Out { reg, .. }
27832786
| Self::InOut { reg, .. }
27842787
| Self::SplitInOut { reg, .. } => Some(reg),
2785-
Self::Const { .. } | Self::SymFn { .. } | Self::SymStatic { .. } => None,
2788+
Self::Const { .. }
2789+
| Self::SymFnInGlobal { .. }
2790+
| Self::SymFnInInline { .. }
2791+
| Self::SymStatic { .. } => None,
27862792
}
27872793
}
27882794

compiler/rustc_hir/src/intravisit.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,12 @@ pub fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'
12191219
}
12201220
}
12211221
InlineAsmOperand::Const { anon_const, .. }
1222-
| InlineAsmOperand::SymFn { anon_const, .. } => visitor.visit_anon_const(anon_const),
1222+
| InlineAsmOperand::SymFnInGlobal { anon_const, .. } => {
1223+
visitor.visit_anon_const(anon_const)
1224+
}
1225+
InlineAsmOperand::SymFnInInline { expr } => {
1226+
visitor.visit_expr(expr);
1227+
}
12231228
InlineAsmOperand::SymStatic { path, .. } => visitor.visit_qpath(path, id, *op_sp),
12241229
}
12251230
}

compiler/rustc_hir_analysis/src/check/intrinsicck.rs

+24-7
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,24 @@ use rustc_target::asm::{InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass,
1111
pub struct InlineAsmCtxt<'a, 'tcx> {
1212
tcx: TyCtxt<'tcx>,
1313
param_env: ty::ParamEnv<'tcx>,
14-
get_operand_ty: Box<dyn Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a>,
14+
get_expr_ty: Box<dyn Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a>,
1515
}
1616

1717
impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
1818
pub fn new_global_asm(tcx: TyCtxt<'tcx>) -> Self {
1919
InlineAsmCtxt {
2020
tcx,
2121
param_env: ty::ParamEnv::empty(),
22-
get_operand_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")),
22+
get_expr_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")),
2323
}
2424
}
2525

2626
pub fn new_in_fn(
2727
tcx: TyCtxt<'tcx>,
2828
param_env: ty::ParamEnv<'tcx>,
29-
get_operand_ty: impl Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a,
29+
get_expr_ty: impl Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a,
3030
) -> Self {
31-
InlineAsmCtxt { tcx, param_env, get_operand_ty: Box::new(get_operand_ty) }
31+
InlineAsmCtxt { tcx, param_env, get_expr_ty: Box::new(get_expr_ty) }
3232
}
3333

3434
// FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()`
@@ -124,7 +124,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
124124
tied_input: Option<(&'tcx hir::Expr<'tcx>, Option<InlineAsmType>)>,
125125
target_features: &FxIndexSet<Symbol>,
126126
) -> Option<InlineAsmType> {
127-
let ty = (self.get_operand_ty)(expr);
127+
let ty = (self.get_expr_ty)(expr);
128128
if ty.has_non_region_infer() {
129129
bug!("inference variable in asm operand ty: {:?} {:?}", expr, ty);
130130
}
@@ -178,7 +178,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
178178
let msg = "incompatible types for asm inout argument";
179179
let mut err = self.tcx.sess.struct_span_err(vec![in_expr.span, expr.span], msg);
180180

181-
let in_expr_ty = (self.get_operand_ty)(in_expr);
181+
let in_expr_ty = (self.get_expr_ty)(in_expr);
182182
err.span_label(in_expr.span, format!("type `{in_expr_ty}`"));
183183
err.span_label(expr.span, format!("type `{ty}`"));
184184
err.note(
@@ -437,7 +437,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
437437
hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymStatic { .. } => {}
438438
// Check that sym actually points to a function. Later passes
439439
// depend on this.
440-
hir::InlineAsmOperand::SymFn { anon_const } => {
440+
hir::InlineAsmOperand::SymFnInGlobal { anon_const } => {
441441
let ty = self.tcx.type_of(anon_const.def_id).instantiate_identity();
442442
match ty.kind() {
443443
ty::Never | ty::Error(_) => {}
@@ -454,6 +454,23 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
454454
}
455455
};
456456
}
457+
hir::InlineAsmOperand::SymFnInInline { expr } => {
458+
let ty = (self.get_expr_ty)(expr);
459+
match ty.kind() {
460+
ty::Never | ty::Error(_) => {}
461+
ty::FnDef(..) => {}
462+
_ => {
463+
let mut err =
464+
self.tcx.sess.struct_span_err(*op_sp, "invalid `sym` operand");
465+
err.span_label(
466+
expr.span,
467+
format!("is {} `{}`", ty.kind().article(), ty),
468+
);
469+
err.help("`sym` operands must refer to either a function or a static");
470+
err.emit();
471+
}
472+
};
473+
}
457474
}
458475
}
459476
}

compiler/rustc_hir_analysis/src/collect/generics_of.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
128128
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
129129
if asm.operands.iter().any(|(op, _op_sp)| match op {
130130
hir::InlineAsmOperand::Const { anon_const }
131-
| hir::InlineAsmOperand::SymFn { anon_const } => {
131+
| hir::InlineAsmOperand::SymFnInGlobal { anon_const } => {
132132
anon_const.hir_id == hir_id
133133
}
134134
_ => false,

compiler/rustc_hir_analysis/src/collect/type_of.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
3939
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
4040
if asm.operands.iter().any(|(op, _op_sp)| match op {
4141
hir::InlineAsmOperand::Const { anon_const }
42-
| hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
42+
| hir::InlineAsmOperand::SymFnInGlobal { anon_const } => anon_const.hir_id == hir_id,
4343
_ => false,
4444
}) =>
4545
{

compiler/rustc_hir_pretty/src/lib.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1309,11 +1309,16 @@ impl<'a> State<'a> {
13091309
s.space();
13101310
s.print_anon_const(anon_const);
13111311
}
1312-
hir::InlineAsmOperand::SymFn { ref anon_const } => {
1312+
hir::InlineAsmOperand::SymFnInGlobal { ref anon_const } => {
13131313
s.word("sym_fn");
13141314
s.space();
13151315
s.print_anon_const(anon_const);
13161316
}
1317+
hir::InlineAsmOperand::SymFnInInline { ref expr } => {
1318+
s.word("sym_fn");
1319+
s.space();
1320+
s.print_expr(expr);
1321+
}
13171322
hir::InlineAsmOperand::SymStatic { ref path, def_id: _ } => {
13181323
s.word("sym_static");
13191324
s.space();

compiler/rustc_hir_typeck/src/expr.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -3113,10 +3113,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31133113
self.check_expr_asm_operand(out_expr, false);
31143114
}
31153115
}
3116+
hir::InlineAsmOperand::SymFnInInline { expr } => {
3117+
self.check_expr(expr);
3118+
}
31163119
// `AnonConst`s have their own body and is type-checked separately.
31173120
// As they don't flow into the type system we don't need them to
31183121
// be well-formed.
3119-
hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {}
3122+
hir::InlineAsmOperand::Const { .. }
3123+
| hir::InlineAsmOperand::SymFnInGlobal { .. } => {}
31203124
hir::InlineAsmOperand::SymStatic { .. } => {}
31213125
}
31223126
}

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,10 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
291291
}
292292
hir::InlineAsmOperand::Out { expr: None, .. }
293293
| hir::InlineAsmOperand::Const { .. }
294-
| hir::InlineAsmOperand::SymFn { .. }
294+
| hir::InlineAsmOperand::SymFnInGlobal { .. }
295+
// `sym`, even in body, operates like a constant,
296+
// so no need to consume or mutate anything here.
297+
| hir::InlineAsmOperand::SymFnInInline { .. }
295298
| hir::InlineAsmOperand::SymStatic { .. } => {}
296299
}
297300
}

compiler/rustc_hir_typeck/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,9 @@ fn typeck_with_fallback<'tcx>(
223223
// Inline assembly constants must be integers.
224224
Some(fcx.next_int_var())
225225
}
226-
hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == id => {
226+
hir::InlineAsmOperand::SymFnInGlobal { anon_const }
227+
if anon_const.hir_id == id =>
228+
{
227229
Some(fcx.next_ty_var(TypeVariableOrigin {
228230
kind: TypeVariableOriginKind::MiscVariable,
229231
span,

compiler/rustc_middle/src/thir.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -566,10 +566,13 @@ pub enum InlineAsmOperand<'tcx> {
566566
value: mir::Const<'tcx>,
567567
span: Span,
568568
},
569-
SymFn {
569+
SymFnInGlobal {
570570
value: mir::Const<'tcx>,
571571
span: Span,
572572
},
573+
SymFnInInline {
574+
expr: ExprId,
575+
},
573576
SymStatic {
574577
def_id: DefId,
575578
},

0 commit comments

Comments
 (0)