[llvm] [MachO] Preserve weak attributes on aliases (PR #219534)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 30 05:19:58 PDT 2026
https://github.com/AsakuraMizu updated https://github.com/llvm/llvm-project/pull/219534
>From 006b49a699e2b4b787580e0d36553ea6965d0e1e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9C=9D=E5=80=89=E6=B0=B4=E5=B8=8C?= <mizuk1 at mzk1.dev>
Date: Fri, 28 Aug 2026 22:45:30 +0800
Subject: [PATCH 1/2] [MachO] Preserve weak attributes on aliases
---
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 4 +-
llvm/lib/MC/MachObjectWriter.cpp | 6 +-
llvm/test/CodeGen/AArch64/macho-weak-alias.ll | 26 ++++++
llvm/test/MC/MachO/weak-alias.s | 84 +++++++++++++++++++
4 files changed, 118 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/macho-weak-alias.ll
create mode 100644 llvm/test/MC/MachO/weak-alias.s
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index dab57e744db08..67fb460086823 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2702,7 +2702,9 @@ void AsmPrinter::emitGlobalAlias(const Module &M, const GlobalAlias &GA) {
return;
}
- if (GA.hasExternalLinkage() || !MAI.getWeakRefDirective())
+ if (MAI.isMachO())
+ emitLinkage(&GA, Name);
+ else if (GA.hasExternalLinkage() || !MAI.getWeakRefDirective())
OutStreamer->emitSymbolAttribute(Name, MCSA_Global);
else if (GA.hasWeakLinkage() || GA.hasLinkOnceLinkage())
OutStreamer->emitSymbolAttribute(Name, MCSA_WeakReference);
diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp
index 790f7595807b9..ab76d0f94c57d 100644
--- a/llvm/lib/MC/MachObjectWriter.cpp
+++ b/llvm/lib/MC/MachObjectWriter.cpp
@@ -443,7 +443,11 @@ 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();
- W.write<uint16_t>(Symbol->getEncodedFlags(EncodeAsAltEntry));
+ uint16_t Flags = Symbol->getEncodedFlags(EncodeAsAltEntry);
+ if (IsAlias)
+ Flags |= OrigSymbol.getEncodedFlags(false) &
+ (MachO::N_WEAK_DEF | MachO::N_WEAK_REF);
+ W.write<uint16_t>(Flags);
if (is64Bit())
W.write<uint64_t>(Address);
else
diff --git a/llvm/test/CodeGen/AArch64/macho-weak-alias.ll b/llvm/test/CodeGen/AArch64/macho-weak-alias.ll
new file mode 100644
index 0000000000000..13c3f3ec6cd11
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/macho-weak-alias.ll
@@ -0,0 +1,26 @@
+; RUN: llc -mtriple=aarch64-apple-macosx13.0.0 %s -o - | FileCheck %s
+
+ at foo = internal global i32 0
+ at external_alias = alias i32, ptr @foo
+ at internal_alias = internal alias i32, ptr @foo
+ at weak_alias = weak alias i32, ptr @foo
+ at hidden_weak_alias = weak hidden alias i32, ptr @foo
+ at linkonce_alias = linkonce alias i32, ptr @foo
+ at auto_hide_alias = linkonce_odr unnamed_addr alias i32, ptr @foo
+
+; CHECK: .globl _external_alias
+; CHECK-NEXT: _external_alias = _foo
+; CHECK: _internal_alias = _foo
+; CHECK: .globl _weak_alias
+; CHECK-NEXT: .weak_definition _weak_alias
+; CHECK-NEXT: _weak_alias = _foo
+; CHECK: .globl _hidden_weak_alias
+; CHECK-NEXT: .weak_definition _hidden_weak_alias
+; CHECK-NEXT: .private_extern _hidden_weak_alias
+; CHECK-NEXT: _hidden_weak_alias = _foo
+; CHECK: .globl _linkonce_alias
+; CHECK-NEXT: .weak_definition _linkonce_alias
+; CHECK-NEXT: _linkonce_alias = _foo
+; CHECK: .globl _auto_hide_alias
+; CHECK-NEXT: .weak_def_can_be_hidden _auto_hide_alias
+; CHECK-NEXT: _auto_hide_alias = _foo
diff --git a/llvm/test/MC/MachO/weak-alias.s b/llvm/test/MC/MachO/weak-alias.s
new file mode 100644
index 0000000000000..076abc3d2df87
--- /dev/null
+++ b/llvm/test/MC/MachO/weak-alias.s
@@ -0,0 +1,84 @@
+// RUN: llvm-mc -triple x86_64-apple-macosx13.0.0 -filetype=obj %s -o - | llvm-readobj --symbols - | FileCheck %s
+
+.text
+_foo:
+ nop
+
+.globl _external
+_external = _foo
+
+.globl _weak
+.weak_definition _weak
+_weak = _foo
+
+.globl _auto
+.weak_def_can_be_hidden _auto
+_auto = _foo
+
+_local = _foo
+
+.globl _weak_target
+.weak_definition _weak_target
+_weak_target:
+ nop
+
+.globl _strong_to_weak
+_strong_to_weak = _weak_target
+
+// CHECK: Name: _local
+// CHECK-NEXT: Type: Section (0xE)
+// CHECK-NEXT: Section: __text (0x1)
+// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x0)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Value: 0x0
+
+// CHECK: Name: _auto
+// CHECK-NEXT: Extern
+// CHECK-NEXT: Type: Section (0xE)
+// CHECK-NEXT: Section: __text (0x1)
+// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0xC0)
+// CHECK-NEXT: WeakDef (0x80)
+// CHECK-NEXT: WeakRef (0x40)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Value: 0x0
+
+// CHECK: Name: _external
+// CHECK-NEXT: Extern
+// CHECK-NEXT: Type: Section (0xE)
+// CHECK-NEXT: Section: __text (0x1)
+// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x0)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Value: 0x0
+
+// CHECK: Name: _strong_to_weak
+// CHECK-NEXT: Extern
+// CHECK-NEXT: Type: Section (0xE)
+// CHECK-NEXT: Section: __text (0x1)
+// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x80)
+// CHECK-NEXT: WeakDef (0x80)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Value: 0x1
+
+// CHECK: Name: _weak
+// CHECK-NEXT: Extern
+// CHECK-NEXT: Type: Section (0xE)
+// CHECK-NEXT: Section: __text (0x1)
+// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x80)
+// CHECK-NEXT: WeakDef (0x80)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Value: 0x0
+
+// CHECK: Name: _weak_target
+// CHECK-NEXT: Extern
+// CHECK-NEXT: Type: Section (0xE)
+// CHECK-NEXT: Section: __text (0x1)
+// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x80)
+// CHECK-NEXT: WeakDef (0x80)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Value: 0x1
>From 407d9757a0484a24cc132fbe898b4c1d31ee43f4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9C=9D=E5=80=89=E6=B0=B4=E5=B8=8C?= <mizuk1 at mzk1.dev>
Date: Sat, 5 Sep 2026 23:47:03 +0800
Subject: [PATCH 2/2] [MachO] Add alias flag tests
---
llvm/test/MC/MachO/alias-flags.s | 177 +++++++++++++++++++++++++++++++
1 file changed, 177 insertions(+)
create mode 100644 llvm/test/MC/MachO/alias-flags.s
diff --git a/llvm/test/MC/MachO/alias-flags.s b/llvm/test/MC/MachO/alias-flags.s
new file mode 100644
index 0000000000000..cdff037548168
--- /dev/null
+++ b/llvm/test/MC/MachO/alias-flags.s
@@ -0,0 +1,177 @@
+// RUN: llvm-mc -triple x86_64-apple-macosx13.0.0 -filetype=obj %s -o - | llvm-readobj --symbols - | FileCheck %s
+
+// Aliases inherit these n_desc fields from their aliasees. Of these flags,
+// only N_ALT_ENTRY is also preserved when set on the alias itself.
+.text
+_plain:
+ nop
+
+.alt_entry _alt_entry_target
+_alt_entry_target:
+ nop
+
+.cold _cold_target
+_cold_target:
+ nop
+
+.no_dead_strip _no_dead_strip_target
+_no_dead_strip_target:
+ nop
+
+_reference_type_target:
+ nop
+// Set the reference type after the label, which would otherwise clear it.
+.desc _reference_type_target, 2
+
+.symbol_resolver _resolver_target
+_resolver_target:
+ nop
+
+.globl _alt_entry_on_alias
+.alt_entry _alt_entry_on_alias
+_alt_entry_on_alias = _plain
+
+.globl _alt_entry_on_target
+_alt_entry_on_target = _alt_entry_target
+
+.globl _cold_on_alias
+.cold _cold_on_alias
+_cold_on_alias = _plain
+
+.globl _cold_on_target
+_cold_on_target = _cold_target
+
+.globl _no_dead_strip_on_alias
+.no_dead_strip _no_dead_strip_on_alias
+_no_dead_strip_on_alias = _plain
+
+.globl _no_dead_strip_on_target
+_no_dead_strip_on_target = _no_dead_strip_target
+
+// Different reference types must not be ORed together: the aliasee wins.
+.globl _reference_type_both
+.desc _reference_type_both, 1
+_reference_type_both = _reference_type_target
+
+.globl _reference_type_on_alias
+.desc _reference_type_on_alias, 1
+_reference_type_on_alias = _plain
+
+.globl _reference_type_on_target
+_reference_type_on_target = _reference_type_target
+
+.globl _resolver_on_alias
+.symbol_resolver _resolver_on_alias
+_resolver_on_alias = _plain
+
+.globl _resolver_on_target
+_resolver_on_target = _resolver_target
+
+// Preserve the aliasee's alt-entry bit along with both weak bits on the alias.
+.globl _auto_to_alt_entry
+.weak_def_can_be_hidden _auto_to_alt_entry
+_auto_to_alt_entry = _alt_entry_target
+
+// Only the weak bits are taken from the alias, not its no-dead-strip bit.
+.globl _weak_no_dead_strip
+.weak_definition _weak_no_dead_strip
+.no_dead_strip _weak_no_dead_strip
+_weak_no_dead_strip = _plain
+
+// Preserve the aliasee's no-dead-strip bit when adding the alias's weak bit.
+.globl _weak_to_no_dead_strip
+.weak_definition _weak_to_no_dead_strip
+_weak_to_no_dead_strip = _no_dead_strip_target
+
+// CHECK-LABEL: Name: _alt_entry_on_alias
+// CHECK: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x200)
+// CHECK-NEXT: AltEntry (0x200)
+// CHECK-NEXT: ]
+
+// CHECK-LABEL: Name: _alt_entry_on_target
+// CHECK: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x200)
+// CHECK-NEXT: AltEntry (0x200)
+// CHECK-NEXT: ]
+
+// CHECK-LABEL: Name: _auto_to_alt_entry
+// CHECK-NEXT: Extern
+// CHECK-NEXT: Type: Section (0xE)
+// CHECK-NEXT: Section: __text (0x1)
+// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x2C0)
+// CHECK-NEXT: AltEntry (0x200)
+// CHECK-NEXT: WeakDef (0x80)
+// CHECK-NEXT: WeakRef (0x40)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Value: 0x1
+
+// CHECK-LABEL: Name: _cold_on_alias
+// CHECK: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x0)
+// CHECK-NEXT: ]
+
+// CHECK-LABEL: Name: _cold_on_target
+// CHECK: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x400)
+// CHECK-NEXT: ColdFunc (0x400)
+// CHECK-NEXT: ]
+
+// CHECK-LABEL: Name: _no_dead_strip_on_alias
+// CHECK: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x0)
+// CHECK-NEXT: ]
+
+// CHECK-LABEL: Name: _no_dead_strip_on_target
+// CHECK: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x20)
+// CHECK-NEXT: NoDeadStrip (0x20)
+// CHECK-NEXT: ]
+
+// CHECK-LABEL: Name: _reference_type_both
+// CHECK: RefType: ReferenceFlagDefined (0x2)
+// CHECK-NEXT: Flags [ (0x0)
+// CHECK-NEXT: ]
+
+// CHECK-LABEL: Name: _reference_type_on_alias
+// CHECK: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x0)
+// CHECK-NEXT: ]
+
+// CHECK-LABEL: Name: _reference_type_on_target
+// CHECK: RefType: ReferenceFlagDefined (0x2)
+// CHECK-NEXT: Flags [ (0x0)
+// CHECK-NEXT: ]
+
+// CHECK-LABEL: Name: _resolver_on_alias
+// CHECK: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x0)
+// CHECK-NEXT: ]
+
+// CHECK-LABEL: Name: _resolver_on_target
+// CHECK: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x100)
+// CHECK-NEXT: SymbolResolver (0x100)
+// CHECK-NEXT: ]
+
+// CHECK-LABEL: Name: _weak_no_dead_strip
+// CHECK-NEXT: Extern
+// CHECK-NEXT: Type: Section (0xE)
+// CHECK-NEXT: Section: __text (0x1)
+// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0x80)
+// CHECK-NEXT: WeakDef (0x80)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Value: 0x0
+
+// CHECK-LABEL: Name: _weak_to_no_dead_strip
+// CHECK-NEXT: Extern
+// CHECK-NEXT: Type: Section (0xE)
+// CHECK-NEXT: Section: __text (0x1)
+// CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+// CHECK-NEXT: Flags [ (0xA0)
+// CHECK-NEXT: NoDeadStrip (0x20)
+// CHECK-NEXT: WeakDef (0x80)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Value: 0x3
More information about the llvm-commits
mailing list