Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 3400678

Browse files
committed
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
1 parent 7c599a5 commit 3400678

22 files changed

+420
-439
lines changed

Diff for: docs/ControlFlowIntegrityDesign.rst

+9-9
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ For example on x86 a typical virtual call may look like this:
9090
9191
The compiler relies on co-operation from the linker in order to assemble
9292
the bit vectors for the whole program. It currently does this using LLVM's
93-
`bit sets`_ mechanism together with link-time optimization.
93+
`type metadata`_ mechanism together with link-time optimization.
9494

9595
.. _address point: https://mentorembedded.github.io/cxx-abi/abi.html#vtable-general
96-
.. _bit sets: http://llvm.org/docs/BitSets.html
96+
.. _type metadata: http://llvm.org/docs/TypeMetadata.html
9797
.. _ByteArrayBuilder: http://llvm.org/docs/doxygen/html/structllvm_1_1ByteArrayBuilder.html
9898

9999
Optimizations
@@ -196,7 +196,7 @@ those sub-hierarchies need to be (see "Stripping Leading/Trailing Zeros in Bit
196196
Vectors" above). The `GlobalLayoutBuilder`_ class is responsible for laying
197197
out the globals efficiently to minimize the sizes of the underlying bitsets.
198198

199-
.. _GlobalLayoutBuilder: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO/LowerBitSets.h?view=markup
199+
.. _GlobalLayoutBuilder: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO/LowerTypeTests.h?view=markup
200200

201201
Alignment
202202
~~~~~~~~~
@@ -297,8 +297,8 @@ file's symbol table, the symbols for the target functions also refer to the
297297
jump table entries, so that addresses taken outside the module will pass
298298
any verification done inside the module.
299299

300-
In more concrete terms, suppose we have three functions ``f``, ``g``, ``h``
301-
which are members of a single bitset, and a function foo that returns their
300+
In more concrete terms, suppose we have three functions ``f``, ``g``,
301+
``h`` which are all of the same type, and a function foo that returns their
302302
addresses:
303303

304304
.. code-block:: none
@@ -439,10 +439,10 @@ export this information, every DSO implements
439439
440440
void __cfi_check(uint64 CallSiteTypeId, void *TargetAddr)
441441
442-
This function provides external modules with access to CFI checks for
443-
the targets inside this DSO. For each known ``CallSiteTypeId``, this
444-
functions performs an ``llvm.bitset.test`` with the corresponding bit
445-
set. It aborts if the type is unknown, or if the check fails.
442+
This function provides external modules with access to CFI checks for the
443+
targets inside this DSO. For each known ``CallSiteTypeId``, this function
444+
performs an ``llvm.type.test`` with the corresponding type identifier. It
445+
aborts if the type is unknown, or if the check fails.
446446

447447
The basic implementation is a large switch statement over all values
448448
of CallSiteTypeId supported by this DSO, and each case is similar to

Diff for: lib/CodeGen/CGClass.cpp

+18-20
Original file line numberDiff line numberDiff line change
@@ -2485,21 +2485,21 @@ LeastDerivedClassWithSameLayout(const CXXRecordDecl *RD) {
24852485
RD->bases_begin()->getType()->getAsCXXRecordDecl());
24862486
}
24872487

2488-
void CodeGenFunction::EmitBitSetCodeForVCall(const CXXRecordDecl *RD,
2489-
llvm::Value *VTable,
2490-
SourceLocation Loc) {
2488+
void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
2489+
llvm::Value *VTable,
2490+
SourceLocation Loc) {
24912491
if (CGM.getCodeGenOpts().WholeProgramVTables &&
24922492
CGM.HasHiddenLTOVisibility(RD)) {
24932493
llvm::Metadata *MD =
24942494
CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
2495-
llvm::Value *BitSetName =
2495+
llvm::Value *TypeId =
24962496
llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD);
24972497

24982498
llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy);
2499-
llvm::Value *BitSetTest =
2500-
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
2501-
{CastedVTable, BitSetName});
2502-
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), BitSetTest);
2499+
llvm::Value *TypeTest =
2500+
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),
2501+
{CastedVTable, TypeId});
2502+
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest);
25032503
}
25042504

25052505
if (SanOpts.has(SanitizerKind::CFIVCall))
@@ -2595,12 +2595,11 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
25952595

