diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/AST/VTableBuilder.h | 16 | ||||
-rw-r--r-- | clang/include/clang/Basic/ABI.h | 36 | ||||
-rw-r--r-- | clang/lib/AST/MicrosoftMangle.cpp | 86 | ||||
-rw-r--r-- | clang/lib/AST/VTableBuilder.cpp | 72 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCXXABI.h | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVTables.cpp | 49 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVTables.h | 15 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 7 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 12 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-thunks.cpp | 118 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp | 8 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp | 19 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp | 3 |
13 files changed, 90 insertions, 357 deletions
diff --git a/clang/include/clang/AST/VTableBuilder.h b/clang/include/clang/AST/VTableBuilder.h index b1fc6c73d12..877ff407a17 100644 --- a/clang/include/clang/AST/VTableBuilder.h +++ b/clang/include/clang/AST/VTableBuilder.h @@ -200,6 +200,7 @@ private: class VTableLayout { public: typedef std::pair<uint64_t, ThunkInfo> VTableThunkTy; + typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy; typedef const VTableComponent *vtable_component_iterator; typedef const VTableThunkTy *vtable_thunk_iterator; @@ -209,7 +210,7 @@ private: uint64_t NumVTableComponents; llvm::OwningArrayPtr<VTableComponent> VTableComponents; - /// \brief Contains thunks needed by vtables, sorted by indices. + /// \brief Contains thunks needed by vtables. uint64_t NumVTableThunks; llvm::OwningArrayPtr<VTableThunkTy> VTableThunks; @@ -284,12 +285,9 @@ protected: virtual ~VTableContextBase() {} public: - virtual const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()->getCanonicalDecl()); + const ThunkInfoVectorTy *getThunkInfo(const CXXMethodDecl *MD) { computeVTableRelatedInformation(MD->getParent()); - // This assumes that all the destructors present in the vtable - // use exactly the same set of thunks. ThunksMapTy::const_iterator I = Thunks.find(MD); if (I == Thunks.end()) { // We did not find a thunk for this method. @@ -485,14 +483,6 @@ public: CharUnits VFPtrOffset); const MethodVFTableLocation &getMethodVFTableLocation(GlobalDecl GD); - - const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) { - // Complete destructors don't have a slot in a vftable, so no thunks needed. - if (isa<CXXDestructorDecl>(GD.getDecl()) && - GD.getDtorType() == Dtor_Complete) - return 0; - return VTableContextBase::getThunkInfo(GD); - } }; } diff --git a/clang/include/clang/Basic/ABI.h b/clang/include/clang/Basic/ABI.h index 7c76ec130e3..fecf613a046 100644 --- a/clang/include/clang/Basic/ABI.h +++ b/clang/include/clang/Basic/ABI.h @@ -54,10 +54,6 @@ struct ReturnAdjustment { LHS.VBaseOffsetOffset == RHS.VBaseOffsetOffset; } - 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) @@ -87,10 +83,6 @@ struct ThisAdjustment { return LHS.NonVirtual == RHS.NonVirtual && LHS.VCallOffsetOffset == RHS.VCallOffsetOffset; } - - friend bool operator!=(const ThisAdjustment &LHS, const ThisAdjustment &RHS) { - return !(LHS == RHS); - } friend bool operator<(const ThisAdjustment &LHS, const ThisAdjustment &RHS) { @@ -102,8 +94,6 @@ struct ThisAdjustment { } }; -class CXXMethodDecl; - /// \brief The \c this pointer adjustment as well as an optional return /// adjustment for a thunk. struct ThunkInfo { @@ -113,25 +103,23 @@ struct ThunkInfo { /// \brief The return adjustment. ReturnAdjustment Return; - /// \brief 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() { } - ThunkInfo() : Method(0) { } - - ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return, - const CXXMethodDecl *Method = 0) - : This(This), Return(Return), Method(Method) {} + ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return) + : This(This), Return(Return) { } friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) { - return LHS.This == RHS.This && LHS.Return == RHS.Return && - LHS.Method == RHS.Method; + return LHS.This == RHS.This && LHS.Return == RHS.Return; + } + + friend bool operator<(const ThunkInfo &LHS, const ThunkInfo &RHS) { + if (LHS.This < RHS.This) + return true; + + return LHS.This == RHS.This && LHS.Return < RHS.Return; } - bool isEmpty() const { return This.isEmpty() && Return.isEmpty() && Method == 0; } + bool isEmpty() const { return This.isEmpty() && Return.isEmpty(); } }; } // end namespace clang diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 2c37709bcf1..ab0db1acbf6 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -15,7 +15,6 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/CharUnits.h" -#include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" @@ -1406,8 +1405,7 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) { // ::= Z # global far if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { switch (MD->getAccess()) { - case AS_none: - llvm_unreachable("Unsupported access specifier"); + default: case AS_private: if (MD->isStatic()) Out << 'C'; @@ -1860,70 +1858,36 @@ void MicrosoftMangleContextImpl::mangleName(const NamedDecl *D, return Mangler.mangle(D); } -static void mangleThunkThisAdjustment(const CXXMethodDecl *MD, - const ThisAdjustment &Adjustment, - MicrosoftCXXNameMangler &Mangler, - raw_ostream &Out) { - // FIXME: add support for vtordisp thunks. - if (Adjustment.NonVirtual != 0) { - switch (MD->getAccess()) { - case AS_none: - llvm_unreachable("Unsupported access specifier"); - case AS_private: - Out << 'G'; - break; - case AS_protected: - Out << 'O'; - break; - case AS_public: - Out << 'W'; - } - llvm::APSInt APSNumber(/*BitWidth=*/32, /*isUnsigned=*/true); - APSNumber = -Adjustment.NonVirtual; - Mangler.mangleNumber(APSNumber); - } else { - switch (MD->getAccess()) { - case AS_none: - llvm_unreachable("Unsupported access specifier"); - case AS_private: - Out << 'A'; - break; - case AS_protected: - Out << 'I'; - break; - case AS_public: - Out << 'Q'; - } - } -} - void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, raw_ostream &Out) { + // FIXME: this is not yet a complete implementation, but merely a + // reasonably-working stub to avoid crashing when required to emit a thunk. MicrosoftCXXNameMangler Mangler(*this, Out); Out << "\01?"; Mangler.mangleName(MD); - mangleThunkThisAdjustment(MD, Thunk.This, Mangler, Out); - if (!Thunk.Return.isEmpty()) - assert(Thunk.Method != 0 && "Thunk info should hold the overridee decl"); - - const CXXMethodDecl *DeclForFPT = Thunk.Method ? Thunk.Method : MD; - Mangler.mangleFunctionType( - DeclForFPT->getType()->castAs<FunctionProtoType>(), MD); -} - -void MicrosoftMangleContextImpl::mangleCXXDtorThunk( - const CXXDestructorDecl *DD, CXXDtorType Type, - const ThisAdjustment &Adjustment, raw_ostream &Out) { - // FIXME: Actually, the dtor thunk should be emitted for vector deleting - // dtors rather than scalar deleting dtors. Just use the vector deleting dtor - // mangling manually until we support both deleting dtor types. - assert(Type == Dtor_Deleting); - MicrosoftCXXNameMangler Mangler(*this, Out, DD, Type); - Out << "\01??_E"; - Mangler.mangleName(DD->getParent()); - mangleThunkThisAdjustment(DD, Adjustment, Mangler, Out); - Mangler.mangleFunctionType(DD->getType()->castAs<FunctionProtoType>(), DD); + if (Thunk.This.NonVirtual != 0) { + // FIXME: add support for protected/private or use mangleFunctionClass. + Out << "W"; + llvm::APSInt APSNumber(/*BitWidth=*/32 /*FIXME: check on x64*/, + /*isUnsigned=*/true); + APSNumber = -Thunk.This.NonVirtual; + Mangler.mangleNumber(APSNumber); + } else { + // FIXME: add support for protected/private or use mangleFunctionClass. + Out << "Q"; + } + // FIXME: mangle return adjustment? Most likely includes using an overridee FPT? + Mangler.mangleFunctionType(MD->getType()->castAs<FunctionProtoType>(), MD); +} + +void MicrosoftMangleContextImpl::mangleCXXDtorThunk(const CXXDestructorDecl *DD, + CXXDtorType Type, + const ThisAdjustment &, + raw_ostream &) { + unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle thunk for this destructor yet"); + getDiags().Report(DD->getLocation(), DiagID); } void MicrosoftMangleContextImpl::mangleCXXVFTable( diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp index fbc5e3dd93a..9aad711748c 100644 --- a/clang/lib/AST/VTableBuilder.cpp +++ b/clang/lib/AST/VTableBuilder.cpp @@ -992,7 +992,6 @@ public: MostDerivedClassIsVirtual(MostDerivedClassIsVirtual), LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()), Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) { - assert(!Context.getTargetInfo().getCXXABI().isMicrosoft()); LayoutVTable(); @@ -1905,21 +1904,6 @@ VTableBuilder::LayoutVTablesForVirtualBases(const CXXRecordDecl *RD, } } -struct ItaniumThunkInfoComparator { - bool operator() (const ThunkInfo &LHS, const ThunkInfo &RHS) { - assert(LHS.Method == 0); - assert(RHS.Method == 0); - - if (LHS.This != RHS.This) - return LHS.This < RHS.This; - - if (LHS.Return != RHS.Return) - return LHS.Return < RHS.Return; - - llvm_unreachable("Shouldn't observe two equal thunks"); - } -}; - /// dumpLayout - Dump the vtable layout. void VTableBuilder::dumpLayout(raw_ostream& Out) { // FIXME: write more tests that actually use the dumpLayout output to prevent @@ -2162,8 +2146,7 @@ void VTableBuilder::dumpLayout(raw_ostream& Out) { const CXXMethodDecl *MD = I->second; ThunkInfoVectorTy ThunksVector = Thunks[MD]; - std::sort(ThunksVector.begin(), ThunksVector.end(), - ItaniumThunkInfoComparator()); + std::sort(ThunksVector.begin(), ThunksVector.end()); Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size(); Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n"; @@ -2250,15 +2233,7 @@ void VTableBuilder::dumpLayout(raw_ostream& Out) { Out << '\n'; } - -struct VTableThunksComparator { - bool operator()(const VTableLayout::VTableThunkTy &LHS, - const VTableLayout::VTableThunkTy &RHS) { - assert(LHS.first != RHS.first && - "All thunks should have unique indices!"); - return LHS.first < RHS.first; - } -}; + } VTableLayout::VTableLayout(uint64_t NumVTableComponents, @@ -2277,9 +2252,6 @@ VTableLayout::VTableLayout(uint64_t NumVTableComponents, this->VTableComponents.get()); std::copy(VTableThunks, VTableThunks+NumVTableThunks, this->VTableThunks.get()); - std::sort(this->VTableThunks.get(), - this->VTableThunks.get() + NumVTableThunks, - VTableThunksComparator()); } VTableLayout::~VTableLayout() { } @@ -2340,6 +2312,7 @@ VTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, static VTableLayout *CreateVTableLayout(const VTableBuilder &Builder) { SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end()); + std::sort(VTableThunks.begin(), VTableThunks.end()); return new VTableLayout(Builder.getNumVTableComponents(), Builder.vtable_component_begin(), @@ -2547,14 +2520,18 @@ private: /// AddMethod - Add a single virtual member function to the vftable /// components vector. - void AddMethod(const CXXMethodDecl *MD, ThunkInfo TI) { + void AddMethod(const CXXMethodDecl *MD, ThisAdjustment ThisAdjustment, + ReturnAdjustment ReturnAdjustment) { if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { - assert(TI.Return.isEmpty() && + assert(ReturnAdjustment.isEmpty() && "Destructor can't have return adjustment!"); Components.push_back(VTableComponent::MakeDeletingDtor(DD)); } else { - if (!TI.isEmpty()) - VTableThunks[Components.size()] = TI; + // Add the return adjustment if necessary. + if (!ReturnAdjustment.isEmpty() || !ThisAdjustment.isEmpty()) { + VTableThunks[Components.size()].Return = ReturnAdjustment; + VTableThunks[Components.size()].This = ThisAdjustment; + } Components.push_back(VTableComponent::MakeFunction(MD)); } } @@ -2839,7 +2816,6 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, FinalOverriders::OverriderInfo Overrider = Overriders.getOverrider(MD, Base.getBaseOffset()); ThisAdjustment ThisAdjustmentOffset; - bool ForceThunk = false; // Check if this virtual member function overrides // a method in one of the visited bases. @@ -2864,7 +2840,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, AddThunk(MD, VTableThunks[OverriddenMethodInfo.VFTableIndex]); } - if (MD->getResultType() == OverriddenMD->getResultType()) { + if (ComputeReturnAdjustmentBaseOffset(Context, MD, OverriddenMD) + .isEmpty()) { // No return adjustment needed - just replace the overridden method info // with the current info. MethodInfo MI(OverriddenMethodInfo.VBTableIndex, @@ -2882,7 +2859,6 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, // method was in the vftable. // For now, just mark the overriden method as shadowed by a new slot. OverriddenMethodInfo.Shadowed = true; - ForceThunk = true; // Also apply this adjustment to the shadowed slots. if (!ThisAdjustmentOffset.isEmpty()) { @@ -2931,7 +2907,6 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD); } if (!ReturnAdjustmentOffset.isEmpty()) { - ForceThunk = true; ReturnAdjustment.NonVirtual = ReturnAdjustmentOffset.NonVirtualOffset.getQuantity(); if (ReturnAdjustmentOffset.VirtualBase) { @@ -2943,8 +2918,7 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, } } - AddMethod(OverriderMD, ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment, - ForceThunk ? MD : 0)); + AddMethod(Overrider.Method, ThisAdjustmentOffset, ReturnAdjustment); } } @@ -2955,20 +2929,6 @@ void PrintBasePath(const VFPtrInfo::BasePath &Path, raw_ostream &Out) { } } -struct MicrosoftThunkInfoStableSortComparator { - bool operator() (const ThunkInfo &LHS, const ThunkInfo &RHS) { - if (LHS.This != RHS.This) - return LHS.This < RHS.This; - - if (LHS.Return != RHS.Return) - return LHS.Return < RHS.Return; - - // Keep different thunks with the same adjustments in the order they - // were put into the vector. - return false; - } -}; - void VFTableBuilder::dumpLayout(raw_ostream &Out) { Out << "VFTable for "; PrintBasePath(WhichVFPtr.PathToBaseWithVFPtr, Out); @@ -3082,8 +3042,7 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) { const CXXMethodDecl *MD = I->second; ThunkInfoVectorTy ThunksVector = Thunks[MD]; - std::stable_sort(ThunksVector.begin(), ThunksVector.end(), - MicrosoftThunkInfoStableSortComparator()); + std::sort(ThunksVector.begin(), ThunksVector.end()); Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size(); Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n"; @@ -3259,6 +3218,7 @@ void MicrosoftVFTableContext::computeVTableRelatedInformation( assert(VFTableLayouts.count(id) == 0); SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks( Builder.vtable_thunks_begin(), Builder.vtable_thunks_end()); + std::sort(VTableThunks.begin(), VTableThunks.end()); VFTableLayouts[id] = new VTableLayout( Builder.getNumVTableComponents(), Builder.vtable_component_begin(), VTableThunks.size(), VTableThunks.data(), EmptyAddressPointsMap, true); diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index eaeb971dc42..3a1c8d198dc 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -339,17 +339,11 @@ public: SourceLocation CallLoc, llvm::Value *This) = 0; - virtual void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, - GlobalDecl GD, - CallArgList &CallArgs) {} - /// Emit any tables needed to implement virtual inheritance. For Itanium, /// this emits virtual table tables. For the MSVC++ ABI, this emits virtual /// base tables. virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD) = 0; - virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) = 0; - virtual void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResultType); diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 5ede5650b93..b987eb4d079 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -333,9 +333,6 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, // Add our adjusted 'this' pointer. CallArgs.add(RValue::get(AdjustedThisPtr), ThisType); - if (isa<CXXDestructorDecl>(MD)) - CGM.getCXXABI().adjustCallArgsForDestructorThunk(*this, GD, CallArgs); - // Add the rest of the parameters. for (FunctionDecl::param_const_iterator I = MD->param_begin(), E = MD->param_end(); I != E; ++I) { @@ -393,8 +390,14 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, setThunkVisibility(CGM, MD, Thunk, Fn); } -void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk, - bool ForVTable) { +void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk, + bool UseAvailableExternallyLinkage) +{ + if (CGM.getTarget().getCXXABI().isMicrosoft()) { + // Emission of thunks is not supported yet in Microsoft ABI. + return; + } + const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeGlobalDeclaration(GD); // FIXME: re-use FnInfo in this computation. @@ -432,11 +435,9 @@ void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk, } llvm::Function *ThunkFn = cast<llvm::Function>(Entry); - bool ABIHasKeyFunctions = CGM.getTarget().getCXXABI().hasKeyFunctions(); - bool UseAvailableExternallyLinkage = ForVTable && ABIHasKeyFunctions; if (!ThunkFn->isDeclaration()) { - if (!ABIHasKeyFunctions || UseAvailableExternallyLinkage) { + if (UseAvailableExternallyLinkage) { // There is already a thunk emitted for this function, do nothing. return; } @@ -465,17 +466,14 @@ void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk, CodeGenFunction(CGM).GenerateThunk(ThunkFn, FnInfo, GD, Thunk); } - CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable); + if (UseAvailableExternallyLinkage) + ThunkFn->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage); } -void CodeGenVTables::maybeEmitThunkForVTable(GlobalDecl GD, - const ThunkInfo &Thunk) { - // If the ABI has key functions, only the TU with the key function should emit - // the thunk. However, we can allow inlining of thunks if we emit them with - // available_externally linkage together with vtables when optimizations are - // enabled. - if (CGM.getTarget().getCXXABI().hasKeyFunctions() && - !CGM.getCodeGenOpts().OptimizationLevel) +void CodeGenVTables::MaybeEmitThunkAvailableExternally(GlobalDecl GD, + const ThunkInfo &Thunk) { + // We only want to do this when building with optimizations. + if (!CGM.getCodeGenOpts().OptimizationLevel) return; // We can't emit thunks for member functions with incomplete types. @@ -484,7 +482,7 @@ void CodeGenVTables::maybeEmitThunkForVTable(GlobalDecl GD, cast<FunctionType>(MD->getType().getTypePtr()))) return; - emitThunk(GD, Thunk, /*ForVTable=*/true); + EmitThunk(GD, Thunk, /*UseAvailableExternallyLinkage=*/true); } void CodeGenVTables::EmitThunks(GlobalDecl GD) @@ -496,18 +494,21 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD) if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) return; - const VTableContext::ThunkInfoVectorTy *ThunkInfoVector; if (VFTContext.isValid()) { - ThunkInfoVector = VFTContext->getThunkInfo(GD); - } else { - ThunkInfoVector = VTContext.getThunkInfo(GD); + // FIXME: This is a temporary solution to force generation of vftables in + // Microsoft ABI. Remove when we thread VFTableContext through CodeGen. + VFTContext->getVFPtrOffsets(MD->getParent()); + return; } + const VTableContext::ThunkInfoVectorTy *ThunkInfoVector = + VTContext.getThunkInfo(MD); if (!ThunkInfoVector) return; for (unsigned I = 0, E = ThunkInfoVector->size(); I != E; ++I) - emitThunk(GD, (*ThunkInfoVector)[I], /*ForVTable=*/false); + EmitThunk(GD, (*ThunkInfoVector)[I], + /*UseAvailableExternallyLinkage=*/false); } llvm::Constant * @@ -602,7 +603,7 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD, VTableThunks[NextVTableThunkIndex].first == I) { const ThunkInfo &Thunk = VTableThunks[NextVTableThunkIndex].second; - maybeEmitThunkForVTable(GD, Thunk); + MaybeEmitThunkAvailableExternally(GD, Thunk); Init = CGM.GetAddrOfThunk(GD, Thunk); NextVTableThunkIndex++; diff --git a/clang/lib/CodeGen/CGVTables.h b/clang/lib/CodeGen/CGVTables.h index e17ad89c5e7..9b95952e5e8 100644 --- a/clang/lib/CodeGen/CGVTables.h +++ b/clang/lib/CodeGen/CGVTables.h @@ -52,12 +52,15 @@ class CodeGenVTables { /// indices. SecondaryVirtualPointerIndicesMapTy SecondaryVirtualPointerIndices; - /// emitThunk - Emit a single thunk. - void emitThunk(GlobalDecl GD, const ThunkInfo &Thunk, bool ForVTable); - - /// maybeEmitThunkForVTable - Emit the given thunk for the vtable if needed by - /// the ABI. - void maybeEmitThunkForVTable(GlobalDecl GD, const ThunkInfo &Thunk); + /// EmitThunk - Emit a single thunk. + void EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk, + bool UseAvailableExternallyLinkage); + + /// MaybeEmitThunkAvailableExternally - Try to emit the given thunk with + /// available_externally linkage to allow for inlining of thunks. + /// This will be done iff optimizations are enabled and the member function + /// doesn't contain any incomplete types. + void MaybeEmitThunkAvailableExternally(GlobalDecl GD, const ThunkInfo &Thunk); public: /// CreateVTableInitializer - Create a vtable initializer for the given record diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 1e34a16dd99..ecf5d577981 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -173,13 +173,6 @@ public: void emitVirtualInheritanceTables(const CXXRecordDecl *RD); - void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) { - // Allow inlining of thunks by emitting them with available_externally - // linkage together with vtables when needed. - if (ForVTable) - Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage); - } - StringRef GetPureVirtualCallName() { return "__cxa_pure_virtual"; } StringRef GetDeletedVirtualCallName() { return "__cxa_deleted_virtual"; } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 7452c860d0b..1d73b213b7d 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -173,20 +173,8 @@ public: CXXDtorType DtorType, SourceLocation CallLoc, llvm::Value *This); - void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD, - CallArgList &CallArgs) { - assert(GD.getDtorType() == Dtor_Deleting && - "Only deleting destructor thunks are available in this ABI"); - CallArgs.add(RValue::get(getStructorImplicitParamValue(CGF)), - CGM.getContext().IntTy); - } - void emitVirtualInheritanceTables(const CXXRecordDecl *RD); - void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) { - Thunk->setLinkage(llvm::GlobalValue::WeakAnyLinkage); - } - void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, llvm::GlobalVariable *DeclPtr, bool PerformInit); diff --git a/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp b/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp deleted file mode 100644 index 091ef3274b9..00000000000 --- a/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 >%t 2>&1 -// RUN: FileCheck --check-prefix=MANGLING %s < %t -// RUN: FileCheck --check-prefix=XMANGLING %s < %t -// RUN: FileCheck --check-prefix=CODEGEN %s < %t -// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 2>&1 | FileCheck --check-prefix=MANGLING-X64 %s - -void foo(void *); - -struct A { - virtual ~A(); - virtual void public_f(); - // Make sure we don't emit unneeded thunks: - // XMANGLING-NOT: @"\01?public_f@A@@QAEXXZ" - protected: - virtual void protected_f(); - private: - virtual void private_f(); -}; - -struct B { - virtual ~B(); - virtual void public_f(); - protected: - virtual void protected_f(); - private: - virtual void private_f(); -}; - - -struct C : A, B { - C(); - - virtual ~C(); - // MANGLING-DAG: @"\01??1C@@UAE@XZ" - // MANGLING-DAG: @"\01??_GC@@UAEPAXI@Z" - // MANGLING-DAG: @"\01??_EC@@W3AEPAXI@Z" - // MANGLING-X64-DAG: @"\01??1C@@UEAA@XZ" - // MANGLING-X64-DAG: @"\01??_GC@@UEAAPEAXI@Z" - // MANGLING-X64-DAG: @"\01??_EC@@W7EAAPEAXI@Z" - - // Overrides public_f() of two subobjects with distinct vfptrs, thus needs a thunk. - virtual void public_f(); - // MANGLING-DAG: @"\01?public_f@C@@UAEXXZ" - // MANGLING-DAG: @"\01?public_f@C@@W3AEXXZ" - // MANGLING-X64-DAG: @"\01?public_f@C@@UEAAXXZ" - // MANGLING-X64-DAG: @"\01?public_f@C@@W7EAAXXZ" - protected: - virtual void protected_f(); - // MANGLING-DAG: @"\01?protected_f@C@@MAEXXZ" - // MANGLING-DAG: @"\01?protected_f@C@@O3AEXXZ" - // MANGLING-X64-DAG: @"\01?protected_f@C@@MEAAXXZ" - // MANGLING-X64-DAG: @"\01?protected_f@C@@O7EAAXXZ" - - private: - virtual void private_f(); - // MANGLING-DAG: @"\01?private_f@C@@EAEXXZ" - // MANGLING-DAG: @"\01?private_f@C@@G3AEXXZ" - // MANGLING-X64-DAG: @"\01?private_f@C@@EEAAXXZ" - // MANGLING-X64-DAG: @"\01?private_f@C@@G7EAAXXZ" -}; - -C::C() {} // Emits vftable and forces thunk generation. - -// CODEGEN: define weak x86_thiscallcc void @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete) -// CODEGEN: getelementptr inbounds i8* {{.*}}, i64 -4 -// FIXME: should actually call _EC, not _GC. -// CODEGEN: call x86_thiscallcc void @"\01??_GC@@UAEPAXI@Z" -// CODEGEN: ret - -// CODEGEN: define weak x86_thiscallcc void @"\01?public_f@C@@W3AEXXZ"(%struct.C* -// CODEGEN: getelementptr inbounds i8* {{.*}}, i64 -4 -// CODEGEN: call x86_thiscallcc void @"\01?public_f@C@@UAEXXZ"(%struct.C* -// CODEGEN: ret - -void zoo(C* obj) { - delete obj; -} - -struct D { - virtual B* goo(); -}; - -struct E : D { - virtual C* goo(); - // MANGLING-DAG: @"\01?goo@E@@UAEPAUC@@XZ" - // MANGLING-DAG: @"\01?goo@E@@QAEPAUB@@XZ" - // MANGLING-X64-DAG: @"\01?goo@E@@UEAAPEAUC@@XZ" - // MANGLING-X64-DAG: @"\01?goo@E@@QEAAPEAUB@@XZ" -}; - -E e; // Emits vftable and forces thunk generation. - -// CODEGEN: define weak x86_thiscallcc %struct.C* @"\01?goo@E@@QAEPAUB@@XZ" -// CODEGEN: call x86_thiscallcc %struct.C* @"\01?goo@E@@UAEPAUC@@XZ" -// CODEGEN: getelementptr inbounds i8* {{.*}}, i64 4 -// CODEGEN: ret - -struct F : virtual A, virtual B { - virtual ~F(); -}; - -F f; // Just make sure we don't crash, e.g. mangling the complete dtor. - -struct G : C { }; - -struct H : E { - virtual G* goo(); - // MANGLING-DAG: @"\01?goo@H@@UAEPAUG@@XZ" - // MANGLING-DAG: @"\01?goo@H@@QAEPAUB@@XZ" - // MANGLING-DAG: @"\01?goo@H@@QAEPAUC@@XZ" - // MANGLING-X64-DAG: @"\01?goo@H@@UEAAPEAUG@@XZ" - // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUB@@XZ" - // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUC@@XZ" -}; - -H h; - -// FIXME: Write vtordisp adjusting thunk tests diff --git a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp index 3805243c6a4..064a3ffda91 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp @@ -93,11 +93,3 @@ void call_vbase_bar(B *obj) { // // CHECK: ret void } - -struct C : B { - C(); - // has an implicit vdtor. -}; - -// Used to crash on an assertion. -C::C() {} diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp index 8dad4dd7794..a0436c8e810 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp @@ -18,7 +18,6 @@ // RUN: FileCheck --check-prefix=RET-THUNKS-Test3 %s < %t // RUN: FileCheck --check-prefix=RET-THUNKS-Test4 %s < %t // RUN: FileCheck --check-prefix=RET-THUNKS-Test5 %s < %t -// RUN: FileCheck --check-prefix=RET-THUNKS-Test6 %s < %t // RUN: FileCheck --check-prefix=MANGLING %s < %t @@ -459,22 +458,4 @@ struct Test5 : Ret1, Test1 { }; Test5 t5; - -struct Ret3 : this_adjustment::Test1 { }; - -struct Test6 : Test1 { - virtual Ret3* foo(); - // RET-THUNKS-Test6: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test1' in 'return_adjustment::Test6' (4 entries). - // RET-THUNKS-Test6-NEXT: 0 | return_adjustment::Ret3 *return_adjustment::Test6::foo() - // RET-THUNKS-Test6-NEXT: [return adjustment: 4 non-virtual] - // RET-THUNKS-Test6-NEXT: 1 | void return_adjustment::Ret1::z() - // RET-THUNKS-Test6-NEXT: 2 | return_adjustment::Ret3 *return_adjustment::Test6::foo() - // RET-THUNKS-Test6-NEXT: 3 | return_adjustment::Ret3 *return_adjustment::Test6::foo() - - // RET-THUNKS-Test6: VFTable indices for 'return_adjustment::Test6' (1 entries). - // RET-THUNKS-Test6-NEXT: 3 | return_adjustment::Ret3 *return_adjustment::Test6::foo() -}; - -Test6 t6; - } diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp index 4a7f5da15ef..24872609d52 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp @@ -154,9 +154,6 @@ struct X: virtual C { // TEST4-NOT: VFTable indices for 'Test4::X' // MANGLING-DAG: @"\01??_7X@Test4@@6B@" - - // Also check the mangling of the thunk. - // MANGLING-DAG: define weak x86_thiscallcc void @"\01?f@C@@WPPPPPPPE@AEXXZ" }; X x; |