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