lebedev.ri updated this revision to Diff 339757.
lebedev.ri added a comment.
@rsmith i was able to make some forward progress here.
What do you think about this?
(I haven't updated all tests because i don't want to waste hours doing that if
this is still wrong)
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D100388/new/
https://reviews.llvm.org/D100388
Files:
clang/include/clang/AST/VTableBuilder.h
clang/include/clang/Basic/ABI.h
clang/include/clang/Basic/Thunk.h
clang/lib/AST/ItaniumMangle.cpp
clang/lib/AST/MicrosoftMangle.cpp
clang/lib/AST/VTableBuilder.cpp
clang/lib/CodeGen/CGVTables.cpp
clang/lib/CodeGen/CodeGenFunction.h
clang/lib/CodeGen/MicrosoftCXXABI.cpp
clang/test/CodeGen/available-externally-hidden.cpp
clang/test/CodeGenCXX/RelativeVTablesABI/diamond-inheritance.cpp
clang/test/CodeGenCXX/RelativeVTablesABI/multiple-inheritance.cpp
clang/test/CodeGenCXX/thunk-linkonce-odr.cpp
clang/test/CodeGenCXX/thunk-returning-memptr.cpp
clang/test/CodeGenCXX/thunk-wrong-return-type.cpp
clang/test/CodeGenCXX/thunk-wrong-this.cpp
clang/test/CodeGenCXX/thunks.cpp
Index: clang/test/CodeGenCXX/thunks.cpp
===================================================================
--- clang/test/CodeGenCXX/thunks.cpp
+++ clang/test/CodeGenCXX/thunks.cpp
@@ -410,7 +410,7 @@
// CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -32
// CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -24
// CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 8
- // CHECK: ret %"struct.Test13::D"*
+ // CHECK: ret %"struct.Test13::B1"*
// WIN64-LABEL: define weak_odr dso_local nonnull align 8 dereferenceable(8) %"struct.Test13::D"* @"?foo1@D@Test13@@$4PPPPPPPE@A@EAAAEAUB1@2@XZ"(
// This adjustment.
Index: clang/test/CodeGenCXX/thunk-wrong-this.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/thunk-wrong-this.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple %itanium_abi_triple %s -emit-llvm -o - %s | FileCheck %s
+
+class Base1 {
+ virtual void Foo1();
+};
+
+class Base2 {
+ virtual void Foo2();
+};
+
+class alignas(16) Obj : public Base1, public Base2 {
+ void Foo1() override;
+ void Foo2() override;
+ ~Obj();
+};
+
+void Obj::Foo1() {}
+void Obj::Foo2() {}
+
+// CHECK: define dso_local void @_ZThn8_N3Obj4Foo2Ev(%class.Base2.2* nonnull dereferenceable(8) %this) #1 align 2 {
+// CHECK: tail call void @_ZN3Obj4Foo2Ev(%class.Obj.0* nonnull dereferenceable(16) %3)
Index: clang/test/CodeGenCXX/thunk-wrong-return-type.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/thunk-wrong-return-type.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple %itanium_abi_triple %s -emit-llvm -o - %s | FileCheck %s
+
+struct A {};
+struct alignas(32) B : virtual A {
+ char c[32];
+};
+struct Pad {
+ char c[7];
+};
+struct C : B, Pad, virtual A {};
+
+struct X {
+ virtual A &f();
+};
+struct U {
+ virtual ~U();
+};
+C c;
+struct Y : U, X {
+ virtual B &f() override { return c; }
+};
+
+Y y;
+
+// CHECK: define linkonce_odr nonnull align 1 dereferenceable(1) %struct.A.8* @_ZTchn8_v0_n24_N1Y1fEv(%struct.X.7* nonnull dereferenceable(8) %this.coerce) #1 comdat align 2 {
Index: clang/test/CodeGenCXX/thunk-returning-memptr.cpp
===================================================================
--- clang/test/CodeGenCXX/thunk-returning-memptr.cpp
+++ clang/test/CodeGenCXX/thunk-returning-memptr.cpp
@@ -23,5 +23,5 @@
// Because of the tail call, the return value cannot be copied into a local
// alloca. (PR39901)
-// CHECK-LABEL: define linkonce_odr void @_ZThn4_N1C1fEv({ i32, i32 }* noalias sret({ i32, i32 }) align 4 %agg.result, %struct.C* {{[^,]*}} %this)
+// CHECK-LABEL: define linkonce_odr void @_ZThn4_N1C1fEv({ i32, i32 }* noalias sret({ i32, i32 }) align 4 %agg.result, %struct.B* {{[^,]*}} %this.coerce)
// CHECK: tail call void @_ZN1C1fEv({ i32, i32 }* sret({ i32, i32 }) align 4 %agg.result
Index: clang/test/CodeGenCXX/thunk-linkonce-odr.cpp
===================================================================
--- clang/test/CodeGenCXX/thunk-linkonce-odr.cpp
+++ clang/test/CodeGenCXX/thunk-linkonce-odr.cpp
@@ -29,5 +29,5 @@
// Thunks should be marked as "linkonce ODR" not "weak".
//
-// CHECK: define linkonce_odr i32 @_ZThn{{[48]}}_N1D1fEv
// CHECK: define linkonce_odr i32 @_ZThn{{[48]}}_N1C1fEv
+// CHECK: define linkonce_odr i32 @_ZThn{{[48]}}_N1D1fEv
Index: clang/test/CodeGenCXX/RelativeVTablesABI/multiple-inheritance.cpp
===================================================================
--- clang/test/CodeGenCXX/RelativeVTablesABI/multiple-inheritance.cpp
+++ clang/test/CodeGenCXX/RelativeVTablesABI/multiple-inheritance.cpp
@@ -9,7 +9,7 @@
// VTable for C contains 2 sub-vtables (represented as 2 structs). The first contains the components for B and the second contains the components for C. The RTTI ptr in both arrays still point to the RTTI struct for C.
// The component for bar() instead points to a thunk which redirects to C::bar() which overrides B::bar().
// Now that we have a class with 2 parents, the offset to top in the second array is non-zero.
-// CHECK: @_ZTV1C.local = private unnamed_addr constant { [4 x i32], [3 x i32] } { [4 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1C.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZN1C3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZN1C3barEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 0, i32 2) to i64)) to i32)], [3 x i32] [i32 -8, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1C.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 1, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZThn8_N1C3barEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 1, i32 2) to i64)) to i32)] }, align 4
+// CHECK: @_ZTV1C.local = private unnamed_addr constant { [4 x i32], [3 x i32] } { [4 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1C.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZN1C3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZN1C3barEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 0, i32 2) to i64)) to i32)], [3 x i32] [i32 -8, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1C.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 1, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.B*)* dso_local_equivalent @_ZThn8_N1C3barEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 1, i32 2) to i64)) to i32)] }, align 4
// CHECK: @_ZTV1C ={{.*}} unnamed_addr alias { [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local
Index: clang/test/CodeGenCXX/RelativeVTablesABI/diamond-inheritance.cpp
===================================================================
--- clang/test/CodeGenCXX/RelativeVTablesABI/diamond-inheritance.cpp
+++ clang/test/CodeGenCXX/RelativeVTablesABI/diamond-inheritance.cpp
@@ -18,7 +18,7 @@
// vtable contains 2 inner vtables:
// - 1st table containing D::foo(), B::barB(), and D::baz().
// - 2nd table containing a thunk to D::foo() and C::barC().
-// CHECK: @_ZTV1D.local = private unnamed_addr constant { [5 x i32], [4 x i32] } { [5 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.D*)* dso_local_equivalent @_ZN1D3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.B*)* dso_local_equivalent @_ZN1B4barBEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.D*)* dso_local_equivalent @_ZN1D3bazEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32)], [4 x i32] [i32 -8, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 1, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.D*)* dso_local_equivalent @_ZThn8_N1D3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 1, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZN1C4barCEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 1, i32 2) to i64)) to i32)] }, align 4
+// CHECK: @_ZTV1D.local = private unnamed_addr constant { [5 x i32], [4 x i32] } { [5 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.D*)* dso_local_equivalent @_ZN1D3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.B*)* dso_local_equivalent @_ZN1B4barBEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.D*)* dso_local_equivalent @_ZN1D3bazEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32)], [4 x i32] [i32 -8, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 1, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.A*)* dso_local_equivalent @_ZThn8_N1D3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 1, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZN1C4barCEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 1, i32 2) to i64)) to i32)] }, align 4
// @_ZTV1B ={{.*}} unnamed_addr alias { [4 x i32] }, { [4 x i32] }* @_ZTV1B.local
// @_ZTV1C ={{.*}} unnamed_addr alias { [4 x i32] }, { [4 x i32] }* @_ZTV1C.local
Index: clang/test/CodeGen/available-externally-hidden.cpp
===================================================================
--- clang/test/CodeGen/available-externally-hidden.cpp
+++ clang/test/CodeGen/available-externally-hidden.cpp
@@ -21,6 +21,7 @@
class SyncMessageFilter : public Filter, public Sender {
public:
bool Send(Message* message) override;
+ // expected-error@-1 {{cannot compile this thunk for forward declaration yet}}
};
class TestSyncMessageFilter : public SyncMessageFilter {
Index: clang/lib/CodeGen/MicrosoftCXXABI.cpp
===================================================================
--- clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -2084,7 +2084,7 @@
CGF.Builder.CreateAlignedLoad(ThunkTy->getPointerTo(), VFuncPtr,
CGF.getPointerAlign());
- CGF.EmitMustTailThunk(MD, getThisValue(CGF), {ThunkTy, Callee});
+ CGF.EmitMustTailThunk(MD, getThisValue(CGF), FnInfo, {ThunkTy, Callee});
return ThunkFn;
}
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2170,18 +2170,21 @@
const CGFunctionInfo &FnInfo, bool IsUnprototyped);
void EmitCallAndReturnForThunk(llvm::FunctionCallee Callee,
- const ThunkInfo *Thunk, bool IsUnprototyped);
+ const CGFunctionInfo &CalleeFnInfo,
+ GlobalDecl CalleeGD, const ThunkInfo *Thunk,
+ bool IsUnprototyped);
void FinishThunk();
/// Emit a musttail call for a thunk with a potentially adjusted this pointer.
- void EmitMustTailThunk(GlobalDecl GD, llvm::Value *AdjustedThisPtr,
+ void EmitMustTailThunk(GlobalDecl CalleeGD, llvm::Value *AdjustedThisPtr,
+ const CGFunctionInfo &CalleeFnInfo,
llvm::FunctionCallee Callee);
/// Generate a thunk for the given method.
- void generateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo,
- GlobalDecl GD, const ThunkInfo &Thunk,
- bool IsUnprototyped);
+ void generateThunk(llvm::Function *ThunkFn, const CGFunctionInfo &ThunkFnInfo,
+ GlobalDecl ThunkGD, GlobalDecl CalleeGD,
+ const ThunkInfo &Thunk, bool IsUnprototyped);
llvm::Function *GenerateVarArgsThunk(llvm::Function *Fn,
const CGFunctionInfo &FnInfo,
Index: clang/lib/CodeGen/CGVTables.cpp
===================================================================
--- clang/lib/CodeGen/CGVTables.cpp
+++ clang/lib/CodeGen/CGVTables.cpp
@@ -163,8 +163,12 @@
// Get the original function
assert(FnInfo.isVariadic());
- llvm::Type *Ty = CGM.getTypes().GetFunctionType(FnInfo);
- llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
+
+ const CGFunctionInfo &CalleeFnInfo =
+ CGM.getTypes().arrangeGlobalDeclaration(GD);
+ llvm::FunctionType *CalleeFnTy = CGM.getTypes().GetFunctionType(CalleeFnInfo);
+ llvm::Constant *Callee =
+ CGM.GetAddrOfFunction(GD, CalleeFnTy, /*ForVTable=*/true);
llvm::Function *BaseFn = cast<llvm::Function>(Callee);
// Cloning can't work if we don't have a definition. The Microsoft ABI may
@@ -183,7 +187,7 @@
// Ensure that the value mapper does not encounter any of them.
resolveTopLevelMetadata(BaseFn, VMap);
llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap);
- Fn->replaceAllUsesWith(NewFn);
+ Fn->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(NewFn, Fn->getType()));
NewFn->takeName(Fn);
Fn->eraseFromParent();
Fn = NewFn;
@@ -289,9 +293,9 @@
FinishFunction();
}
-void CodeGenFunction::EmitCallAndReturnForThunk(llvm::FunctionCallee Callee,
- const ThunkInfo *Thunk,
- bool IsUnprototyped) {
+void CodeGenFunction::EmitCallAndReturnForThunk(
+ llvm::FunctionCallee Callee, const CGFunctionInfo &CalleeFnInfo,
+ GlobalDecl CalleeGD, const ThunkInfo *Thunk, bool IsUnprototyped) {
assert(isa<CXXMethodDecl>(CurGD.getDecl()) &&
"Please use a new CGF for this thunk");
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CurGD.getDecl());
@@ -317,14 +321,15 @@
CGM.ErrorUnsupported(
MD, "non-trivial argument copy for return-adjusting thunk");
}
- EmitMustTailThunk(CurGD, AdjustedThisPtr, Callee);
+ EmitMustTailThunk(CalleeGD, AdjustedThisPtr, CalleeFnInfo, Callee);
return;
}
// Start building CallArgs.
CallArgList CallArgs;
- QualType ThisType = MD->getThisType();
- CallArgs.add(RValue::get(AdjustedThisPtr), ThisType);
+ QualType CalleeThisType =
+ cast<CXXMethodDecl>(CalleeGD.getDecl())->getThisType();
+ CallArgs.add(RValue::get(AdjustedThisPtr), CalleeThisType);
if (isa<CXXDestructorDecl>(MD))
CGM.getCXXABI().adjustCallArgsForDestructorThunk(*this, CurGD, CallArgs);
@@ -356,11 +361,10 @@
#endif
// Determine whether we have a return value slot to use.
- QualType ResultType = CGM.getCXXABI().HasThisReturn(CurGD)
- ? ThisType
- : CGM.getCXXABI().hasMostDerivedReturn(CurGD)
- ? CGM.getContext().VoidPtrTy
- : FPT->getReturnType();
+ QualType ResultType = CGM.getCXXABI().HasThisReturn(CurGD) ? CalleeThisType
+ : CGM.getCXXABI().hasMostDerivedReturn(CurGD)
+ ? CGM.getContext().VoidPtrTy
+ : FPT->getReturnType();
ReturnValueSlot Slot;
if (!ResultType->isVoidType() &&
(CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect ||
@@ -370,8 +374,8 @@
// Now emit our call.
llvm::CallBase *CallOrInvoke;
- RValue RV = EmitCall(*CurFnInfo, CGCallee::forDirect(Callee, CurGD), Slot,
- CallArgs, &CallOrInvoke);
+ RValue RV = EmitCall(CalleeFnInfo, CGCallee::forDirect(Callee, CalleeGD),
+ Slot, CallArgs, &CallOrInvoke);
// Consider return adjustment if we have ThunkInfo.
if (Thunk && !Thunk->Return.isEmpty())
@@ -380,8 +384,12 @@
Call->setTailCallKind(llvm::CallInst::TCK_Tail);
// Emit return.
- if (!ResultType->isVoidType() && Slot.isNull())
+ if (!ResultType->isVoidType() && Slot.isNull()) {
+ if (RV.getScalarVal())
+ RV = RValue::get(
+ Builder.CreateBitCast(RV.getScalarVal(), CurFn->getReturnType()));
CGM.getCXXABI().EmitReturnFromThunk(*this, RV, ResultType);
+ }
// Disable the final ARC autorelease.
AutoreleaseResult = false;
@@ -389,8 +397,9 @@
FinishThunk();
}
-void CodeGenFunction::EmitMustTailThunk(GlobalDecl GD,
+void CodeGenFunction::EmitMustTailThunk(GlobalDecl CalleeGD,
llvm::Value *AdjustedThisPtr,
+ const CGFunctionInfo &CalleeFnInfo,
llvm::FunctionCallee Callee) {
// Emitting a musttail call thunk doesn't use any of the CGCall.cpp machinery
// to translate AST arguments into LLVM IR arguments. For thunks, we know
@@ -401,11 +410,11 @@
Args.push_back(&A);
// Set the adjusted 'this' pointer.
- const ABIArgInfo &ThisAI = CurFnInfo->arg_begin()->info;
+ const ABIArgInfo &ThisAI = CalleeFnInfo.arg_begin()->info;
if (ThisAI.isDirect()) {
- const ABIArgInfo &RetAI = CurFnInfo->getReturnInfo();
+ const ABIArgInfo &RetAI = CalleeFnInfo.getReturnInfo();
int ThisArgNo = RetAI.isIndirect() && !RetAI.isSRetAfterThis() ? 1 : 0;
- llvm::Type *ThisType = Args[ThisArgNo]->getType();
+ llvm::Type *ThisType = Callee.getFunctionType()->getParamType(ThisArgNo);
if (ThisType != AdjustedThisPtr->getType())
AdjustedThisPtr = Builder.CreateBitCast(AdjustedThisPtr, ThisType);
Args[ThisArgNo] = AdjustedThisPtr;
@@ -426,15 +435,16 @@
// Apply the standard set of call attributes.
unsigned CallingConv;
llvm::AttributeList Attrs;
- CGM.ConstructAttributeList(Callee.getCallee()->getName(), *CurFnInfo, GD,
- Attrs, CallingConv, /*AttrOnCallSite=*/true);
+ CGM.ConstructAttributeList(Callee.getCallee()->getName(), CalleeFnInfo,
+ CalleeGD, Attrs, CallingConv,
+ /*AttrOnCallSite=*/true);
Call->setAttributes(Attrs);
Call->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
if (Call->getType()->isVoidTy())
Builder.CreateRetVoid();
else
- Builder.CreateRet(Call);
+ Builder.CreateRet(Builder.CreateBitCast(Call, CurFn->getReturnType()));
// Finish the function to maintain CodeGenFunction invariants.
// FIXME: Don't emit unreachable code.
@@ -443,31 +453,34 @@
FinishThunk();
}
-void CodeGenFunction::generateThunk(llvm::Function *Fn,
- const CGFunctionInfo &FnInfo, GlobalDecl GD,
+void CodeGenFunction::generateThunk(llvm::Function *ThunkFn,
+ const CGFunctionInfo &ThunkFnInfo,
+ GlobalDecl ThunkGD, GlobalDecl CalleeGD,
const ThunkInfo &Thunk,
bool IsUnprototyped) {
- StartThunk(Fn, GD, FnInfo, IsUnprototyped);
+ StartThunk(ThunkFn, ThunkGD, ThunkFnInfo, IsUnprototyped);
// Create a scope with an artificial location for the body of this function.
auto AL = ApplyDebugLocation::CreateArtificial(*this);
- // Get our callee. Use a placeholder type if this method is unprototyped so
- // that CodeGenModule doesn't try to set attributes.
- llvm::Type *Ty;
- if (IsUnprototyped)
- Ty = llvm::StructType::get(getLLVMContext());
- else
- Ty = CGM.getTypes().GetFunctionType(FnInfo);
+ auto *CalleeMD = cast<CXXMethodDecl>(CalleeGD.getDecl());
+ if (!CalleeMD->isDefined()) {
+ CGM.ErrorUnsupported(ThunkGD.getDecl(), "thunk for forward declaration");
+ return;
+ }
- llvm::Constant *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
+ const CGFunctionInfo &CalleeFnInfo =
+ CGM.getTypes().arrangeGlobalDeclaration(CalleeGD);
+ llvm::FunctionType *CalleeFnTy = CGM.getTypes().GetFunctionType(CalleeFnInfo);
+ llvm::Constant *Callee =
+ CGM.GetAddrOfFunction(CalleeGD, CalleeFnTy, /*ForVTable=*/true);
// Fix up the function type for an unprototyped musttail call.
if (IsUnprototyped)
- Callee = llvm::ConstantExpr::getBitCast(Callee, Fn->getType());
+ Callee = llvm::ConstantExpr::getBitCast(Callee, CalleeFnTy);
// Make the call and return the result.
- EmitCallAndReturnForThunk(llvm::FunctionCallee(Fn->getFunctionType(), Callee),
- &Thunk, IsUnprototyped);
+ EmitCallAndReturnForThunk(llvm::FunctionCallee(CalleeFnTy, Callee),
+ CalleeFnInfo, CalleeGD, &Thunk, IsUnprototyped);
}
static bool shouldEmitVTableThunk(CodeGenModule &CGM, const CXXMethodDecl *MD,
@@ -503,21 +516,25 @@
MCtx.mangleCXXDtorThunk(DD, GD.getDtorType(), TI.This, Out);
else
MCtx.mangleThunk(MD, TI, Out);
+
llvm::Type *ThunkVTableTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
llvm::Constant *Thunk = CGM.GetAddrOfThunk(Name, ThunkVTableTy, GD);
// If we don't need to emit a definition, return this declaration as is.
bool IsUnprototyped = !CGM.getTypes().isFuncTypeConvertible(
- MD->getType()->castAs<FunctionType>());
+ cast<CXXMethodDecl>(TI.BaseMethod.getDecl())
+ ->getType()
+ ->castAs<FunctionType>());
if (!shouldEmitVTableThunk(CGM, MD, IsUnprototyped, ForVTable))
return Thunk;
- // Arrange a function prototype appropriate for a function definition. In some
+ // Arrange a thunk function prototype appropriate for a function def. In some
// cases in the MS ABI, we may need to build an unprototyped musttail thunk.
- const CGFunctionInfo &FnInfo =
- IsUnprototyped ? CGM.getTypes().arrangeUnprototypedMustTailThunk(MD)
- : CGM.getTypes().arrangeGlobalDeclaration(GD);
- llvm::FunctionType *ThunkFnTy = CGM.getTypes().GetFunctionType(FnInfo);
+ const CGFunctionInfo &ThunkFnInfo =
+ IsUnprototyped ? CGM.getTypes().arrangeUnprototypedMustTailThunk(
+ cast<CXXMethodDecl>(TI.BaseMethod.getDecl()))
+ : CGM.getTypes().arrangeGlobalDeclaration(TI.BaseMethod);
+ llvm::FunctionType *ThunkFnTy = CGM.getTypes().GetFunctionType(ThunkFnInfo);
// If the type of the underlying GlobalValue is wrong, we'll have to replace
// it. It should be a declaration.
@@ -525,13 +542,15 @@
if (ThunkFn->getFunctionType() != ThunkFnTy) {
llvm::GlobalValue *OldThunkFn = ThunkFn;
- assert(OldThunkFn->isDeclaration() && "Shouldn't replace non-declaration");
+ // FIXME: ???
+ // assert(OldThunkFn->isDeclaration() && "Shouldn't replace
+ // non-declaration");
// Remove the name from the old thunk function and get a new thunk.
OldThunkFn->setName(StringRef());
ThunkFn = llvm::Function::Create(ThunkFnTy, llvm::Function::ExternalLinkage,
Name.str(), &CGM.getModule());
- CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn);
+ CGM.SetLLVMFunctionAttributes(GD, ThunkFnInfo, ThunkFn);
// If needed, replace the old thunk with a bitcast.
if (!OldThunkFn->use_empty()) {
@@ -564,7 +583,7 @@
if (IsUnprototyped)
ThunkFn->addFnAttr("thunk");
- CGM.SetLLVMFunctionAttributesForDefinition(GD.getDecl(), ThunkFn);
+ CGM.SetLLVMFunctionAttributesForDefinition(MD, ThunkFn);
// Thunks for variadic methods are special because in general variadic
// arguments cannot be perfectly forwarded. In the general case, clang
@@ -591,10 +610,11 @@
if (UseAvailableExternallyLinkage)
return ThunkFn;
ThunkFn =
- CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, TI);
+ CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, ThunkFnInfo, GD, TI);
} else {
// Normal thunk body generation.
- CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, TI, IsUnprototyped);
+ CodeGenFunction(CGM).generateThunk(ThunkFn, ThunkFnInfo, TI.BaseMethod, GD,
+ TI, IsUnprototyped);
}
setThunkProperties(CGM, TI, ThunkFn, ForVTable, GD);
@@ -727,22 +747,7 @@
case VTableComponent::CK_FunctionPointer:
case VTableComponent::CK_CompleteDtorPointer:
case VTableComponent::CK_DeletingDtorPointer: {
- GlobalDecl GD;
-
- // Get the right global decl.
- switch (component.getKind()) {
- default:
- llvm_unreachable("Unexpected vtable component kind");
- case VTableComponent::CK_FunctionPointer:
- GD = component.getFunctionDecl();
- break;
- case VTableComponent::CK_CompleteDtorPointer:
- GD = GlobalDecl(component.getDestructorDecl(), Dtor_Complete);
- break;
- case VTableComponent::CK_DeletingDtorPointer:
- GD = GlobalDecl(component.getDestructorDecl(), Dtor_Deleting);
- break;
- }
+ GlobalDecl GD = component.getGlobalDecl();
if (CGM.getLangOpts().CUDA) {
// Emit NULL for methods we can't codegen on this
Index: clang/lib/AST/VTableBuilder.cpp
===================================================================
--- clang/lib/AST/VTableBuilder.cpp
+++ clang/lib/AST/VTableBuilder.cpp
@@ -913,7 +913,8 @@
/// AddMethod - Add a single virtual member function to the vtable
/// components vector.
- void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment);
+ void AddMethod(const CXXMethodDecl *BaseMethod, const CXXMethodDecl *MD,
+ ReturnAdjustment ReturnAdjustment);
/// IsOverriderUsed - Returns whether the overrider will ever be used in this
/// part of the vtable.
@@ -1115,10 +1116,12 @@
// Ignore adjustments for unused function pointers.
uint64_t VTableIndex = MethodInfo.VTableIndex;
- if (Components[VTableIndex].getKind() ==
- VTableComponent::CK_UnusedFunctionPointer)
+ const VTableComponent &component = Components[VTableIndex];
+ if (component.getKind() == VTableComponent::CK_UnusedFunctionPointer)
continue;
+ GlobalDecl GD = component.getGlobalDecl();
+
// Get the final overrider for this method.
FinalOverriders::OverriderInfo Overrider =
Overriders.getOverrider(MD, MethodInfo.BaseOffset);
@@ -1130,7 +1133,8 @@
// While the thunk itself might be needed by vtables in subclasses or
// in construction vtables, there doesn't seem to be a reason for using
// the thunk in this vtable. Still, we do so to match gcc.
- if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
+ auto it = VTableThunks.find(VTableIndex);
+ if (it == VTableThunks.end() || it->second.Return.isEmpty())
continue;
}
@@ -1140,12 +1144,33 @@
if (ThisAdjustment.isEmpty())
continue;
- // Add it.
- VTableThunks[VTableIndex].This = ThisAdjustment;
+ auto ApplyThisAdjustment = [&](unsigned Idx) {
+ Optional<ThunkInfo> TI;
+
+ auto it = VTableThunks.find(Idx);
+ if (it != VTableThunks.end()) {
+ TI = it->second;
+ TI->This = ThisAdjustment;
+ } else {
+ GlobalDecl BaseMethod;
+ if (auto *DD = dyn_cast<CXXDestructorDecl>(MD))
+ BaseMethod = GlobalDecl(DD, GD.getDtorType());
+ else
+ BaseMethod = MD;
+
+ TI = {BaseMethod, ThisAdjustment, ReturnAdjustment()};
+ }
+
+ // Override it. Note that there may or may not be a thunk already.
+ VTableThunks.erase(Idx);
+ VTableThunks.insert({Idx, *TI});
+ };
+
+ ApplyThisAdjustment(VTableIndex);
if (isa<CXXDestructorDecl>(MD)) {
// Add an adjustment for the deleting destructor as well.
- VTableThunks[VTableIndex + 1].This = ThisAdjustment;
+ ApplyThisAdjustment(VTableIndex + 1);
}
}
@@ -1300,7 +1325,8 @@
return Adjustment;
}
-void ItaniumVTableBuilder::AddMethod(const CXXMethodDecl *MD,
+void ItaniumVTableBuilder::AddMethod(const CXXMethodDecl *BaseMethod,
+ const CXXMethodDecl *MD,
ReturnAdjustment ReturnAdjustment) {
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
assert(ReturnAdjustment.isEmpty() &&
@@ -1311,8 +1337,13 @@
Components.push_back(VTableComponent::MakeDeletingDtor(DD));
} else {
// Add the return adjustment if necessary.
- if (!ReturnAdjustment.isEmpty())
- VTableThunks[Components.size()].Return = ReturnAdjustment;
+ if (!ReturnAdjustment.isEmpty()) {
+ assert(VTableThunks.find(Components.size()) == VTableThunks.end() &&
+ "ZZZ");
+ VTableThunks.insert(
+ {Components.size(),
+ ThunkInfo(BaseMethod, ThisAdjustment(), ReturnAdjustment)});
+ }
// Add the function.
Components.push_back(VTableComponent::MakeFunction(MD));
@@ -1513,6 +1544,10 @@
MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
OverriddenMethodInfo.VTableIndex);
+ uint64_t VTableIndex = MethodInfo.VTableIndex;
+ const VTableComponent &component = Components[VTableIndex];
+ GlobalDecl GD = component.getGlobalDecl();
+
assert(!MethodInfoMap.count(MD) &&
"Should not have method info for this method yet!");
@@ -1540,9 +1575,15 @@
ReturnAdjustment ReturnAdjustment =
ComputeReturnAdjustment(ReturnAdjustmentOffset);
+ GlobalDecl BaseMethod;
+ if (auto *DD = dyn_cast<CXXDestructorDecl>(MD))
+ BaseMethod = GlobalDecl(DD, GD.getDtorType());
+ else
+ BaseMethod = MD;
+
// This is a virtual thunk for the most derived class, add it.
AddThunk(Overrider.Method,
- ThunkInfo(ThisAdjustment, ReturnAdjustment));
+ ThunkInfo(BaseMethod, ThisAdjustment, ReturnAdjustment));
}
}
@@ -1608,7 +1649,7 @@
ReturnAdjustment ReturnAdjustment =
ComputeReturnAdjustment(ReturnAdjustmentOffset);
- AddMethod(Overrider.Method, ReturnAdjustment);
+ AddMethod(MD, Overrider.Method, ReturnAdjustment);
}
}
@@ -1958,8 +1999,9 @@
if (MD->isDeleted())
Out << " [deleted]";
- ThunkInfo Thunk = VTableThunks.lookup(I);
- if (!Thunk.isEmpty()) {
+ auto it = VTableThunks.find(I);
+ if (it != VTableThunks.end()) {
+ ThunkInfo Thunk = it->second;
// If this function pointer has a return adjustment, dump it.
if (!Thunk.Return.isEmpty()) {
Out << "\n [return adjustment: ";
@@ -2006,8 +2048,9 @@
if (DD->isPure())
Out << " [pure]";
- ThunkInfo Thunk = VTableThunks.lookup(I);
- if (!Thunk.isEmpty()) {
+ auto it = VTableThunks.find(I);
+ if (it != VTableThunks.end()) {
+ ThunkInfo Thunk = it->second;
// If this destructor has a 'this' pointer adjustment, dump it.
if (!Thunk.This.isEmpty()) {
Out << "\n [this adjustment: ";
@@ -2120,7 +2163,6 @@
ThunkInfoVectorTy ThunksVector = Thunks[MD];
llvm::sort(ThunksVector, [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
- assert(LHS.Method == nullptr && RHS.Method == nullptr);
return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return);
});
@@ -2513,18 +2555,29 @@
/// AddMethod - Add a single virtual member function to the vftable
/// components vector.
- void AddMethod(const CXXMethodDecl *MD, ThunkInfo TI) {
- if (!TI.isEmpty()) {
- VTableThunks[Components.size()] = TI;
- AddThunk(MD, TI);
- }
+ void AddMethod(const CXXMethodDecl *BaseMD, const CXXMethodDecl *MD,
+ ThisAdjustment This, ReturnAdjustment Return) {
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- assert(TI.Return.isEmpty() &&
- "Destructor can't have return adjustment!");
+ assert(Return.isEmpty() && "Destructor can't have return adjustment!");
Components.push_back(VTableComponent::MakeDeletingDtor(DD));
} else {
Components.push_back(VTableComponent::MakeFunction(MD));
}
+
+ GlobalDecl GD;
+ if (isa<CXXDestructorDecl>(BaseMD))
+ GD = GlobalDecl(cast<CXXDestructorDecl>(BaseMD),
+ CXXDtorType::Dtor_Deleting);
+ else
+ GD = BaseMD;
+
+ ThunkInfo TI(GD, This, Return);
+ if (!TI.isEmpty()) {
+ assert(VTableThunks.find(Components.size() - 1) == VTableThunks.end() &&
+ "ZZZ");
+ VTableThunks.insert({Components.size() - 1, TI});
+ AddThunk(MD, TI);
+ }
}
/// AddMethods - Add the methods of this base subobject and the relevant
@@ -3091,9 +3144,7 @@
}
}
- AddMethod(FinalOverriderMD,
- ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
- ForceReturnAdjustmentMangling ? MD : nullptr));
+ AddMethod(MD, FinalOverriderMD, ThisAdjustmentOffset, ReturnAdjustment);
}
}
@@ -3111,11 +3162,14 @@
const ReturnAdjustment &R = TI.Return;
bool Multiline = false;
const char *LinePrefix = "\n ";
- if (!R.isEmpty() || TI.Method) {
+ if (!R.isEmpty()) {
if (!ContinueFirstLine)
Out << LinePrefix;
Out << "[return adjustment (to type '"
- << TI.Method->getReturnType().getCanonicalType().getAsString()
+ << cast<CXXMethodDecl>(TI.BaseMethod.getDecl())
+ ->getReturnType()
+ .getCanonicalType()
+ .getAsString()
<< "'): ";
if (R.Virtual.Microsoft.VBPtrOffset)
Out << "vbptr at offset " << R.Virtual.Microsoft.VBPtrOffset << ", ";
@@ -3179,9 +3233,11 @@
if (MD->isDeleted())
Out << " [deleted]";
- ThunkInfo Thunk = VTableThunks.lookup(I);
- if (!Thunk.isEmpty())
+ auto it = VTableThunks.find(I);
+ if (it != VTableThunks.end()) {
+ ThunkInfo Thunk = it->second;
dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/false);
+ }
break;
}
@@ -3195,8 +3251,9 @@
if (DD->isPure())
Out << " [pure]";
- ThunkInfo Thunk = VTableThunks.lookup(I);
- if (!Thunk.isEmpty()) {
+ auto it = VTableThunks.find(I);
+ if (it != VTableThunks.end()) {
+ ThunkInfo Thunk = it->second;
assert(Thunk.Return.isEmpty() &&
"No return adjustment needed for destructors!");
dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/false);
Index: clang/lib/AST/MicrosoftMangle.cpp
===================================================================
--- clang/lib/AST/MicrosoftMangle.cpp
+++ clang/lib/AST/MicrosoftMangle.cpp
@@ -3466,13 +3466,10 @@
AccessSpecifier AS = Thunk.Return.isEmpty() ? MD->getAccess() : AS_public;
mangleThunkThisAdjustment(AS, Thunk.This, Mangler, MHO);
- if (!Thunk.Return.isEmpty())
- assert(Thunk.Method != nullptr &&
- "Thunk info should hold the overridee decl");
-
- const CXXMethodDecl *DeclForFPT = Thunk.Method ? Thunk.Method : MD;
- Mangler.mangleFunctionType(
- DeclForFPT->getType()->castAs<FunctionProtoType>(), MD);
+ Mangler.mangleFunctionType(cast<FunctionDecl>(Thunk.BaseMethod.getDecl())
+ ->getType()
+ ->castAs<FunctionProtoType>(),
+ MD);
}
void MicrosoftMangleContextImpl::mangleCXXDtorThunk(
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -14,7 +14,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/Mangle.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
@@ -23,14 +22,16 @@
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
-#include "clang/AST/ExprConcepts.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprConcepts.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Mangle.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Thunk.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
Index: clang/include/clang/Basic/Thunk.h
===================================================================
--- /dev/null
+++ clang/include/clang/Basic/Thunk.h
@@ -0,0 +1,181 @@
+//===----- Thunk.h - Declarations related to VTable Thunks ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Enums/classes describing THUNK related information about constructors,
+/// destructors and thunks.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_THUNK_H
+#define LLVM_CLANG_BASIC_THUNK_H
+
+#include "clang/AST/GlobalDecl.h"
+
+namespace clang {
+
+/// A return adjustment.
+struct ReturnAdjustment {
+ /// The non-virtual adjustment from the derived object to its
+ /// nearest virtual base.
+ int64_t NonVirtual;
+
+ /// Holds the ABI-specific information about the virtual return
+ /// adjustment, if needed.
+ union VirtualAdjustment {
+ // Itanium ABI
+ struct {
+ /// The offset (in bytes), relative to the address point
+ /// of the virtual base class offset.
+ int64_t VBaseOffsetOffset;
+ } Itanium;
+
+ // Microsoft ABI
+ struct {
+ /// The offset (in bytes) of the vbptr, relative to the beginning
+ /// of the derived class.
+ uint32_t VBPtrOffset;
+
+ /// Index of the virtual base in the vbtable.
+ uint32_t VBIndex;
+ } Microsoft;
+
+ VirtualAdjustment() { memset(this, 0, sizeof(*this)); }
+
+ bool Equals(const VirtualAdjustment &Other) const {
+ return memcmp(this, &Other, sizeof(Other)) == 0;
+ }
+
+ bool isEmpty() const {
+ VirtualAdjustment Zero;
+ return Equals(Zero);
+ }
+
+ bool Less(const VirtualAdjustment &RHS) const {
+ return memcmp(this, &RHS, sizeof(RHS)) < 0;
+ }
+ } Virtual;
+
+ ReturnAdjustment() : NonVirtual(0) {}
+
+ bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
+
+ friend bool operator==(const ReturnAdjustment &LHS,
+ const ReturnAdjustment &RHS) {
+ return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
+ }
+
+ friend bool operator!=(const ReturnAdjustment &LHS,
+ const ReturnAdjustment &RHS) {
+ return !(LHS == RHS);
+ }
+
+ friend bool operator<(const ReturnAdjustment &LHS,
+ const ReturnAdjustment &RHS) {
+ if (LHS.NonVirtual < RHS.NonVirtual)
+ return true;
+
+ return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
+ }
+};
+
+/// A \c this pointer adjustment.
+struct ThisAdjustment {
+ /// The non-virtual adjustment from the derived object to its
+ /// nearest virtual base.
+ int64_t NonVirtual;
+
+ /// Holds the ABI-specific information about the virtual this
+ /// adjustment, if needed.
+ union VirtualAdjustment {
+ // Itanium ABI
+ struct {
+ /// The offset (in bytes), relative to the address point,
+ /// of the virtual call offset.
+ int64_t VCallOffsetOffset;
+ } Itanium;
+
+ struct {
+ /// The offset of the vtordisp (in bytes), relative to the ECX.
+ int32_t VtordispOffset;
+
+ /// The offset of the vbptr of the derived class (in bytes),
+ /// relative to the ECX after vtordisp adjustment.
+ int32_t VBPtrOffset;
+
+ /// The offset (in bytes) of the vbase offset in the vbtable.
+ int32_t VBOffsetOffset;
+ } Microsoft;
+
+ VirtualAdjustment() { memset(this, 0, sizeof(*this)); }
+
+ bool Equals(const VirtualAdjustment &Other) const {
+ return memcmp(this, &Other, sizeof(Other)) == 0;
+ }
+
+ bool isEmpty() const {
+ VirtualAdjustment Zero;
+ return Equals(Zero);
+ }
+
+ bool Less(const VirtualAdjustment &RHS) const {
+ return memcmp(this, &RHS, sizeof(RHS)) < 0;
+ }
+ } Virtual;
+
+ ThisAdjustment() : NonVirtual(0) {}
+
+ bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
+
+ friend bool operator==(const ThisAdjustment &LHS, const ThisAdjustment &RHS) {
+ return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
+ }
+
+ friend bool operator!=(const ThisAdjustment &LHS, const ThisAdjustment &RHS) {
+ return !(LHS == RHS);
+ }
+
+ friend bool operator<(const ThisAdjustment &LHS, const ThisAdjustment &RHS) {
+ if (LHS.NonVirtual < RHS.NonVirtual)
+ return true;
+
+ return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
+ }
+};
+
+/// The \c this pointer adjustment as well as an optional return
+/// adjustment for a thunk.
+struct ThunkInfo {
+ /// Holds a pointer to the overridden (i.e. base) method this thunk is for.
+ /// CAUTION: In the unlikely event you need to sort ThunkInfos, consider using
+ /// an ABI-specific comparator.
+ GlobalDecl BaseMethod;
+
+ /// The \c this pointer adjustment.
+ ThisAdjustment This;
+
+ /// The return adjustment.
+ ReturnAdjustment Return;
+
+ ThunkInfo() = delete;
+
+ ThunkInfo(GlobalDecl BaseMethod, const ThisAdjustment &This,
+ const ReturnAdjustment &Return)
+ : BaseMethod(BaseMethod), This(This), Return(Return) {}
+
+ friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) {
+ return LHS.BaseMethod == RHS.BaseMethod && LHS.This == RHS.This &&
+ LHS.Return == RHS.Return;
+ }
+
+ bool isEmpty() const { return This.isEmpty() && Return.isEmpty(); }
+};
+
+} // end namespace clang
+
+#endif
Index: clang/include/clang/Basic/ABI.h
===================================================================
--- clang/include/clang/Basic/ABI.h
+++ clang/include/clang/Basic/ABI.h
@@ -37,174 +37,6 @@
Dtor_Comdat ///< The COMDAT used for dtors
};
-/// A return adjustment.
-struct ReturnAdjustment {
- /// The non-virtual adjustment from the derived object to its
- /// nearest virtual base.
- int64_t NonVirtual;
-
- /// Holds the ABI-specific information about the virtual return
- /// adjustment, if needed.
- union VirtualAdjustment {
- // Itanium ABI
- struct {
- /// The offset (in bytes), relative to the address point
- /// of the virtual base class offset.
- int64_t VBaseOffsetOffset;
- } Itanium;
-
- // Microsoft ABI
- struct {
- /// The offset (in bytes) of the vbptr, relative to the beginning
- /// of the derived class.
- uint32_t VBPtrOffset;
-
- /// Index of the virtual base in the vbtable.
- uint32_t VBIndex;
- } Microsoft;
-
- VirtualAdjustment() {
- memset(this, 0, sizeof(*this));
- }
-
- bool Equals(const VirtualAdjustment &Other) const {
- return memcmp(this, &Other, sizeof(Other)) == 0;
- }
-
- bool isEmpty() const {
- VirtualAdjustment Zero;
- return Equals(Zero);
- }
-
- bool Less(const VirtualAdjustment &RHS) const {
- return memcmp(this, &RHS, sizeof(RHS)) < 0;
- }
- } Virtual;
-
- ReturnAdjustment() : NonVirtual(0) {}
-
- bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
-
- friend bool operator==(const ReturnAdjustment &LHS,
- const ReturnAdjustment &RHS) {
- return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
- }
-
- friend bool operator!=(const ReturnAdjustment &LHS, const ReturnAdjustment &RHS) {
- return !(LHS == RHS);
- }
-
- friend bool operator<(const ReturnAdjustment &LHS,
- const ReturnAdjustment &RHS) {
- if (LHS.NonVirtual < RHS.NonVirtual)
- return true;
-
- return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
- }
-};
-
-/// A \c this pointer adjustment.
-struct ThisAdjustment {
- /// The non-virtual adjustment from the derived object to its
- /// nearest virtual base.
- int64_t NonVirtual;
-
- /// Holds the ABI-specific information about the virtual this
- /// adjustment, if needed.
- union VirtualAdjustment {
- // Itanium ABI
- struct {
- /// The offset (in bytes), relative to the address point,
- /// of the virtual call offset.
- int64_t VCallOffsetOffset;
- } Itanium;
-
- struct {
- /// The offset of the vtordisp (in bytes), relative to the ECX.
- int32_t VtordispOffset;
-
- /// The offset of the vbptr of the derived class (in bytes),
- /// relative to the ECX after vtordisp adjustment.
- int32_t VBPtrOffset;
-
- /// The offset (in bytes) of the vbase offset in the vbtable.
- int32_t VBOffsetOffset;
- } Microsoft;
-
- VirtualAdjustment() {
- memset(this, 0, sizeof(*this));
- }
-
- bool Equals(const VirtualAdjustment &Other) const {
- return memcmp(this, &Other, sizeof(Other)) == 0;
- }
-
- bool isEmpty() const {
- VirtualAdjustment Zero;
- return Equals(Zero);
- }
-
- bool Less(const VirtualAdjustment &RHS) const {
- return memcmp(this, &RHS, sizeof(RHS)) < 0;
- }
- } Virtual;
-
- ThisAdjustment() : NonVirtual(0) { }
-
- bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
-
- friend bool operator==(const ThisAdjustment &LHS,
- const ThisAdjustment &RHS) {
- return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
- }
-
- friend bool operator!=(const ThisAdjustment &LHS, const ThisAdjustment &RHS) {
- return !(LHS == RHS);
- }
-
- friend bool operator<(const ThisAdjustment &LHS,
- const ThisAdjustment &RHS) {
- if (LHS.NonVirtual < RHS.NonVirtual)
- return true;
-
- return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
- }
-};
-
-class CXXMethodDecl;
-
-/// The \c this pointer adjustment as well as an optional return
-/// adjustment for a thunk.
-struct ThunkInfo {
- /// The \c this pointer adjustment.
- ThisAdjustment This;
-
- /// The return adjustment.
- ReturnAdjustment Return;
-
- /// Holds a pointer to the overridden method this thunk is for,
- /// if needed by the ABI to distinguish different thunks with equal
- /// adjustments. Otherwise, null.
- /// CAUTION: In the unlikely event you need to sort ThunkInfos, consider using
- /// an ABI-specific comparator.
- const CXXMethodDecl *Method;
-
- ThunkInfo() : Method(nullptr) { }
-
- ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return,
- const CXXMethodDecl *Method = nullptr)
- : This(This), Return(Return), Method(Method) {}
-
- friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) {
- return LHS.This == RHS.This && LHS.Return == RHS.Return &&
- LHS.Method == RHS.Method;
- }
-
- bool isEmpty() const {
- return This.isEmpty() && Return.isEmpty() && Method == nullptr;
- }
-};
-
} // end namespace clang
#endif
Index: clang/include/clang/AST/VTableBuilder.h
===================================================================
--- clang/include/clang/AST/VTableBuilder.h
+++ clang/include/clang/AST/VTableBuilder.h
@@ -18,6 +18,7 @@
#include "clang/AST/GlobalDecl.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/ABI.h"
+#include "clang/Basic/Thunk.h"
#include "llvm/ADT/DenseMap.h"
#include <memory>
#include <utility>
@@ -253,7 +254,7 @@
OwningArrayRef<VTableComponent> VTableComponents;
/// Contains thunks needed by vtables, sorted by indices.
- OwningArrayRef<VTableThunkTy> VTableThunks;
+ std::vector<VTableThunkTy> VTableThunks;
/// Address points for all vtables.
AddressPointsMapTy AddressPoints;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits