Index: llvm/include/llvm/MC/MCAsmInfo.h =================================================================== --- llvm/include/llvm/MC/MCAsmInfo.h +++ llvm/include/llvm/MC/MCAsmInfo.h @@ -322,9 +322,10 @@ /// symbol that can be hidden (unexported). Defaults to false. bool HasWeakDefCanBeHiddenDirective = false; - /// True if we have a .linkonce directive. This is used on cygwin/mingw. + /// True if we should mark symbols as global instead of weak, for + /// weak*/linkonce*, if the symbol has a comdat. /// Defaults to false. - bool HasLinkOnceDirective = false; + bool AvoidWeakIfComdat = false; /// True if we have a .lglobl directive, which is used to emit the information /// of a static symbol into the symbol table. Defaults to false. @@ -590,7 +591,7 @@ return HasWeakDefCanBeHiddenDirective; } - bool hasLinkOnceDirective() const { return HasLinkOnceDirective; } + bool avoidWeakIfComdat() const { return AvoidWeakIfComdat; } bool hasDotLGloblDirective() const { return HasDotLGloblDirective; } Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -414,7 +414,7 @@ OutStreamer->emitSymbolAttribute(GVSym, MCSA_WeakDefinition); else OutStreamer->emitSymbolAttribute(GVSym, MCSA_WeakDefAutoPrivate); - } else if (MAI->hasLinkOnceDirective()) { + } else if (MAI->avoidWeakIfComdat() && GV->hasComdat()) { // .globl _foo OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global); //NOTE: linkonce is handled by the section the symbol was assigned to. Index: llvm/lib/MC/MCAsmInfoCOFF.cpp =================================================================== --- llvm/lib/MC/MCAsmInfoCOFF.cpp +++ llvm/lib/MC/MCAsmInfoCOFF.cpp @@ -26,7 +26,7 @@ HasDotTypeDotSizeDirective = false; HasSingleParameterDotFile = true; WeakRefDirective = "\t.weak\t"; - HasLinkOnceDirective = true; + AvoidWeakIfComdat = true; // Doesn't support visibility: HiddenVisibilityAttr = HiddenDeclarationVisibilityAttr = MCSA_Invalid; Index: llvm/test/CodeGen/X86/coff-linkonce.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/coff-linkonce.ll @@ -0,0 +1,9 @@ +; RUN: llc -function-sections -o - %s | FileCheck %s + +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +; CHECK: .section{{.*}}one_only +define linkonce_odr void @foo() { + ret void +} Index: llvm/test/CodeGen/X86/coff-weak.ll =================================================================== --- llvm/test/CodeGen/X86/coff-weak.ll +++ llvm/test/CodeGen/X86/coff-weak.ll @@ -1,9 +1,50 @@ -; RUN: llc -function-sections -o - %s | FileCheck %s +; RUN: llc -mtriple=i686-windows-msvc -o - %s | FileCheck -check-prefix=X86 %s +; RUN: llc -mtriple=x86_64-windows-msvc -o - %s | FileCheck -check-prefix=X64 %s -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" +; X86: .weak _foo +; X64: .weak foo +define weak void @foo() { + ret void +} + +; X86: .weak _bar +; X64: .weak bar +define weak_odr void @bar() { + ret void +} + +; X86-NOT: .weak _bar_comdat +; X64-NOT: .weak bar_comdat +$bar_comdat = comdat any + +define weak_odr void @bar_comdat() comdat { + ret void +} + +; X86: .weak _baz +; X64: .weak baz +define linkonce void @baz() { + ret void +} + +; X86-NOT: .weak _baz_comdat +; X64-NOT: .weak baz_comdat +$baz_comdat = comdat any + +define linkonce void @baz_comdat() comdat { + ret void +} + +; X86: .weak _quux +; X64: .weak quux +define linkonce_odr void @quux() { + ret void +} + +; X86-NOT: .weak _quux_comdat +; X64-NOT: .weak quux_comdat +$quux_comdat = comdat any -; CHECK: .section{{.*}}one_only -define linkonce_odr void @foo() { +define linkonce_odr void @quux_comdat() comdat { ret void } Index: llvm/test/CodeGen/X86/dllexport-x86_64.ll =================================================================== --- llvm/test/CodeGen/X86/dllexport-x86_64.ll +++ llvm/test/CodeGen/X86/dllexport-x86_64.ll @@ -20,16 +20,20 @@ } ; CHECK: .globl lnk1 -define linkonce_odr dllexport void @lnk1() { +$lnk1 = comdat any + +define linkonce_odr dllexport void @lnk1() comdat { ret void } ; CHECK: .globl lnk2 -define linkonce_odr dllexport void @lnk2() alwaysinline { +$lnk2 = comdat any + +define linkonce_odr dllexport void @lnk2() alwaysinline comdat { ret void } -; CHECK: .globl weak1 +; CHECK: .weak weak1 define weak_odr dllexport void @weak1() { ret void } @@ -46,14 +50,14 @@ ; CHECK: .comm Var3 @Var3 = common dllexport global i32 0, align 4 -; CHECK: .globl WeakVar1 +; CHECK: .weak WeakVar1 @WeakVar1 = weak_odr dllexport global i32 1, align 4 -; CHECK: .globl WeakVar2 +; CHECK: .weak WeakVar2 @WeakVar2 = weak_odr dllexport unnamed_addr constant i32 1 ; CHECK: .bss -; CHECK: .globl WeakVar3 +; CHECK: .weak WeakVar3 @WeakVar3 = weak_odr dllexport global i32 0, align 4 Index: llvm/test/CodeGen/X86/dllexport.ll =================================================================== --- llvm/test/CodeGen/X86/dllexport.ll +++ llvm/test/CodeGen/X86/dllexport.ll @@ -45,16 +45,20 @@ } ; CHECK: .globl _lnk1 -define linkonce_odr dllexport void @lnk1() { +$lnk1 = comdat any + +define linkonce_odr dllexport void @lnk1() comdat { ret void } ; CHECK: .globl _lnk2 -define linkonce_odr dllexport void @lnk2() alwaysinline { +$lnk2 = comdat any + +define linkonce_odr dllexport void @lnk2() alwaysinline comdat { ret void } -; CHECK: .globl _weak1 +; CHECK: .weak _weak1 define weak_odr dllexport void @weak1() { ret void } @@ -71,10 +75,10 @@ ; CHECK: .comm _Var3 @Var3 = common dllexport global i32 0, align 4 -; CHECK: .globl _WeakVar1 +; CHECK: .weak _WeakVar1 @WeakVar1 = weak_odr dllexport global i32 1, align 4 -; CHECK: .globl _WeakVar2 +; CHECK: .weak _WeakVar2 @WeakVar2 = weak_odr dllexport unnamed_addr constant i32 1