Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -404,7 +404,8 @@ case GlobalValue::LinkOnceAnyLinkage: case GlobalValue::LinkOnceODRLinkage: case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: + case GlobalValue::WeakODRLinkage: { + const Triple &TT = TM.getTargetTriple(); if (MAI->hasWeakDefDirective()) { // .globl _foo OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global); @@ -414,6 +415,13 @@ OutStreamer->emitSymbolAttribute(GVSym, MCSA_WeakDefinition); else OutStreamer->emitSymbolAttribute(GVSym, MCSA_WeakDefAutoPrivate); + } else if (TT.isOSWindows() && TT.isOSBinFormatCOFF() && !GV->hasComdat()) { + // hasLinkOnceDirective is true for COFF, but the linkonce directive + // can only be expressed if the symbol is associated with a comdat group. + // Thus emit weak if we can't express the intent with a linkonce + // directive. + // .weak _foo + OutStreamer->emitSymbolAttribute(GVSym, MCSA_Weak); } else if (MAI->hasLinkOnceDirective()) { // .globl _foo OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global); @@ -423,6 +431,7 @@ OutStreamer->emitSymbolAttribute(GVSym, MCSA_Weak); } return; + } case GlobalValue::ExternalLinkage: // If external, declare as a global symbol: .globl _foo OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global); 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