25962596
llvm::Metadata *MD =
25972597
CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
2598-
llvm::Value *BitSetName = llvm::MetadataAsValue::get(getLLVMContext(), MD);
2598+
llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD);
25992599

26002600
llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy);
2601-
llvm::Value *BitSetTest =
2602-
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
2603-
{CastedVTable, BitSetName});
2601+
llvm::Value *TypeTest = Builder.CreateCall(
2602+
CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedVTable, TypeId});
26042603

26052604
SanitizerMask M;
26062605
switch (TCK) {
@@ -2626,24 +2625,23 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
26262625
EmitCheckTypeDescriptor(QualType(RD->getTypeForDecl(), 0)),
26272626
};
26282627

2629-
auto TypeId = CGM.CreateCfiIdForTypeMetadata(MD);
2630-
if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && TypeId) {
2631-
EmitCfiSlowPathCheck(M, BitSetTest, TypeId, CastedVTable, StaticData);
2628+
auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD);
2629+
if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) {
2630+
EmitCfiSlowPathCheck(M, TypeTest, CrossDsoTypeId, CastedVTable, StaticData);
26322631
return;
26332632
}
26342633

26352634
if (CGM.getCodeGenOpts().SanitizeTrap.has(M)) {
2636-
EmitTrapCheck(BitSetTest);
2635+
EmitTrapCheck(TypeTest);
26372636
return;
26382637
}
26392638

26402639
llvm::Value *AllVtables = llvm::MetadataAsValue::get(
26412640
CGM.getLLVMContext(),
26422641
llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
2643-
llvm::Value *ValidVtable =
2644-
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
2645-
{CastedVTable, AllVtables});
2646-
EmitCheck(std::make_pair(BitSetTest, M), "cfi_check_fail", StaticData,
2642+
llvm::Value *ValidVtable = Builder.CreateCall(
2643+
CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedVTable, AllVtables});
2644+
EmitCheck(std::make_pair(TypeTest, M), "cfi_check_fail", StaticData,
26472645
{CastedVTable, ValidVtable});
26482646
}
26492647

Diff for: lib/CodeGen/CGExpr.cpp

+8-9
Original file line numberDiff line numberDiff line change
@@ -2682,7 +2682,7 @@ void CodeGenFunction::EmitCfiCheckFail() {
26822682
CGM.getLLVMContext(),
26832683
llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
26842684
llvm::Value *ValidVtable = Builder.CreateZExt(
2685-
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
2685+
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),
26862686
{Addr, AllVtables}),
26872687
IntPtrTy);
26882688

@@ -4050,24 +4050,23 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
40504050
EmitSanitizerStatReport(llvm::SanStat_CFI_ICall);
40514051

40524052
llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(QualType(FnType, 0));
4053-
llvm::Value *BitSetName = llvm::MetadataAsValue::get(getLLVMContext(), MD);
4053+
llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD);
40544054

40554055
llvm::Value *CastedCallee = Builder.CreateBitCast(Callee, Int8PtrTy);
4056-
llvm::Value *BitSetTest =
4057-
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
4058-
{CastedCallee, BitSetName});
4056+
llvm::Value *TypeTest = Builder.CreateCall(
4057+
CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedCallee, TypeId});
40594058

4060-
auto TypeId = CGM.CreateCfiIdForTypeMetadata(MD);
4059+
auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD);
40614060
llvm::Constant *StaticData[] = {
40624061
llvm::ConstantInt::get(Int8Ty, CFITCK_ICall),
40634062
EmitCheckSourceLocation(E->getLocStart()),
40644063
EmitCheckTypeDescriptor(QualType(FnType, 0)),
40654064
};
4066-
if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && TypeId) {
4067-
EmitCfiSlowPathCheck(SanitizerKind::CFIICall, BitSetTest, TypeId,
4065+
if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) {
4066+
EmitCfiSlowPathCheck(SanitizerKind::CFIICall, TypeTest, CrossDsoTypeId,
40684067
CastedCallee, StaticData);
40694068
} else {
4070-
EmitCheck(std::make_pair(BitSetTest, SanitizerKind::CFIICall),
4069+
EmitCheck(std::make_pair(TypeTest, SanitizerKind::CFIICall),
40714070
"cfi_check_fail", StaticData,
40724071
{CastedCallee, llvm::UndefValue::get(IntPtrTy)});
40734072
}

Diff for: lib/CodeGen/CGVTables.cpp

+5-8
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
709709
VTLayout->getNumVTableThunks(), RTTI);
710710
VTable->setInitializer(Init);
711711

712-
CGM.EmitVTableBitSetEntries(VTable, *VTLayout.get());
712+
CGM.EmitVTableTypeMetadata(VTable, *VTLayout.get());
713713

714714
return VTable;
715715
}
@@ -933,8 +933,8 @@ bool CodeGenModule::HasHiddenLTOVisibility(const CXXRecordDecl *RD) {
933933
return true;
934934
}
935935

