[llvm] [MachO] Refine alias n_desc flag ownership (name flags from alias, not aliasee) (PR #212001)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 25 02:39:47 PDT 2026
https://github.com/syhhyl updated https://github.com/llvm/llvm-project/pull/212001
>From 7fb418a0f38ce623f95110cc2a844b5644bb996a Mon Sep 17 00:00:00 2001
From: syhhyl <syhhyl926 at 126.com>
Date: Sat, 25 Jul 2026 16:43:28 +0800
Subject: [PATCH] [MachO] Refine alias n_desc flag ownership
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
For alias symbols, n_desc mixes name attributes (N_WEAK_DEF,
N_WEAK_REF, N_ALT_ENTRY, N_NO_DEAD_STRIP — from the alias)
and location attributes (N_ARM_THUMB_DEF, N_COLD_FUNC,
N_SYMBOL_RESOLVER — from the aliasee).
The original fix in #198148 used a full OR of flags, which
preserves the alias weak def but incorrectly propagates the
aliasee weak def to strong aliases in the reverse direction.
Replace the OR with a NameMask that takes name flags from
the alias and location flags from the aliasee.
Assisted-by: opencode
---
llvm/lib/MC/MachObjectWriter.cpp | 15 ++--
llvm/test/CodeGen/AArch64/macho-weak-alias.ll | 73 ++++++++++++++++++-
2 files changed, 79 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp
index 657f6f40fd9e9..edf4bc3f740e4 100644
--- a/llvm/lib/MC/MachObjectWriter.cpp
+++ b/llvm/lib/MC/MachObjectWriter.cpp
@@ -443,11 +443,16 @@ void MachObjectWriter::writeNlist(MachSymbolData &MSD, const MCAssembler &Asm) {
// The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
// value.
bool EncodeAsAltEntry = IsAlias && OrigSymbol.isAltEntry();
- uint16_t Flags = Symbol->getEncodedFlags(EncodeAsAltEntry);
- // Preserve the aliasee's flags while adding alias-specific flags,
- // such as N_WEAK_DEF emitted by .weak_definition.
- if (IsAlias)
- Flags |= OrigSymbol.getEncodedFlags(EncodeAsAltEntry);
+ uint16_t Flags;
+ if (!IsAlias) {
+ Flags = Symbol->getEncodedFlags(EncodeAsAltEntry);
+ } else {
+ uint16_t AliaseeFlags = Symbol->getEncodedFlags(false);
+ uint16_t AliasFlags = OrigSymbol.getEncodedFlags(EncodeAsAltEntry);
+ constexpr uint16_t NameMask = MachO::N_WEAK_DEF | MachO::N_WEAK_REF |
+ MachO::N_ALT_ENTRY | MachO::N_NO_DEAD_STRIP;
+ Flags = (AliaseeFlags & ~NameMask) | (AliasFlags & NameMask);
+ }
W.write<uint16_t>(Flags);
if (is64Bit())
W.write<uint64_t>(Address);
diff --git a/llvm/test/CodeGen/AArch64/macho-weak-alias.ll b/llvm/test/CodeGen/AArch64/macho-weak-alias.ll
index a936cea618b38..48adcdaf154a0 100644
--- a/llvm/test/CodeGen/AArch64/macho-weak-alias.ll
+++ b/llvm/test/CodeGen/AArch64/macho-weak-alias.ll
@@ -1,17 +1,82 @@
; RUN: llc -mtriple=aarch64-apple-macosx13.0.0 -filetype=obj %s -o %t.o
-; RUN: llvm-nm -m %t.o | FileCheck %s
+; RUN: llvm-nm -m %t.o | FileCheck --check-prefix=NM %s
+; RUN: llvm-readobj --symbols %t.o | FileCheck --check-prefix=SYMBOL %s
+
+; llvm.used gives foo_internal N_NO_DEAD_STRIP.
+; Under the name-flag rule, aliases must NOT inherit it.
+ at llvm.used = appending global [1 x ptr] [ptr @foo_internal], section "llvm.metadata"
define internal void @foo_internal() {
ret void
}
+; Weak alias to internal target: bar sets N_WEAK_DEF, foo has N_NO_DEAD_STRIP.
+; Result: N_WEAK_DEF only (0x80), no N_NO_DEAD_STRIP.
@foo_default = weak_odr alias void (), ptr @foo_internal
+
+; Weak hidden alias: bar sets N_WEAK_DEF + hidden.
@foo_hidden = weak_odr hidden alias void (), ptr @foo_internal
+; Baseline: ordinary weak hidden definition.
define weak_odr hidden void @foo_defined() {
ret void
}
-; CHECK-DAG: weak external _foo_default
-; CHECK-DAG: weak private external _foo_hidden
-; CHECK-DAG: weak private external _foo_defined
+; Weak aliasee target.
+define weak_odr void @foo_weak_aliasee() {
+ ret void
+}
+
+; Strong alias to weak target: bar has no weak, foo has N_WEAK_DEF.
+; Result: no weak flags (0x0).
+ at foo_strong_alias = alias void (), ptr @foo_weak_aliasee
+
+; Auto-hide weak: linkonce_odr unnamed_addr -> emit .weak_def_can_be_hidden.
+; Result: N_WEAK_DEF | N_WEAK_REF (0xC0).
+ at foo_auto = linkonce_odr unnamed_addr alias void (), ptr @foo_internal
+
+; NM-DAG: weak external _foo_default
+; NM-DAG: weak private external _foo_hidden
+; NM-DAG: weak private external _foo_defined
+; NM-DAG: {{^[0-9a-fA-F]+ \(__TEXT,__text\) external _foo_strong_alias$}}
+; NM-DAG: weak external automatically hidden _foo_auto
+; NM-DAG: non-external [no dead strip] _foo_internal
+
+; _foo_internal: N_NO_DEAD_STRIP from llvm.used (0x20).
+; SYMBOL: Name: _foo_internal
+; SYMBOL-NEXT: Type: Section (0xE)
+; SYMBOL-NEXT: Section: __text
+; SYMBOL-NEXT: RefType: UndefinedNonLazy (0x0)
+; SYMBOL-NEXT: Flags [ (0x20)
+; SYMBOL-NEXT: NoDeadStrip (0x20)
+; SYMBOL-NEXT: ]
+
+; _foo_auto: 0xC0 = N_WEAK_DEF | N_WEAK_REF.
+; SYMBOL: Name: _foo_auto
+; SYMBOL-NEXT: Extern
+; SYMBOL-NEXT: Type: Section (0xE)
+; SYMBOL-NEXT: Section: __text
+; SYMBOL-NEXT: RefType: UndefinedNonLazy (0x0)
+; SYMBOL-NEXT: Flags [ (0xC0)
+; SYMBOL-NEXT: WeakDef (0x80)
+; SYMBOL-NEXT: WeakRef (0x40)
+; SYMBOL-NEXT: ]
+
+; _foo_default: 0x80 = N_WEAK_DEF, no N_NO_DEAD_STRIP inherited.
+; SYMBOL: Name: _foo_default
+; SYMBOL-NEXT: Extern
+; SYMBOL-NEXT: Type: Section (0xE)
+; SYMBOL-NEXT: Section: __text
+; SYMBOL-NEXT: RefType: UndefinedNonLazy (0x0)
+; SYMBOL-NEXT: Flags [ (0x80)
+; SYMBOL-NEXT: WeakDef (0x80)
+; SYMBOL-NEXT: ]
+
+; _foo_strong_alias: 0x0, no weak inherited from foo.
+; SYMBOL: Name: _foo_strong_alias
+; SYMBOL-NEXT: Extern
+; SYMBOL-NEXT: Type: Section (0xE)
+; SYMBOL-NEXT: Section: __text
+; SYMBOL-NEXT: RefType: UndefinedNonLazy (0x0)
+; SYMBOL-NEXT: Flags [ (0x0)
+; SYMBOL-NEXT: ]
More information about the llvm-commits
mailing list