[llvm] r360207 - [COFF] Use COFF stubs for extern_weak functions
Reid Kleckner via llvm-commits
llvm-commits at lists.llvm.org
Tue May 7 16:06:21 PDT 2019
Author: rnk
Date: Tue May 7 16:06:21 2019
New Revision: 360207
URL: http://llvm.org/viewvc/llvm-project?rev=360207&view=rev
Log:
[COFF] Use COFF stubs for extern_weak functions
Summary:
A COFF stub indirects the reference to a symbol through memory. A
.refptr.$sym global variable pointer is created to refer to $sym.
Typically mingw uses these for external global variable declarations,
but we can use them for weak function declarations as well.
Updates the dso_local classification to add a special case for
extern_weak symbols on COFF in both clang and LLVM.
Fixes PR37598
Reviewers: smeenai, mstorsjo
Subscribers: hiraditya, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D61615
Modified:
llvm/trunk/lib/Target/TargetMachine.cpp
llvm/trunk/lib/Target/X86/X86FastISel.cpp
llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
llvm/trunk/lib/Target/X86/X86Subtarget.cpp
llvm/trunk/test/CodeGen/X86/extern_weak.ll
Modified: llvm/trunk/lib/Target/TargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/TargetMachine.cpp?rev=360207&r1=360206&r2=360207&view=diff
==============================================================================
--- llvm/trunk/lib/Target/TargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/TargetMachine.cpp Tue May 7 16:06:21 2019
@@ -144,6 +144,12 @@ bool TargetMachine::shouldAssumeDSOLocal
isa<GlobalVariable>(GV))
return false;
+ // On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols
+ // remain unresolved in the link, they can be resolved to zero, which is
+ // outside the current DSO.
+ if (TT.isOSBinFormatCOFF() && GV && GV->hasExternalWeakLinkage())
+ return false;
+
// Every other GV is local on COFF.
// Make an exception for windows OS in the triple: Some firmware builds use
// *-win32-macho triples. This (accidentally?) produced windows relocations
Modified: llvm/trunk/lib/Target/X86/X86FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FastISel.cpp?rev=360207&r1=360206&r2=360207&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86FastISel.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86FastISel.cpp Tue May 7 16:06:21 2019
@@ -3503,8 +3503,9 @@ bool X86FastISel::fastLowerCall(CallLowe
// This will be a direct call, or an indirect call through memory for
// NonLazyBind calls or dllimport calls.
- bool NeedLoad =
- OpFlags == X86II::MO_DLLIMPORT || OpFlags == X86II::MO_GOTPCREL;
+ bool NeedLoad = OpFlags == X86II::MO_DLLIMPORT ||
+ OpFlags == X86II::MO_GOTPCREL ||
+ OpFlags == X86II::MO_COFFSTUB;
unsigned CallOpc = NeedLoad
? (Is64Bit ? X86::CALL64m : X86::CALL32m)
: (Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32);
Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=360207&r1=360206&r2=360207&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue May 7 16:06:21 2019
@@ -3969,10 +3969,10 @@ X86TargetLowering::LowerCall(TargetLower
Callee = DAG.getTargetGlobalAddress(
GV, dl, getPointerTy(DAG.getDataLayout()), G->getOffset(), OpFlags);
- if (OpFlags == X86II::MO_GOTPCREL) {
+ if (isGlobalStubReference(OpFlags)) {
// Add a wrapper.
- Callee = DAG.getNode(X86ISD::WrapperRIP, dl,
- getPointerTy(DAG.getDataLayout()), Callee);
+ Callee = DAG.getNode(getGlobalWrapperKind(GV, OpFlags), dl,
+ getPointerTy(DAG.getDataLayout()), Callee);
// Add extra indirection
Callee = DAG.getLoad(
getPointerTy(DAG.getDataLayout()), dl, DAG.getEntryNode(), Callee,
@@ -3987,9 +3987,9 @@ X86TargetLowering::LowerCall(TargetLower
Callee = DAG.getTargetExternalSymbol(
S->getSymbol(), getPointerTy(DAG.getDataLayout()), OpFlags);
- if (OpFlags == X86II::MO_GOTPCREL) {
- Callee = DAG.getNode(X86ISD::WrapperRIP, dl,
- getPointerTy(DAG.getDataLayout()), Callee);
+ if (isGlobalStubReference(OpFlags)) {
+ Callee = DAG.getNode(getGlobalWrapperKind(nullptr, OpFlags), dl,
+ getPointerTy(DAG.getDataLayout()), Callee);
Callee = DAG.getLoad(
getPointerTy(DAG.getDataLayout()), dl, DAG.getEntryNode(), Callee,
MachinePointerInfo::getGOT(DAG.getMachineFunction()));
Modified: llvm/trunk/lib/Target/X86/X86Subtarget.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.cpp?rev=360207&r1=360206&r2=360207&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86Subtarget.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86Subtarget.cpp Tue May 7 16:06:21 2019
@@ -176,10 +176,13 @@ X86Subtarget::classifyGlobalFunctionRefe
if (TM.shouldAssumeDSOLocal(M, GV))
return X86II::MO_NO_FLAG;
+ // Functions on COFF can be non-DSO local for two reasons:
+ // - They are marked dllimport
+ // - They are extern_weak, and a stub is needed
if (isTargetCOFF()) {
- assert(GV->hasDLLImportStorageClass() &&
- "shouldAssumeDSOLocal gave inconsistent answer");
- return X86II::MO_DLLIMPORT;
+ if (GV->hasDLLImportStorageClass())
+ return X86II::MO_DLLIMPORT;
+ return X86II::MO_COFFSTUB;
}
const Function *F = dyn_cast_or_null<Function>(GV);
Modified: llvm/trunk/test/CodeGen/X86/extern_weak.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/extern_weak.ll?rev=360207&r1=360206&r2=360207&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/extern_weak.ll (original)
+++ llvm/trunk/test/CodeGen/X86/extern_weak.ll Tue May 7 16:06:21 2019
@@ -1,13 +1,64 @@
-; RUN: llc < %s -mtriple=i686-apple-darwin | grep weak_reference | count 2
+; RUN: llc < %s -mtriple=i686-apple-darwin | FileCheck %s --check-prefix=DARWIN
+; RUN: llc < %s -mtriple=i686-windows-msvc | FileCheck %s --check-prefix=WIN32
+; RUN: llc < %s -mtriple=x86_64-windows-msvc | FileCheck %s --check-prefix=WIN64
- at Y = global i32 (i8*)* @X ; <i32 (i8*)**> [#uses=0]
-
-declare extern_weak i32 @X(i8*)
+declare extern_weak void @foo(...)
define void @bar() {
- tail call void (...) @foo( )
- ret void
+entry:
+ br i1 icmp ne (void (...)* @foo, void (...)* null), label %if.then, label %if.end
+
+if.then:
+ tail call void (...) @foo( )
+ ret void
+
+if.end:
+ ret void
}
-declare extern_weak void @foo(...)
+; DARWIN-LABEL: _bar:
+; DARWIN: cmpl $0, L_foo$non_lazy_ptr
+; DARWIN: jmp _foo ## TAILCALL
+
+; WIN32-LABEL: _bar:
+; WIN32: cmpl $0, .refptr._foo
+; WIN32: jmpl *.refptr._foo
+
+; WIN64-LABEL: bar:
+; WIN64: cmpq $0, .refptr.foo(%rip)
+; WIN64: jmpq *.refptr.foo
+
+
+declare extern_weak i32 @X(i8*)
+
+ at Y = global i32 (i8*)* @X ; <i32 (i8*)**> [#uses=0]
+
+; DARWIN-LABEL: _Y:
+; DARWIN: .long _X
+
+; WIN32-LABEL: _Y:
+; WIN32: .long _X
+
+; WIN64-LABEL: Y:
+; WIN64: .quad X
+
+
+; DARWIN: .weak_reference _foo
+; DARWIN: .weak_reference _X
+
+; WIN32: .section .rdata$.refptr._foo,"dr",discard,.refptr._foo
+; WIN32: .globl .refptr._foo
+; WIN32: .refptr._foo:
+; WIN32: .long _foo
+
+; WIN32: .weak _foo
+; WIN32: .weak _X
+
+; WIN64: .section .rdata$.refptr.foo,"dr",discard,.refptr.foo
+; WIN64: .globl .refptr.foo
+; WIN64: .refptr.foo:
+; WIN64: .quad foo
+
+; WIN64: .weak foo
+; WIN64: .weak X
More information about the llvm-commits
mailing list