use rustc_span::{InnerSpan, Span};
struct AsmArgs {
- template: P<ast::Expr>,
+ templates: Vec<P<ast::Expr>>,
operands: Vec<(ast::InlineAsmOperand, Span)>,
named_args: FxHashMap<Symbol, usize>,
reg_args: FxHashSet<usize>,
return Err(err);
}
- let template = p.parse_expr()?;
+ let first_template = p.parse_expr()?;
let mut args = AsmArgs {
- template,
+ templates: vec![first_template],
operands: vec![],
named_args: FxHashMap::default(),
reg_args: FxHashSet::default(),
options_span: None,
};
- let mut first = true;
+ let mut allow_templates = true;
while p.token != token::Eof {
if !p.eat(&token::Comma) {
- if first {
- // After `asm!(""` we always expect *only* a comma...
+ if allow_templates {
+ // After a template string, we always expect *only* a comma...
let mut err = ecx.struct_span_err(p.token.span, "expected token: `,`");
err.span_label(p.token.span, "expected `,`");
p.maybe_annotate_with_ascription(&mut err, false);
return Err(p.expect(&token::Comma).err().unwrap());
}
}
- first = false;
if p.token == token::Eof {
break;
} // accept trailing commas
// Parse options
if p.eat(&token::Ident(sym::options, false)) {
parse_options(&mut p, &mut args)?;
+ allow_templates = false;
continue;
}
let (ident, _) = p.token.ident().unwrap();
p.bump();
p.expect(&token::Eq)?;
+ allow_templates = false;
Some(ident.name)
} else {
None
}
}
ast::InlineAsmOperand::Sym { expr }
+ } else if allow_templates {
+ let template = p.parse_expr()?;
+ // If it can't possibly expand to a string, provide diagnostics here to include other
+ // things it could have been.
+ match template.kind {
+ ast::ExprKind::Lit(ast::Lit { kind: ast::LitKind::Str(..), .. }) => {}
+ ast::ExprKind::MacCall(..) => {}
+ _ => {
+ let errstr = "expected operand, options, or additional template string";
+ let mut err = ecx.struct_span_err(template.span, errstr);
+ err.span_label(template.span, errstr);
+ return Err(err);
+ }
+ }
+ args.templates.push(template);
+ continue;
} else {
return Err(p.expect_one_of(&[], &[]).unwrap_err());
};
+ allow_templates = false;
let span = span_start.to(p.prev_token.span);
let slot = args.operands.len();
args.operands.push((op, span));
}
fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast::Expr> {
- let msg = "asm template must be a string literal";
- let template_sp = args.template.span;
- let (template_str, template_style, template_span) =
- match expr_to_spanned_string(ecx, args.template, msg) {
- Ok(template) => template,
- Err(err) => {
- if let Some(mut err) = err {
- err.emit();
- }
- return DummyResult::raw_expr(sp, true);
- }
- };
-
- let str_style = match template_style {
- ast::StrStyle::Cooked => None,
- ast::StrStyle::Raw(raw) => Some(raw as usize),
- };
-
- let template_str = &template_str.as_str();
- let template_snippet = ecx.source_map().span_to_snippet(template_sp).ok();
- let mut parser = parse::Parser::new(
- template_str,
- str_style,
- template_snippet,
- false,
- parse::ParseMode::InlineAsm,
- );
-
- let mut unverified_pieces = Vec::new();
- while let Some(piece) = parser.next() {
- if !parser.errors.is_empty() {
- break;
- } else {
- unverified_pieces.push(piece);
- }
- }
-
- if !parser.errors.is_empty() {
- let err = parser.errors.remove(0);
- let err_sp = template_span.from_inner(err.span);
- let mut e = ecx
- .struct_span_err(err_sp, &format!("invalid asm template string: {}", err.description));
- e.span_label(err_sp, err.label + " in asm template string");
- if let Some(note) = err.note {
- e.note(¬e);
- }
- if let Some((label, span)) = err.secondary_label {
- let err_sp = template_span.from_inner(span);
- e.span_label(err_sp, label);
- }
- e.emit();
- return DummyResult::raw_expr(sp, true);
- }
-
+ let mut template = vec![];
// Register operands are implicitly used since they are not allowed to be
// referenced in the template string.
let mut used = vec![false; args.operands.len()];
for pos in &args.reg_args {
used[*pos] = true;
}
-
let named_pos: FxHashMap<usize, Symbol> =
args.named_args.iter().map(|(&sym, &idx)| (idx, sym)).collect();
- let mut arg_spans = parser.arg_places.iter().map(|span| template_span.from_inner(*span));
- let mut template = vec![];
- for piece in unverified_pieces {
- match piece {
- parse::Piece::String(s) => {
- template.push(ast::InlineAsmTemplatePiece::String(s.to_string()))
+ let mut line_spans = Vec::with_capacity(args.templates.len());
+ let mut curarg = 0;
+
+ for template_expr in args.templates.into_iter() {
+ if !template.is_empty() {
+ template.push(ast::InlineAsmTemplatePiece::String("\n".to_string()));
+ }
+
+ let msg = "asm template must be a string literal";
+ let template_sp = template_expr.span;
+ let (template_str, template_style, template_span) =
+ match expr_to_spanned_string(ecx, template_expr, msg) {
+ Ok(template_part) => template_part,
+ Err(err) => {
+ if let Some(mut err) = err {
+ err.emit();
+ }
+ return DummyResult::raw_expr(sp, true);
+ }
+ };
+
+ let str_style = match template_style {
+ ast::StrStyle::Cooked => None,
+ ast::StrStyle::Raw(raw) => Some(raw as usize),
+ };
+
+ let template_str = &template_str.as_str();
+ let template_snippet = ecx.source_map().span_to_snippet(template_sp).ok();
+ let mut parser = parse::Parser::new(
+ template_str,
+ str_style,
+ template_snippet,
+ false,
+ parse::ParseMode::InlineAsm,
+ );
+ parser.curarg = curarg;
+
+ let mut unverified_pieces = Vec::new();
+ while let Some(piece) = parser.next() {
+ if !parser.errors.is_empty() {
+ break;
+ } else {
+ unverified_pieces.push(piece);
+ }
+ }
+
+ if !parser.errors.is_empty() {
+ let err = parser.errors.remove(0);
+ let err_sp = template_span.from_inner(err.span);
+ let msg = &format!("invalid asm template string: {}", err.description);
+ let mut e = ecx.struct_span_err(err_sp, msg);
+ e.span_label(err_sp, err.label + " in asm template string");
+ if let Some(note) = err.note {
+ e.note(¬e);
+ }
+ if let Some((label, span)) = err.secondary_label {
+ let err_sp = template_span.from_inner(span);
+ e.span_label(err_sp, label);
}
- parse::Piece::NextArgument(arg) => {
- let span = arg_spans.next().unwrap_or(template_sp);
-
- let operand_idx = match arg.position {
- parse::ArgumentIs(idx) | parse::ArgumentImplicitlyIs(idx) => {
- if idx >= args.operands.len()
- || named_pos.contains_key(&idx)
- || args.reg_args.contains(&idx)
- {
- let msg = format!("invalid reference to argument at index {}", idx);
- let mut err = ecx.struct_span_err(span, &msg);
- err.span_label(span, "from here");
-
- let positional_args =
- args.operands.len() - args.named_args.len() - args.reg_args.len();
- let positional = if positional_args != args.operands.len() {
- "positional "
+ e.emit();
+ return DummyResult::raw_expr(sp, true);
+ }
+
+ curarg = parser.curarg;
+
+ let mut arg_spans = parser.arg_places.iter().map(|span| template_span.from_inner(*span));
+ for piece in unverified_pieces {
+ match piece {
+ parse::Piece::String(s) => {
+ template.push(ast::InlineAsmTemplatePiece::String(s.to_string()))
+ }
+ parse::Piece::NextArgument(arg) => {
+ let span = arg_spans.next().unwrap_or(template_sp);
+
+ let operand_idx = match arg.position {
+ parse::ArgumentIs(idx) | parse::ArgumentImplicitlyIs(idx) => {
+ if idx >= args.operands.len()
+ || named_pos.contains_key(&idx)
+ || args.reg_args.contains(&idx)
+ {
+ let msg = format!("invalid reference to argument at index {}", idx);
+ let mut err = ecx.struct_span_err(span, &msg);
+ err.span_label(span, "from here");
+
+ let positional_args = args.operands.len()
+ - args.named_args.len()
+ - args.reg_args.len();
+ let positional = if positional_args != args.operands.len() {
+ "positional "
+ } else {
+ ""
+ };
+ let msg = match positional_args {
+ 0 => format!("no {}arguments were given", positional),
+ 1 => format!("there is 1 {}argument", positional),
+ x => format!("there are {} {}arguments", x, positional),
+ };
+ err.note(&msg);
+
+ if named_pos.contains_key(&idx) {
+ err.span_label(args.operands[idx].1, "named argument");
+ err.span_note(
+ args.operands[idx].1,
+ "named arguments cannot be referenced by position",
+ );
+ } else if args.reg_args.contains(&idx) {
+ err.span_label(
+ args.operands[idx].1,
+ "explicit register argument",
+ );
+ err.span_note(
+ args.operands[idx].1,
+ "explicit register arguments cannot be used in the asm template",
+ );
+ }
+ err.emit();
+ None
} else {
- ""
- };
- let msg = match positional_args {
- 0 => format!("no {}arguments were given", positional),
- 1 => format!("there is 1 {}argument", positional),
- x => format!("there are {} {}arguments", x, positional),
- };
- err.note(&msg);
-
- if named_pos.contains_key(&idx) {
- err.span_label(args.operands[idx].1, "named argument");
- err.span_note(
- args.operands[idx].1,
- "named arguments cannot be referenced by position",
- );
- } else if args.reg_args.contains(&idx) {
- err.span_label(args.operands[idx].1, "explicit register argument");
- err.span_note(
- args.operands[idx].1,
- "explicit register arguments cannot be used in the asm template",
- );
+ Some(idx)
}
- err.emit();
- None
- } else {
- Some(idx)
- }
- }
- parse::ArgumentNamed(name) => match args.named_args.get(&name) {
- Some(&idx) => Some(idx),
- None => {
- let msg = format!("there is no argument named `{}`", name);
- ecx.struct_span_err(span, &msg[..]).emit();
- None
}
- },
- };
-
- let mut chars = arg.format.ty.chars();
- let mut modifier = chars.next();
- if chars.next().is_some() {
- let span = arg
- .format
- .ty_span
- .map(|sp| template_sp.from_inner(sp))
- .unwrap_or(template_sp);
- ecx.struct_span_err(span, "asm template modifier must be a single character")
+ parse::ArgumentNamed(name) => match args.named_args.get(&name) {
+ Some(&idx) => Some(idx),
+ None => {
+ let msg = format!("there is no argument named `{}`", name);
+ ecx.struct_span_err(span, &msg[..]).emit();
+ None
+ }
+ },
+ };
+
+ let mut chars = arg.format.ty.chars();
+ let mut modifier = chars.next();
+ if chars.next().is_some() {
+ let span = arg
+ .format
+ .ty_span
+ .map(|sp| template_sp.from_inner(sp))
+ .unwrap_or(template_sp);
+ ecx.struct_span_err(
+ span,
+ "asm template modifier must be a single character",
+ )
.emit();
- modifier = None;
- }
+ modifier = None;
+ }
- if let Some(operand_idx) = operand_idx {
- used[operand_idx] = true;
- template.push(ast::InlineAsmTemplatePiece::Placeholder {
- operand_idx,
- modifier,
- span,
- });
+ if let Some(operand_idx) = operand_idx {
+ used[operand_idx] = true;
+ template.push(ast::InlineAsmTemplatePiece::Placeholder {
+ operand_idx,
+ modifier,
+ span,
+ });
+ }
}
}
}
+
+ if parser.line_spans.is_empty() {
+ let template_num_lines = 1 + template_str.matches('\n').count();
+ line_spans.extend(std::iter::repeat(template_sp).take(template_num_lines));
+ } else {
+ line_spans.extend(parser.line_spans.iter().map(|span| template_span.from_inner(*span)));
+ };
}
let mut unused_operands = vec![];
}
}
- let line_spans = if parser.line_spans.is_empty() {
- vec![template_sp]
- } else {
- parser.line_spans.iter().map(|span| template_span.from_inner(*span)).collect()
- };
-
let inline_asm =
ast::InlineAsm { template, operands: args.operands, options: args.options, line_spans };
P(ast::Expr {
/// Error messages accumulated during parsing
pub errors: Vec<ParseError>,
/// Current position of implicit positional argument pointer
- curarg: usize,
+ pub curarg: usize,
/// `Some(raw count)` when the string is "raw", used to position spans correctly
style: Option<usize>,
/// Start and end byte offset of every successfully parsed argument
_ => Some(String(self.string(pos))),
}
} else {
- if self.is_literal && self.cur_line_start != self.input.len() {
+ if self.is_literal {
let start = self.to_span_index(self.cur_line_start);
let end = self.to_span_index(self.input.len());
- self.line_spans.push(start.to(end));
- self.cur_line_start = self.input.len();
+ let span = start.to(end);
+ if self.line_spans.last() != Some(&span) {
+ self.line_spans.push(span);
+ }
}
None
}
asm!("{0}", inout(reg) b);
asm!("{0} {1}", out(reg) _, inlateout(reg) b => _);
asm!("", out("al") _, lateout("rbx") _);
+ asm!("inst1\ninst2");
+ asm!("inst1 {0}, 42\ninst2 {1}, 24", in(reg) a, out(reg) b);
+ asm!("inst2 {1}, 24\ninst1 {0}, 42", in(reg) a, out(reg) b);
+ asm!("inst1 {0}, 42\ninst2 {1}, 24", in(reg) a, out(reg) b);
+ asm!("inst1\ninst2");
+ asm!("inst1\ninst2");
+ asm!("inst1\n\tinst2");
+ asm!("inst1\ninst2\ninst3\ninst4");
}
}
asm!("{name}", name = inout(reg) b);
asm!("{} {}", out(reg) _, inlateout(reg) b => _);
asm!("", out("al") _, lateout("rbx") _);
+ asm!("inst1", "inst2");
+ asm!("inst1 {}, 42", "inst2 {}, 24", in(reg) a, out(reg) b);
+ asm!("inst2 {1}, 24", "inst1 {0}, 42", in(reg) a, out(reg) b);
+ asm!("inst1 {}, 42", "inst2 {name}, 24", in(reg) a, name = out(reg) b);
+ asm!("inst1
+inst2");
+ asm!("inst1\ninst2");
+ asm!("inst1\n\tinst2");
+ asm!("inst1\ninst2", "inst3\ninst4");
}
}
asm!("{}" foo);
//~^ ERROR expected token: `,`
asm!("{}", foo);
- //~^ ERROR expected one of
+ //~^ ERROR expected operand, options, or additional template string
asm!("{}", in foo);
//~^ ERROR expected `(`, found `foo`
asm!("{}", in(reg foo));
//~^ ERROR named arguments cannot follow explicit register arguments
asm!("{1}", in("eax") foo, const bar);
//~^ ERROR positional arguments cannot follow named arguments or explicit register arguments
+ asm!("", options(), "");
+ //~^ ERROR expected one of
+ asm!("{}", in(reg) foo, "{}", out(reg) foo);
+ //~^ ERROR expected one of
+ asm!(format!("{{{}}}", 0), in(reg) foo);
+ //~^ ERROR asm template must be a string literal
+ asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
+ //~^ ERROR asm template must be a string literal
}
}
LL | asm!("{}" foo);
| ^^^ expected `,`
-error: expected one of `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `foo`
+error: expected operand, options, or additional template string
--> $DIR/parse-error.rs:15:20
|
LL | asm!("{}", foo);
- | ^^^ expected one of 8 possible tokens
+ | ^^^ expected operand, options, or additional template string
error: expected `(`, found `foo`
--> $DIR/parse-error.rs:17:23
| |
| explicit register argument
-error: aborting due to 24 previous errors
+error: expected one of `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""`
+ --> $DIR/parse-error.rs:55:29
+ |
+LL | asm!("", options(), "");
+ | ^^ expected one of 8 possible tokens
+
+error: expected one of `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
+ --> $DIR/parse-error.rs:57:33
+ |
+LL | asm!("{}", in(reg) foo, "{}", out(reg) foo);
+ | ^^^^ expected one of 8 possible tokens
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:59:14
+ |
+LL | asm!(format!("{{{}}}", 0), in(reg) foo);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:61:21
+ |
+LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 28 previous errors
asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
//~^ WARN: scale factor without index register is ignored
+
+ asm!(
+ "invalid_instruction",
+ );
+ //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(
+ "mov eax, eax",
+ "invalid_instruction",
+ "mov eax, eax",
+ );
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(
+ "mov eax, eax\n",
+ "invalid_instruction",
+ "mov eax, eax",
+ );
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(
+ "mov eax, eax",
+ concat!("invalid", "_", "instruction"),
+ "mov eax, eax",
+ );
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(
+ concat!("mov eax", ", ", "eax"),
+ concat!("invalid", "_", "instruction"),
+ concat!("mov eax", ", ", "eax"),
+ );
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ // Make sure template strings get separated
+ asm!(
+ "invalid_instruction1",
+ "invalid_instruction2",
+ );
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
+
+ asm!(
+ concat!(
+ "invalid", "_", "instruction1", "\n",
+ "invalid", "_", "instruction2",
+ ),
+ );
+ //~^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
+ //~^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
+
+ asm!(
+ concat!(
+ "invalid", "_", "instruction1", "\n",
+ "invalid", "_", "instruction2",
+ ),
+ concat!(
+ "invalid", "_", "instruction3", "\n",
+ "invalid", "_", "instruction4",
+ ),
+ );
+ //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
+ //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
+ //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3'
+ //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4'
+
+ asm!(
+ concat!(
+ "invalid", "_", "instruction1", "\n",
+ "invalid", "_", "instruction2", "\n",
+ ),
+ concat!(
+ "invalid", "_", "instruction3", "\n",
+ "invalid", "_", "instruction4", "\n",
+ ),
+ );
+ //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
+ //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
+ //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3'
+ //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4'
}
}
LL | movaps %xmm3, (%esi, 2)
| ^
-error: aborting due to 6 previous errors; 1 warning emitted
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:45:14
+ |
+LL | "invalid_instruction",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:51:14
+ |
+LL | "invalid_instruction",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:58:14
+ |
+LL | "invalid_instruction",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:4:1
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:65:13
+ |
+LL | concat!("invalid", "_", "instruction"),
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:72:13
+ |
+LL | concat!("invalid", "_", "instruction"),
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+ --> $DIR/srcloc.rs:79:14
+ |
+LL | "invalid_instruction1",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction1
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+ --> $DIR/srcloc.rs:80:14
+ |
+LL | "invalid_instruction2",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction2
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+ --> $DIR/srcloc.rs:86:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction1
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+ --> $DIR/srcloc.rs:86:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction2
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+ --> $DIR/srcloc.rs:95:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction1
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+ --> $DIR/srcloc.rs:95:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction2
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction3'
+ --> $DIR/srcloc.rs:99:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:4:1
+ |
+LL | invalid_instruction3
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction4'
+ --> $DIR/srcloc.rs:99:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:5:1
+ |
+LL | invalid_instruction4
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+ --> $DIR/srcloc.rs:110:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction1
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+ --> $DIR/srcloc.rs:110:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction2
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction3'
+ --> $DIR/srcloc.rs:114:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:5:1
+ |
+LL | invalid_instruction3
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction4'
+ --> $DIR/srcloc.rs:114:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:6:1
+ |
+LL | invalid_instruction4
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 23 previous errors; 1 warning emitted