Skip to content

Commit db8af3f

Browse files
committed
Add support for specifying multiple clobber_abi in asm!
1 parent addb4da commit db8af3f

File tree

7 files changed

+98
-80
lines changed

7 files changed

+98
-80
lines changed

compiler/rustc_ast/src/ast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2056,7 +2056,7 @@ pub struct InlineAsm {
20562056
pub template: Vec<InlineAsmTemplatePiece>,
20572057
pub template_strs: Box<[(Symbol, Option<Symbol>, Span)]>,
20582058
pub operands: Vec<(InlineAsmOperand, Span)>,
2059-
pub clobber_abi: Option<(Symbol, Span)>,
2059+
pub clobber_abis: Vec<(Symbol, Span)>,
20602060
pub options: InlineAsmOptions,
20612061
pub line_spans: Vec<Span>,
20622062
}
@@ -2744,7 +2744,7 @@ pub enum ItemKind {
27442744
}
27452745

27462746
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2747-
rustc_data_structures::static_assert_size!(ItemKind, 112);
2747+
rustc_data_structures::static_assert_size!(ItemKind, 128);
27482748

27492749
impl ItemKind {
27502750
pub fn article(&self) -> &str {

compiler/rustc_ast_lowering/src/asm.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use super::LoweringContext;
22

33
use rustc_ast::*;
44
use rustc_data_structures::fx::FxHashMap;
5+
use rustc_data_structures::stable_set::FxHashSet;
56
use rustc_errors::struct_span_err;
67
use rustc_hir as hir;
78
use rustc_span::{Span, Symbol};
@@ -27,11 +28,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
2728
.emit();
2829
}
2930

30-
let mut clobber_abi = None;
31+
let mut clobber_abis = FxHashSet::default();
3132
if let Some(asm_arch) = asm_arch {
32-
if let Some((abi_name, abi_span)) = asm.clobber_abi {
33+
for &(abi_name, abi_span) in &asm.clobber_abis {
3334
match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, abi_name) {
34-
Ok(abi) => clobber_abi = Some((abi, abi_span)),
35+
Ok(abi) => {
36+
clobber_abis.insert((abi, abi_span));
37+
}
3538
Err(&[]) => {
3639
self.sess
3740
.struct_span_err(
@@ -368,7 +371,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
368371

369372
// If a clobber_abi is specified, add the necessary clobbers to the
370373
// operands list.
371-
if let Some((abi, abi_span)) = clobber_abi {
374+
for (abi, abi_span) in clobber_abis {
372375
for &clobber in abi.clobbered_regs() {
373376
let mut output_used = false;
374377
clobber.overlapping_regs(|reg| {

compiler/rustc_ast_pretty/src/pprust/state.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2199,8 +2199,8 @@ impl<'a> State<'a> {
21992199

22002200
let mut args = vec![AsmArg::Template(InlineAsmTemplatePiece::to_string(&asm.template))];
22012201
args.extend(asm.operands.iter().map(|(o, _)| AsmArg::Operand(o)));
2202-
if let Some((abi, _)) = asm.clobber_abi {
2203-
args.push(AsmArg::ClobberAbi(abi));
2202+
for (abi, _) in &asm.clobber_abis {
2203+
args.push(AsmArg::ClobberAbi(*abi));
22042204
}
22052205
if !asm.options.is_empty() {
22062206
args.push(AsmArg::Options(asm.options));

compiler/rustc_builtin_macros/src/asm.rs

+7-14
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ struct AsmArgs {
1919
operands: Vec<(ast::InlineAsmOperand, Span)>,
2020
named_args: FxHashMap<Symbol, usize>,
2121
reg_args: FxHashSet<usize>,
22-
clobber_abi: Option<(Symbol, Span)>,
22+
clobber_abis: Vec<(Symbol, Span)>,
2323
options: ast::InlineAsmOptions,
2424
options_spans: Vec<Span>,
2525
}
@@ -64,7 +64,7 @@ fn parse_args<'a>(
6464
operands: vec![],
6565
named_args: FxHashMap::default(),
6666
reg_args: FxHashSet::default(),
67-
clobber_abi: None,
67+
clobber_abis: Vec::new(),
6868
options: ast::InlineAsmOptions::empty(),
6969
options_spans: vec![],
7070
};
@@ -210,7 +210,7 @@ fn parse_args<'a>(
210210
.span_labels(args.options_spans.clone(), "previous options")
211211
.span_label(span, "argument")
212212
.emit();
213-
} else if let Some((_, abi_span)) = args.clobber_abi {
213+
} else if let Some(&(_, abi_span)) = args.clobber_abis.last() {
214214
ecx.struct_span_err(span, "arguments are not allowed after clobber_abi")
215215
.span_label(abi_span, "clobber_abi")
216216
.span_label(span, "argument")
@@ -322,7 +322,7 @@ fn parse_args<'a>(
322322
// Bail out now since this is likely to confuse MIR
323323
return Err(err);
324324
}
325-
if let Some((_, abi_span)) = args.clobber_abi {
325+
if let Some(&(_, abi_span)) = args.clobber_abis.last() {
326326
if is_global_asm {
327327
let err =
328328
ecx.struct_span_err(abi_span, "`clobber_abi` cannot be used with `global_asm!`");
@@ -453,14 +453,7 @@ fn parse_clobber_abi<'a>(
453453

454454
let new_span = span_start.to(p.prev_token.span);
455455

456-
if let Some((_, prev_span)) = args.clobber_abi {
457-
let mut err = p
458-
.sess
459-
.span_diagnostic
460-
.struct_span_err(new_span, "clobber_abi specified multiple times");
461-
err.span_label(prev_span, "clobber_abi previously specified here");
462-
return Err(err);
463-
} else if !args.options_spans.is_empty() {
456+
if !args.options_spans.is_empty() {
464457
let mut err = p
465458
.sess
466459
.span_diagnostic
@@ -469,7 +462,7 @@ fn parse_clobber_abi<'a>(
469462
return Err(err);
470463
}
471464

472-
args.clobber_abi = Some((clobber_abi, new_span));
465+
args.clobber_abis.push((clobber_abi, new_span));
473466

474467
Ok(())
475468
}
@@ -770,7 +763,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
770763
template,
771764
template_strs: template_strs.into_boxed_slice(),
772765
operands: args.operands,
773-
clobber_abi: args.clobber_abi,
766+
clobber_abis: args.clobber_abis,
774767
options: args.options,
775768
line_spans,
776769
})
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// run-pass
2+
// needs-asm-support
3+
// only-x86_64
4+
5+
// Checks that multiple clobber_abi options can be used
6+
7+
#![feature(asm)]
8+
9+
extern "sysv64" fn foo(x: i32) -> i32 {
10+
x + 16
11+
}
12+
13+
extern "win64" fn bar(x: i32) -> i32 {
14+
x / 2
15+
}
16+
17+
fn main() {
18+
let x = 8;
19+
let y: i32;
20+
// call `foo` with `x` as the input, and then `bar` with the output of `foo`
21+
// and output that to `y`
22+
unsafe {
23+
asm!(
24+
"call {}; mov rcx, rax; call {}",
25+
sym foo,
26+
sym bar,
27+
in("rdi") x,
28+
out("rax") y,
29+
clobber_abi("sysv64"),
30+
clobber_abi("win64")
31+
);
32+
}
33+
assert_eq!((x, y), (8, 12));
34+
}

src/test/ui/asm/x86_64/parse-error.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ fn main() {
5050
//~^ ERROR clobber_abi is not allowed after options
5151
asm!("{}", options(), clobber_abi("C"), const foo);
5252
//~^ ERROR clobber_abi is not allowed after options
53-
asm!("", clobber_abi("C"), clobber_abi("C"));
54-
//~^ ERROR clobber_abi specified multiple times
5553
asm!("{a}", a = const foo, a = const bar);
5654
//~^ ERROR duplicate argument named `a`
5755
//~^^ ERROR argument never used
@@ -121,7 +119,7 @@ global_asm!("", options(), clobber_abi("C"));
121119
global_asm!("{}", options(), clobber_abi("C"), const FOO);
122120
//~^ ERROR clobber_abi is not allowed after options
123121
global_asm!("", clobber_abi("C"), clobber_abi("C"));
124-
//~^ ERROR clobber_abi specified multiple times
122+
//~^ ERROR `clobber_abi` cannot be used with `global_asm!`
125123
global_asm!("{a}", a = const FOO, a = const BAR);
126124
//~^ ERROR duplicate argument named `a`
127125
//~^^ ERROR argument never used

0 commit comments

Comments
 (0)