[llvm] 10c17c9 - [COFF] Add MC support for emitting IMAGE_WEAK_EXTERN_ANTI_DEPENDENCY symbols

Eli Friedman via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 17 13:17:42 PDT 2023


Author: Eli Friedman
Date: 2023-04-17T13:17:25-07:00
New Revision: 10c17c97ebaf81ac26f6830e51a7a57ddcf63cd2

URL: https://github.com/llvm/llvm-project/commit/10c17c97ebaf81ac26f6830e51a7a57ddcf63cd2
DIFF: https://github.com/llvm/llvm-project/commit/10c17c97ebaf81ac26f6830e51a7a57ddcf63cd2.diff

LOG: [COFF] Add MC support for emitting IMAGE_WEAK_EXTERN_ANTI_DEPENDENCY symbols

This is mostly useful for ARM64EC, which uses such symbols extensively.

One interesting quirk of ARM64EC is that we need to be able to emit weak
symbols that point at each other (so if either symbol is defined
elsewhere, both symbols point at the definition).  This required a few
changes to the way we handle weak symbols on Windows.

Differential Revision: https://reviews.llvm.org/D145208

Added: 
    llvm/test/MC/COFF/weak-anti-dep.s

Modified: 
    llvm/include/llvm/MC/MCDirectives.h
    llvm/include/llvm/MC/MCSymbol.h
    llvm/include/llvm/MC/MCSymbolCOFF.h
    llvm/lib/MC/MCAsmStreamer.cpp
    llvm/lib/MC/MCELFStreamer.cpp
    llvm/lib/MC/MCExpr.cpp
    llvm/lib/MC/MCMachOStreamer.cpp
    llvm/lib/MC/MCParser/AsmParser.cpp
    llvm/lib/MC/MCParser/COFFAsmParser.cpp
    llvm/lib/MC/MCWinCOFFStreamer.cpp
    llvm/lib/MC/WinCOFFObjectWriter.cpp
    llvm/test/MC/COFF/addrsig.s
    llvm/test/MC/COFF/alias.s

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCDirectives.h b/llvm/include/llvm/MC/MCDirectives.h
index b9668a0c994fa..fcab56ff0a740 100644
--- a/llvm/include/llvm/MC/MCDirectives.h
+++ b/llvm/include/llvm/MC/MCDirectives.h
@@ -46,6 +46,7 @@ enum MCSymbolAttr {
   MCSA_WeakDefinition,          ///< .weak_definition (MachO)
   MCSA_WeakReference,           ///< .weak_reference (MachO)
   MCSA_WeakDefAutoPrivate,      ///< .weak_def_can_be_hidden (MachO)
+  MCSA_WeakAntiDep,             ///< .weak_anti_dep (COFF)
   MCSA_Memtag,                  ///< .memtag (ELF)
 };
 

