diff options
author | Hans Wennborg <hans@hanshq.net> | 2014-06-06 20:04:01 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2014-06-06 20:04:01 +0000 |
commit | c94391d3bfb18ed6ec0989fad1cdf66afd1292f7 (patch) | |
tree | 79d3f58f5657986f0a5559f71854f6bc9e1c93b3 | |
parent | 0766ae08e58cb6358ed1ce407439bd3614380b2e (diff) | |
download | bcm5719-llvm-c94391d3bfb18ed6ec0989fad1cdf66afd1292f7.tar.gz bcm5719-llvm-c94391d3bfb18ed6ec0989fad1cdf66afd1292f7.zip |
MS ABI: Update the thunk linkage computation
As suggested by Reid:
- class has GVA_Internal linkage -> internal
- thunk has return adjustment -> weak_odr, to handle evil corner case [1]
- all other normal methods -> linkonce_odr
1. Evil corner case:
struct Incomplete;
struct A { int a; virtual A *bar(); };
struct B { int b; virtual B *foo(Incomplete); };
struct C : A, B { int c; virtual C *foo(Incomplete); };
C c;
Here, the thunk for C::foo() will be emitted when C::foo() is defined, which
might be in a different translation unit, so it needs to be weak_odr.
Differential Revision: http://reviews.llvm.org/D3992
llvm-svn: 210368
-rw-r--r-- | clang/lib/CodeGen/CGCXXABI.h | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVTables.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 15 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/dllimport.cpp | 2 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-structors.cpp | 2 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-thunks.cpp | 19 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp | 6 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp | 2 |
9 files changed, 41 insertions, 17 deletions
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index 615ec23aa7d..82687746eda 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -359,7 +359,8 @@ public: /// base tables. virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD) = 0; - virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) = 0; + virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, + GlobalDecl GD, bool ReturnAdjustment) = 0; virtual llvm::Value *performThisAdjustment(CodeGenFunction &CGF, llvm::Value *This, diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 8984a707c4f..91e6a18398b 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -382,12 +382,14 @@ void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk, // FIXME: Do something better here; GenerateVarArgsThunk is extremely ugly. if (!UseAvailableExternallyLinkage) { CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, Thunk); - CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable); + CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD, + !Thunk.Return.isEmpty()); } } else { // Normal thunk body generation. CodeGenFunction(CGM).GenerateThunk(ThunkFn, FnInfo, GD, Thunk); - CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable); + CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD, + !Thunk.Return.isEmpty()); } } diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 951174b4858..86eb36d8653 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -174,7 +174,8 @@ public: void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override; - void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) override { + void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD, + bool ReturnAdjustment) override { // Allow inlining of thunks by emitting them with available_externally // linkage together with vtables when needed. if (ForVTable) diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 5fd9e979487..ffcf76eb421 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -201,11 +201,20 @@ public: void emitVBTableDefinition(const VPtrInfo &VBT, const CXXRecordDecl *RD, llvm::GlobalVariable *GV) const; - void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) override { - Thunk->setLinkage(llvm::GlobalValue::WeakAnyLinkage); - + void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, + GlobalDecl GD, bool ReturnAdjustment) override { // Never dllimport/dllexport thunks. Thunk->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); + + GVALinkage Linkage = + getContext().GetGVALinkageForFunction(cast<FunctionDecl>(GD.getDecl())); + + if (Linkage == GVA_Internal) + Thunk->setLinkage(llvm::GlobalValue::InternalLinkage); + else if (ReturnAdjustment) + Thunk->setLinkage(llvm::GlobalValue::WeakODRLinkage); + else + Thunk->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage); } llvm::Value *performThisAdjustment(CodeGenFunction &CGF, llvm::Value *This, diff --git a/clang/test/CodeGenCXX/dllimport.cpp b/clang/test/CodeGenCXX/dllimport.cpp index 004c07e9f63..0295943fdea 100644 --- a/clang/test/CodeGenCXX/dllimport.cpp +++ b/clang/test/CodeGenCXX/dllimport.cpp @@ -566,7 +566,7 @@ namespace DontUseDtorAlias { namespace Vtordisp { // Don't dllimport the vtordisp. - // MO1-DAG: define weak x86_thiscallcc void @"\01?f@?$C@D@Vtordisp@@$4PPPPPPPM@A@AEXXZ" + // MO1-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@?$C@D@Vtordisp@@$4PPPPPPPM@A@AEXXZ" class Base { virtual void f() {} diff --git a/clang/test/CodeGenCXX/microsoft-abi-structors.cpp b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp index b79da8d6cb1..04227e311b0 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-structors.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp @@ -153,7 +153,7 @@ C::~C() { void foo() { C c; } -// DTORS2-LABEL: define weak x86_thiscallcc void @"\01??_EC@dtor_in_second_nvbase@@W3AEPAXI@Z" +// DTORS2-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_EC@dtor_in_second_nvbase@@W3AEPAXI@Z" // DTORS2: (%"struct.dtor_in_second_nvbase::C"* %this, i32 %should_call_delete) // Do an adjustment from B* to C*. // DTORS2: getelementptr i8* %{{.*}}, i32 -4 diff --git a/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp b/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp index 2be642c47d0..c755b300067 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp @@ -61,13 +61,13 @@ struct C : A, B { C::C() {} // Emits vftable and forces thunk generation. -// CODEGEN-LABEL: define weak x86_thiscallcc void @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete) +// CODEGEN-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete) // CODEGEN: getelementptr i8* {{.*}}, i32 -4 // FIXME: should actually call _EC, not _GC. // CODEGEN: call x86_thiscallcc void @"\01??_GC@@UAEPAXI@Z" // CODEGEN: ret -// CODEGEN-LABEL: define weak x86_thiscallcc void @"\01?public_f@C@@W3AEXXZ"(%struct.C* +// CODEGEN-LABEL: define linkonce_odr x86_thiscallcc void @"\01?public_f@C@@W3AEXXZ"(%struct.C* // CODEGEN: getelementptr i8* {{.*}}, i32 -4 // CODEGEN: call x86_thiscallcc void @"\01?public_f@C@@UAEXXZ"(%struct.C* // CODEGEN: ret @@ -91,7 +91,7 @@ struct E : D { E::E() {} // Emits vftable and forces thunk generation. -// CODEGEN-LABEL: define weak x86_thiscallcc %struct.C* @"\01?goo@E@@QAEPAUB@@XZ" +// CODEGEN-LABEL: define weak_odr x86_thiscallcc %struct.C* @"\01?goo@E@@QAEPAUB@@XZ" // CODEGEN: call x86_thiscallcc %struct.C* @"\01?goo@E@@UAEPAUC@@XZ" // CODEGEN: getelementptr inbounds i8* {{.*}}, i32 4 // CODEGEN: ret @@ -124,7 +124,7 @@ struct I : D { I::I() {} // Emits vftable and forces thunk generation. -// CODEGEN-LABEL: define weak x86_thiscallcc %struct.{{[BF]}}* @"\01?goo@I@@QAEPAUB@@XZ" +// CODEGEN-LABEL: define weak_odr x86_thiscallcc %struct.{{[BF]}}* @"\01?goo@I@@QAEPAUB@@XZ" // CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc %struct.F* @"\01?goo@I@@UAEPAUF@@XZ" // CODEGEN: %[[ORIG_RET_i8:.*]] = bitcast %struct.F* %[[ORIG_RET]] to i8* // CODEGEN: %[[VBPTR_i8:.*]] = getelementptr inbounds i8* %[[ORIG_RET_i8]], i32 4 @@ -152,3 +152,14 @@ struct C : A, B { }; C c; } + +namespace { +struct E : D { + E(); + virtual C* goo(); +}; +E::E() {} +E e; +// Class with internal linkage has internal linkage thunks. +// CODEGEN: define internal x86_thiscallcc %struct.C* @"\01?goo@E@?A@@QAEPAUB@@XZ" +} diff --git a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp index 5d118962472..a6fcdea749a 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp @@ -23,7 +23,7 @@ struct D : virtual C { D::D() {} // Forces vftable emission. -// CHECK-LABEL: define weak x86_thiscallcc void @"\01?f@D@@$4PPPPPPPM@A@AEXXZ" +// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@D@@$4PPPPPPPM@A@AEXXZ" // CHECK: %[[ECX:.*]] = load %struct.D** %{{.*}} // CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8* // CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr i8* %[[ECX_i8]], i32 -4 @@ -34,7 +34,7 @@ D::D() {} // Forces vftable emission. // CHECK: call x86_thiscallcc void @"\01?f@D@@UAEXXZ"(i8* %[[ADJUSTED_i8]]) // CHECK: ret void -// CHECK-LABEL: define weak x86_thiscallcc void @"\01?f@D@@$4PPPPPPPI@3AEXXZ" +// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@D@@$4PPPPPPPI@3AEXXZ" // CHECK: %[[ECX:.*]] = load %struct.D** %{{.*}} // CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8* // CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr i8* %[[ECX_i8]], i32 -8 @@ -63,7 +63,7 @@ struct G : virtual F, virtual E { G::G() {} // Forces vftable emission. -// CHECK-LABEL: define weak x86_thiscallcc void @"\01?f@E@@$R4BA@M@PPPPPPPM@7AEXXZ"(i8*) +// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@E@@$R4BA@M@PPPPPPPM@7AEXXZ"(i8*) // CHECK: %[[ECX:.*]] = load %struct.E** %{{.*}} // CHECK: %[[ECX_i8:.*]] = bitcast %struct.E* %[[ECX]] to i8* // CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr i8* %[[ECX_i8]], i32 -4 diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp index 6ef31769350..4ce4e9c2e17 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp @@ -145,7 +145,7 @@ struct X: virtual C { // MANGLING-DAG: @"\01??_7X@Test4@@6B@" // Also check the mangling of the thunk. - // MANGLING-DAG: define weak x86_thiscallcc void @"\01?f@C@@WPPPPPPPI@AEXXZ" + // MANGLING-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@C@@WPPPPPPPI@AEXXZ" }; X::X() {} |