936-
void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
937-
const VTableLayout &VTLayout) {
936+
void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable,
937+
const VTableLayout &VTLayout) {
938938
if (!getCodeGenOpts().PrepareForLTO)
939939
return;
940940

@@ -973,10 +973,7 @@ void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
973973
return E1.second < E2.second;
974974
});
975975

976-
llvm::NamedMDNode *BitsetsMD =
977-
getModule().getOrInsertNamedMetadata("llvm.bitsets");
978976
for (auto BitsetEntry : BitsetEntries)
979-
CreateVTableBitSetEntry(BitsetsMD, VTable,
980-
PointerWidth * BitsetEntry.second,
981-
BitsetEntry.first);
977+
AddVTableTypeMetadata(VTable, PointerWidth * BitsetEntry.second,
978+
BitsetEntry.first);
982979
}

Diff for: lib/CodeGen/CodeGenFunction.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -1413,15 +1413,15 @@ class CodeGenFunction : public CodeGenTypeCache {
14131413
CFITypeCheckKind TCK, SourceLocation Loc);
14141414

14151415
/// EmitVTablePtrCheck - Emit a check that VTable is a valid virtual table for
1416-
/// RD using llvm.bitset.test.
1416+
/// RD using llvm.type.test.
14171417
void EmitVTablePtrCheck(const CXXRecordDecl *RD, llvm::Value *VTable,
14181418
CFITypeCheckKind TCK, SourceLocation Loc);
14191419

14201420
/// If whole-program virtual table optimization is enabled, emit an assumption
1421-
/// that VTable is a member of the type's bitset. Or, if vptr CFI is enabled,
1422-
/// emit a check that VTable is a member of the type's bitset.
1423-
void EmitBitSetCodeForVCall(const CXXRecordDecl *RD, llvm::Value *VTable,
1424-
SourceLocation Loc);
1421+
/// that VTable is a member of RD's type identifier. Or, if vptr CFI is
1422+
/// enabled, emit a check that VTable is a member of RD's type identifier.
1423+
void EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
1424+
llvm::Value *VTable, SourceLocation Loc);
14251425

14261426
/// CanDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given
14271427
/// expr can be devirtualized.

Diff for: lib/CodeGen/CodeGenModule.cpp

+20-50
Original file line numberDiff line numberDiff line change
@@ -787,8 +787,7 @@ void CodeGenModule::setFunctionDLLStorageClass(GlobalDecl GD, llvm::Function *F)
787787
F->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass);
788788
}
789789

790-
llvm::ConstantInt *
791-
CodeGenModule::CreateCfiIdForTypeMetadata(llvm::Metadata *MD) {
790+
llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) {
792791
llvm::MDString *MDS = dyn_cast<llvm::MDString>(MD);
793792
if (!MDS) return nullptr;
794793

@@ -989,8 +988,8 @@ static void setLinkageAndVisibilityForGV(llvm::GlobalValue *GV,
989988
}
990989
}
991990

