r212125 - MS ABI: Reference MSVC RTTI from the VFTable

Timur Iskhodzhanov timurrrr at google.com
Tue Jul 8 06:35:28 PDT 2014


... and let's move the discussion of the fix there too.

2014-07-08 17:15 GMT+04:00 Timur Iskhodzhanov <timurrrr at google.com>:
> Filed
> http://llvm.org/bugs/show_bug.cgi?id=20244
> to track the progress.
>
> 2014-07-08 16:28 GMT+04:00 Timur Iskhodzhanov <timurrrr at google.com>:
>> 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
>>
>>



More information about the cfe-commits mailing list