r212125 - MS ABI: Reference MSVC RTTI from the VFTable

Timur Iskhodzhanov timurrrr at google.com
Tue Jul 8 05:28:19 PDT 2014


I'm trying to understand how to fix the ASan/Windows breakage wrt vftables.

Here's what David told me on the r212138 thread:
2014-07-08 4:39 GMT+04:00 David Majnemer <david.majnemer at gmail.com>:
> ASAN replaces one internal global with another. Because the new symbol
> isn't in a Comdat, it's alias isn't either.  This makes the alias a
> strong definition.

After rethinking this a bit, I'm puzzled.
Not only we need to correctly link no-rtti with rtti-enabled TUs but we
should also handle asan vs no-asan TUs.
ASan increases the size of globals by adding redzones.
It looks like an internal GV for a vftable in a (asan enabled, no-rtti)
configuration will be *larger* than the same vftable in a
(no-asan,rtti-enabled) configuration and the linking process will cause bad
result.
That said, I think we have to disable instrumentation of vftables on
Windows as long as we want to support mixing rtti- with no-rtti TUs or asan
with no-asan TUs.
Are we on the same page here?

If we agree that we can't add redzones to vftables, we should
adjust AddressSanitizerModule::ShouldInstrumentGlobal(GV) to handle this.
The problem is that those GVs are unnamed.
Is there a condition that's only true for the internal vftable GVs so I can
write an "if()"?
I think "if (G->hasComdat() && G->getLinkage() == InternalLinkage)" is a
too wide condition.
Or can we name these internal GVs somehow to make them easy to filter out?
 E.g. "\02?_7blah"?


2014-07-02 0:30 GMT+04:00 David Majnemer <david.majnemer at gmail.com>:

