summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2016-06-24 21:21:46 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2016-06-24 21:21:46 +0000
commit3400678c4baef75ea1bd67e3f03b6f034302e51c (patch)
treef82348f1d4fb6c245b9c6560f60a7dbe8b8832fe
parent7c599a54a6a9431a44112599fc9166a0e381e932 (diff)
CodeGen: Update Clang to use the new type metadata.
Differential Revision: http://reviews.llvm.org/D21054 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@273730 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--docs/ControlFlowIntegrityDesign.rst18
-rw-r--r--lib/CodeGen/CGClass.cpp38
-rw-r--r--lib/CodeGen/CGExpr.cpp17
-rw-r--r--lib/CodeGen/CGVTables.cpp13
-rw-r--r--lib/CodeGen/CodeGenFunction.h10
-rw-r--r--lib/CodeGen/CodeGenModule.cpp70
-rw-r--r--lib/CodeGen/CodeGenModule.h26
-rw-r--r--lib/CodeGen/ItaniumCXXABI.cpp4
-rw-r--r--lib/CodeGen/MicrosoftCXXABI.cpp29
-rw-r--r--test/CodeGen/cfi-check-fail.c2
-rw-r--r--test/CodeGen/cfi-check-fail2.c2
-rw-r--r--test/CodeGen/cfi-icall-cross-dso.c64
-rw-r--r--test/CodeGen/cfi-icall.c18
-rw-r--r--test/CodeGenCXX/bitsets.cpp211
-rw-r--r--test/CodeGenCXX/cfi-blacklist.cpp8
-rw-r--r--test/CodeGenCXX/cfi-cast.cpp28
-rw-r--r--test/CodeGenCXX/cfi-cross-dso.cpp4
-rw-r--r--test/CodeGenCXX/cfi-icall.cpp9
-rw-r--r--test/CodeGenCXX/cfi-ms-rtti.cpp4
-rw-r--r--test/CodeGenCXX/cfi-nvcall.cpp8
-rw-r--r--test/CodeGenCXX/lto-visibility-inference.cpp (renamed from test/CodeGenCXX/bitset-inference.cpp)50
-rw-r--r--test/CodeGenCXX/type-metadata.cpp226
22 files changed, 420 insertions, 439 deletions
diff --git a/docs/ControlFlowIntegrityDesign.rst b/docs/ControlFlowIntegrityDesign.rst
index b4aacd3656..38c5e5b99e 100644
--- a/docs/ControlFlowIntegrityDesign.rst
+++ b/docs/ControlFlowIntegrityDesign.rst
@@ -90,10 +90,10 @@ For example on x86 a typical virtual call may look like this:
The compiler relies on co-operation from the linker in order to assemble
the bit vectors for the whole program. It currently does this using LLVM's
-`bit sets`_ mechanism together with link-time optimization.
+`type metadata`_ mechanism together with link-time optimization.
.. _address point: https://mentorembedded.github.io/cxx-abi/abi.html#vtable-general
-.. _bit sets: http://llvm.org/docs/BitSets.html
+.. _type metadata: http://llvm.org/docs/TypeMetadata.html
.. _ByteArrayBuilder: http://llvm.org/docs/doxygen/html/structllvm_1_1ByteArrayBuilder.html
Optimizations
@@ -196,7 +196,7 @@ those sub-hierarchies need to be (see "Stripping Leading/Trailing Zeros in Bit
Vectors" above). The `GlobalLayoutBuilder`_ class is responsible for laying
out the globals efficiently to minimize the sizes of the underlying bitsets.
-.. _GlobalLayoutBuilder: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO/LowerBitSets.h?view=markup
+.. _GlobalLayoutBuilder: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO/LowerTypeTests.h?view=markup
Alignment
~~~~~~~~~
@@ -297,8 +297,8 @@ file's symbol table, the symbols for the target functions also refer to the
jump table entries, so that addresses taken outside the module will pass
any verification done inside the module.
-In more concrete terms, suppose we have three functions ``f``, ``g``, ``h``
-which are members of a single bitset, and a function foo that returns their
+In more concrete terms, suppose we have three functions ``f``, ``g``,
+``h`` which are all of the same type, and a function foo that returns their
addresses:
.. code-block:: none
@@ -439,10 +439,10 @@ export this information, every DSO implements
void __cfi_check(uint64 CallSiteTypeId, void *TargetAddr)
-This function provides external modules with access to CFI checks for
-the targets inside this DSO. For each known ``CallSiteTypeId``, this
-functions performs an ``llvm.bitset.test`` with the corresponding bit
-set. It aborts if the type is unknown, or if the check fails.
+This function provides external modules with access to CFI checks for the
+targets inside this DSO. For each known ``CallSiteTypeId``, this function
+performs an ``llvm.type.test`` with the corresponding type identifier. It
+aborts if the type is unknown, or if the check fails.
The basic implementation is a large switch statement over all values
of CallSiteTypeId supported by this DSO, and each case is similar to
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index dc4455fbc7..ba46541b02 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -2485,21 +2485,21 @@ LeastDerivedClassWithSameLayout(const CXXRecordDecl *RD) {
RD->bases_begin()->getType()->getAsCXXRecordDecl());
}
-void CodeGenFunction::EmitBitSetCodeForVCall(const CXXRecordDecl *RD,
- llvm::Value *VTable,
- SourceLocation Loc) {
+void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
+ llvm::Value *VTable,
+ SourceLocation Loc) {
if (CGM.getCodeGenOpts().WholeProgramVTables &&
CGM.HasHiddenLTOVisibility(RD)) {
llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
- llvm::Value *BitSetName =
+ llvm::Value *TypeId =
llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD);
llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy);
- llvm::Value *BitSetTest =
- Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
- {CastedVTable, BitSetName});
- Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), BitSetTest);
+ llvm::Value *TypeTest =
+ Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),
+ {CastedVTable, TypeId});
+ Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest);
}
if (SanOpts.has(SanitizerKind::CFIVCall))
@@ -2595,12 +2595,11 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
- llvm::Value *BitSetName = llvm::MetadataAsValue::get(getLLVMContext(), MD);
+ llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD);
llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy);
- llvm::Value *BitSetTest =
- Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
- {CastedVTable, BitSetName});
+ llvm::Value *TypeTest = Builder.CreateCall(
+ CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedVTable, TypeId});
SanitizerMask M;
switch (TCK) {
@@ -2626,24 +2625,23 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
EmitCheckTypeDescriptor(QualType(RD->getTypeForDecl(), 0)),
};
- auto TypeId = CGM.CreateCfiIdForTypeMetadata(MD);
- if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && TypeId) {
- EmitCfiSlowPathCheck(M, BitSetTest, TypeId, CastedVTable, StaticData);
+ auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD);
+ if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) {
+ EmitCfiSlowPathCheck(M, TypeTest, CrossDsoTypeId, CastedVTable, StaticData);
return;
}
if (CGM.getCodeGenOpts().SanitizeTrap.has(M)) {
- EmitTrapCheck(BitSetTest);
+ EmitTrapCheck(TypeTest);
return;
}
llvm::Value *AllVtables = llvm::MetadataAsValue::get(
CGM.getLLVMContext(),
llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
- llvm::Value *ValidVtable =
- Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
- {CastedVTable, AllVtables});
- EmitCheck(std::make_pair(BitSetTest, M), "cfi_check_fail", StaticData,
+ llvm::Value *ValidVtable = Builder.CreateCall(
+ CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedVTable, AllVtables});
+ EmitCheck(std::make_pair(TypeTest, M), "cfi_check_fail", StaticData,
{CastedVTable, ValidVtable});
}
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 7f8d87e925..9917a6b414 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -2682,7 +2682,7 @@ void CodeGenFunction::EmitCfiCheckFail() {
CGM.getLLVMContext(),
llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
llvm::Value *ValidVtable = Builder.CreateZExt(
- Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
+ Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),
{Addr, AllVtables}),
IntPtrTy);
@@ -4050,24 +4050,23 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
EmitSanitizerStatReport(llvm::SanStat_CFI_ICall);
llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(QualType(FnType, 0));
- llvm::Value *BitSetName = llvm::MetadataAsValue::get(getLLVMContext(), MD);
+ llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD);
llvm::Value *CastedCallee = Builder.CreateBitCast(Callee, Int8PtrTy);
- llvm::Value *BitSetTest =
- Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
- {CastedCallee, BitSetName});
+ llvm::Value *TypeTest = Builder.CreateCall(
+ CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedCallee, TypeId});
- auto TypeId = CGM.CreateCfiIdForTypeMetadata(MD);
+ auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD);
llvm::Constant *StaticData[] = {
llvm::ConstantInt::get(Int8Ty, CFITCK_ICall),
EmitCheckSourceLocation(E->getLocStart()),
EmitCheckTypeDescriptor(QualType(FnType, 0)),
};
- if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && TypeId) {
- EmitCfiSlowPathCheck(SanitizerKind::CFIICall, BitSetTest, TypeId,
+ if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) {
+ EmitCfiSlowPathCheck(SanitizerKind::CFIICall, TypeTest, CrossDsoTypeId,
CastedCallee, StaticData);
} else {
- EmitCheck(std::make_pair(BitSetTest, SanitizerKind::CFIICall),
+ EmitCheck(std::make_pair(TypeTest, SanitizerKind::CFIICall),
"cfi_check_fail", StaticData,
{CastedCallee, llvm::UndefValue::get(IntPtrTy)});
}
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index 6f749056ad..83974e0d21 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -709,7 +709,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
VTLayout->getNumVTableThunks(), RTTI);
VTable->setInitializer(Init);
- CGM.EmitVTableBitSetEntries(VTable, *VTLayout.get());
+ CGM.EmitVTableTypeMetadata(VTable, *VTLayout.get());
return VTable;
}
@@ -933,8 +933,8 @@ bool CodeGenModule::HasHiddenLTOVisibility(const CXXRecordDecl *RD) {
return true;
}
-void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
- const VTableLayout &VTLayout) {
+void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable,
+ const VTableLayout &VTLayout) {
if (!getCodeGenOpts().PrepareForLTO)
return;
@@ -973,10 +973,7 @@ void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
return E1.second < E2.second;
});
- llvm::NamedMDNode *BitsetsMD =
- getModule().getOrInsertNamedMetadata("llvm.bitsets");
for (auto BitsetEntry : BitsetEntries)
- CreateVTableBitSetEntry(BitsetsMD, VTable,
- PointerWidth * BitsetEntry.second,
- BitsetEntry.first);
+ AddVTableTypeMetadata(VTable, PointerWidth * BitsetEntry.second,
+ BitsetEntry.first);
}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index af7e6114af..28ee621b31 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -1413,15 +1413,15 @@ public:
CFITypeCheckKind TCK, SourceLocation Loc);
/// EmitVTablePtrCheck - Emit a check that VTable is a valid virtual table for
- /// RD using llvm.bitset.test.
+ /// RD using llvm.type.test.
void EmitVTablePtrCheck(const CXXRecordDecl *RD, llvm::Value *VTable,
CFITypeCheckKind TCK, SourceLocation Loc);
/// If whole-program virtual table optimization is enabled, emit an assumption
- /// that VTable is a member of the type's bitset. Or, if vptr CFI is enabled,
- /// emit a check that VTable is a member of the type's bitset.
- void EmitBitSetCodeForVCall(const CXXRecordDecl *RD, llvm::Value *VTable,
- SourceLocation Loc);
+ /// that VTable is a member of RD's type identifier. Or, if vptr CFI is
+ /// enabled, emit a check that VTable is a member of RD's type identifier.
+ void EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
+ llvm::Value *VTable, SourceLocation Loc);
/// CanDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given
/// expr can be devirtualized.
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 507772707c..02858b3864 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -787,8 +787,7 @@ void CodeGenModule::setFunctionDLLStorageClass(GlobalDecl GD, llvm::Function *F)
F->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass);
}
-llvm::ConstantInt *
-CodeGenModule::CreateCfiIdForTypeMetadata(llvm::Metadata *MD) {
+llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) {
llvm::MDString *MDS = dyn_cast<llvm::MDString>(MD);
if (!MDS) return nullptr;
@@ -989,8 +988,8 @@ static void setLinkageAndVisibilityForGV(llvm::GlobalValue *GV,
}
}
-void CodeGenModule::CreateFunctionBitSetEntry(const FunctionDecl *FD,
- llvm::Function *F) {
+void CodeGenModule::CreateFunctionTypeMetadata(const FunctionDecl *FD,
+ llvm::Function *F) {
// Only if we are checking indirect calls.
if (!LangOpts.Sanitize.has(SanitizerKind::CFIICall))
return;
@@ -1011,25 +1010,13 @@ void CodeGenModule::CreateFunctionBitSetEntry(const FunctionDecl *FD,
return;
}
- llvm::NamedMDNode *BitsetsMD =
- getModule().getOrInsertNamedMetadata("llvm.bitsets");
-
llvm::Metadata *MD = CreateMetadataIdentifierForType(FD->getType());
- llvm::Metadata *BitsetOps[] = {
- MD, llvm::ConstantAsMetadata::get(F),
- llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(Int64Ty, 0))};
- BitsetsMD->addOperand(llvm::MDTuple::get(getLLVMContext(), BitsetOps));
+ F->addTypeMetadata(0, MD);
// Emit a hash-based bit set entry for cross-DSO calls.
- if (CodeGenOpts.SanitizeCfiCrossDso) {
- if (auto TypeId = CreateCfiIdForTypeMetadata(MD)) {
- llvm::Metadata *BitsetOps2[] = {
- llvm::ConstantAsMetadata::get(TypeId),
- llvm::ConstantAsMetadata::get(F),
- llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(Int64Ty, 0))};
- BitsetsMD->addOperand(llvm::MDTuple::get(getLLVMContext(), BitsetOps2));
- }
- }
+ if (CodeGenOpts.SanitizeCfiCrossDso)
+ if (auto CrossDsoTypeId = CreateCrossDsoCfiTypeId(MD))
+ F->addTypeMetadata(0, llvm::ConstantAsMetadata::get(CrossDsoTypeId));
}
void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
@@ -1090,7 +1077,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
if (MD->isVirtual())
F->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- CreateFunctionBitSetEntry(FD, F);
+ CreateFunctionTypeMetadata(FD, F);
}
void CodeGenModule::addUsedGlobal(llvm::GlobalValue *GV) {
@@ -4219,8 +4206,8 @@ llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) {
return InternalId;
}
-/// Returns whether this module needs the "all-vtables" bitset.
-bool CodeGenModule::NeedAllVtablesBitSet() const {
+/// Returns whether this module needs the "all-vtables" type identifier.
+bool CodeGenModule::NeedAllVtablesTypeId() const {
// Returns true if at least one of vtable-based CFI checkers is enabled and
// is not in the trapping mode.
return ((LangOpts.Sanitize.has(SanitizerKind::CFIVCall) &&
@@ -4233,38 +4220,21 @@ bool CodeGenModule::NeedAllVtablesBitSet() const {
!CodeGenOpts.SanitizeTrap.has(SanitizerKind::CFIUnrelatedCast)));
}
-void CodeGenModule::CreateVTableBitSetEntry(llvm::NamedMDNode *BitsetsMD,
- llvm::GlobalVariable *VTable,
- CharUnits Offset,
- const CXXRecordDecl *RD) {
+void CodeGenModule::AddVTableTypeMetadata(llvm::GlobalVariable *VTable,
+ CharUnits Offset,
+ const CXXRecordDecl *RD) {
llvm::Metadata *MD =
CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
- llvm::Metadata *BitsetOps[] = {
- MD, llvm::ConstantAsMetadata::get(VTable),
- llvm::ConstantAsMetadata::get(
- llvm::ConstantInt::get(Int64Ty, Offset.getQuantity()))};
- BitsetsMD->addOperand(llvm::MDTuple::get(getLLVMContext(), BitsetOps));
+ VTable->addTypeMetadata(Offset.getQuantity(), MD);
- if (CodeGenOpts.SanitizeCfiCrossDso) {
- if (auto TypeId = CreateCfiIdForTypeMetadata(MD)) {
- llvm::Metadata *BitsetOps2[] = {
- llvm::ConstantAsMetadata::get(TypeId),
- llvm::ConstantAsMetadata::get(VTable),
- llvm::ConstantAsMetadata::get(
- llvm::ConstantInt::get(Int64Ty, Offset.getQuantity()))};
- BitsetsMD->addOperand(llvm::MDTuple::get(getLLVMContext(), BitsetOps2));
- }
- }
+ if (CodeGenOpts.SanitizeCfiCrossDso)
+ if (auto CrossDsoTypeId = CreateCrossDsoCfiTypeId(MD))
+ VTable->addTypeMetadata(Offset.getQuantity(),
+ llvm::ConstantAsMetadata::get(CrossDsoTypeId));
- if (NeedAllVtablesBitSet()) {
+ if (NeedAllVtablesTypeId()) {
llvm::Metadata *MD = llvm::MDString::get(getLLVMContext(), "all-vtables");
- llvm::Metadata *BitsetOps[] = {
- MD, llvm::ConstantAsMetadata::get(VTable),
- llvm::ConstantAsMetadata::get(
- llvm::ConstantInt::get(Int64Ty, Offset.getQuantity()))};
- // Avoid adding a node to BitsetsMD twice.
- if (!llvm::MDTuple::getIfExists(getLLVMContext(), BitsetOps))
- BitsetsMD->addOperand(llvm::MDTuple::get(getLLVMContext(), BitsetOps));
+ VTable->addTypeMetadata(Offset.getQuantity(), MD);
}
}
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index a75e4aa2a3..94904997d6 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -1118,29 +1118,27 @@ public:
/// optimization.
bool HasHiddenLTOVisibility(const CXXRecordDecl *RD);
- /// Emit bit set entries for the given vtable using the given layout if
- /// vptr CFI is enabled.
- void EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
- const VTableLayout &VTLayout);
+ /// Emit type metadata for the given vtable using the given layout.
+ void EmitVTableTypeMetadata(llvm::GlobalVariable *VTable,
+ const VTableLayout &VTLayout);
- /// Generate a cross-DSO type identifier for type.
- llvm::ConstantInt *CreateCfiIdForTypeMetadata(llvm::Metadata *MD);
+ /// Generate a cross-DSO type identifier for MD.
+ llvm::ConstantInt *CreateCrossDsoCfiTypeId(llvm::Metadata *MD);
/// Create a metadata identifier for the given type. This may either be an
/// MDString (for external identifiers) or a distinct unnamed MDNode (for
/// internal identifiers).
llvm::Metadata *CreateMetadataIdentifierForType(QualType T);
- /// Create a bitset entry for the given function and add it to BitsetsMD.
- void CreateFunctionBitSetEntry(const FunctionDecl *FD, llvm::Function *F);
+ /// Create and attach type metadata to the given function.
+ void CreateFunctionTypeMetadata(const FunctionDecl *FD, llvm::Function *F);
- /// Returns whether this module needs the "all-vtables" bitset.
- bool NeedAllVtablesBitSet() const;
+ /// Returns whether this module needs the "all-vtables" type identifier.
+ bool NeedAllVtablesTypeId() const;
- /// Create a bitset entry for the given vtable and add it to BitsetsMD.
- void CreateVTableBitSetEntry(llvm::NamedMDNode *BitsetsMD,
- llvm::GlobalVariable *VTable, CharUnits Offset,
- const CXXRecordDecl *RD);
+ /// Create and attach type metadata for the given vtable.
+ void AddVTableTypeMetadata(llvm::GlobalVariable *VTable, CharUnits Offset,
+ const CXXRecordDecl *RD);
/// \breif Get the declaration of std::terminate for the platform.
llvm::Constant *getTerminateFn();
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index 891db6df42..b33ef73fa4 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -1490,7 +1490,7 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
EmitFundamentalRTTIDescriptors();
if (!VTable->isDeclarationForLinker())
- CGM.EmitVTableBitSetEntries(VTable, VTLayout);
+ CGM.EmitVTableTypeMetadata(VTable, VTLayout);
}
bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(
@@ -1595,7 +1595,7 @@ llvm::Value *ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl());
llvm::Value *VTable = CGF.GetVTablePtr(This, Ty, MethodDecl->getParent());
- CGF.EmitBitSetCodeForVCall(MethodDecl->getParent(), VTable, Loc);
+ CGF.EmitTypeMetadataCodeForVCall(MethodDecl->getParent(), VTable, Loc);
uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
llvm::Value *VFuncPtr =
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index 4482372c5d..a48e084158 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -254,8 +254,8 @@ public:
CXXDtorType Type, bool ForVirtualBase,
bool Delegating, Address This) override;
- void emitVTableBitSetEntries(VPtrInfo *Info, const CXXRecordDecl *RD,
- llvm::GlobalVariable *VTable);
+ void emitVTableTypeMetadata(VPtrInfo *Info, const CXXRecordDecl *RD,
+ llvm::GlobalVariable *VTable);
void emitVTableDefinitions(CodeGenVTables &CGVT,
const CXXRecordDecl *RD) override;
@@ -1502,15 +1502,12 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
getFromDtorType(Type));
}
-void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info,
- const CXXRecordDecl *RD,
- llvm::GlobalVariable *VTable) {
+void MicrosoftCXXABI::emitVTableTypeMetadata(VPtrInfo *Info,
+ const CXXRecordDecl *RD,
+ llvm::GlobalVariable *VTable) {
if (!CGM.getCodeGenOpts().PrepareForLTO)
return;
- llvm::NamedMDNode *BitsetsMD =
- CGM.getModule().getOrInsertNamedMetadata("llvm.bitsets");
-
// The location of the first virtual function pointer in the virtual table,
// aka the "address point" on Itanium. This is at offset 0 if RTTI is
// disabled, or sizeof(void*) if RTTI is enabled.
@@ -1521,13 +1518,13 @@ void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info,
: CharUnits::Zero();
if (Info->PathToBaseWithVPtr.empty()) {
- CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD);
+ CGM.AddVTableTypeMetadata(VTable, AddressPoint, RD);
return;
}
// Add a bitset entry for the least derived base belonging to this vftable.
- CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint,
- Info->PathToBaseWithVPtr.back());
+ CGM.AddVTableTypeMetadata(VTable, AddressPoint,
+ Info->PathToBaseWithVPtr.back());
// Add a bitset entry for each derived class that is laid out at the same
// offset as the least derived base.
@@ -1545,12 +1542,12 @@ void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info,
Offset = VBI->second.VBaseOffset;
if (!Offset.isZero())
return;
- CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, DerivedRD);
+ CGM.AddVTableTypeMetadata(VTable, AddressPoint, DerivedRD);
}
// Finally do the same for the most derived class.
if (Info->FullOffsetInMDC.isZero())
- CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD);
+ CGM.AddVTableTypeMetadata(VTable, AddressPoint, RD);
}
void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
@@ -1578,7 +1575,7 @@ void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
VTable->setInitializer(Init);
- emitVTableBitSetEntries(Info, RD, VTable);
+ emitVTableTypeMetadata(Info, RD, VTable);
}
}
@@ -1819,8 +1816,8 @@ llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
MicrosoftVTableContext::MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
if (CGM.getCodeGenOpts().PrepareForLTO)
- CGF.EmitBitSetCodeForVCall(getClassAtVTableLocation(getContext(), GD, ML),
- VTable, Loc);
+ CGF.EmitTypeMetadataCodeForVCall(
+ getClassAtVTableLocation(getContext(), GD, ML), VTable, Loc);
llvm::Value *VFuncPtr =
Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn");
diff --git a/test/CodeGen/cfi-check-fail.c b/test/CodeGen/cfi-check-fail.c
index 4560cd8747..b850193b54 100644
--- a/test/CodeGen/cfi-check-fail.c
+++ b/test/CodeGen/cfi-check-fail.c
@@ -23,7 +23,7 @@ void caller(void (*f)()) {
// CHECK: %[[A:.*]] = bitcast i8* %[[DATA]] to { i8, { i8*, i32, i32 }, i8* }*
// CHECK: %[[KINDPTR:.*]] = getelementptr {{.*}} %[[A]], i32 0, i32 0
// CHECK: %[[KIND:.*]] = load i8, i8* %[[KINDPTR]], align 4
-// CHECK: %[[VTVALID0:.*]] = call i1 @llvm.bitset.test(i8* %[[ADDR]], metadata !"all-vtables")
+// CHECK: %[[VTVALID0:.*]] = call i1 @llvm.type.test(i8* %[[ADDR]], metadata !"all-vtables")
// CHECK: %[[VTVALID:.*]] = zext i1 %[[VTVALID0]] to i64
// CHECK: %[[NOT_0:.*]] = icmp ne i8 %[[KIND]], 0
// CHECK: br i1 %[[NOT_0]], label %[[CONT1:.*]], label %[[HANDLE0:.*]], !prof
diff --git a/test/CodeGen/cfi-check-fail2.c b/test/CodeGen/cfi-check-fail2.c
index 02ceb930e6..5340871c2e 100644
--- a/test/CodeGen/cfi-check-fail2.c
+++ b/test/CodeGen/cfi-check-fail2.c
@@ -23,7 +23,7 @@ void caller(void (*f)()) {
// CHECK: %[[A:.*]] = bitcast i8* %[[DATA]] to { i8, { i8*, i32, i32 }, i8* }*
// CHECK: %[[KINDPTR:.*]] = getelementptr {{.*}} %[[A]], i32 0, i32 0
// CHECK: %[[KIND:.*]] = load i8, i8* %[[KINDPTR]], align 4
-// CHECK: %[[VTVALID0:.*]] = call i1 @llvm.bitset.test(i8* %[[ADDR]], metadata !"all-vtables")
+// CHECK: %[[VTVALID0:.*]] = call i1 @llvm.type.test(i8* %[[ADDR]], metadata !"all-vtables")
// CHECK: %[[VTVALID:.*]] = zext i1 %[[VTVALID0]] to i64
// CHECK: %[[NOT_0:.*]] = icmp ne i8 %[[KIND]], 0
// CHECK: br i1 %[[NOT_0]], label %[[CONT1:.*]], label %[[HANDLE0:.*]], !prof
diff --git a/test/CodeGen/cfi-icall-cross-dso.c b/test/CodeGen/cfi-icall-cross-dso.c
index 13cff1065f..636a9e4aed 100644
--- a/test/CodeGen/cfi-icall-cross-dso.c
+++ b/test/CodeGen/cfi-icall-cross-dso.c
@@ -26,11 +26,30 @@
// RUN: --check-prefix=MS --check-prefix=MS-TRAP \
// RUN: %s
+// CHECK-DIAG: @[[SRC:.*]] = private unnamed_addr constant {{.*}}cfi-icall-cross-dso.c\00
+// CHECK-DIAG: @[[TYPE:.*]] = private unnamed_addr constant { i16, i16, [{{.*}} x i8] } { i16 -1, i16 0, [{{.*}} x i8] c"'void ()'\00"
+// CHECK-DIAG: @[[DATA:.*]] = private unnamed_addr global {{.*}}@[[SRC]]{{.*}}@[[TYPE]]
+
+
+// ITANIUM: call i1 @llvm.type.test(i8* %{{.*}}, metadata !"_ZTSFvE"), !nosanitize
+// ITANIUM-DIAG: call void @__cfi_slowpath_diag(i64 6588678392271548388, i8* %{{.*}}, {{.*}}@[[DATA]]{{.*}}) {{.*}}, !nosanitize
+// ITANIUM-TRAP: call void @__cfi_slowpath(i64 6588678392271548388, i8* %{{.*}}) {{.*}}, !nosanitize
+
+// MS: call i1 @llvm.type.test(i8* %{{.*}}, metadata !"?6AX@Z"), !nosanitize
+// MS-DIAG: call void @__cfi_slowpath_diag(i64 4195979634929632483, i8* %{{.*}}, {{.*}}@[[DATA]]{{.*}}) {{.*}}, !nosanitize
+// MS-TRAP: call void @__cfi_slowpath(i64 4195979634929632483, i8* %{{.*}}) {{.*}}, !nosanitize
+
void caller(void (*f)()) {
f();
}
+// Check that we emit both string and hash based type entries for static void g(),
+// and don't emit them for the declaration of h().
+
+// CHECK: define internal void @g({{.*}} !type [[TVOID:![0-9]+]] !type [[TVOID_ID:![0-9]+]]
static void g(void) {}
+
+// CHECK: declare void @h({{[^!]*$}}
void h(void);
typedef void (*Fn)(void);
@@ -41,41 +60,22 @@ Fn h1() {
return &h;
}
+// CHECK: define void @bar({{.*}} !type [[TNOPROTO:![0-9]+]] !type [[TNOPROTO_ID:![0-9]+]]
+// ITANIUM: define available_externally void @foo({{[^!]*$}}
+// MS: define linkonce_odr void @foo({{.*}} !type [[TNOPROTO]] !type [[TNOPROTO_ID]]
inline void foo() {}
void bar() { foo(); }
-// CHECK-DIAG: @[[SRC:.*]] = private unnamed_addr constant {{.*}}cfi-icall-cross-dso.c\00
-// CHECK-DIAG: @[[TYPE:.*]] = private unnamed_addr constant { i16, i16, [{{.*}} x i8] } { i16 -1, i16 0, [{{.*}} x i8] c"'void ()'\00"
-// CHECK-DIAG: @[[DATA:.*]] = private unnamed_addr global {{.*}}@[[SRC]]{{.*}}@[[TYPE]]
-
-
-// ITANIUM: call i1 @llvm.bitset.test(i8* %{{.*}}, metadata !"_ZTSFvE"), !nosanitize
-// ITANIUM-DIAG: call void @__cfi_slowpath_diag(i64 6588678392271548388, i8* %{{.*}}, {{.*}}@[[DATA]]{{.*}}) {{.*}}, !nosanitize
-// ITANIUM-TRAP: call void @__cfi_slowpath(i64 6588678392271548388, i8* %{{.*}}) {{.*}}, !nosanitize
-
-// MS: call i1 @llvm.bitset.test(i8* %{{.*}}, metadata !"?6AX@Z"), !nosanitize
-// MS-DIAG: call void @__cfi_slowpath_diag(i64 4195979634929632483, i8* %{{.*}}, {{.*}}@[[DATA]]{{.*}}) {{.*}}, !nosanitize
-// MS-TRAP: call void @__cfi_slowpath(i64 4195979634929632483, i8* %{{.*}}) {{.*}}, !nosanitize
-
-// ITANIUM: define available_externally void @foo()
-// MS: define linkonce_odr void @foo()
-
-// Check that we emit both string and hash based bit set entries for static void g(),
-// and don't emit them for the declaration of h().
-
-// CHECK-NOT: !{!"{{.*}}", void ()* @h, i64 0}
-// CHECK: !{!"{{.*}}", void ()* @g, i64 0}
-// CHECK-NOT: !{!"{{.*}}", void ()* @h, i64 0}
-// CHECK: !{i64 {{.*}}, void ()* @g, i64 0}
-// CHECK-NOT: !{!"{{.*}}", void ()* @h, i64 0}
+// CHECK: !{i32 4, !"Cross-DSO CFI", i32 1}
-// ITANIUM-NOT: !{!{{.*}}, void ()* @foo,
-// ITANIUM: !{!"_ZTSFvE", void ()* @bar, i64 0}
-// ITANIUM-NOT: !{!{{.*}}, void ()* @foo,
-// ITANIUM: !{i64 6588678392271548388, void ()* @bar, i64 0}
-// ITANIUM-NOT: !{!{{.*}}, void ()* @foo,
+// Check that the type entries are correct.
-// MS: !{!"?6AX@Z", void ()* @foo, i64 0}
-// MS: !{i64 4195979634929632483, void ()* @foo, i64 0}
+// ITANIUM: [[TVOID]] = !{i64 0, !"_ZTSFvvE"}
+// ITANIUM: [[TVOID_ID]] = !{i64 0, i64 9080559750644022485}
+// ITANIUM: [[TNOPROTO]] = !{i64 0, !"_ZTSFvE"}
+// ITANIUM: [[TNOPROTO_ID]] = !{i64 0, i64 6588678392271548388}
-// CHECK: !{i32 4, !"Cross-DSO CFI", i32 1}
+// MS: [[TVOID]] = !{i64 0, !"?6AXXZ"}
+// MS: [[TVOID_ID]] = !{i64 0, i64 5113650790573562461}
+// MS: [[TNOPROTO]] = !{i64 0, !"?6AX@Z"}
+// MS: [[TNOPROTO_ID]] = !{i64 0, i64 4195979634929632483}
diff --git a/test/CodeGen/cfi-icall.c b/test/CodeGen/cfi-icall.c
index d6cebef49a..ed34f4f44b 100644
--- a/test/CodeGen/cfi-icall.c
+++ b/test/CodeGen/cfi-icall.c
@@ -1,20 +1,24 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-icall -fsanitize-trap=cfi-icall -emit-llvm -o - %s | FileCheck --check-prefix=ITANIUM %s
-// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fsanitize=cfi-icall -fsanitize-trap=cfi-icall -emit-llvm -o - %s | FileCheck --check-prefix=MS %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-icall -fsanitize-trap=cfi-icall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=ITANIUM %s
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fsanitize=cfi-icall -fsanitize-trap=cfi-icall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=MS %s
// Tests that we assign appropriate identifiers to unprototyped functions.
+// CHECK: define void @f({{.*}} !type [[TVOID:![0-9]+]]
void f() {
}
void xf();
+// CHECK: define void @g({{.*}} !type [[TINT:![0-9]+]]
void g(int b) {
void (*fp)() = b ? f : xf;
- // ITANIUM: call i1 @llvm.bitset.test(i8* {{.*}}, metadata !"_ZTSFvE")
+ // ITANIUM: call i1 @llvm.type.test(i8* {{.*}}, metadata !"_ZTSFvE")
fp();
}
-// ITANIUM-DAG: !{!"_ZTSFvE", void ()* @f, i64 0}
-// ITANIUM-DAG: !{!"_ZTSFvE", void (...)* @xf, i64 0}
-// MS-DAG: !{!"?6AX@Z", void ()* @f, i64 0}
-// MS-DAG: !{!"?6AX@Z", void (...)* @xf, i64 0}
+// CHECK: declare !type [[TVOID:![0-9]+]] void @xf({{.*}}
+
+// ITANIUM-DAG: [[TVOID]] = !{i64 0, !"_ZTSFvE"}
+// ITANIUM-DAG: [[TINT]] = !{i64 0, !"_ZTSFviE"}
+// MS-DAG: [[TVOID]] = !{i64 0, !"?6AX@Z"}
+// MS-DAG: [[TINT]] = !{i64 0, !"?6AXH@Z"}
diff --git a/test/CodeGenCXX/bitsets.cpp b/test/CodeGenCXX/bitsets.cpp
deleted file mode 100644
index 4d11f39b66..0000000000
--- a/test/CodeGenCXX/bitsets.cpp
+++ /dev/null
@@ -1,211 +0,0 @@
-// Tests for the cfi-vcall feature:
-// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=ITANIUM --check-prefix=ITANIUM-NDIAG --check-prefix=NDIAG %s
-// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=ITANIUM --check-prefix=ITANIUM-DIAG --check-prefix=DIAG --check-prefix=DIAG-ABORT %s
-// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-recover=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=ITANIUM --check-prefix=DIAG --check-prefix=DIAG-RECOVER %s
-// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=MS --check-prefix=NDIAG %s
-
-// Tests for the whole-program-vtables feature:
-// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=ITANIUM %s
-// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=MS %s
-
-// MS: @[[VTA:[0-9]*]] {{.*}} comdat($"\01??_7A@@6B@")
-// MS: @[[VTB:[0-9]*]] {{.*}} comdat($"\01??_7B@@6B0@@")
-// MS: @[[VTAinB:[0-9]*]] {{.*}} comdat($"\01??_7B@@6BA@@@")
-// MS: @[[VTAinC:[0-9]*]] {{.*}} comdat($"\01??_7C@@6B@")
-// MS: @[[VTBinD:[0-9]*]] {{.*}} comdat($"\01??_7D@?A@@6BB@@@")
-// MS: @[[VTAinBinD:[0-9]*]] {{.*}} comdat($"\01??_7D@?A@@6BA@@@")
-// MS: @[[VTFA:[0-9]*]] {{.*}} comdat($"\01??_7FA@?1??foo@@YAXXZ@6B@")
-
-struct A {
- A();
- virtual void f();
-};
-
-struct B : virtual A {
- B();
- virtual void g();
- virtual void h();
-};
-
-struct C : virtual A {
- C();
-};
-
-namespace {
-
-struct D : B, C {
- D();
- virtual void f();
- virtual void h();
-};
-
-}
-
-A::A() {}
-B::B() {}
-C::C() {}
-D::D() {}
-
-void A::f() {
-}
-
-void B::g() {
-}
-
-void D::f() {
-}
-
-void D::h() {
-}
-
-// DIAG: @[[SRC:.*]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*}}bitsets.cpp\00", align 1
-// DIAG: @[[TYPE:.*]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'A'\00" }
-// DIAG: @[[BADTYPESTATIC:.*]] = private unnamed_addr global { i8, { [{{.*}} x i8]*, i32, i32 }, { i16, i16, [4 x i8] }* } { i8 0, { [{{.*}} x i8]*, i32, i32 } { [{{.*}} x i8]* @[[SRC]], i32 [[@LINE+24]], i32 3 }, { i16, i16, [4 x i8] }* @[[TYPE]] }
-
-// ITANIUM: define hidden void @_Z2afP1A
-// MS: define void @"\01?af@@YAXPEAUA@@@Z"
-void af(A *a) {
- // ITANIUM: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* [[VT:%[^ ]*]], metadata !"_ZTS1A")
- // MS: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* [[VT:%[^ ]*]], metadata !"?AUA@@")
- // DIAG-NEXT: [[VTVALID0:%[^ ]*]] = call i1 @llvm.bitset.test(i8* [[VT]], metadata !"all-vtables")
- // VTABLE-OPT: call void @llvm.assume(i1 [[P]])
- // CFI-NEXT: br i1 [[P]], label %[[CONTBB:[^ ,]*]], label %[[TRAPBB:[^ ,]*]]
- // CFI-NEXT: {{^$}}
-
- // CFI: [[TRAPBB]]
- // NDIAG-NEXT: call void @llvm.trap()
- // NDIAG-NEXT: unreachable
- // DIAG-NEXT: [[VTINT:%[^ ]*]] = ptrtoint i8* [[VT]] to i64
- // DIAG-NEXT: [[VTVALID:%[^ ]*]] = zext i1 [[VTVALID0]] to i64
- // DIAG-ABORT-NEXT: call void @__ubsan_handle_cfi_check_fail_abort(i8* getelementptr inbounds ({{.*}} @[[BADTYPESTATIC]], i32 0, i32 0), i64 [[VTINT]], i64 [[VTVALID]])
- // DIAG-ABORT-NEXT: unreachable
- // DIAG-RECOVER-NEXT: call void @__ubsan_handle_cfi_check_fail(i8* getelementptr inbounds ({{.*}} @[[BADTYPESTATIC]], i32 0, i32 0), i64 [[VTINT]], i64 [[VTVALID]])
- // DIAG-RECOVER-NEXT: br label %[[CONTBB]]
-
- // CFI: [[CONTBB]]
- // CFI: call void %
- a->f();
-}
-
-// ITANIUM: define internal void @_Z3df1PN12_GLOBAL__N_11DE
-// MS: define internal void @"\01?df1@@YAXPEAUD@?A@@@Z"
-void df1(D *d) {
- // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]])
- // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"?AUA@@")
- d->f();
-}
-
-// ITANIUM: define internal void @_Z3dg1PN12_GLOBAL__N_11DE
-// MS: define internal void @"\01?dg1@@YAXPEAUD@?A@@@Z"
-void dg1(D *d) {
- // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
- // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"?AUB@@")
- d->g();
-}
-
-// ITANIUM: define internal void @_Z3dh1PN12_GLOBAL__N_11DE
-// MS: define internal void @"\01?dh1@@YAXPEAUD@?A@@@Z"
-void dh1(D *d) {
- // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata ![[DTYPE]])
- // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]])
- d->h();
-}
-
-// ITANIUM: define internal void @_Z3df2PN12_GLOBAL__N_11DE
-// MS: define internal void @"\01?df2@@YAXPEAUD@?A@@@Z"
-__attribute__((no_sanitize("cfi")))
-void df2(D *d) {
- // CFI-NOT: call i1 @llvm.bitset.test
- d->f();
-}
-
-// ITANIUM: define internal void @_Z3df3PN12_GLOBAL__N_11DE
-// MS: define internal void @"\01?df3@@YAXPEAUD@?A@@@Z"
-__attribute__((no_sanitize("address"))) __attribute__((no_sanitize("cfi-vcall")))
-void df3(D *d) {
- // CFI-NOT: call i1 @llvm.bitset.test
- d->f();
-}
-
-D d;
-
-void foo() {
- df1(&d);
- dg1(&d);
- dh1(&d);
- df2(&d);
- df3(&d);
-
- struct FA : A {
- void f() {}
- } fa;
- af(&fa);
-}
-
-namespace test2 {
-
-struct A {
- virtual void m_fn1();
-};
-struct B {
- virtual void m_fn2();
-};
-struct C : B, A {};
-struct D : C {
- void m_fn1();
-};
-
-// ITANIUM: define hidden void @_ZN5test21fEPNS_1DE
-// MS: define void @"\01?f@test2@@YAXPEAUD@1@@Z"
-void f(D *d) {
- // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTSN5test21DE")
- // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"?AUA@test2@@")
- d->m_fn1();
-}
-
-}
-
-// Check for the expected number of elements (15 or 23 respectively).
-// MS-NDIAG: !llvm.bitsets = !{[[X:[^,]*(,[^,]*){9}]]}
-// MS-DIAG: !llvm.bitsets = !{[[X:[^,]*(,[^,]*){15}]]}
-// ITANIUM-NDIAG: !llvm.bitsets = !{[[X:[^,]*(,[^,]*){14}]]}
-// ITANIUM-DIAG: !llvm.bitsets = !{[[X:[^,]*(,[^,]*){23}]]}
-
-// ITANIUM-DAG: !{!"_ZTS1A", [3 x i8*]* @_ZTV1A, i64 16}
-// ITANIUM-DIAG-DAG: !{!"all-vtables", [3 x i8*]* @_ZTV1A, i64 16}
-// ITANIUM-DAG: !{!"_ZTS1A", [7 x i8*]* @_ZTCN12_GLOBAL__N_11DE0_1B, i64 32}
-// ITANIUM-DIAG-DAG: !{!"all-vtables", [7 x i8*]* @_ZTCN12_GLOBAL__N_11DE0_1B, i64 32}
-// ITANIUM-DAG: !{!"_ZTS1B", [7 x i8*]* @_ZTCN12_GLOBAL__N_11DE0_1B, i64 32}
-// ITANIUM-DAG: !{!"_ZTS1A", [9 x i8*]* @_ZTCN12_GLOBAL__N_11DE8_1C, i64 64}
-// ITANIUM-DIAG-DAG: !{!"all-vtables", [9 x i8*]* @_ZTCN12_GLOBAL__N_11DE8_1C, i64 64}
-// ITANIUM-DAG: !{!"_ZTS1C", [9 x i8*]* @_ZTCN12_GLOBAL__N_11DE8_1C, i64 32}
-// ITANIUM-DAG: !{!"_ZTS1A", [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32}
-// ITANIUM-DIAG-DAG: !{!"all-vtables", [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32}
-// ITANIUM-DAG: !{!"_ZTS1B", [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32}
-// ITANIUM-DAG: !{!"_ZTS1C", [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 88}
-// ITANIUM-DIAG-DAG: !{!"all-vtables", [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 88}
-// ITANIUM-DAG: !{![[DTYPE]], [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32}
-// ITANIUM-DAG: !{!"_ZTS1A", [7 x i8*]* @_ZTV1B, i64 32}
-// ITANIUM-DIAG-DAG: !{!"all-vtables", [7 x i8*]* @_ZTV1B, i64 32}
-// ITANIUM-DAG: !{!"_ZTS1B", [7 x i8*]* @_ZTV1B, i64 32}
-// ITANIUM-DAG: !{!"_ZTS1A", [5 x i8*]* @_ZTV1C, i64 32}
-// ITANIUM-DAG: !{!"_ZTS1C", [5 x i8*]* @_ZTV1C, i64 32}
-// ITANIUM-DAG: !{!"_ZTS1A", [3 x i8*]* @_ZTVZ3foovE2FA, i64 16}
-// ITANIUM-DAG: !{!{{[0-9]+}}, [3 x i8*]* @_ZTVZ3foovE2FA, i64 16}
-
-// MS-DAG: !{!"?AUA@@", [2 x i8*]* @[[VTA]], i64 8}
-// MS-DIAG-DAG: !{!"all-vtables", [2 x i8*]* @[[VTA]], i64 8}
-// MS-DAG: !{!"?AUB@@", [3 x i8*]* @[[VTB]], i64 8}
-// MS-DIAG-DAG: !{!"all-vtables", [3 x i8*]* @[[VTB]], i64 8}
-// MS-DAG: !{!"?AUA@@", [2 x i8*]* @[[VTAinB]], i64 8}
-// MS-DIAG-DAG: !{!"all-vtables", [2 x i8*]* @[[VTAinB]], i64 8}
-// MS-DAG: !{!"?AUA@@", [2 x i8*]* @[[VTAinC]], i64 8}
-// MS-DIAG-DAG: !{!"all-vtables", [2 x i8*]* @[[VTAinC]], i64 8}
-// MS-DAG: !{!"?AUB@@", [3 x i8*]* @[[VTBinD]], i64 8}
-// MS-DIAG-DAG: !{!"all-vtables", [3 x i8*]* @[[VTBinD]], i64 8}
-// MS-DAG: !{![[DTYPE]], [3 x i8*]* @[[VTBinD]], i64 8}
-// MS-DAG: !{!"?AUA@@", [2 x i8*]* @[[VTAinBinD]], i64 8}
-// MS-DIAG-DAG: !{!"all-vtables", [2 x i8*]* @[[VTAinBinD]], i64 8}
-// MS-DAG: !{!"?AUA@@", [2 x i8*]* @[[VTFA]], i64 8}
-// MS-DIAG-DAG: !{!"all-vtables", [2 x i8*]* @[[VTFA]], i64 8}
-// MS-DAG: !{!{{[0-9]+}}, [2 x i8*]* @[[VTFA]], i64 8}
diff --git a/test/CodeGenCXX/cfi-blacklist.cpp b/test/CodeGenCXX/cfi-blacklist.cpp
index 38b9971c90..af8a10601d 100644
--- a/test/CodeGenCXX/cfi-blacklist.cpp
+++ b/test/CodeGenCXX/cfi-blacklist.cpp
@@ -15,15 +15,15 @@ struct S2 {
}
// CHECK: define{{.*}}s1f
-// NOBL: llvm.bitset.test
-// NOSTD: llvm.bitset.test
+// NOBL: llvm.type.test
+// NOSTD: llvm.type.test
void s1f(S1 *s1) {
s1->f();
}
// CHECK: define{{.*}}s2f
-// NOBL: llvm.bitset.test
-// NOSTD-NOT: llvm.bitset.test
+// NOBL: llvm.type.test
+// NOSTD-NOT: llvm.type.test
void s2f(std::S2 *s2) {
s2->f();
}
diff --git a/test/CodeGenCXX/cfi-cast.cpp b/test/CodeGenCXX/cfi-cast.cpp
index 9fe87111b3..54641b5233 100644
--- a/test/CodeGenCXX/cfi-cast.cpp
+++ b/test/CodeGenCXX/cfi-cast.cpp
@@ -19,7 +19,7 @@ struct C : A {};
// CHECK-DCAST-LABEL: define hidden void @_Z3abpP1A
void abp(A *a) {
- // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
+ // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
// CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
// CHECK-DCAST: [[TRAPBB]]
@@ -33,7 +33,7 @@ void abp(A *a) {
// CHECK-DCAST-LABEL: define hidden void @_Z3abrR1A
void abr(A &a) {
- // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
+ // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
// CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
// CHECK-DCAST: [[TRAPBB]]
@@ -47,7 +47,7 @@ void abr(A &a) {
// CHECK-DCAST-LABEL: define hidden void @_Z4abrrO1A
void abrr(A &&a) {
- // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
+ // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
// CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
// CHECK-DCAST: [[TRAPBB]]
@@ -61,7 +61,7 @@ void abrr(A &&a) {
// CHECK-UCAST-LABEL: define hidden void @_Z3vbpPv
void vbp(void *p) {
- // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
+ // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
// CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
// CHECK-UCAST: [[TRAPBB]]
@@ -75,7 +75,7 @@ void vbp(void *p) {
// CHECK-UCAST-LABEL: define hidden void @_Z3vbrRc
void vbr(char &r) {
- // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
+ // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
// CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
// CHECK-UCAST: [[TRAPBB]]
@@ -89,7 +89,7 @@ void vbr(char &r) {
// CHECK-UCAST-LABEL: define hidden void @_Z4vbrrOc
void vbrr(char &&r) {
- // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
+ // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
// CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]]
// CHECK-UCAST: [[TRAPBB]]
@@ -104,31 +104,31 @@ void vbrr(char &&r) {
// CHECK-UCAST-LABEL: define hidden void @_Z3vcpPv
// CHECK-UCAST-STRICT-LABEL: define hidden void @_Z3vcpPv
void vcp(void *p) {
- // CHECK-UCAST: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A")
- // CHECK-UCAST-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C")
+ // CHECK-UCAST: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A")
+ // CHECK-UCAST-STRICT: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C")
(void)static_cast<C*>(p);
}
// CHECK-UCAST-LABEL: define hidden void @_Z3bcpP1B
// CHECK-UCAST-STRICT-LABEL: define hidden void @_Z3bcpP1B
void bcp(B *p) {
- // CHECK-UCAST: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A")
- // CHECK-UCAST-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C")
+ // CHECK-UCAST: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A")
+ // CHECK-UCAST-STRICT: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C")
(void)(C *)p;
}
// CHECK-UCAST-LABEL: define hidden void @_Z8bcp_callP1B
// CHECK-UCAST-STRICT-LABEL: define hidden void @_Z8bcp_callP1B
void bcp_call(B *p) {
- // CHECK-UCAST: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A")
- // CHECK-UCAST-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C")
+ // CHECK-UCAST: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A")
+ // CHECK-UCAST-STRICT: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C")
((C *)p)->f();
}
// CHECK-UCAST-LABEL: define hidden i32 @_Z6a_callP1A
// CHECK-UCAST-STRICT-LABEL: define hidden i32 @_Z6a_callP1A
int a_call(A *a) {
- // CHECK-UCAST-NOT: @llvm.bitset.test
- // CHECK-UCAST-STRICT-NOT: @llvm.bitset.test
+ // CHECK-UCAST-NOT: @llvm.type.test
+ // CHECK-UCAST-STRICT-NOT: @llvm.type.test
return a->i();
}
diff --git a/test/CodeGenCXX/cfi-cross-dso.cpp b/test/CodeGenCXX/cfi-cross-dso.cpp
index 84a6879e55..d67927d4d2 100644
--- a/test/CodeGenCXX/cfi-cross-dso.cpp
+++ b/test/CodeGenCXX/cfi-cross-dso.cpp
@@ -30,8 +30,8 @@ void g() {
// CHECK: %[[VT:.*]] = load void (%struct.A*)**, void (%struct.A*)***
// CHECK: %[[VT2:.*]] = bitcast {{.*}}%[[VT]] to i8*, !nosanitize
-// ITANIUM: %[[TEST:.*]] = call i1 @llvm.bitset.test(i8* %[[VT2]], metadata !"_ZTS1A"), !nosanitize
-// MS: %[[TEST:.*]] = call i1 @llvm.bitset.test(i8* %[[VT2]], metadata !"?AUA@@"), !nosanitize
+// ITANIUM: %[[TEST:.*]] = call i1 @llvm.type.test(i8* %[[VT2]], metadata !"_ZTS1A"), !nosanitize
+// MS: %[[TEST:.*]] = call i1 @llvm.type.test(i8* %[[VT2]], metadata !"?AUA@@"), !nosanitize
// CHECK: br i1 %[[TEST]], label %[[CONT:.*]], label %[[SLOW:.*]], {{.*}} !nosanitize
// CHECK: [[SLOW]]
// ITANIUM: call void @__cfi_slowpath_diag(i64 7004155349499253778, i8* %[[VT2]], {{.*}}) {{.*}} !nosanitize
diff --git a/test/CodeGenCXX/cfi-icall.cpp b/test/CodeGenCXX/cfi-icall.cpp
index eceb92a442..c3c6ed309c 100644
--- a/test/CodeGenCXX/cfi-icall.cpp
+++ b/test/CodeGenCXX/cfi-icall.cpp
@@ -15,9 +15,12 @@ void f(S *s) {
void g() {
void (*fp)(S *) = f;
- // CHECK: call i1 @llvm.bitset.test(i8* {{.*}}, metadata ![[VOIDS:[0-9]+]])
+ // CHECK: call i1 @llvm.type.test(i8* {{.*}}, metadata [[VOIDS:![0-9]+]])
fp(0);
}
-// ITANIUM: !{![[VOIDS]], void (%"struct.(anonymous namespace)::S"*)* @_ZN12_GLOBAL__N_11fEPNS_1SE, i64 0}
-// MS: !{![[VOIDS]], void (%"struct.(anonymous namespace)::S"*)* @"\01?f@?A@@YAXPEAUS@?A@@@Z", i64 0}
+// ITANIUM: define internal void @_ZN12_GLOBAL__N_11fEPNS_1SE({{.*}} !type [[TS:![0-9]+]]
+// MS: define internal void @"\01?f@?A@@YAXPEAUS@?A@@@Z"({{.*}} !type [[TS:![0-9]+]]
+
+// CHECK: [[VOIDS]] = distinct !{}
+// CHECK: [[TS]] = !{i64 0, [[VOIDS]]}
diff --git a/test/CodeGenCXX/cfi-ms-rtti.cpp b/test/CodeGenCXX/cfi-ms-rtti.cpp
index 12c9868cee..fbebad4b1b 100644
--- a/test/CodeGenCXX/cfi-ms-rtti.cpp
+++ b/test/CodeGenCXX/cfi-ms-rtti.cpp
@@ -8,5 +8,5 @@ struct A {
A::A() {}
-// RTTI: !{!"?AUA@@", [2 x i8*]* {{.*}}, i64 8}
-// NO-RTTI: !{!"?AUA@@", [1 x i8*]* {{.*}}, i64 0}
+// RTTI: !{i64 8, !"?AUA@@"}
+// NO-RTTI: !{i64 0, !"?AUA@@"}
diff --git a/test/CodeGenCXX/cfi-nvcall.cpp b/test/CodeGenCXX/cfi-nvcall.cpp
index ea18e216f0..e968f05600 100644
--- a/test/CodeGenCXX/cfi-nvcall.cpp
+++ b/test/CodeGenCXX/cfi-nvcall.cpp
@@ -17,8 +17,8 @@ struct C : A {
// CHECK-LABEL: @bg
// CHECK-STRICT-LABEL: @bg
extern "C" void bg(B *b) {
- // CHECK: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
- // CHECK-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
+ // CHECK: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
+ // CHECK-STRICT: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
b->g();
}
@@ -29,7 +29,7 @@ extern "C" void cg(C *c) {
// In this case C's layout is the same as its base class, so we allow
// c to be of type A in non-strict mode.
- // CHECK: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A")
- // CHECK-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C")
+ // CHECK: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A")
+ // CHECK-STRICT: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C")
c->g();
}
diff --git a/test/CodeGenCXX/bitset-inference.cpp b/test/CodeGenCXX/lto-visibility-inference.cpp
index d9528609ff..8e57ef5e0b 100644
--- a/test/CodeGenCXX/bitset-inference.cpp
+++ b/test/CodeGenCXX/lto-visibility-inference.cpp
@@ -67,41 +67,41 @@ struct C11 {
void f(C1 *c1, C2 *c2, C3 *c3, C4 *c4, C5 *c5, C6 *c6, std::C7 *c7,
std::C7::C8 *c8, stdext::C9 *c9, other::C10 *c10) {
- // ITANIUM: bitset.test{{.*}}!"_ZTS2C1"
- // MS: bitset.test{{.*}}!"?AUC1@@"
+ // ITANIUM: type.test{{.*}}!"_ZTS2C1"
+ // MS: type.test{{.*}}!"?AUC1@@"
c1->f();
- // ITANIUM-NOT: bitset.test{{.*}}!"_ZTS2C2"
- // MS: bitset.test{{.*}}!"?AUC2@@"
+ // ITANIUM-NOT: type.test{{.*}}!"_ZTS2C2"
+ // MS: type.test{{.*}}!"?AUC2@@"
c2->f();
- // ITANIUM: bitset.test{{.*}}!"_ZTS2C3"
- // MS-NOT: bitset.test{{.*}}!"?AUC3@@"
+ // ITANIUM: type.test{{.*}}!"_ZTS2C3"
+ // MS-NOT: type.test{{.*}}!"?AUC3@@"
c3->f();
- // ITANIUM: bitset.test{{.*}}!"_ZTS2C4"
- // MS-NOT: bitset.test{{.*}}!"?AUC4@@"
+ // ITANIUM: type.test{{.*}}!"_ZTS2C4"
+ // MS-NOT: type.test{{.*}}!"?AUC4@@"
c4->f();
- // ITANIUM-NOT: bitset.test{{.*}}!"_ZTS2C5"
- // MS-NOT: bitset.test{{.*}}!"?AUC5@@"
+ // ITANIUM-NOT: type.test{{.*}}!"_ZTS2C5"
+ // MS-NOT: type.test{{.*}}!"?AUC5@@"
c5->f();
- // ITANIUM-NOT: bitset.test{{.*}}!"_ZTS2C6"
- // MS-NOT: bitset.test{{.*}}!"?AUC6@@"
+ // ITANIUM-NOT: type.test{{.*}}!"_ZTS2C6"
+ // MS-NOT: type.test{{.*}}!"?AUC6@@"
c6->f();
- // ITANIUM: bitset.test{{.*}}!"_ZTSSt2C7"
- // MS-STD: bitset.test{{.*}}!"?AUC7@std@@"
- // MS-NOSTD-NOT: bitset.test{{.*}}!"?AUC7@std@@"
+ // ITANIUM: type.test{{.*}}!"_ZTSSt2C7"
+ // MS-STD: type.test{{.*}}!"?AUC7@std@@"
+ // MS-NOSTD-NOT: type.test{{.*}}!"?AUC7@std@@"
c7->f();
- // ITANIUM: bitset.test{{.*}}!"_ZTSNSt2C72C8E"
- // MS-STD: bitset.test{{.*}}!"?AUC8@C7@std@@"
- // MS-NOSTD-NOT: bitset.test{{.*}}!"?AUC8@C7@std@@"
+ // ITANIUM: type.test{{.*}}!"_ZTSNSt2C72C8E"
+ // MS-STD: type.test{{.*}}!"?AUC8@C7@std@@"
+ // MS-NOSTD-NOT: type.test{{.*}}!"?AUC8@C7@std@@"
c8->f();
- // ITANIUM: bitset.test{{.*}}!"_ZTSN6stdext2C9E"
- // MS-STD: bitset.test{{.*}}!"?AUC9@stdext@@"
- // MS-NOSTD-NOT: bitset.test{{.*}}!"?AUC9@stdext@@"
+ // ITANIUM: type.test{{.*}}!"_ZTSN6stdext2C9E"
+ // MS-STD: type.test{{.*}}!"?AUC9@stdext@@"
+ // MS-NOSTD-NOT: type.test{{.*}}!"?AUC9@stdext@@"
c9->f();
- // ITANIUM: bitset.test{{.*}}!"_ZTSN5other3C10E"
- // MS: bitset.test{{.*}}!"?AUC10@other@@"
+ // ITANIUM: type.test{{.*}}!"_ZTSN5other3C10E"
+ // MS: type.test{{.*}}!"?AUC10@other@@"
c10->f();
- // ITANIUM: bitset.test{{.*}}!{{[0-9]}}
- // MS: bitset.test{{.*}}!{{[0-9]}}
+ // ITANIUM: type.test{{.*}}!{{[0-9]}}
+ // MS: type.test{{.*}}!{{[0-9]}}
C11 *c11;
c11->f();
}
diff --git a/test/CodeGenCXX/type-metadata.cpp b/test/CodeGenCXX/type-metadata.cpp
new file mode 100644
index 0000000000..f1edbd858c
--- /dev/null
+++ b/test/CodeGenCXX/type-metadata.cpp
@@ -0,0 +1,226 @@
+// Tests for the cfi-vcall feature:
+// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=ITANIUM --check-prefix=ITANIUM-NDIAG --check-prefix=NDIAG %s
+// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=ITANIUM --check-prefix=ITANIUM-DIAG --check-prefix=DIAG --check-prefix=DIAG-ABORT %s
+// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-recover=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=ITANIUM --check-prefix=ITANIUM-DIAG --check-prefix=DIAG --check-prefix=DIAG-RECOVER %s
+// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CFI --check-prefix=MS --check-prefix=NDIAG %s
+
+// Tests for the whole-program-vtables feature:
+// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=ITANIUM %s
+// RUN: %clang_cc1 -flto -triple x86_64-pc-windows-msvc -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=VTABLE-OPT --check-prefix=MS %s
+
+// ITANIUM: @_ZTV1A = {{[^!]*}}, !type [[A16:![0-9]+]]
+// ITANIUM-DIAG-SAME: !type [[ALL16:![0-9]+]]
+
+// ITANIUM: @_ZTV1B = {{[^!]*}}, !type [[A32:![0-9]+]]
+// ITANIUM-DIAG-SAME: !type [[ALL32:![0-9]+]]
+// ITANIUM-SAME: !type [[B32:![0-9]+]]
+// ITANIUM-DIAG-SAME: !type [[ALL32]]
+
+// ITANIUM: @_ZTV1C = {{[^!]*}}, !type [[A32]]
+// ITANIUM-DIAG-SAME: !type [[ALL32]]
+// ITANIUM-SAME: !type [[C32:![0-9]+]]
+// ITANIUM-DIAG-SAME: !type [[ALL32]]
+
+// DIAG: @[[SRC:.*]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*}}type-metadata.cpp\00", align 1
+// DIAG: @[[TYPE:.*]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'A'\00" }
+// DIAG: @[[BADTYPESTATIC:.*]] = private unnamed_addr global { i8, { [{{.*}} x i8]*, i32, i32 }, { i16, i16, [4 x i8] }* } { i8 0, { [{{.*}} x i8]*, i32, i32 } { [{{.*}} x i8]* @[[SRC]], i32 123, i32 3 }, { i16, i16, [4 x i8] }* @[[TYPE]] }
+
+// ITANIUM: @_ZTVN12_GLOBAL__N_11DE = {{[^!]*}}, !type [[A32]]
+// ITANIUM-DIAG-SAME: !type [[ALL32]]
+// ITANIUM-SAME: !type [[B32]]
+// ITANIUM-DIAG-SAME: !type [[ALL32]]
+// ITANIUM-SAME: !type [[C88:![0-9]+]]
+// ITANIUM-DIAG-SAME: !type [[ALL88:![0-9]+]]
+// ITANIUM-SAME: !type [[D32:![0-9]+]]
+// ITANIUM-DIAG-SAME: !type [[ALL32]]
+
+// ITANIUM: @_ZTCN12_GLOBAL__N_11DE0_1B = {{[^!]*}}, !type [[A32]]
+// ITANIUM-DIAG-SAME: !type [[ALL32]]
+// ITANIUM-SAME: !type [[B32]]
+// ITANIUM-DIAG-SAME: !type [[ALL32]]
+
+// ITANIUM: @_ZTCN12_GLOBAL__N_11DE8_1C = {{[^!]*}}, !type [[A64:![0-9]+]]
+// ITANIUM-DIAG-SAME: !type [[ALL64:![0-9]+]]
+// ITANIUM-SAME: !type [[C32]]
+// ITANIUM-DIAG-SAME: !type [[ALL32]]
+
+// ITANIUM: @_ZTVZ3foovE2FA = {{[^!]*}}, !type [[A16]]
+// ITANIUM-DIAG-SAME: !type [[ALL16]]
+// ITANIUM-SAME: !type [[FA16:![0-9]+]]
+// ITANIUM-DIAG-SAME: !type [[ALL16]]
+
+// MS: comdat($"\01??_7A@@6B@"), !type [[A8:![0-9]+]]
+// MS: comdat($"\01??_7B@@6B0@@"), !type [[B8:![0-9]+]]
+// MS: comdat($"\01??_7B@@6BA@@@"), !type [[A8]]
+// MS: comdat($"\01??_7C@@6B@"), !type [[A8]]
+// MS: comdat($"\01??_7D@?A@@6BB@@@"), !type [[B8]], !type [[D8:![0-9]+]]
+// MS: comdat($"\01??_7D@?A@@6BA@@@"), !type [[A8]]
+// MS: comdat($"\01??_7FA@?1??foo@@YAXXZ@6B@"), !type [[A8]], !type [[FA8:![0-9]+]]
+
+struct A {
+ A();
+ virtual void f();
+};
+
+struct B : virtual A {
+ B();
+ virtual void g();
+ virtual void h();
+};
+
+struct C : virtual A {
+ C();
+};
+
+namespace {
+
+struct D : B, C {
+ D();
+ virtual void f();
+ virtual void h();
+};
+
+}
+
+A::A() {}
+B::B() {}
+C::C() {}
+D::D() {}
+
+void A::f() {
+}
+
+void B::g() {
+}
+
+void D::f() {
+}
+
+void D::h() {
+}
+
+// ITANIUM: define hidden void @_Z2afP1A
+// MS: define void @"\01?af@@YAXPEAUA@@@Z"
+void af(A *a) {
+ // ITANIUM: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* [[VT:%[^ ]*]], metadata !"_ZTS1A")
+ // MS: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* [[VT:%[^ ]*]], metadata !"?AUA@@")
+ // DIAG-NEXT: [[VTVALID0:%[^ ]*]] = call i1 @llvm.type.test(i8* [[VT]], metadata !"all-vtables")
+ // VTABLE-OPT: call void @llvm.assume(i1 [[P]])
+ // CFI-NEXT: br i1 [[P]], label %[[CONTBB:[^ ,]*]], label %[[TRAPBB:[^ ,]*]]
+ // CFI-NEXT: {{^$}}
+
+ // CFI: [[TRAPBB]]
+ // NDIAG-NEXT: call void @llvm.trap()
+ // NDIAG-NEXT: unreachable
+ // DIAG-NEXT: [[VTINT:%[^ ]*]] = ptrtoint i8* [[VT]] to i64
+ // DIAG-NEXT: [[VTVALID:%[^ ]*]] = zext i1 [[VTVALID0]] to i64
+ // DIAG-ABORT-NEXT: call void @__ubsan_handle_cfi_check_fail_abort(i8* getelementptr inbounds ({{.*}} @[[BADTYPESTATIC]], i32 0, i32 0), i64 [[VTINT]], i64 [[VTVALID]])
+ // DIAG-ABORT-NEXT: unreachable
+ // DIAG-RECOVER-NEXT: call void @__ubsan_handle_cfi_check_fail(i8* getelementptr inbounds ({{.*}} @[[BADTYPESTATIC]], i32 0, i32 0), i64 [[VTINT]], i64 [[VTVALID]])
+ // DIAG-RECOVER-NEXT: br label %[[CONTBB]]
+
+ // CFI: [[CONTBB]]
+ // CFI: call void %
+#line 123
+ a->f();
+}
+
+// ITANIUM: define internal void @_Z3df1PN12_GLOBAL__N_11DE
+// MS: define internal void @"\01?df1@@YAXPEAUD@?A@@@Z"
+void df1(D *d) {
+ // ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]])
+ // MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUA@@")
+ d->f();
+}
+
+// ITANIUM: define internal void @_Z3dg1PN12_GLOBAL__N_11DE
+// MS: define internal void @"\01?dg1@@YAXPEAUD@?A@@@Z"
+void dg1(D *d) {
+ // ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B")
+ // MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUB@@")
+ d->g();
+}
+
+// ITANIUM: define internal void @_Z3dh1PN12_GLOBAL__N_11DE
+// MS: define internal void @"\01?dh1@@YAXPEAUD@?A@@@Z"
+void dh1(D *d) {
+ // ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE]])
+ // MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]])
+ d->h();
+}
+
+// ITANIUM: define internal void @_Z3df2PN12_GLOBAL__N_11DE
+// MS: define internal void @"\01?df2@@YAXPEAUD@?A@@@Z"
+__attribute__((no_sanitize("cfi")))
+void df2(D *d) {
+ // CFI-NOT: call i1 @llvm.type.test
+ d->f();
+}
+
+// ITANIUM: define internal void @_Z3df3PN12_GLOBAL__N_11DE
+// MS: define internal void @"\01?df3@@YAXPEAUD@?A@@@Z"
+__attribute__((no_sanitize("address"))) __attribute__((no_sanitize("cfi-vcall")))
+void df3(D *d) {
+ // CFI-NOT: call i1 @llvm.type.test
+ d->f();
+}
+
+D d;
+
+void foo() {
+ df1(&d);
+ dg1(&d);
+ dh1(&d);
+ df2(&d);
+ df3(&d);
+
+ struct FA : A {
+ void f() {}
+ } fa;
+ af(&fa);
+}
+
+namespace test2 {
+
+struct A {
+ virtual void m_fn1();
+};
+struct B {
+ virtual void m_fn2();
+};
+struct C : B, A {};
+struct D : C {
+ void m_fn1();
+};
+
+// ITANIUM: define hidden void @_ZN5test21fEPNS_1DE
+// MS: define void @"\01?f@test2@@YAXPEAUD@1@@Z"
+void f(D *d) {
+ // ITANIUM: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTSN5test21DE")
+ // MS: {{%[^ ]*}} = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"?AUA@test2@@")
+ d->m_fn1();
+}
+
+}
+
+// ITANIUM: [[A16]] = !{i64 16, !"_ZTS1A"}
+// ITANIUM-DIAG: [[ALL16]] = !{i64 16, !"all-vtables"}
+// ITANIUM: [[A32]] = !{i64 32, !"_ZTS1A"}
+// ITANIUM-DIAG: [[ALL32]] = !{i64 32, !"all-vtables"}
+// ITANIUM: [[B32]] = !{i64 32, !"_ZTS1B"}
+// ITANIUM: [[C32]] = !{i64 32, !"_ZTS1C"}
+// ITANIUM: [[C88]] = !{i64 88, !"_ZTS1C"}
+// ITANIUM-DIAG: [[ALL88]] = !{i64 88, !"all-vtables"}
+// ITANIUM: [[D32]] = !{i64 32, [[D_ID:![0-9]+]]}
+// ITANIUM: [[D_ID]] = distinct !{}
+// ITANIUM: [[A64]] = !{i64 64, !"_ZTS1A"}
+// ITANIUM-DIAG: [[ALL64]] = !{i64 64, !"all-vtables"}
+// ITANIUM: [[FA16]] = !{i64 16, [[FA_ID:![0-9]+]]}
+// ITANIUM: [[FA_ID]] = distinct !{}
+
+// MS: [[A8]] = !{i64 8, !"?AUA@@"}
+// MS: [[B8]] = !{i64 8, !"?AUB@@"}
+// MS: [[D8]] = !{i64 8, [[D_ID:![0-9]+]]}
+// MS: [[D_ID]] = distinct !{}
+// MS: [[FA8]] = !{i64 8, [[FA_ID:![0-9]+]]}
+// MS: [[FA_ID]] = distinct !{}