Skip to content

Commit 64e1b63

Browse files
committed
Forbid ! from being used in asm! output
1 parent 4498e30 commit 64e1b63

File tree

3 files changed

+37
-5
lines changed

3 files changed

+37
-5
lines changed

compiler/rustc_passes/src/intrinsicck.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ impl ExprVisitor<'tcx> {
139139
reg: InlineAsmRegOrRegClass,
140140
expr: &hir::Expr<'tcx>,
141141
template: &[InlineAsmTemplatePiece],
142+
is_input: bool,
142143
tied_input: Option<(&hir::Expr<'tcx>, Option<InlineAsmType>)>,
143144
) -> Option<InlineAsmType> {
144145
// Check the type against the allowed types for inline asm.
@@ -150,7 +151,9 @@ impl ExprVisitor<'tcx> {
150151
_ => unreachable!(),
151152
};
152153
let asm_ty = match *ty.kind() {
153-
ty::Never | ty::Error(_) => return None,
154+
// `!` is allowed for input but not for output (issue #87802)
155+
ty::Never if is_input => return None,
156+
ty::Error(_) => return None,
154157
ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::I8),
155158
ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Some(InlineAsmType::I16),
156159
ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Some(InlineAsmType::I32),
@@ -350,24 +353,26 @@ impl ExprVisitor<'tcx> {
350353
for (idx, (op, _)) in asm.operands.iter().enumerate() {
351354
match *op {
352355
hir::InlineAsmOperand::In { reg, ref expr } => {
353-
self.check_asm_operand_type(idx, reg, expr, asm.template, None);
356+
self.check_asm_operand_type(idx, reg, expr, asm.template, true, None);
354357
}
355358
hir::InlineAsmOperand::Out { reg, late: _, ref expr } => {
356359
if let Some(expr) = expr {
357-
self.check_asm_operand_type(idx, reg, expr, asm.template, None);
360+
self.check_asm_operand_type(idx, reg, expr, asm.template, false, None);
358361
}
359362
}
360363
hir::InlineAsmOperand::InOut { reg, late: _, ref expr } => {
361-
self.check_asm_operand_type(idx, reg, expr, asm.template, None);
364+
self.check_asm_operand_type(idx, reg, expr, asm.template, false, None);
362365
}
363366
hir::InlineAsmOperand::SplitInOut { reg, late: _, ref in_expr, ref out_expr } => {
364-
let in_ty = self.check_asm_operand_type(idx, reg, in_expr, asm.template, None);
367+
let in_ty =
368+
self.check_asm_operand_type(idx, reg, in_expr, asm.template, true, None);
365369
if let Some(out_expr) = out_expr {
366370
self.check_asm_operand_type(
367371
idx,
368372
reg,
369373
out_expr,
370374
asm.template,
375+
false,
371376
Some((in_expr, in_ty)),
372377
);
373378
}

src/test/ui/asm/issue-87802.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// only-x86_64
2+
// Make sure rustc doesn't ICE on asm! when output type is !.
3+
4+
#![feature(asm)]
5+
6+
fn hmm() -> ! {
7+
let x;
8+
unsafe {
9+
asm!("/* {0} */", out(reg) x);
10+
//~^ ERROR cannot use value of type `!` for inline assembly
11+
}
12+
x
13+
}
14+
15+
fn main() {
16+
hmm();
17+
}

src/test/ui/asm/issue-87802.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: cannot use value of type `!` for inline assembly
2+
--> $DIR/issue-87802.rs:9:36
3+
|
4+
LL | asm!("/* {0} */", out(reg) x);
5+
| ^
6+
|
7+
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)