r212125 - MS ABI: Reference MSVC RTTI from the VFTable
Timur Iskhodzhanov
timurrrr at google.com
Tue Jul 8 06:15:11 PDT 2014
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