diff  --git a/llvm/include/llvm/MC/MCSymbol.h b/llvm/include/llvm/MC/MCSymbol.h
index 8954960e3b8c7..f59821d48dc3d 100644
--- a/llvm/include/llvm/MC/MCSymbol.h
+++ b/llvm/include/llvm/MC/MCSymbol.h
@@ -102,6 +102,9 @@ class MCSymbol {
   /// This symbol is private extern.
   mutable unsigned IsPrivateExtern : 1;
 
+  /// This symbol is weak external.
+  mutable unsigned IsWeakExternal : 1;
+
   /// LLVM RTTI discriminator. This is actually a SymbolKind enumerator, but is
   /// unsigned to avoid sign extension and achieve better bitpacking with MSVC.
   unsigned Kind : 3;
@@ -161,8 +164,8 @@ class MCSymbol {
   MCSymbol(SymbolKind Kind, const StringMapEntry<bool> *Name, bool isTemporary)
       : IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false),
         IsRegistered(false), IsExternal(false), IsPrivateExtern(false),
-        Kind(Kind), IsUsedInReloc(false), SymbolContents(SymContentsUnset),
-        CommonAlignLog2(0), Flags(0) {
+        IsWeakExternal(false), Kind(Kind), IsUsedInReloc(false),
+        SymbolContents(SymContentsUnset), CommonAlignLog2(0), Flags(0) {
     Offset = 0;
     FragmentAndHasName.setInt(!!Name);
     if (Name)
@@ -394,8 +397,10 @@ class MCSymbol {
 
   MCFragment *getFragment(bool SetUsed = true) const {
     MCFragment *Fragment = FragmentAndHasName.getPointer();
-    if (Fragment || !isVariable())
+    if (Fragment || !isVariable() || isWeakExternal())
       return Fragment;
+    // If the symbol is a non-weak alias, get information about
+    // the aliasee. (Don't try to resolve weak aliases.)
     Fragment = getVariableValue(SetUsed)->findAssociatedFragment();
     FragmentAndHasName.setPointer(Fragment);
     return Fragment;
@@ -407,6 +412,8 @@ class MCSymbol {
   bool isPrivateExtern() const { return IsPrivateExtern; }
   void setPrivateExtern(bool Value) { IsPrivateExtern = Value; }
 
+  bool isWeakExternal() const { return IsWeakExternal; }
+
   /// print - Print the value to the stream \p OS.
   void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
 

diff  --git a/llvm/include/llvm/MC/MCSymbolCOFF.h b/llvm/include/llvm/MC/MCSymbolCOFF.h
index b25993c32db6d..7f077c7986c01 100644
--- a/llvm/include/llvm/MC/MCSymbolCOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolCOFF.h
@@ -23,8 +23,9 @@ class MCSymbolCOFF : public MCSymbol {
     SF_ClassMask = 0x00FF,
     SF_ClassShift = 0,
 
-    SF_WeakExternal = 0x0100,
-    SF_SafeSEH = 0x0200,
+    SF_SafeSEH = 0x0100,
+    SF_WeakExternalCharacteristicsMask = 0x0E00,
+    SF_WeakExternalCharacteristicsShift = 9,
   };
 
 public:
@@ -45,11 +46,14 @@ class MCSymbolCOFF : public MCSymbol {
     modifyFlags(StorageClass << SF_ClassShift, SF_ClassMask);
   }
 
-  bool isWeakExternal() const {
-    return getFlags() & SF_WeakExternal;
+  COFF::WeakExternalCharacteristics getWeakExternalCharacteristics() const {
+    return static_cast<COFF::WeakExternalCharacteristics>((getFlags() & SF_WeakExternalCharacteristicsMask) >>
+           SF_WeakExternalCharacteristicsShift);
   }
-  void setIsWeakExternal() const {
-    modifyFlags(SF_WeakExternal, SF_WeakExternal);
+  void setIsWeakExternal(COFF::WeakExternalCharacteristics Characteristics) const {
+    IsWeakExternal = true;
+    modifyFlags(Characteristics << SF_WeakExternalCharacteristicsShift,
+                SF_WeakExternalCharacteristicsMask);
   }
 
   bool isSafeSEH() const {

diff  --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index c11d28b746f60..6f21566a50f25 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -772,6 +772,9 @@ bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,
   case MCSA_Memtag:
     OS << "\t.memtag\t";
     break;
+  case MCSA_WeakAntiDep:
+    OS << "\t.weak_anti_dep\t";
+    break;
   }
 
   Symbol->print(OS, MAI);

diff  --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index 8dd002fba0e1a..303eb16011d17 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -216,6 +216,7 @@ bool MCELFStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
   case MCSA_Invalid:
   case MCSA_IndirectSymbol:
   case MCSA_Exported:
+  case MCSA_WeakAntiDep:
     return false;
 
   case MCSA_NoDeadStrip:

diff  --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index 04682fdc7ecec..68cd88f822066 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -761,6 +761,9 @@ bool MCExpr::evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const {
 }
 
 static bool canExpand(const MCSymbol &Sym, bool InSet) {
+  if (Sym.isWeakExternal())
+    return false;
+
   const MCExpr *Expr = Sym.getVariableValue();
   const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr);
   if (Inner) {

diff  --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp
index 986c0c2c506bf..6711ff9001a32 100644
--- a/llvm/lib/MC/MCMachOStreamer.cpp
+++ b/llvm/lib/MC/MCMachOStreamer.cpp
@@ -358,6 +358,7 @@ bool MCMachOStreamer::emitSymbolAttribute(MCSymbol *Sym,
   case MCSA_LGlobal:
   case MCSA_Exported:
   case MCSA_Memtag:
+  case MCSA_WeakAntiDep:
     return false;
 
   case MCSA_Global:

diff  --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index c49e51332b126..254c747aca050 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -6371,7 +6371,7 @@ static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) {
   case MCExpr::SymbolRef: {
     const MCSymbol &S =
         static_cast<const MCSymbolRefExpr *>(Value)->getSymbol();
-    if (S.isVariable())
+    if (S.isVariable() && !S.isWeakExternal())
       return isSymbolUsedInExpression(Sym, S.getVariableValue());
     return &S == Sym;
   }

diff  --git a/llvm/lib/MC/MCParser/COFFAsmParser.cpp b/llvm/lib/MC/MCParser/COFFAsmParser.cpp
index fc3d1e94e49f7..3f88257d37db9 100644
--- a/llvm/lib/MC/MCParser/COFFAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/COFFAsmParser.cpp
@@ -67,6 +67,7 @@ class COFFAsmParser : public MCAsmParserExtension {
     addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
     addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");
     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
+    addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak_anti_dep");
     addDirectiveHandler<&COFFAsmParser::ParseDirectiveCGProfile>(".cg_profile");
 
     // Win64 EH directives.
@@ -281,6 +282,7 @@ bool COFFAsmParser::ParseSectionFlags(StringRef SectionName,
 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
   MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
     .Case(".weak", MCSA_Weak)
+    .Case(".weak_anti_dep", MCSA_WeakAntiDep)
     .Default(MCSA_Invalid);
   assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
   if (getLexer().isNot(AsmToken::EndOfStatement)) {

diff  --git a/llvm/lib/MC/MCWinCOFFStreamer.cpp b/llvm/lib/MC/MCWinCOFFStreamer.cpp
index c9a9681648341..ad0b1c157278a 100644
--- a/llvm/lib/MC/MCWinCOFFStreamer.cpp
+++ b/llvm/lib/MC/MCWinCOFFStreamer.cpp
@@ -115,7 +115,11 @@ bool MCWinCOFFStreamer::emitSymbolAttribute(MCSymbol *S,
   default: return false;
   case MCSA_WeakReference:
   case MCSA_Weak:
-    Symbol->setIsWeakExternal();
+    Symbol->setIsWeakExternal(COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS);
+    Symbol->setExternal(true);
+    break;
+  case MCSA_WeakAntiDep:
+    Symbol->setIsWeakExternal(COFF::IMAGE_WEAK_EXTERN_ANTI_DEPENDENCY);
     Symbol->setExternal(true);
     break;
   case MCSA_Global:

diff  --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp
index 4927ea6177fdb..6687fd6af9c8f 100644
--- a/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -414,9 +414,9 @@ void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &MCSym,
     Sym->Aux.resize(1);
     memset(&Sym->Aux[0], 0, sizeof(Sym->Aux[0]));
     Sym->Aux[0].AuxType = ATWeakExternal;
-    Sym->Aux[0].Aux.WeakExternal.TagIndex = 0;
+    Sym->Aux[0].Aux.WeakExternal.TagIndex = 0; // Filled in later
     Sym->Aux[0].Aux.WeakExternal.Characteristics =
-        COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS;
+        cast<MCSymbolCOFF>(MCSym).getWeakExternalCharacteristics();
   } else {
     if (!Base)
       Sym->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;

diff  --git a/llvm/test/MC/COFF/addrsig.s b/llvm/test/MC/COFF/addrsig.s
index 7c3b25d52edae..a181bb06508be 100644
--- a/llvm/test/MC/COFF/addrsig.s
+++ b/llvm/test/MC/COFF/addrsig.s
@@ -3,7 +3,7 @@
 // CHECK:      Name: .llvm_addrsig
 // CHECK-NEXT: VirtualSize: 0x0
 // CHECK-NEXT: VirtualAddress: 0x0
-// CHECK-NEXT: RawDataSize: 4
+// CHECK-NEXT: RawDataSize: 6
 // CHECK-NEXT: PointerToRawData:
 // CHECK-NEXT: PointerToRelocations: 0x0
 // CHECK-NEXT: PointerToLineNumbers: 0x0
@@ -46,6 +46,8 @@
 // CHECK-NEXT:   Sym: g3 (11)
 // CHECK-NEXT:   Sym: local (10)
 // CHECK-NEXT:   Sym: .data (2)
+// CHECK-NEXT:   Sym: weak_sym (12)
+// CHECK-NEXT:   Sym: .data (2)
 // CHECK-NEXT: ]
 
 .globl g1
@@ -64,3 +66,10 @@ local:
 
 .data
 .Llocal:
+
+.weak weak_sym
+weak_sym:
+.addrsig_sym weak_sym
+
+.set .Lalias_weak_sym, weak_sym
+.addrsig_sym .Lalias_weak_sym

diff  --git a/llvm/test/MC/COFF/alias.s b/llvm/test/MC/COFF/alias.s
index b6828c658132b..cfb44ca1503fe 100644
--- a/llvm/test/MC/COFF/alias.s
+++ b/llvm/test/MC/COFF/alias.s
@@ -24,7 +24,7 @@ weak_aliased_to_external = external2
 // CHECK:        0x0 IMAGE_REL_I386_DIR32 external_aliased_to_local
 // CHECK:        0x4 IMAGE_REL_I386_DIR32 external1
 // CHECK:        0x8 IMAGE_REL_I386_DIR32 global_aliased_to_local
-// CHECK:        0xC IMAGE_REL_I386_DIR32 external2
+// CHECK:        0xC IMAGE_REL_I386_DIR32 weak_aliased_to_external
 // CHECK:      ]
 // CHECK:      Symbols [
 // CHECK-NEXT:   Symbol {

diff  --git a/llvm/test/MC/COFF/weak-anti-dep.s b/llvm/test/MC/COFF/weak-anti-dep.s
new file mode 100644
index 0000000000000..dbf5ffc0a35bf
--- /dev/null
+++ b/llvm/test/MC/COFF/weak-anti-dep.s
@@ -0,0 +1,68 @@
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-win32 %s | llvm-readobj --symbols - | FileCheck %s
+
+// CHECK:       Symbol {
+// CHECK-NEXT:    Name: .text
+// CHECK:       Symbol {
+// CHECK-NEXT:    Name: .data
+// CHECK:       Symbol {
+// CHECK-NEXT:    Name: .bss
+
+.weak_anti_dep a
+a = b
+
+// CHECK:       Symbol {
+// CHECK-NEXT:    Name: a
+// CHECK-NEXT:    Value: 0
+// CHECK-NEXT:    Section: IMAGE_SYM_UNDEFINED (0)
+// CHECK-NEXT:    BaseType: Null (0x0)
+// CHECK-NEXT:    ComplexType: Null (0x0)
+// CHECK-NEXT:    StorageClass: WeakExternal (0x69)
+// CHECK-NEXT:    AuxSymbolCount: 1
+// CHECK-NEXT:    AuxWeakExternal {
+// CHECK-NEXT:      Linked: b (8)
+// CHECK-NEXT:      Search: AntiDependency (0x4)
+// CHECK-NEXT:    }
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Symbol {
+// CHECK-NEXT:    Name: b
+// CHECK-NEXT:    Value: 0
+// CHECK-NEXT:    Section: IMAGE_SYM_UNDEFINED (0)
+// CHECK-NEXT:    BaseType: Null (0x0)
+// CHECK-NEXT:    ComplexType: Null (0x0)
+// CHECK-NEXT:    StorageClass: External (0x2)
+// CHECK-NEXT:    AuxSymbolCount: 0
+// CHECK-NEXT:  }
+
+
+.weak_anti_dep r1
+.weak_anti_dep r2
+r1 = r2
+r2 = r1
+
+
+// CHECK:       Symbol {
+// CHECK-NEXT:    Name: r1
+// CHECK-NEXT:    Value: 0
+// CHECK-NEXT:    Section: IMAGE_SYM_UNDEFINED (0)
+// CHECK-NEXT:    BaseType: Null (0x0)
+// CHECK-NEXT:    ComplexType: Null (0x0)
+// CHECK-NEXT:    StorageClass: WeakExternal (0x69)
+// CHECK-NEXT:    AuxSymbolCount: 1
+// CHECK-NEXT:    AuxWeakExternal {
+// CHECK-NEXT:      Linked: r2 (11)
+// CHECK-NEXT:      Search: AntiDependency (0x4)
+// CHECK-NEXT:    }
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Symbol {
+// CHECK-NEXT:    Name: r2
+// CHECK-NEXT:    Value: 0
+// CHECK-NEXT:    Section: IMAGE_SYM_UNDEFINED (0)
+// CHECK-NEXT:    BaseType: Null (0x0)
+// CHECK-NEXT:    ComplexType: Null (0x0)
+// CHECK-NEXT:    StorageClass: WeakExternal (0x69)
+// CHECK-NEXT:    AuxSymbolCount: 1
+// CHECK-NEXT:    AuxWeakExternal {
+// CHECK-NEXT:      Linked: r1 (9)
+// CHECK-NEXT:      Search: AntiDependency (0x4)
+// CHECK-NEXT:    }
+// CHECK-NEXT:  }


        


More information about the llvm-commits mailing list