@@ -7,7 +7,10 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
77use rustc_expand:: base:: { self , * } ;
88use rustc_parse:: parser:: Parser ;
99use rustc_parse_format as parse;
10- use rustc_span:: symbol:: { kw, sym, Symbol } ;
10+ use rustc_span:: {
11+ symbol:: { kw, sym, Symbol } ,
12+ BytePos ,
13+ } ;
1114use rustc_span:: { InnerSpan , Span } ;
1215
1316struct AsmArgs {
@@ -399,6 +402,8 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
399402 let mut line_spans = Vec :: with_capacity ( args. templates . len ( ) ) ;
400403 let mut curarg = 0 ;
401404
405+ let default_dialect = ecx. sess . inline_asm_dialect ( ) ;
406+
402407 for template_expr in args. templates . into_iter ( ) {
403408 if !template. is_empty ( ) {
404409 template. push ( ast:: InlineAsmTemplatePiece :: String ( "\n " . to_string ( ) ) ) ;
@@ -424,6 +429,60 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
424429
425430 let template_str = & template_str. as_str ( ) ;
426431 let template_snippet = ecx. source_map ( ) . span_to_snippet ( template_sp) . ok ( ) ;
432+
433+ if let Some ( snippet) = & template_snippet {
434+ let snippet = snippet. trim_matches ( '"' ) ;
435+ match default_dialect {
436+ ast:: LlvmAsmDialect :: Intel => {
437+ if let Some ( span) = check_syntax_directive ( snippet, ".intel_syntax" ) {
438+ let span = template_span. from_inner ( span) ;
439+ let mut err = ecx. struct_span_err ( span, "intel syntax is the default syntax on this target, and trying to use this directive may cause issues" ) ;
440+ err. span_suggestion (
441+ span,
442+ "remove this assembler directive" ,
443+ "" . to_string ( ) ,
444+ Applicability :: MachineApplicable ,
445+ ) ;
446+ err. emit ( ) ;
447+ }
448+
449+ if let Some ( span) = check_syntax_directive ( snippet, ".att_syntax" ) {
450+ let span = template_span. from_inner ( span) ;
451+ let mut err = ecx. struct_span_err ( span, "using the .att_syntax directive may cause issues, use the att_syntax option instead" ) ;
452+ let asm_end = sp. hi ( ) - BytePos ( 2 ) ;
453+ let suggestions = vec ! [
454+ ( span, "" . to_string( ) ) ,
455+ (
456+ Span :: new( asm_end, asm_end, sp. ctxt( ) ) ,
457+ ", options(att_syntax)" . to_string( ) ,
458+ ) ,
459+ ] ;
460+ err. multipart_suggestion (
461+ "remove the assembler directive and replace it with options(att_syntax)" ,
462+ suggestions,
463+ Applicability :: MachineApplicable ,
464+ ) ;
465+ err. emit ( ) ;
466+ }
467+ }
468+ ast:: LlvmAsmDialect :: Att => {
469+ if let Some ( span) = check_syntax_directive ( snippet, ".att_syntax" ) {
470+ let span = template_span. from_inner ( span) ;
471+ let mut err = ecx. struct_span_err ( span, "att syntax is the default syntax on this target, and trying to use this directive may cause issues" ) ;
472+ err. span_suggestion (
473+ span,
474+ "remove this assembler directive" ,
475+ "" . to_string ( ) ,
476+ Applicability :: MachineApplicable ,
477+ ) ;
478+ err. emit ( ) ;
479+ }
480+
481+ // Use of .intel_syntax is ignored
482+ }
483+ }
484+ }
485+
427486 let mut parser = parse:: Parser :: new (
428487 template_str,
429488 str_style,
@@ -631,3 +690,15 @@ pub fn expand_asm<'cx>(
631690 }
632691 }
633692}
693+
694+ fn check_syntax_directive < S : AsRef < str > > ( piece : S , syntax : & str ) -> Option < InnerSpan > {
695+ let piece = piece. as_ref ( ) ;
696+ if let Some ( idx) = piece. find ( syntax) {
697+ let end =
698+ idx + & piece[ idx..] . find ( |c| matches ! ( c, '\n' | ';' ) ) . unwrap_or ( piece[ idx..] . len ( ) ) ;
699+ // Offset by one because these represent the span with the " removed
700+ Some ( InnerSpan :: new ( idx + 1 , end + 1 ) )
701+ } else {
702+ None
703+ }
704+ }
0 commit comments