[llvm] [MC][X86/M68k] Emit syntax directive for AT&T (PR #167234)

Raul Tambre via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 10 12:59:35 PST 2025


https://github.com/tambry updated https://github.com/llvm/llvm-project/pull/167234

>From a9732a21afe912a1a6e74e8b9fe93e00be5f84de Mon Sep 17 00:00:00 2001
From: Raul Tambre <raul at tambre.ee>
Date: Sun, 9 Nov 2025 16:41:20 +0200
Subject: [PATCH] [MC][X86/m68k] Emit syntax directive for AT&T

This eases interoperability by making it explicit in emitted assembly code which syntax is used.
Refactored to remove X86-specific directives and logic from the generic MC(Asm)Streamer.

Motivated by building LLVM with `-mllvm -x86-asm-syntax=intel` (i.e. a global preference for Intel
syntax). A Bolt test (`runtime/X86/fdata-escape-chars.ll`) was using `llc` to compile to assembly
and then assembling with `clang`. The specific option causes Clang to assume Intel syntax but only
for assembly and not inline assembly.
---
 llvm/docs/ReleaseNotes.md                     |  2 ++
 llvm/include/llvm/MC/MCStreamer.h             |  2 +-
 llvm/lib/MC/MCAsmStreamer.cpp                 | 14 ++++++--------
 llvm/lib/MC/MCStreamer.cpp                    |  2 +-
 llvm/lib/Target/M68k/M68kAsmPrinter.cpp       |  6 +++++-
 llvm/lib/Target/X86/X86AsmPrinter.cpp         |  8 +++++++-
 llvm/test/CodeGen/X86/asm-syntax-directive.ll |  7 +++++++
 llvm/test/CodeGen/X86/coal-sections.ll        |  2 +-
 8 files changed, 30 insertions(+), 13 deletions(-)
 create mode 100644 llvm/test/CodeGen/X86/asm-syntax-directive.ll

diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index fd78c97c86d24..ee8072c68855d 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -152,6 +152,8 @@ Changes to the X86 Backend
 
 * `-mcpu=wildcatlake` is now supported.
 * `-mcpu=novalake` is now supported.
+* `.att_syntax` is now emitted at the beginning of the file when emitting AT&T
+  syntax assembly.
 
 Changes to the OCaml bindings
 -----------------------------
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index 79c715e3820a6..eaee7957e090d 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -1055,7 +1055,7 @@ class LLVM_ABI MCStreamer {
   /// Get the .xdata section used for the given section.
   MCSection *getAssociatedXDataSection(const MCSection *TextSec);
 
-  virtual void emitSyntaxDirective();
+  virtual void emitSyntaxDirective(StringRef Syntax, StringRef Options);
 
   /// Record a relocation described by the .reloc directive.
   virtual void emitRelocDirective(const MCExpr &Offset, StringRef Name,
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 885fa55b65d50..dc5673234ed2e 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -123,7 +123,7 @@ class MCAsmStreamer final : public MCStreamer {
     EmitCommentsAndEOL();
   }
 
-  void emitSyntaxDirective() override;
+  void emitSyntaxDirective(StringRef Syntax, StringRef Options) override;
 
   void EmitCommentsAndEOL();
 
@@ -796,14 +796,12 @@ void MCAsmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
   EmitEOL();
 }
 
-void MCAsmStreamer::emitSyntaxDirective() {
-  if (MAI->getAssemblerDialect() == 1) {
-    OS << "\t.intel_syntax noprefix";
-    EmitEOL();
+void MCAsmStreamer::emitSyntaxDirective(StringRef Syntax, StringRef Options) {
+  OS << "\t." << Syntax << "_syntax";
+  if (!Options.empty()) {
+    OS << " " << Options;
   }
-  // FIXME: Currently emit unprefix'ed registers.
-  // The intel_syntax directive has one optional argument
-  // with may have a value of prefix or noprefix.
+  EmitEOL();
 }
 
 void MCAsmStreamer::beginCOFFSymbolDef(const MCSymbol *Symbol) {
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index bc7398120096e..108ddf9910f82 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -876,7 +876,7 @@ MCSection *MCStreamer::getAssociatedXDataSection(const MCSection *TextSec) {
                           TextSec);
 }
 
-void MCStreamer::emitSyntaxDirective() {}
+void MCStreamer::emitSyntaxDirective(StringRef Syntax, StringRef Options) {}
 
 static unsigned encodeSEHRegNum(MCContext &Ctx, MCRegister Reg) {
   return Ctx.getRegisterInfo()->getSEHRegNum(Reg);
diff --git a/llvm/lib/Target/M68k/M68kAsmPrinter.cpp b/llvm/lib/Target/M68k/M68kAsmPrinter.cpp
index 0437400b81d84..15b4760a2f06e 100644
--- a/llvm/lib/Target/M68k/M68kAsmPrinter.cpp
+++ b/llvm/lib/Target/M68k/M68kAsmPrinter.cpp
@@ -190,7 +190,11 @@ void M68kAsmPrinter::emitFunctionBodyStart() {}
 void M68kAsmPrinter::emitFunctionBodyEnd() {}
 
 void M68kAsmPrinter::emitStartOfAsmFile(Module &M) {
-  OutStreamer->emitSyntaxDirective();
+  // m68k assemblers generally don't support .att_syntax so we only emit the
+  // directive for Intel syntax.
+  if (MAI->getAssemblerDialect() == InlineAsm::AD_Intel) {
+    OutStreamer->emitSyntaxDirective("intel", "noprefix");
+  }
 }
 
 void M68kAsmPrinter::emitEndOfAsmFile(Module &M) {}
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp
index 84b921222a116..7dbc548d3c05b 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.cpp
+++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp
@@ -932,7 +932,13 @@ void X86AsmPrinter::emitStartOfAsmFile(Module &M) {
     if (M.getModuleFlag("import-call-optimization"))
       EnableImportCallOptimization = true;
   }
-  OutStreamer->emitSyntaxDirective();
+
+  // FIXME: Currently emit unprefix'ed registers.
+  // The intel_syntax directive has one optional argument
+  // with may have a value of prefix or noprefix.
+  const bool IntelSyntax = MAI->getAssemblerDialect() == InlineAsm::AD_Intel;
+  OutStreamer->emitSyntaxDirective(IntelSyntax ? "intel" : "att",
+                                   IntelSyntax ? "noprefix" : "");
 
   // If this is not inline asm and we're in 16-bit
   // mode prefix assembly with .code16.
diff --git a/llvm/test/CodeGen/X86/asm-syntax-directive.ll b/llvm/test/CodeGen/X86/asm-syntax-directive.ll
new file mode 100644
index 0000000000000..4cdf4408c2084
--- /dev/null
+++ b/llvm/test/CodeGen/X86/asm-syntax-directive.ll
@@ -0,0 +1,7 @@
+;; Make sure that we always emit an assembly syntax directive for X86.
+; RUN: llc < %s -mtriple=x86_64 | FileCheck %s --check-prefix=ATT
+; RUN: llc < %s -mtriple=x86_64 -x86-asm-syntax=att | FileCheck %s --check-prefix=ATT
+; RUN: llc < %s -mtriple=x86_64 -x86-asm-syntax=intel | FileCheck %s --check-prefix=INTEL
+
+; INTEL: .intel_syntax noprefix
+; ATT: .att_syntax
diff --git a/llvm/test/CodeGen/X86/coal-sections.ll b/llvm/test/CodeGen/X86/coal-sections.ll
index 3fed158befdd8..faab0397a4053 100644
--- a/llvm/test/CodeGen/X86/coal-sections.ll
+++ b/llvm/test/CodeGen/X86/coal-sections.ll
@@ -3,7 +3,7 @@
 ; Check that *coal* sections are not emitted.
 
 ; CHECK: .section  __TEXT,__text,regular,pure_instructions{{$}}
-; CHECK-NEXT: .globl  _foo
+; CHECK: .globl  _foo
 
 ; CHECK: .section  __TEXT,__const{{$}}
 ; CHECK-NEXT: .globl  _a



More information about the llvm-commits mailing list