992-
void CodeGenModule::CreateFunctionBitSetEntry(const FunctionDecl *FD,
993-
llvm::Function *F) {
991+
void CodeGenModule::CreateFunctionTypeMetadata(const FunctionDecl *FD,
992+
llvm::Function *F) {
994993
// Only if we are checking indirect calls.
995994
if (!LangOpts.Sanitize.has(SanitizerKind::CFIICall))
996995
return;
@@ -1011,25 +1010,13 @@ void CodeGenModule::CreateFunctionBitSetEntry(const FunctionDecl *FD,
10111010
return;
10121011
}
10131012

1014-
llvm::NamedMDNode *BitsetsMD =
1015-
getModule().getOrInsertNamedMetadata("llvm.bitsets");
1016-
10171013
llvm::Metadata *MD = CreateMetadataIdentifierForType(FD->getType());
1018-
llvm::Metadata *BitsetOps[] = {
1019-
MD, llvm::ConstantAsMetadata::get(F),
1020-
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(Int64Ty, 0))};
1021-
BitsetsMD->addOperand(llvm::MDTuple::get(getLLVMContext(), BitsetOps));
1014+
F->addTypeMetadata(0, MD);
10221015

10231016
// Emit a hash-based bit set entry for cross-DSO calls.
1024-
if (CodeGenOpts.SanitizeCfiCrossDso) {
1025-
if (auto TypeId = CreateCfiIdForTypeMetadata(MD)) {
1026-
llvm::Metadata *BitsetOps2[] = {
1027-
llvm::ConstantAsMetadata::get(TypeId),
1028-
llvm::ConstantAsMetadata::get(F),
1029-
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(Int64Ty, 0))};
1030-
BitsetsMD->addOperand(llvm::MDTuple::get(getLLVMContext(), BitsetOps2));
1031-
}
1032-
}
1017+
if (CodeGenOpts.SanitizeCfiCrossDso)
1018+
if (auto CrossDsoTypeId = CreateCrossDsoCfiTypeId(MD))
1019+
F->addTypeMetadata(0, llvm::ConstantAsMetadata::get(CrossDsoTypeId));
10331020
}
10341021

10351022
void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
@@ -1090,7 +1077,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
10901077
if (MD->isVirtual())
10911078
F->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
10921079

1093-
CreateFunctionBitSetEntry(FD, F);
1080+
CreateFunctionTypeMetadata(FD, F);
10941081
}
10951082

10961083
void CodeGenModule::addUsedGlobal(llvm::GlobalValue *GV) {
@@ -4219,8 +4206,8 @@ llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) {
42194206
return InternalId;
42204207
}
42214208

