[cfe-commits] r173035 - in /cfe/trunk: include/clang/AST/VTableBuilder.h lib/AST/VTableBuilder.cpp lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGenCXX/microsoft-abi-constructors.cpp test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
Timur Iskhodzhanov
timurrrr at google.com
Mon Jan 21 05:02:42 PST 2013
Author: timurrrr
Date: Mon Jan 21 07:02:41 2013
New Revision: 173035
URL: http://llvm.org/viewvc/llvm-project?rev=173035&view=rev
Log:
First step towards vftable generation with -cxx-abi microsoft PR13231
Added:
cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp (with props)
Modified:
cfe/trunk/include/clang/AST/VTableBuilder.h
cfe/trunk/lib/AST/VTableBuilder.cpp
cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
cfe/trunk/test/CodeGenCXX/microsoft-abi-constructors.cpp
Modified: cfe/trunk/include/clang/AST/VTableBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/VTableBuilder.h?rev=173035&r1=173034&r2=173035&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/VTableBuilder.h (original)
+++ cfe/trunk/include/clang/AST/VTableBuilder.h Mon Jan 21 07:02:41 2013
@@ -215,12 +215,15 @@
/// Address points - Address points for all vtables.
AddressPointsMapTy AddressPoints;
+ bool IsMicrosoftABI;
+
public:
VTableLayout(uint64_t NumVTableComponents,
const VTableComponent *VTableComponents,
uint64_t NumVTableThunks,
const VTableThunkTy *VTableThunks,
- const AddressPointsMapTy &AddressPoints);
+ const AddressPointsMapTy &AddressPoints,
+ bool IsMicrosoftABI);
~VTableLayout();
uint64_t getNumVTableComponents() const {
@@ -252,7 +255,7 @@
"Did not find address point!");
uint64_t AddressPoint = AddressPoints.lookup(Base);
- assert(AddressPoint && "Address point must not be zero!");
+ assert(AddressPoint != 0 || IsMicrosoftABI);
return AddressPoint;
}
@@ -271,6 +274,8 @@
typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
private:
+ bool IsMicrosoftABI;
+
/// MethodVTableIndices - Contains the index (relative to the vtable address
/// point) where the function pointer for a virtual function is stored.
typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
@@ -306,10 +311,21 @@
/// given record decl.
void ComputeVTableRelatedInformation(const CXXRecordDecl *RD);
+ /// ErrorUnsupported - Print out an error that the v-table layout code
+ /// doesn't support the particular C++ feature yet.
+ void ErrorUnsupported(StringRef Feature, SourceLocation Location);
+
public:
- VTableContext(ASTContext &Context) : Context(Context) {}
+ VTableContext(ASTContext &Context);
~VTableContext();
+ bool isMicrosoftABI() const {
+ // FIXME: Currently, this method is only used in the VTableContext and
+ // VTableBuilder code which is ABI-specific. Probably we can remove it
+ // when we add a layer of abstraction for vtable generation.
+ return IsMicrosoftABI;
+ }
+
const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) {
ComputeVTableRelatedInformation(RD);
assert(VTableLayouts.count(RD) && "No layout for this record decl!");
Modified: cfe/trunk/lib/AST/VTableBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/VTableBuilder.cpp?rev=173035&r1=173034&r2=173035&view=diff
==============================================================================
--- cfe/trunk/lib/AST/VTableBuilder.cpp (original)
+++ cfe/trunk/lib/AST/VTableBuilder.cpp Mon Jan 21 07:02:41 2013
@@ -1002,6 +1002,10 @@
dumpLayout(llvm::errs());
}
+ bool isMicrosoftABI() const {
+ return VTables.isMicrosoftABI();
+ }
+
uint64_t getNumThunks() const {
return Thunks.size();
}
@@ -1296,9 +1300,18 @@
assert(ReturnAdjustment.isEmpty() &&
"Destructor can't have return adjustment!");
- // Add both the complete destructor and the deleting destructor.
- Components.push_back(VTableComponent::MakeCompleteDtor(DD));
- Components.push_back(VTableComponent::MakeDeletingDtor(DD));
+ // FIXME: Should probably add a layer of abstraction for vtable generation.
+ if (!isMicrosoftABI()) {
+ // Add both the complete destructor and the deleting destructor.
+ Components.push_back(VTableComponent::MakeCompleteDtor(DD));
+ Components.push_back(VTableComponent::MakeDeletingDtor(DD));
+ } else {
+ // Add only one destructor in MS mode.
+ // FIXME: The virtual destructors are handled differently in MS ABI,
+ // we should add such a support later. For now, put the complete
+ // destructor into the vftable just to make its layout right.
+ Components.push_back(VTableComponent::MakeCompleteDtor(DD));
+ }
} else {
// Add the return adjustment if necessary.
if (!ReturnAdjustment.isEmpty())
@@ -1613,14 +1626,19 @@
if (Base.getBase() == MostDerivedClass)
VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
- // Add the offset to top.
- CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
- Components.push_back(
- VTableComponent::MakeOffsetToTop(OffsetToTop));
-
- // Next, add the RTTI.
- Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
-
+ // FIXME: Should probably add a layer of abstraction for vtable generation.
+ if (!isMicrosoftABI()) {
+ // Add the offset to top.
+ CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
+ Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop));
+
+ // Next, add the RTTI.
+ Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
+ } else {
+ // FIXME: unclear what to do with RTTI in MS ABI as emitting it anywhere
+ // breaks the vftable layout. Just skip RTTI for now, can't mangle anyway.
+ }
+
uint64_t AddressPoint = Components.size();
// Now go through all virtual member functions and add them.
@@ -2121,10 +2139,16 @@
MD);
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Complete))] =
- MethodName + " [complete]";
- IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))] =
- MethodName + " [deleting]";
+ // FIXME: Should add a layer of abstraction for vtable generation.
+ if (!isMicrosoftABI()) {
+ IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Complete))]
+ = MethodName + " [complete]";
+ IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))]
+ = MethodName + " [deleting]";
+ } else {
+ IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Complete))]
+ = MethodName;
+ }
} else {
IndicesMap[VTables.getMethodVTableIndex(MD)] = MethodName;
}
@@ -2155,12 +2179,14 @@
const VTableComponent *VTableComponents,
uint64_t NumVTableThunks,
const VTableThunkTy *VTableThunks,
- const AddressPointsMapTy &AddressPoints)
+ const AddressPointsMapTy &AddressPoints,
+ bool IsMicrosoftABI)
: NumVTableComponents(NumVTableComponents),
VTableComponents(new VTableComponent[NumVTableComponents]),
NumVTableThunks(NumVTableThunks),
VTableThunks(new VTableThunkTy[NumVTableThunks]),
- AddressPoints(AddressPoints) {
+ AddressPoints(AddressPoints),
+ IsMicrosoftABI(IsMicrosoftABI) {
std::copy(VTableComponents, VTableComponents+NumVTableComponents,
this->VTableComponents.get());
std::copy(VTableThunks, VTableThunks+NumVTableThunks,
@@ -2169,6 +2195,10 @@
VTableLayout::~VTableLayout() { }
+VTableContext::VTableContext(ASTContext &Context)
+ : Context(Context),
+ IsMicrosoftABI(Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft) { }
+
VTableContext::~VTableContext() {
llvm::DeleteContainerSeconds(VTableLayouts);
}
@@ -2240,12 +2270,17 @@
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
const CXXDestructorDecl *OverriddenDD =
cast<CXXDestructorDecl>(OverriddenMD);
-
- // Add both the complete and deleting entries.
- MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] =
- getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Complete));
- MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] =
- getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting));
+
+ if (!isMicrosoftABI()) {
+ // Add both the complete and deleting entries.
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] =
+ getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Complete));
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] =
+ getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting));
+ } else {
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] =
+ getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Complete));
+ }
} else {
MethodVTableIndices[MD] = getMethodVTableIndex(OverriddenMD);
}
@@ -2263,11 +2298,19 @@
continue;
}
- // Add the complete dtor.
- MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
-
- // Add the deleting dtor.
- MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
+ if (!isMicrosoftABI()) {
+ // Add the complete dtor.
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
+
+ // Add the deleting dtor.
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
+ } else {
+ // Add only the deleting dtor.
+ // FIXME: The virtual destructors are handled differently in MS ABI,
+ // we should add such a support later. For now, put the complete
+ // destructor into the vftable indices.
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
+ }
} else {
// Add the entry.
MethodVTableIndices[MD] = CurrentIndex++;
@@ -2279,6 +2322,11 @@
// If a class has an implicitly-defined virtual destructor,
// its entries come after the declared virtual function pointers.
+ if (isMicrosoftABI()) {
+ ErrorUnsupported("implicit virtual destructor in the Microsoft ABI",
+ ImplicitVirtualDtor->getLocation());
+ }
+
// Add the complete dtor.
MethodVTableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Complete)] =
CurrentIndex++;
@@ -2358,7 +2406,8 @@
Builder.vtable_component_begin(),
VTableThunks.size(),
VTableThunks.data(),
- Builder.getAddressPoints());
+ Builder.getAddressPoints(),
+ Builder.isMicrosoftABI());
}
void VTableContext::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) {
@@ -2398,6 +2447,14 @@
}
}
+void VTableContext::ErrorUnsupported(StringRef Feature,
+ SourceLocation Location) {
+ clang::DiagnosticsEngine &Diags = Context.getDiagnostics();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "v-table layout for %0 is not supported yet");
+ Diags.Report(Context.getFullLoc(Location), DiagID) << Feature;
+}
+
VTableLayout *VTableContext::createConstructionVTableLayout(
const CXXRecordDecl *MostDerivedClass,
CharUnits MostDerivedClassOffset,
Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=173035&r1=173034&r2=173035&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Mon Jan 21 07:02:41 2013
@@ -207,7 +207,7 @@
}
void MicrosoftCXXABI::EmitVTables(const CXXRecordDecl *Class) {
- // FIXME: implement
+ CGM.getVTables().GenerateClassData(CGM.getVTableLinkage(Class), Class);
}
CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-constructors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-constructors.cpp?rev=173035&r1=173034&r2=173035&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-constructors.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-constructors.cpp Mon Jan 21 07:02:41 2013
@@ -22,3 +22,14 @@
// CHECK: ret
}
+struct B {
+ virtual ~B();
+ virtual void foo();
+};
+
+void check_vftable_offset() {
+ B b;
+// The vftable pointer should point at the beginning of the vftable.
+// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %struct.B* {{.*}} to i8***
+// CHECK: store i8** getelementptr inbounds ([2 x i8*]* @"\01??_7B@@6B@", i64 0, i64 0), i8*** [[THIS_PTR]]
+}
Added: cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp?rev=173035&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp Mon Jan 21 07:02:41 2013
@@ -0,0 +1,113 @@
+// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -fdump-vtable-layouts -o - > %t 2>&1
+// RUN: FileCheck --check-prefix=EMITS-VTABLE %s < %t
+// RUN: FileCheck --check-prefix=CHECK-A %s < %t
+// RUN: FileCheck --check-prefix=CHECK-B %s < %t
+// RUN: FileCheck --check-prefix=CHECK-C %s < %t
+// RUN: FileCheck --check-prefix=CHECK-D %s < %t
+// RUN: FileCheck --check-prefix=CHECK-E %s < %t
+// RUN: FileCheck --check-prefix=CHECK-F %s < %t
+// RUN: FileCheck --check-prefix=CHECK-G %s < %t
+
+struct A {
+ // CHECK-A: Vtable for 'A' (3 entries)
+ // CHECK-A-NEXT: 0 | void A::f()
+ // CHECK-A-NEXT: 1 | void A::g()
+ // CHECK-A-NEXT: 2 | void A::h()
+ // EMITS-VTABLE: @"\01??_7A@@6B@" = unnamed_addr constant [3 x i8*]
+ virtual void f();
+ virtual void g();
+ virtual void h();
+ int ia;
+};
+void A::f() {}
+
+struct B : A {
+ // CHECK-B: Vtable for 'B' (5 entries)
+ // CHECK-B-NEXT: 0 | void B::f()
+ // CHECK-B-NEXT: 1 | void A::g()
+ // CHECK-B-NEXT: 2 | void A::h()
+ // CHECK-B-NEXT: 3 | void B::i()
+ // CHECK-B-NEXT: 4 | void B::j()
+ // EMITS-VTABLE: @"\01??_7B@@6B@" = unnamed_addr constant [5 x i8*]
+ virtual void f(); // overrides A::f()
+ virtual void i();
+ virtual void j();
+};
+void B::f() {}
+
+struct C {
+ // CHECK-C: Vtable for 'C' (2 entries)
+ // CHECK-C-NEXT: 0 | C::~C()
+ // CHECK-C-NEXT: 1 | void C::f()
+ // CHECK-C: VTable indices for 'C' (2 entries).
+ // CHECK-C-NEXT: 0 | C::~C()
+ // CHECK-C-NEXT: 1 | void C::f()
+ // Never used, so doesn't emit a vtable.
+ virtual ~C();
+
+ virtual void f();
+};
+void C::f() {}
+
+struct D {
+ // CHECK-D: Vtable for 'D' (2 entries)
+ // CHECK-D-NEXT: 0 | void D::f()
+ // CHECK-D-NEXT: 1 | D::~D()
+ // EMITS-VTABLE: @"\01??_7D@@6B@" = unnamed_addr constant [2 x i8*]
+ virtual void f();
+
+ virtual ~D();
+};
+void D::f() {}
+
+struct E : A {
+ // CHECK-E: Vtable for 'E' (5 entries)
+ // CHECK-E-NEXT: 0 | void A::f()
+ // CHECK-E-NEXT: 1 | void A::g()
+ // CHECK-E-NEXT: 2 | void A::h()
+ // CHECK-E-NEXT: 3 | E::~E()
+ // CHECK-E-NEXT: 4 | void E::i()
+ // CHECK-E: VTable indices for 'E' (2 entries).
+ // CHECK-E-NEXT: 3 | E::~E()
+ // CHECK-E-NEXT: 4 | void E::i()
+
+ // Never used, so doesn't emit a vtable.
+ virtual ~E();
+ virtual void i();
+};
+void E::i() {}
+
+struct F : A {
+ // CHECK-F: Vtable for 'F' (5 entries)
+ // CHECK-F-NEXT: 0 | void A::f()
+ // CHECK-F-NEXT: 1 | void A::g()
+ // CHECK-F-NEXT: 2 | void A::h()
+ // CHECK-F-NEXT: 3 | void F::i()
+ // CHECK-F-NEXT: 4 | F::~F()
+ // CHECK-F: VTable indices for 'F' (2 entries).
+ // CHECK-F-NEXT: 3 | void F::i()
+ // CHECK-F-NEXT: 4 | F::~F()
+ // EMITS-VTABLE: @"\01??_7F@@6B@" = unnamed_addr constant [5 x i8*]
+ virtual void i();
+ virtual ~F();
+};
+void F::i() {}
+
+struct G : E {
+ // CHECK-G: Vtable for 'G' (6 entries)
+ // CHECK-G-NEXT: 0 | void G::f()
+ // CHECK-G-NEXT: 1 | void A::g()
+ // CHECK-G-NEXT: 2 | void A::h()
+ // CHECK-G-NEXT: 3 | G::~G()
+ // CHECK-G-NEXT: 4 | void E::i()
+ // CHECK-G-NEXT: 5 | void G::j()
+ // CHECK-G: VTable indices for 'G' (3 entries).
+ // CHECK-G-NEXT: 0 | void G::f()
+ // CHECK-G-NEXT: 3 | G::~G()
+ // CHECK-G-NEXT: 5 | void G::j()
+ // Never used, so doesn't emit a vtable.
+ virtual void f(); // overrides A::f()
+ virtual ~G();
+ virtual void j();
+};
+void G::j() {}
Propchange: cfe/trunk/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
------------------------------------------------------------------------------
svn:eol-style = LF
More information about the cfe-commits
mailing list