From 6b622b3ac38b7cc0653ae03980e590e48d190b11 Mon Sep 17 00:00:00 2001 From: Brian Cain 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 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 +#include #include #include #include @@ -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 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 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