From c883fa45d39a5ef7316e2b6637885ec222b609d5 Mon Sep 17 00:00:00 2001 From: Camelid Date: Wed, 10 Jun 2020 17:47:13 -0700 Subject: [PATCH] Allow multiple `asm!` options --- src/librustc_builtin_macros/asm.rs | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/librustc_builtin_macros/asm.rs b/src/librustc_builtin_macros/asm.rs index 29885679604..e98431a2695 100644 --- a/src/librustc_builtin_macros/asm.rs +++ b/src/librustc_builtin_macros/asm.rs @@ -16,7 +16,7 @@ struct AsmArgs { named_args: FxHashMap, reg_args: FxHashSet, options: ast::InlineAsmOptions, - options_span: Option, + options_spans: Option>, } fn parse_args<'a>( @@ -59,7 +59,7 @@ fn parse_args<'a>( named_args: FxHashMap::default(), reg_args: FxHashSet::default(), options: ast::InlineAsmOptions::empty(), - options_span: None, + options_spans: None, }; let mut allow_templates = true; @@ -174,9 +174,9 @@ fn parse_args<'a>( // Validate the order of named, positional & explicit register operands and options. We do // this at the end once we have the full span of the argument available. - if let Some(options_span) = args.options_span { + if let Some(ref options_spans) = args.options_spans { ecx.struct_span_err(span, "arguments are not allowed after options") - .span_label(options_span, "previous options") + .span_labels(options_spans.clone(), "previous options") .span_label(span, "argument") .emit(); } @@ -227,21 +227,21 @@ fn parse_args<'a>( if args.options.contains(ast::InlineAsmOptions::NOMEM) && args.options.contains(ast::InlineAsmOptions::READONLY) { - let span = args.options_span.unwrap(); - ecx.struct_span_err(span, "the `nomem` and `readonly` options are mutually exclusive") + let spans = args.options_spans.clone().unwrap(); + ecx.struct_span_err(spans, "the `nomem` and `readonly` options are mutually exclusive") .emit(); } if args.options.contains(ast::InlineAsmOptions::PURE) && args.options.contains(ast::InlineAsmOptions::NORETURN) { - let span = args.options_span.unwrap(); - ecx.struct_span_err(span, "the `pure` and `noreturn` options are mutually exclusive") + let spans = args.options_spans.clone().unwrap(); + ecx.struct_span_err(spans, "the `pure` and `noreturn` options are mutually exclusive") .emit(); } if args.options.contains(ast::InlineAsmOptions::PURE) && !args.options.intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY) { - let span = args.options_span.unwrap(); + let span = args.options_spans.clone().unwrap(); ecx.struct_span_err( span, "the `pure` option must be combined with either `nomem` or `readonly`", @@ -267,7 +267,7 @@ fn parse_args<'a>( } if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output { ecx.struct_span_err( - args.options_span.unwrap(), + args.options_spans.clone().unwrap(), "asm with `pure` option must have at least one output", ) .emit(); @@ -314,13 +314,10 @@ fn parse_options<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> Result<(), Diagn } let new_span = span_start.to(p.prev_token.span); - if let Some(options_span) = args.options_span { - p.struct_span_err(new_span, "asm options cannot be specified multiple times") - .span_label(options_span, "previously here") - .span_label(new_span, "duplicate options") - .emit(); + if let Some(options_spans) = &mut args.options_spans { + options_spans.push(new_span); } else { - args.options_span = Some(new_span); + args.options_spans = Some(vec![new_span]); } Ok(())