> Author: majnemer
> Date: Tue Jul  1 15:30:31 2014
> New Revision: 212125
>
> URL: http://llvm.org/viewvc/llvm-project?rev=212125&view=rev
> Log:
> MS ABI: Reference MSVC RTTI from the VFTable
>
> The pointer for a class's RTTI data comes right before the VFTable but
> has no name.  To be properly compatible with this, we do the following:
> * Create a single GlobalVariable which holds the contents of the VFTable
>   _and_ the pointer to the RTTI data.
> * Create a GlobalAlias, with appropriate linkage/visibility, that points
>   just after the RTTI data pointer.  This ensures that the VFTable
>   symbol will always refer to VFTable data.
> * Create a Comdat with a "Largest" SelectionKind and stick the private
>   GlobalVariable in it.  By transitivity, the GlobalAlias will be a
>   member of the Comdat group.  Using "Largest" ensures that foreign
>   definitions without an RTTI data pointer will _not_ be chosen in the
>   final linked image.
>
> Whether or not we emit RTTI data depends on several things:
> * The -fno-rtti flag implies that we should never not emit a pointer to
>   RTTI data before the VFTable.
> * __declspec(dllimport) brings in the VFTable from a remote DLL. Use an
>   available_externally GlobalVariable to provide a local definition of
>   the VFTable.  This means that we won't have any available_externally
>   definitions of things like complete object locators.  This is
>   acceptable because they are never directly referenced.
>
> To my knowledge, this completes the implementation of MSVC RTTI code
> generation.
>
> Further semantic work should be done to properly support /GR-.
>
> Modified:
>     cfe/trunk/lib/AST/VTableBuilder.cpp
>     cfe/trunk/lib/CodeGen/CGVTables.cpp
>     cfe/trunk/lib/CodeGen/CGVTables.h
>     cfe/trunk/lib/CodeGen/CodeGenModule.h
>     cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
>     cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
>     cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp
>     cfe/trunk/test/CodeGenCXX/dllexport.cpp
>
> Modified: cfe/trunk/lib/AST/VTableBuilder.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/VTableBuilder.cpp?rev=212125&r1=212124&r2=212125&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/VTableBuilder.cpp (original)
> +++ cfe/trunk/lib/AST/VTableBuilder.cpp Tue Jul  1 15:30:31 2014
> @@ -2574,6 +2574,12 @@ public:
>
>  MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)),
>          WhichVFPtr(*Which),
>          Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) {
> +    // Only include the RTTI component if we know that we will provide a
> +    // definition of the vftable.
> +    if (Context.getLangOpts().RTTI &&
> +        !MostDerivedClass->hasAttr<DLLImportAttr>())
> +      Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
> +
>      LayoutVFTable();
>
>      if (Context.getLangOpts().DumpVTableLayouts)
> @@ -2915,7 +2921,8 @@ void VFTableBuilder::AddMethods(BaseSubo
>      // it requires return adjustment. Insert the method info for this
> method.
>      unsigned VBIndex =
>          LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase)
> : 0;
> -    MethodInfo MI(VBIndex, Components.size());
> +    MethodInfo MI(VBIndex, Context.getLangOpts().RTTI ? Components.size()
> - 1
> +                                                      :
> Components.size());
>
>      assert(!MethodInfoMap.count(MD) &&
>             "Should not have method info for this method yet!");
>
> Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=212125&r1=212124&r2=212125&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGVTables.cpp Tue Jul  1 15:30:31 2014
> @@ -431,12 +431,10 @@ void CodeGenVTables::EmitThunks(GlobalDe
>      emitThunk(GD, (*ThunkInfoVector)[I], /*ForVTable=*/false);
>  }
>
> -llvm::Constant *
> -CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,
> -                                        const VTableComponent *Components,
> -                                        unsigned NumComponents,
> -                                const VTableLayout::VTableThunkTy
> *VTableThunks,
> -                                        unsigned NumVTableThunks) {
> +llvm::Constant *CodeGenVTables::CreateVTableInitializer(
> +    const CXXRecordDecl *RD, const VTableComponent *Components,
> +    unsigned NumComponents, const VTableLayout::VTableThunkTy
> *VTableThunks,
> +    unsigned NumVTableThunks, llvm::Constant *RTTI) {
>    SmallVector<llvm::Constant *, 64> Inits;
>
>    llvm::Type *Int8PtrTy = CGM.Int8PtrTy;
> @@ -444,9 +442,6 @@ CodeGenVTables::CreateVTableInitializer(
>    llvm::Type *PtrDiffTy =
>      CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
>
> -  QualType ClassType = CGM.getContext().getTagDeclType(RD);
> -  llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(ClassType);
> -
>    unsigned NextVTableThunkIndex = 0;
>
>    llvm::Constant *PureVirtualFn = nullptr, *DeletedVirtualFn = nullptr;
> @@ -594,13 +589,14 @@ CodeGenVTables::GenerateConstructionVTab
>    // V-tables are always unnamed_addr.
>    VTable->setUnnamedAddr(true);
>
> +  llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(
> +      CGM.getContext().getTagDeclType(Base.getBase()));
> +
>    // Create and set the initializer.
> -  llvm::Constant *Init =
> -    CreateVTableInitializer(Base.getBase(),
> -                            VTLayout->vtable_component_begin(),
> -                            VTLayout->getNumVTableComponents(),
> -                            VTLayout->vtable_thunk_begin(),
> -                            VTLayout->getNumVTableThunks());
> +  llvm::Constant *Init = CreateVTableInitializer(
> +      Base.getBase(), VTLayout->vtable_component_begin(),
> +      VTLayout->getNumVTableComponents(), VTLayout->vtable_thunk_begin(),
> +      VTLayout->getNumVTableThunks(), RTTI);
>    VTable->setInitializer(Init);
>
>    return VTable;
>
> Modified: cfe/trunk/lib/CodeGen/CGVTables.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.h?rev=212125&r1=212124&r2=212125&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGVTables.h (original)
> +++ cfe/trunk/lib/CodeGen/CGVTables.h Tue Jul  1 15:30:31 2014
> @@ -61,11 +61,10 @@ public:
>    /// decl.
>    /// \param Components - The vtable components; this is really an array
> of
>    /// VTableComponents.
> -  llvm::Constant *CreateVTableInitializer(const CXXRecordDecl *RD,
> -                                          const VTableComponent
> *Components,
> -                                          unsigned NumComponents,
> -                                const VTableLayout::VTableThunkTy
> *VTableThunks,
> -                                          unsigned NumVTableThunks);
> +  llvm::Constant *CreateVTableInitializer(
> +      const CXXRecordDecl *RD, const VTableComponent *Components,
> +      unsigned NumComponents, const VTableLayout::VTableThunkTy
> *VTableThunks,
> +      unsigned NumVTableThunks, llvm::Constant *RTTI);
>
>    CodeGenVTables(CodeGenModule &CGM);
>
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=212125&r1=212124&r2=212125&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenModule.h Tue Jul  1 15:30:31 2014
> @@ -750,8 +750,8 @@ public:
>    /// \brief Gets or a creats a Microsoft TypeDescriptor.
>    llvm::Constant *getMSTypeDescriptor(QualType Ty);
>    /// \brief Gets or a creats a Microsoft CompleteObjectLocator.
> -  llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl
> *RD,
> -                                                   const VPtrInfo *Info);
> +  llvm::Constant *getMSCompleteObjectLocator(const CXXRecordDecl *RD,
> +                                             const VPtrInfo *Info);
>
>    /// Gets the address of a block which requires no captures.
>    llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *);
>
> Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=212125&r1=212124&r2=212125&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
> +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Tue Jul  1 15:30:31 2014
> @@ -1182,11 +1182,13 @@ void ItaniumCXXABI::emitVTableDefinition
>    ItaniumVTableContext &VTContext = CGM.getItaniumVTableContext();
>    const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);
>    llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
> +  llvm::Constant *RTTI =
> +      CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));
>
>    // Create and set the initializer.
>    llvm::Constant *Init = CGVT.CreateVTableInitializer(
>        RD, VTLayout.vtable_component_begin(),
> VTLayout.getNumVTableComponents(),
> -      VTLayout.vtable_thunk_begin(), VTLayout.getNumVTableThunks());
> +      VTLayout.vtable_thunk_begin(), VTLayout.getNumVTableThunks(), RTTI);
>    VTable->setInitializer(Init);
>
>    // Set the correct linkage.
>
> Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=212125&r1=212124&r2=212125&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
> +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Tue Jul  1 15:30:31 2014
> @@ -403,9 +403,11 @@ public:
>
>  private:
>    typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
> -  typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *>
> VFTablesMapTy;
> +  typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *>
> VTablesMapTy;
> +  typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalValue *> VFTablesMapTy;
>    /// \brief All the vftables that have been referenced.
>    VFTablesMapTy VFTablesMap;
> +  VTablesMapTy VTablesMap;
>
>    /// \brief This set holds the record decls we've deferred vtable
> emission for.
>    llvm::SmallPtrSet<const CXXRecordDecl *, 4> DeferredVFTables;
> @@ -1051,26 +1053,22 @@ void MicrosoftCXXABI::emitVTableDefiniti
>                                              const CXXRecordDecl *RD) {
>    MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext();
>    VPtrInfoVector VFPtrs = VFTContext.getVFPtrOffsets(RD);
> -  llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
>
>    for (VPtrInfo *Info : VFPtrs) {
>      llvm::GlobalVariable *VTable = getAddrOfVTable(RD,
> Info->FullOffsetInMDC);
>      if (VTable->hasInitializer())
>        continue;
> -    if (getContext().getLangOpts().RTTI)
> -      CGM.getMSCompleteObjectLocator(RD, Info);
> +
> +    llvm::Constant *RTTI = CGM.getMSCompleteObjectLocator(RD, Info);
>
>      const VTableLayout &VTLayout =
>        VFTContext.getVFTableLayout(RD, Info->FullOffsetInMDC);
>      llvm::Constant *Init = CGVT.CreateVTableInitializer(
>          RD, VTLayout.vtable_component_begin(),
>          VTLayout.getNumVTableComponents(), VTLayout.vtable_thunk_begin(),
> -        VTLayout.getNumVTableThunks());
> -    VTable->setInitializer(Init);
> -
> -    VTable->setLinkage(Linkage);
> +        VTLayout.getNumVTableThunks(), RTTI);
>
> -    CGM.setGlobalVisibility(VTable, RD);
> +    VTable->setInitializer(Init);
>    }
>  }
>
> @@ -1079,8 +1077,9 @@ llvm::Value *MicrosoftCXXABI::getVTableA
>      const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {
>    NeedsVirtualOffset = (NearestVBase != nullptr);
>
> -  llvm::Value *VTableAddressPoint =
> -      getAddrOfVTable(VTableClass, Base.getBaseOffset());
> +  (void)getAddrOfVTable(VTableClass, Base.getBaseOffset());
> +  VFTableIdTy ID(VTableClass, Base.getBaseOffset());
> +  llvm::GlobalValue *VTableAddressPoint = VFTablesMap[ID];
>    if (!VTableAddressPoint) {
>      assert(Base.getBase()->getNumVBases() &&
>
> !CGM.getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr());
> @@ -1097,9 +1096,11 @@ static void mangleVFTableName(MicrosoftM
>
>  llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr(
>      BaseSubobject Base, const CXXRecordDecl *VTableClass) {
> -  llvm::Constant *VTable = getAddrOfVTable(VTableClass,
> Base.getBaseOffset());
> -  assert(VTable && "Couldn't find a vftable for the given base?");
> -  return VTable;
> +  (void)getAddrOfVTable(VTableClass, Base.getBaseOffset());
> +  VFTableIdTy ID(VTableClass, Base.getBaseOffset());
> +  llvm::GlobalValue *VFTable = VFTablesMap[ID];
> +  assert(VFTable && "Couldn't find a vftable for the given base?");
> +  return VFTable;
>  }
>
>  llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const
> CXXRecordDecl *RD,
> @@ -1108,9 +1109,9 @@ llvm::GlobalVariable *MicrosoftCXXABI::g
>    // shouldn't be used in the given record type. We want to cache this
> result in
>    // VFTablesMap, thus a simple zero check is not sufficient.
>    VFTableIdTy ID(RD, VPtrOffset);
> -  VFTablesMapTy::iterator I;
> +  VTablesMapTy::iterator I;
>    bool Inserted;
> -  std::tie(I, Inserted) = VFTablesMap.insert(std::make_pair(ID, nullptr));
> +  std::tie(I, Inserted) = VTablesMap.insert(std::make_pair(ID, nullptr));
>    if (!Inserted)
>      return I->second;
>
> @@ -1140,21 +1141,73 @@ llvm::GlobalVariable *MicrosoftCXXABI::g
>    for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {
>      if (VFPtrs[J]->FullOffsetInMDC != VPtrOffset)
>        continue;
> +    SmallString<256> VFTableName;
> +    mangleVFTableName(getMangleContext(), RD, VFPtrs[J], VFTableName);
> +    StringRef VTableName = VFTableName;
>
> -    llvm::ArrayType *ArrayType = llvm::ArrayType::get(
> -        CGM.Int8PtrTy,
> +    uint64_t NumVTableSlots =
>          VTContext.getVFTableLayout(RD, VFPtrs[J]->FullOffsetInMDC)
> -            .getNumVTableComponents());
> +            .getNumVTableComponents();
> +    llvm::GlobalValue::LinkageTypes VTableLinkage =
> +        llvm::GlobalValue::ExternalLinkage;
> +    llvm::ArrayType *VTableType =
> +        llvm::ArrayType::get(CGM.Int8PtrTy, NumVTableSlots);
> +    if (getContext().getLangOpts().RTTI) {
> +      VTableLinkage = llvm::GlobalValue::PrivateLinkage;
> +      VTableName = "";
> +    }
>
> -    SmallString<256> Name;
> -    mangleVFTableName(getMangleContext(), RD, VFPtrs[J], Name);
> -    VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
> -        Name.str(), ArrayType, llvm::GlobalValue::ExternalLinkage);
> -    VTable->setUnnamedAddr(true);
> -    if (RD->hasAttr<DLLImportAttr>())
> -
>  VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
> -    else if (RD->hasAttr<DLLExportAttr>())
> -
>  VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
> +    VTable = CGM.getModule().getNamedGlobal(VFTableName);
> +    if (!VTable) {
> +      llvm::GlobalValue *VFTable = VTable = new llvm::GlobalVariable(
> +          CGM.getModule(), VTableType, /*isConstant=*/true, VTableLinkage,
> +          /*Initializer=*/nullptr, VTableName);
> +      VTable->setUnnamedAddr(true);
> +      if (getContext().getLangOpts().RTTI &&
> !RD->hasAttr<DLLImportAttr>()) {
> +        llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0),
> +                                     llvm::ConstantInt::get(CGM.IntTy,
> 1)};
> +        llvm::Constant *VTableGEP =
> +            llvm::ConstantExpr::getInBoundsGetElementPtr(VTable,
> GEPIndices);
> +        VFTable = llvm::GlobalAlias::create(
> +
>  cast<llvm::SequentialType>(VTableGEP->getType())->getElementType(),
> +            /*AddressSpace=*/0, llvm::GlobalValue::ExternalLinkage,
> +            VFTableName.str(), VTableGEP, &CGM.getModule());
> +      } else {
> +        VTable->setName(VFTableName.str());
> +      }
> +
> +      VFTable->setUnnamedAddr(true);
> +      if (RD->hasAttr<DLLImportAttr>())
> +
>  VFTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
> +      else if (RD->hasAttr<DLLExportAttr>())
> +
>  VFTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
> +
> +      llvm::GlobalValue::LinkageTypes VFTableLinkage =
> CGM.getVTableLinkage(RD);
> +      if (VFTable != VTable) {
> +        if
> (llvm::GlobalValue::isAvailableExternallyLinkage(VFTableLinkage)) {
> +          // AvailableExternally implies that we grabbed the data from
> another
> +          // executable.  No need to stick the alias in a Comdat.
> +        } else if (llvm::GlobalValue::isLocalLinkage(VFTableLinkage)) {
> +          // If it's local, it means that the virtual function table
> can't be
> +          // referenced in another translation unit. No need to stick the
> alias
> +          // in a Comdat.
> +        } else if (llvm::GlobalValue::isWeakODRLinkage(VFTableLinkage) ||
> +
> llvm::GlobalValue::isLinkOnceODRLinkage(VFTableLinkage)) {
> +          // The alias is going to be dropped into a Comdat, no need to
> make it
> +          // weak.
> +          VFTableLinkage = llvm::GlobalValue::ExternalLinkage;
> +          llvm::Comdat *C =
> +              CGM.getModule().getOrInsertComdat(VFTable->getName());
> +          C->setSelectionKind(llvm::Comdat::Largest);
> +          VTable->setComdat(C);
> +        } else {
> +          llvm_unreachable("unexpected linkage for vftable!");
> +        }
> +      }
> +      VFTable->setLinkage(VFTableLinkage);
> +      CGM.setGlobalVisibility(VFTable, RD);
> +      VFTablesMap[ID] = VFTable;
> +    }
>      break;
>    }
>
>
> Modified: cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp?rev=212125&r1=212124&r2=212125&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp (original)
> +++ cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp Tue Jul  1 15:30:31 2014
> @@ -505,8 +505,10 @@ llvm::Constant *CodeGenModule::getMSType
>        Int8PtrTy);
>  }
>
> -llvm::GlobalVariable *
> +llvm::Constant *
>  CodeGenModule::getMSCompleteObjectLocator(const CXXRecordDecl *RD,
>                                            const VPtrInfo *Info) {
> +  if (!getLangOpts().RTTI)
> +    return llvm::Constant::getNullValue(Int8PtrTy);
>    return MSRTTIBuilder(*this, RD).getCompleteObjectLocator(Info);
>  }
>
> Modified: cfe/trunk/test/CodeGenCXX/dllexport.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport.cpp?rev=212125&r1=212124&r2=212125&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/dllexport.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/dllexport.cpp Tue Jul  1 15:30:31 2014
> @@ -24,6 +24,9 @@ struct External { int v; };
>  #define INSTVAR(var) template int var;
>  #define INST(func) template void func();
>
> +// The vftable for struct W is comdat largest because we have RTTI.
> +// M32-DAG: $"\01??_7W@@6B@" = comdat largest
> +
>
>
>  //===----------------------------------------------------------------------===//
>  // Globals
> @@ -518,7 +521,8 @@ struct __declspec(dllexport) W { virtual
>  // Copy ctor:
>  // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.W* @"\01??0W@
> @QAE at ABU0@@Z"
>  // vftable:
> -// M32-DAG: @"\01??_7W@@6B@" = weak_odr dllexport unnamed_addr constant
> [1 x i8*] [i8* bitcast (void (%struct.W*)* @"\01?foo at W@@UAEXXZ" to i8*)]
> +// M32-DAG: [[W_VTABLE:@.*]] = private unnamed_addr constant [2 x i8*]
> [i8* bitcast (%MSRTTICompleteObjectLocator* @"\01??_R4W@@6B@" to i8*),
> i8* bitcast (void (%struct.W*)* @"\01?foo at W@@UAEXXZ" to i8*)], comdat
> $"\01??_7W@@6B@"
> +// M32-DAG: @"\01??_7W@@6B@" = dllexport unnamed_addr alias
> getelementptr inbounds ([2 x i8*]* [[W_VTABLE]], i32 0, i32 1), comdat
> $"\01??_7W@@6B@"
>  // G32-DAG: @_ZTV1W = weak_odr dllexport unnamed_addr constant [3 x i8*]
> [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1W to i8*), i8* bitcast (void
> (%struct.W*)* @_ZN1W3fooEv to i8*)]
>
>  struct __declspec(dllexport) X : public virtual W {};
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140708/5e9d4e0c/attachment.html>


More information about the cfe-commits mailing list