[llvm] draft: inline asm mode (PR #146215)

Brian Cain via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 29 19:37:54 PDT 2025


https://github.com/androm3da updated https://github.com/llvm/llvm-project/pull/146215

>From 6b622b3ac38b7cc0653ae03980e590e48d190b11 Mon Sep 17 00:00:00 2001
From: Brian Cain <brian.cain at oss.qualcomm.com>
Date: Fri, 27 Jun 2025 23:28:45 -0500
Subject: [PATCH 1/4] draft: inline asm mode

---
 llvm/docs/InlineAsmSafetyDirective.md        | 110 +++++++++++++++++++
 llvm/include/llvm/MC/MCStreamer.h            |   8 ++
 llvm/lib/MC/MCParser/AsmParser.cpp           |  28 +++++
 llvm/lib/MC/MCStreamer.cpp                   |  12 ++
 llvm/test/MC/X86/inline-asm-mode-basic.s     |  25 +++++
 llvm/test/MC/X86/inline-asm-mode-directive.s |  57 ++++++++++
 6 files changed, 240 insertions(+)
 create mode 100644 llvm/docs/InlineAsmSafetyDirective.md
 create mode 100644 llvm/test/MC/X86/inline-asm-mode-basic.s
 create mode 100644 llvm/test/MC/X86/inline-asm-mode-directive.s

diff --git a/llvm/docs/InlineAsmSafetyDirective.md b/llvm/docs/InlineAsmSafetyDirective.md
new file mode 100644
index 0000000000000..0285020cbf6f1
--- /dev/null
+++ b/llvm/docs/InlineAsmSafetyDirective.md
@@ -0,0 +1,110 @@
+# Inline Assembly Safety Directive
+
+## Overview
+
+The `.inline_asm_mode` directive provides enhanced safety for inline assembly blocks by warning about potentially unsafe label usage. This directive helps prevent common errors where programmers create non-local labels in inline assembly that could be inadvertently jumped to from external code.
+
+## Syntax
+
+```assembly
+.inline_asm_mode strict   # Enable strict mode - warn on non-local labels
+.inline_asm_mode relaxed  # Disable strict mode (default)
+```
+
+## Description
+
+When `.inline_asm_mode strict` is active, the assembler will emit warnings for labels that are considered potentially unsafe for inline assembly:
+
+- **Safe labels** (no warnings):
+  - Local labels starting with `.L` (e.g., `.L_loop`, `.L_end`)
+  - Numeric labels (e.g., `1:`, `42:`)
+  - Labels starting with special prefixes (`$`, `__`)
+  - Labels starting with `.` (local scope)
+
+- **Unsafe labels** (warnings emitted):
+  - Global labels without special prefixes (e.g., `my_function:`, `loop:`)
+  - Labels that could be accessed from outside the inline assembly block
+
+## Use Cases
+
+### Frontend Integration
+
+Compiler frontends can use this directive when generating inline assembly:
+
+```c++
+// Emitted by the compiler: .inline_asm_mode strict
+// C++ inline assembly example
+asm(
+    ".L_loop:\n"              // Safe - no warning
+    "  add %0, %1\n"
+    "  jne .L_loop\n"         // Safe - local jump
+    "exit:\n"                 // Warning
+    : "=r"(result) : "r"(input));
+```
+// Emitted by the compiler: .inline_asm_mode relaxed
+
+## Rationale
+
+Inline assembly blocks are often embedded within larger functions or modules. Non-local labels in these blocks can create several problems:
+
+1. **Naming conflicts**: Global labels may conflict with other symbols in the compilation unit
+2. **Unintended control flow**: External code might accidentally jump to labels intended for internal use
+3. **Maintenance issues**: Global labels make inline assembly less encapsulated
+
+The strict mode helps identify these potential issues during compilation, allowing developers to use safer local labels instead.
+
+## Error Handling
+
+Invalid directive usage will produce parse errors:
+
+```assembly
+.inline_asm_mode invalid_mode
+# Error: expected 'strict' or 'relaxed'
+
+.inline_asm_mode
+# Error: expected 'strict' or 'relaxed' after '.inline_asm_mode'
+```
+
+## Implementation Details
+
+- The directive affects only subsequent label definitions until changed
+- Default mode is `relaxed` (no additional warnings)
+- The directive state is maintained in the MC streamer
+- Warnings are emitted through the standard LLVM diagnostic system
+
+## Examples
+
+### Complete Example
+
+```assembly
+.text
+.globl example_function
+example_function:
+    # Regular function labels (outside inline asm) - no warnings
+
+    # Simulate inline assembly block with safety
+    .inline_asm_mode strict
+
+    # These are safe
+    .L_inline_start:
+        mov $1, %eax
+        test %eax, %eax
+        jz .L_inline_end
+
+    1:  # Numeric label
+        inc %eax
+        cmp $10, %eax
+        jl 1b
+
+    .L_inline_end:
+        # End of safe inline block
+
+    # This would generate a warning
+    # global_inline_label:  # Warning would be emitted
+
+    .inline_asm_mode relaxed
+
+    # Back to normal mode
+    ret
+```
+
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index 8f2e137ea0c84..834425a17c723 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -260,6 +260,11 @@ class LLVM_ABI MCStreamer {
   /// discussion for future inclusion.
   bool AllowAutoPadding = false;
 
+  /// Is strict inline assembly mode enabled? When enabled, the assembler
+  /// will warn about non-local labels that could be unsafe jump targets
+  /// in inline assembly blocks.
+  bool InlineAsmStrictMode = false;
+
 protected:
   // Symbol of the current epilog for which we are processing SEH directives.
   WinEH::FrameInfo::Epilog *CurrentWinEpilog = nullptr;
@@ -325,6 +330,9 @@ class LLVM_ABI MCStreamer {
   void setAllowAutoPadding(bool v) { AllowAutoPadding = v; }
   bool getAllowAutoPadding() const { return AllowAutoPadding; }
 
+  void setInlineAsmMode(bool v) { InlineAsmStrictMode = v; }
+  bool getInlineAsmMode() const { return InlineAsmStrictMode; }
+
   MCSymbol *emitLineTableLabel();
 
   /// When emitting an object file, create and emit a real label. When emitting
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index bb8c45bd901cd..8095992efe84a 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -533,6 +533,7 @@ class AsmParser : public MCAsmParser {
     DK_LTO_SET_CONDITIONAL,
     DK_CFI_MTE_TAGGED_FRAME,
     DK_MEMTAG,
+    DK_INLINE_ASM_MODE,
     DK_END
   };
 
@@ -703,6 +704,9 @@ class AsmParser : public MCAsmParser {
   // ".lto_discard"
   bool parseDirectiveLTODiscard();
 
+  // ".inline_asm_mode"
+  bool parseDirectiveInlineAsmMode(SMLoc DirectiveLoc);
+
   // Directives to support address-significance tables.
   bool parseDirectiveAddrsig();
   bool parseDirectiveAddrsigSym();
@@ -2222,6 +2226,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
       return parseDirectiveLTODiscard();
     case DK_MEMTAG:
       return parseDirectiveSymbolAttribute(MCSA_Memtag);
+    case DK_INLINE_ASM_MODE:
+      return parseDirectiveInlineAsmMode(IDLoc);
     }
 
     return Error(IDLoc, "unknown directive");
@@ -5590,6 +5596,7 @@ void AsmParser::initializeDirectiveKindMap() {
   DirectiveKindMap[".lto_discard"] = DK_LTO_DISCARD;
   DirectiveKindMap[".lto_set_conditional"] = DK_LTO_SET_CONDITIONAL;
   DirectiveKindMap[".memtag"] = DK_MEMTAG;
+  DirectiveKindMap[".inline_asm_mode"] = DK_INLINE_ASM_MODE;
 }
 
 MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
@@ -5912,6 +5919,27 @@ bool AsmParser::parseDirectiveLTODiscard() {
   return parseMany(ParseOp);
 }
 
+/// parseDirectiveInlineAsmMode
+///  ::= ".inline_asm_mode" ( "strict" | "relaxed" )
+bool AsmParser::parseDirectiveInlineAsmMode(SMLoc DirectiveLoc) {
+  if (getLexer().isNot(AsmToken::Identifier)) {
+    return Error(DirectiveLoc,
+                 "expected 'strict' or 'relaxed' after '.inline_asm_mode'");
+  }
+
+  StringRef Mode = getTok().getIdentifier();
+  if (Mode == "strict") {
+    getStreamer().setInlineAsmMode(true);
+  } else if (Mode == "relaxed") {
+    getStreamer().setInlineAsmMode(false);
+  } else {
+    return Error(getTok().getLoc(), "expected 'strict' or 'relaxed'");
+  }
+
+  Lex(); // consume mode identifier
+  return false;
+}
+
 // We are comparing pointers, but the pointers are relative to a single string.
 // Thus, this should always be deterministic.
 static int rewritesSort(const AsmRewrite *AsmRewriteA,
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index 6cd6b4abdd327..0abac03c55d22 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -400,6 +400,18 @@ void MCStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
     return getContext().reportError(Loc, "symbol '" + Twine(Symbol->getName()) +
                                              "' is already defined");
 
+  if (InlineAsmStrictMode) {
+    StringRef Name = Symbol->getName();
+    if (!Name.empty() && !Name.starts_with(".L") && !Name.starts_with("L..") &&
+        !Name.starts_with("$") && !Name.starts_with("__") &&
+        Name.front() != '.' && !std::isdigit(Name.front())) {
+      getContext().reportWarning(
+          Loc, "non-local label '" + Name +
+                   "' in inline assembly strict mode may be unsafe for "
+                   "external jumps; consider using local labels (.L*) instead");
+    }
+  }
+
   assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
   assert(getCurrentSectionOnly() && "Cannot emit before setting section!");
   assert(!Symbol->getFragment() && "Unexpected fragment on symbol data!");
diff --git a/llvm/test/MC/X86/inline-asm-mode-basic.s b/llvm/test/MC/X86/inline-asm-mode-basic.s
new file mode 100644
index 0000000000000..e15194980c8f7
--- /dev/null
+++ b/llvm/test/MC/X86/inline-asm-mode-basic.s
@@ -0,0 +1,25 @@
+# RUN: llvm-mc -triple x86_64-unknown-unknown %s 2>&1 | FileCheck %s
+
+# Test basic .inline_asm_mode directive functionality
+
+.text
+
+# Test that the directive is parsed correctly
+.inline_asm_mode strict
+.inline_asm_mode relaxed
+
+# Test strict mode warnings
+.inline_asm_mode strict
+
+# This should produce a warning
+# CHECK: warning: non-local label 'unsafe_global' in inline assembly strict mode may be unsafe for external jumps; consider using local labels (.L*) instead
+unsafe_global:
+    nop
+
+# This should not warn (local label)
+.L_safe_local:
+    nop
+
+# Test error handling
+.inline_asm_mode invalid
+# CHECK: error: expected 'strict' or 'relaxed'
\ No newline at end of file
diff --git a/llvm/test/MC/X86/inline-asm-mode-directive.s b/llvm/test/MC/X86/inline-asm-mode-directive.s
new file mode 100644
index 0000000000000..534948e81081c
--- /dev/null
+++ b/llvm/test/MC/X86/inline-asm-mode-directive.s
@@ -0,0 +1,57 @@
+# RUN: llvm-mc -triple x86_64-unknown-unknown %s 2>&1 | FileCheck %s --check-prefix=RELAX
+# RUN: llvm-mc -triple x86_64-unknown-unknown %s 2>&1 | FileCheck %s --check-prefix=STRICT
+
+# Test the .inline_asm_mode directive for safer inline assembly label handling
+
+.text
+
+# Test relaxed mode (default) - no warnings
+.inline_asm_mode relaxed
+
+# These labels should not produce warnings in relaxed mode
+my_label:
+    nop
+global_symbol:
+    nop
+.L_local_label:
+    nop
+
+# RELAX-NOT: warning
+
+# Test strict mode - should warn about non-local labels
+.inline_asm_mode strict
+
+# Local labels - should not warn
+.L_local1:
+    nop
+.L_local_with_numbers_123:
+    nop
+1:
+    nop
+42:
+    nop
+
+# Non-local labels - should warn
+# STRICT: :[[@LINE+1]]:1: warning: non-local label 'unsafe_label' in inline assembly strict mode may be unsafe for external jumps; consider using local labels (.L*) instead
+unsafe_label:
+    nop
+
+# STRICT: :[[@LINE+1]]:1: warning: non-local label 'another_global' in inline assembly strict mode may be unsafe for external jumps; consider using local labels (.L*) instead
+another_global:
+    nop
+
+# Switch back to relaxed mode
+.inline_asm_mode relaxed
+
+# This should not warn again
+yet_another_label:
+    nop
+
+# RELAX-NOT: warning
+
+# Test error cases
+.inline_asm_mode invalid_mode
+# CHECK: :[[@LINE-1]]:18: error: expected 'strict' or 'relaxed'
+
+.inline_asm_mode
+# CHECK: :[[@LINE-1]]:17: error: expected 'strict' or 'relaxed' after '.inline_asm_mode'
\ No newline at end of file

>From d1c2cc85fb5d20d521d238c62dcdff650ab96690 Mon Sep 17 00:00:00 2001
From: Brian Cain <brian.cain at oss.qualcomm.com>
Date: Sun, 29 Jun 2025 20:10:33 -0500
Subject: [PATCH 2/4] change criteria to numeric labels

Fix test cases
---
 llvm/docs/InlineAsmSafetyDirective.md        | 92 +++++++++++++++-----
 llvm/include/llvm/MC/MCSectionGOFF.h         |  2 +-
 llvm/lib/MC/MCStreamer.cpp                   | 11 +--
 llvm/test/MC/X86/inline-asm-mode-basic.s     | 16 ++--
 llvm/test/MC/X86/inline-asm-mode-directive.s | 35 ++++----
 llvm/test/MC/X86/inline-asm-mode-errors.s    | 13 +++
 6 files changed, 113 insertions(+), 56 deletions(-)
 create mode 100644 llvm/test/MC/X86/inline-asm-mode-errors.s

diff --git a/llvm/docs/InlineAsmSafetyDirective.md b/llvm/docs/InlineAsmSafetyDirective.md
index 0285020cbf6f1..37cc37f0d4062 100644
--- a/llvm/docs/InlineAsmSafetyDirective.md
+++ b/llvm/docs/InlineAsmSafetyDirective.md
@@ -2,12 +2,12 @@
 
 ## Overview
 
-The `.inline_asm_mode` directive provides enhanced safety for inline assembly blocks by warning about potentially unsafe label usage. This directive helps prevent common errors where programmers create non-local labels in inline assembly that could be inadvertently jumped to from external code.
+The `.inline_asm_mode` directive provides enhanced safety for inline assembly blocks by warning about potentially unsafe label usage. This directive helps prevent common errors where programmers create non-numeric labels in inline assembly that could be inadvertently jumped to from external code.
 
 ## Syntax
 
 ```assembly
-.inline_asm_mode strict   # Enable strict mode - warn on non-local labels
+.inline_asm_mode strict   # Enable strict mode - warn on non-numeric labels
 .inline_asm_mode relaxed  # Disable strict mode (default)
 ```
 
@@ -16,14 +16,14 @@ The `.inline_asm_mode` directive provides enhanced safety for inline assembly bl
 When `.inline_asm_mode strict` is active, the assembler will emit warnings for labels that are considered potentially unsafe for inline assembly:
 
 - **Safe labels** (no warnings):
-  - Local labels starting with `.L` (e.g., `.L_loop`, `.L_end`)
-  - Numeric labels (e.g., `1:`, `42:`)
-  - Labels starting with special prefixes (`$`, `__`)
-  - Labels starting with `.` (local scope)
+  - Numeric labels (e.g., `1:`, `42:`, `999:`)
 
 - **Unsafe labels** (warnings emitted):
-  - Global labels without special prefixes (e.g., `my_function:`, `loop:`)
-  - Labels that could be accessed from outside the inline assembly block
+  - All non-numeric labels including:
+    - Global labels (e.g., `my_function:`, `loop:`)
+    - Local labels (e.g., `.L_loop`, `.L_end`)
+    - Special prefixed labels (e.g., `$symbol`, `__symbol`)
+    - Any label that doesn't start with a digit
 
 ## Use Cases
 
@@ -35,23 +35,52 @@ Compiler frontends can use this directive when generating inline assembly:
 // Emitted by the compiler: .inline_asm_mode strict
 // C++ inline assembly example
 asm(
-    ".L_loop:\n"              // Safe - no warning
+    "1:\n"                    // Safe - numeric label
     "  add %0, %1\n"
-    "  jne .L_loop\n"         // Safe - local jump
-    "exit:\n"                 // Warning
+    "  jne 1b\n"              // Safe - numeric jump
+    "exit:\n"                 // Warning - non-numeric label
     : "=r"(result) : "r"(input));
 ```
 // Emitted by the compiler: .inline_asm_mode relaxed
 
+### Assembly Development
+
+Assembly programmers can use this directive for safer inline assembly blocks:
+
+```assembly
+.inline_asm_mode strict
+
+# Safe labels - no warnings (numeric only)
+1:  # Loop start
+    inc %eax
+    dec %ebx
+    jnz 1b      # Jump back to label 1
+
+2:  # Alternative path
+    nop
+    jmp 3f      # Jump forward to label 3
+
+3:  # End label
+    ret
+
+# Unsafe labels - will generate warnings
+# unsafe_global:    # Warning: non-numeric label
+# .L_local:         # Warning: non-numeric label
+# $special:         # Warning: non-numeric label
+
+.inline_asm_mode relaxed
+```
+
 ## Rationale
 
-Inline assembly blocks are often embedded within larger functions or modules. Non-local labels in these blocks can create several problems:
+Inline assembly blocks are often embedded within larger functions or modules. Non-numeric labels in these blocks can create several problems:
 
-1. **Naming conflicts**: Global labels may conflict with other symbols in the compilation unit
-2. **Unintended control flow**: External code might accidentally jump to labels intended for internal use
-3. **Maintenance issues**: Global labels make inline assembly less encapsulated
+1. **Naming conflicts**: Named labels may conflict with other symbols in the compilation unit
+2. **Unintended control flow**: External code might accidentally jump to named labels intended for internal use
+3. **Maintenance issues**: Named labels make inline assembly less self-contained
+4. **Assembly convention**: Numeric labels are the standard convention for temporary, local labels in assembly
 
-The strict mode helps identify these potential issues during compilation, allowing developers to use safer local labels instead.
+The strict mode helps identify these potential issues during compilation, encouraging developers to use safer numeric labels instead.
 
 ## Error Handling
 
@@ -85,22 +114,23 @@ example_function:
     # Simulate inline assembly block with safety
     .inline_asm_mode strict
 
-    # These are safe
-    .L_inline_start:
+    # Only numeric labels are safe
+    1:  # Safe - numeric label
         mov $1, %eax
         test %eax, %eax
-        jz .L_inline_end
+        jz 2f
 
-    1:  # Numeric label
+    3:  # Safe - numeric label
         inc %eax
         cmp $10, %eax
-        jl 1b
+        jl 3b
 
-    .L_inline_end:
+    2:  # Safe - numeric label
         # End of safe inline block
 
-    # This would generate a warning
-    # global_inline_label:  # Warning would be emitted
+    # These would generate warnings
+    # .L_inline_start:      # Warning - non-numeric
+    # global_inline_label:  # Warning - non-numeric
 
     .inline_asm_mode relaxed
 
@@ -108,3 +138,17 @@ example_function:
     ret
 ```
 
+## Integration with Build Systems
+
+Build systems can use standard LLVM warning controls to manage these diagnostics:
+
+```bash
+# Treat inline assembly warnings as errors
+llvm-mc -Werror=inline-asm-unsafe-label input.s
+
+# Suppress inline assembly warnings
+llvm-mc -Wno-inline-asm-unsafe-label input.s
+```
+
+Note: The specific warning flag names are implementation-dependent and may vary.
+
diff --git a/llvm/include/llvm/MC/MCSectionGOFF.h b/llvm/include/llvm/MC/MCSectionGOFF.h
index b2ca74c3ba78a..1e6a331202f3c 100644
--- a/llvm/include/llvm/MC/MCSectionGOFF.h
+++ b/llvm/include/llvm/MC/MCSectionGOFF.h
@@ -110,7 +110,7 @@ class MCSectionGOFF final : public MCSection {
 
   // Returns the text style for a section. Only defined for ED and PR sections.
   GOFF::ESDTextStyle getTextStyle() const {
-    assert(isED() || isPR() || isVirtualSection() && "Expect ED or PR section");
+    assert((isED() || isPR() || isVirtualSection()) && "Expect ED or PR section");
     if (isED())
       return EDAttributes.TextStyle;
     if (isPR())
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index 0abac03c55d22..3e9523b75a098 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -36,6 +36,7 @@
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
+#include <cctype>
 #include <cstdint>
 #include <cstdlib>
 #include <optional>
@@ -402,13 +403,13 @@ void MCStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
 
   if (InlineAsmStrictMode) {
     StringRef Name = Symbol->getName();
-    if (!Name.empty() && !Name.starts_with(".L") && !Name.starts_with("L..") &&
-        !Name.starts_with("$") && !Name.starts_with("__") &&
-        Name.front() != '.' && !std::isdigit(Name.front())) {
+    // Only numeric labels are considered safe in inline assembly
+    // Skip compiler-generated temporary labels (like .Ltmp0, .Ltmp1, etc.)
+    if (!Name.empty() && !std::isdigit(Name.front()) && !Name.starts_with(".Ltmp")) {
       getContext().reportWarning(
-          Loc, "non-local label '" + Name +
+          Loc, "non-numeric label '" + Name +
                    "' in inline assembly strict mode may be unsafe for "
-                   "external jumps; consider using local labels (.L*) instead");
+                   "external jumps; consider using numeric labels (1:, 2:, etc.) instead");
     }
   }
 
diff --git a/llvm/test/MC/X86/inline-asm-mode-basic.s b/llvm/test/MC/X86/inline-asm-mode-basic.s
index e15194980c8f7..10f9fad5ff0e0 100644
--- a/llvm/test/MC/X86/inline-asm-mode-basic.s
+++ b/llvm/test/MC/X86/inline-asm-mode-basic.s
@@ -11,15 +11,17 @@
 # Test strict mode warnings
 .inline_asm_mode strict
 
-# This should produce a warning
-# CHECK: warning: non-local label 'unsafe_global' in inline assembly strict mode may be unsafe for external jumps; consider using local labels (.L*) instead
+# This should produce a warning (non-numeric label)
+# CHECK: warning: non-numeric label 'unsafe_global' in inline assembly strict mode may be unsafe for external jumps; consider using numeric labels (1:, 2:, etc.) instead
 unsafe_global:
     nop
 
-# This should not warn (local label)
-.L_safe_local:
+# This should also warn
+# CHECK: warning: non-numeric label '.L_unsafe_local' in inline assembly strict mode may be unsafe for external jumps; consider using numeric labels (1:, 2:, etc.) instead
+.L_unsafe_local:
+    nop
+
+# No warning
+1:
     nop
 
-# Test error handling
-.inline_asm_mode invalid
-# CHECK: error: expected 'strict' or 'relaxed'
\ No newline at end of file
diff --git a/llvm/test/MC/X86/inline-asm-mode-directive.s b/llvm/test/MC/X86/inline-asm-mode-directive.s
index 534948e81081c..fc5f6de18c669 100644
--- a/llvm/test/MC/X86/inline-asm-mode-directive.s
+++ b/llvm/test/MC/X86/inline-asm-mode-directive.s
@@ -1,5 +1,4 @@
-# RUN: llvm-mc -triple x86_64-unknown-unknown %s 2>&1 | FileCheck %s --check-prefix=RELAX
-# RUN: llvm-mc -triple x86_64-unknown-unknown %s 2>&1 | FileCheck %s --check-prefix=STRICT
+# RUN: llvm-mc -triple x86_64-unknown-unknown %s 2>&1 | FileCheck %s
 
 # Test the .inline_asm_mode directive for safer inline assembly label handling
 
@@ -16,27 +15,32 @@ global_symbol:
 .L_local_label:
     nop
 
-# RELAX-NOT: warning
 
-# Test strict mode - should warn about non-local labels
+# Test strict mode - should warn about non-numeric labels
 .inline_asm_mode strict
 
-# Local labels - should not warn
-.L_local1:
-    nop
-.L_local_with_numbers_123:
-    nop
+# Only numeric labels are safe - should not warn
 1:
     nop
 42:
     nop
+999:
+    nop
+
+# All other labels should warn
+# CHECK: :[[@LINE+1]]:1: warning: non-numeric label '.L_local1' in inline assembly strict mode may be unsafe for external jumps; consider using numeric labels (1:, 2:, etc.) instead
+.L_local1:
+    nop
+
+# CHECK: :[[@LINE+1]]:1: warning: non-numeric label '.L_local_with_numbers_123' in inline assembly strict mode may be unsafe for external jumps; consider using numeric labels (1:, 2:, etc.) instead
+.L_local_with_numbers_123:
+    nop
 
-# Non-local labels - should warn
-# STRICT: :[[@LINE+1]]:1: warning: non-local label 'unsafe_label' in inline assembly strict mode may be unsafe for external jumps; consider using local labels (.L*) instead
+# CHECK: :[[@LINE+1]]:1: warning: non-numeric label 'unsafe_label' in inline assembly strict mode may be unsafe for external jumps; consider using numeric labels (1:, 2:, etc.) instead
 unsafe_label:
     nop
 
-# STRICT: :[[@LINE+1]]:1: warning: non-local label 'another_global' in inline assembly strict mode may be unsafe for external jumps; consider using local labels (.L*) instead
+# CHECK: :[[@LINE+1]]:1: warning: non-numeric label 'another_global' in inline assembly strict mode may be unsafe for external jumps; consider using numeric labels (1:, 2:, etc.) instead
 another_global:
     nop
 
@@ -47,11 +51,4 @@ another_global:
 yet_another_label:
     nop
 
-# RELAX-NOT: warning
-
-# Test error cases
-.inline_asm_mode invalid_mode
-# CHECK: :[[@LINE-1]]:18: error: expected 'strict' or 'relaxed'
 
-.inline_asm_mode
-# CHECK: :[[@LINE-1]]:17: error: expected 'strict' or 'relaxed' after '.inline_asm_mode'
\ No newline at end of file
diff --git a/llvm/test/MC/X86/inline-asm-mode-errors.s b/llvm/test/MC/X86/inline-asm-mode-errors.s
new file mode 100644
index 0000000000000..aa6d1aaed7db2
--- /dev/null
+++ b/llvm/test/MC/X86/inline-asm-mode-errors.s
@@ -0,0 +1,13 @@
+# RUN: not llvm-mc -triple x86_64-unknown-unknown %s 2>&1 | FileCheck %s
+
+# Test error handling for .inline_asm_mode directive
+
+.text
+
+# Test invalid mode
+.inline_asm_mode invalid
+# CHECK: error: expected 'strict' or 'relaxed'
+
+# Test missing mode
+.inline_asm_mode
+# CHECK: error: expected 'strict' or 'relaxed' after '.inline_asm_mode'
\ No newline at end of file

>From bb3e8f66916b0ccc5110420a5d8d13075552208d Mon Sep 17 00:00:00 2001
From: Brian Cain <brian.cain at oss.qualcomm.com>
Date: Sun, 29 Jun 2025 21:35:17 -0500
Subject: [PATCH 3/4] fix formatting

---
 llvm/include/llvm/MC/MCSectionGOFF.h | 3 ++-
 llvm/lib/MC/MCStreamer.cpp           | 6 ++++--
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/MC/MCSectionGOFF.h b/llvm/include/llvm/MC/MCSectionGOFF.h
index 1e6a331202f3c..e4b5e4592d83a 100644
--- a/llvm/include/llvm/MC/MCSectionGOFF.h
+++ b/llvm/include/llvm/MC/MCSectionGOFF.h
@@ -110,7 +110,8 @@ class MCSectionGOFF final : public MCSection {
 
   // Returns the text style for a section. Only defined for ED and PR sections.
   GOFF::ESDTextStyle getTextStyle() const {
-    assert((isED() || isPR() || isVirtualSection()) && "Expect ED or PR section");
+    assert((isED() || isPR() || isVirtualSection()) &&
+           "Expect ED or PR section");
     if (isED())
       return EDAttributes.TextStyle;
     if (isPR())
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index 3e9523b75a098..b90345461366b 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -405,11 +405,13 @@ void MCStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
     StringRef Name = Symbol->getName();
     // Only numeric labels are considered safe in inline assembly
     // Skip compiler-generated temporary labels (like .Ltmp0, .Ltmp1, etc.)
-    if (!Name.empty() && !std::isdigit(Name.front()) && !Name.starts_with(".Ltmp")) {
+    if (!Name.empty() && !std::isdigit(Name.front()) &&
+        !Name.starts_with(".Ltmp")) {
       getContext().reportWarning(
           Loc, "non-numeric label '" + Name +
                    "' in inline assembly strict mode may be unsafe for "
-                   "external jumps; consider using numeric labels (1:, 2:, etc.) instead");
+                   "external jumps; consider using numeric labels (1:, 2:, "
+                   "etc.) instead");
     }
   }
 

>From 6a5811a82b131c7c4384a921739b084449e889fe Mon Sep 17 00:00:00 2001
From: Brian Cain <brian.cain at oss.qualcomm.com>
Date: Sun, 29 Jun 2025 21:37:43 -0500
Subject: [PATCH 4/4] refer to new doc

---
 llvm/docs/Reference.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/docs/Reference.rst b/llvm/docs/Reference.rst
index cb9576b15d701..ec30858f07e83 100644
--- a/llvm/docs/Reference.rst
+++ b/llvm/docs/Reference.rst
@@ -31,6 +31,7 @@ LLVM and API reference documentation.
    HowToSetUpLLVMStyleRTTI
    HowToUseAttributes
    InAlloca
+   InlineAsmSafetyDirective
    InterfaceExportAnnotations
    LangRef
    LibFuzzer



More information about the llvm-commits mailing list