4222-
/// Returns whether this module needs the "all-vtables" bitset.
4223-
bool CodeGenModule::NeedAllVtablesBitSet() const {
4209+
/// Returns whether this module needs the "all-vtables" type identifier.
4210+
bool CodeGenModule::NeedAllVtablesTypeId() const {
42244211
// Returns true if at least one of vtable-based CFI checkers is enabled and
42254212
// is not in the trapping mode.
42264213
return ((LangOpts.Sanitize.has(SanitizerKind::CFIVCall) &&
@@ -4233,38 +4220,21 @@ bool CodeGenModule::NeedAllVtablesBitSet() const {
42334220
!CodeGenOpts.SanitizeTrap.has(SanitizerKind::CFIUnrelatedCast)));
42344221
}
42354222

4236-
void CodeGenModule::CreateVTableBitSetEntry(llvm::NamedMDNode *BitsetsMD,
4237-
llvm::GlobalVariable *VTable,
4238-
CharUnits Offset,
4239-
const CXXRecordDecl *RD) {
4223+
void CodeGenModule::AddVTableTypeMetadata(llvm::GlobalVariable *VTable,
4224+
CharUnits Offset,
4225+
const CXXRecordDecl *RD) {
42404226
llvm::Metadata *MD =
42414227
CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
4242-
llvm::Metadata *BitsetOps[] = {
4243-
MD, llvm::ConstantAsMetadata::get(VTable),
4244-
llvm::ConstantAsMetadata::get(
4245-
llvm::ConstantInt::get(Int64Ty, Offset.getQuantity()))};
4246-
BitsetsMD->addOperand(llvm::MDTuple::get(getLLVMContext(), BitsetOps));
4228+
VTable->addTypeMetadata(Offset.getQuantity(), MD);
42474229

4248-
if (CodeGenOpts.SanitizeCfiCrossDso) {
4249-
if (auto TypeId = CreateCfiIdForTypeMetadata(MD)) {
4250-
llvm::Metadata *BitsetOps2[] = {
4251-
llvm::ConstantAsMetadata::get(TypeId),
4252-
llvm::ConstantAsMetadata::get(VTable),
4253-
llvm::ConstantAsMetadata::get(
4254-
llvm::ConstantInt::get(Int64Ty, Offset.getQuantity()))};
4255-
BitsetsMD->addOperand(llvm::MDTuple::get(getLLVMContext(), BitsetOps2));
4256-
}
4257-
}
4230+
if (CodeGenOpts.SanitizeCfiCrossDso)
4231+
if (auto CrossDsoTypeId = CreateCrossDsoCfiTypeId(MD))
4232+
VTable->addTypeMetadata(Offset.getQuantity(),
4233+
llvm::ConstantAsMetadata::get(CrossDsoTypeId));
42584234

4259-
if (NeedAllVtablesBitSet()) {
4235+
if (NeedAllVtablesTypeId()) {
42604236
llvm::Metadata *MD = llvm::MDString::get(getLLVMContext(), "all-vtables");
4261-
llvm::Metadata *BitsetOps[] = {
4262-
MD, llvm::ConstantAsMetadata::get(VTable),
4263-
llvm::ConstantAsMetadata::get(
4264-
llvm::ConstantInt::get(Int64Ty, Offset.getQuantity()))};
4265-
// Avoid adding a node to BitsetsMD twice.
4266-
if (!llvm::MDTuple::getIfExists(getLLVMContext(), BitsetOps))
4267-
BitsetsMD->addOperand(llvm::MDTuple::get(getLLVMContext(), BitsetOps));
4237+
VTable->addTypeMetadata(Offset.getQuantity(), MD);
42684238
}
42694239
}
42704240

Diff for: lib/CodeGen/CodeGenModule.h

+12-14
Original file line numberDiff line numberDiff line change
@@ -1118,29 +1118,27 @@ class CodeGenModule : public CodeGenTypeCache {
11181118
/// optimization.
11191119
bool HasHiddenLTOVisibility(const CXXRecordDecl *RD);
11201120

1121-
/// Emit bit set entries for the given vtable using the given layout if
1122-
/// vptr CFI is enabled.
1123-
void EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
1124-
const VTableLayout &VTLayout);
1121+
/// Emit type metadata for the given vtable using the given layout.
1122+
void EmitVTableTypeMetadata(llvm::GlobalVariable *VTable,
1123+
const VTableLayout &VTLayout);
11251124

1126-
/// Generate a cross-DSO type identifier for type.
1127-
llvm::ConstantInt *CreateCfiIdForTypeMetadata(llvm::Metadata *MD);
1125+
/// Generate a cross-DSO type identifier for MD.
1126+
llvm::ConstantInt *CreateCrossDsoCfiTypeId(llvm::Metadata *MD);
11281127

11291128
/// Create a metadata identifier for the given type. This may either be an
11301129
/// MDString (for external identifiers) or a distinct unnamed MDNode (for
11311130
/// internal identifiers).
11321131
llvm::Metadata *CreateMetadataIdentifierForType(QualType T);
11331132

1134-
/// Create a bitset entry for the given function and add it to BitsetsMD.
1135-
void CreateFunctionBitSetEntry(const FunctionDecl *FD, llvm::Function *F);
1133+
/// Create and attach type metadata to the given function.
1134+
void CreateFunctionTypeMetadata(const FunctionDecl *FD, llvm::Function *F);
11361135

1137-
/// Returns whether this module needs the "all-vtables" bitset.
1138-
bool NeedAllVtablesBitSet() const;
1136+
/// Returns whether this module needs the "all-vtables" type identifier.
1137+
bool NeedAllVtablesTypeId() const;
11391138

1140-
/// Create a bitset entry for the given vtable and add it to BitsetsMD.
1141-
void CreateVTableBitSetEntry(llvm::NamedMDNode *BitsetsMD,
1142-
llvm::GlobalVariable *VTable, CharUnits Offset,
1143-
const CXXRecordDecl *RD);
1139+
/// Create and attach type metadata for the given vtable.
1140+
void AddVTableTypeMetadata(llvm::GlobalVariable *VTable, CharUnits Offset,
1141+
const CXXRecordDecl *RD);
11441142

11451143
/// \breif Get the declaration of std::terminate for the platform.
11461144
llvm::Constant *getTerminateFn();

0 commit comments

Comments
 (0)