diff --git a/llvm/include/llvm/MC/MCDirectives.h b/llvm/include/llvm/MC/MCDirectives.h --- a/llvm/include/llvm/MC/MCDirectives.h +++ b/llvm/include/llvm/MC/MCDirectives.h @@ -46,6 +46,7 @@ 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 --- a/llvm/include/llvm/MC/MCSymbol.h +++ b/llvm/include/llvm/MC/MCSymbol.h @@ -102,6 +102,9 @@ /// 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 @@ MCSymbol(SymbolKind Kind, const StringMapEntry *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 @@ 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 @@ 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 --- a/llvm/include/llvm/MC/MCSymbolCOFF.h +++ b/llvm/include/llvm/MC/MCSymbolCOFF.h @@ -23,8 +23,9 @@ 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 @@ modifyFlags(StorageClass << SF_ClassShift, SF_ClassMask); } - bool isWeakExternal() const { - return getFlags() & SF_WeakExternal; + COFF::WeakExternalCharacteristics getWeakExternalCharacteristics() const { + return static_cast((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 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -772,6 +772,9 @@ 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 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -216,6 +216,7 @@ 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 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -761,6 +761,9 @@ } static bool canExpand(const MCSymbol &Sym, bool InSet) { + if (Sym.isWeakExternal()) + return false; + const MCExpr *Expr = Sym.getVariableValue(); const auto *Inner = dyn_cast(Expr); if (Inner) { diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp --- a/llvm/lib/MC/MCMachOStreamer.cpp +++ b/llvm/lib/MC/MCMachOStreamer.cpp @@ -358,6 +358,7 @@ 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 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -6371,7 +6371,7 @@ case MCExpr::SymbolRef: { const MCSymbol &S = static_cast(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 --- a/llvm/lib/MC/MCParser/COFFAsmParser.cpp +++ b/llvm/lib/MC/MCParser/COFFAsmParser.cpp @@ -67,6 +67,7 @@ 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::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { MCSymbolAttr Attr = StringSwitch(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 --- a/llvm/lib/MC/MCWinCOFFStreamer.cpp +++ b/llvm/lib/MC/MCWinCOFFStreamer.cpp @@ -115,7 +115,11 @@ 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 --- a/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -414,9 +414,9 @@ 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(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 --- 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 @@ .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 --- a/llvm/test/MC/COFF/alias.s +++ b/llvm/test/MC/COFF/alias.s @@ -24,7 +24,7 @@ // 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 --- /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: }