Allow multiple asm! options

This commit is contained in:
Camelid 2020-06-10 17:47:13 -07:00
parent 033013cab3
commit c883fa45d3

View File

@ -16,7 +16,7 @@ struct AsmArgs {
named_args: FxHashMap<Symbol, usize>,
reg_args: FxHashSet<usize>,
options: ast::InlineAsmOptions,
options_span: Option<Span>,
options_spans: Option<Vec<Span>>,
}
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(())