llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen @llvm/pr-subscribers-llvm-ir Author: None (luxufan) <details> <summary>Changes</summary> This commit enhances the ThinLTO pipeline to support the elimination of unused Run-Time Type Information (RTTI) data when the `-fno-split-lto-unit` flag is used. Previously, dead RTTI data was not effectively removed, leading to larger binary sizes. --- Patch is 35.63 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/126336.diff 26 Files Affected: - (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+1) - (added) clang/test/CodeGenCXX/typeid-type-test.cpp (+32) - (modified) llvm/include/llvm/Analysis/TypeMetadataUtils.h (+2) - (modified) llvm/include/llvm/AsmParser/LLParser.h (+1) - (modified) llvm/include/llvm/AsmParser/LLToken.h (+1) - (modified) llvm/include/llvm/Bitcode/LLVMBitCodes.h (+1) - (modified) llvm/include/llvm/IR/ModuleSummaryIndex.h (+22) - (modified) llvm/include/llvm/LTO/LTO.h (+10-2) - (added) llvm/include/llvm/Support/LibCXXABI.h (+49) - (added) llvm/include/llvm/Transforms/IPO/DeadRTTIElimination.h (+21) - (modified) llvm/lib/Analysis/ModuleSummaryAnalysis.cpp (+64-2) - (modified) llvm/lib/Analysis/TypeMetadataUtils.cpp (+61) - (modified) llvm/lib/AsmParser/LLLexer.cpp (+1) - (modified) llvm/lib/AsmParser/LLParser.cpp (+30) - (modified) llvm/lib/Bitcode/Reader/BitcodeReader.cpp (+13) - (modified) llvm/lib/Bitcode/Writer/BitcodeWriter.cpp (+15) - (modified) llvm/lib/IR/AsmWriter.cpp (+12) - (modified) llvm/lib/LTO/LTO.cpp (+25-9) - (modified) llvm/lib/LTO/LTOBackend.cpp (+13-3) - (modified) llvm/lib/Support/CMakeLists.txt (+1) - (added) llvm/lib/Support/LibCXXABI.cpp (+25) - (modified) llvm/lib/Transforms/IPO/CMakeLists.txt (+1) - (added) llvm/lib/Transforms/IPO/DeadRTTIElimination.cpp (+46) - (added) llvm/test/Assembler/thinlto-rtti-summary.ll (+20) - (added) llvm/test/ThinLTO/X86/rtti-clean.ll (+34) - (added) llvm/test/ThinLTO/X86/rtti-dont-clean.ll (+46) ``````````diff diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 7c463f51f63dc5c..090eb4c16ce0b47 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -1592,6 +1592,7 @@ llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF, cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getDecl()); llvm::Value *Value = CGF.GetVTablePtr(ThisPtr, CGM.GlobalsInt8PtrTy, ClassDecl); + CGF.EmitTypeMetadataCodeForVCall(ClassDecl, Value, SourceLocation()); if (CGM.getItaniumVTableContext().isRelativeLayout()) { // Load the type info. diff --git a/clang/test/CodeGenCXX/typeid-type-test.cpp b/clang/test/CodeGenCXX/typeid-type-test.cpp new file mode 100644 index 000000000000000..9408d87495c608b --- /dev/null +++ b/clang/test/CodeGenCXX/typeid-type-test.cpp @@ -0,0 +1,32 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -I%S -triple x86_64-unknown-linux -flto -fwhole-program-vtables -fvisibility=hidden -emit-llvm -o - %s | FileCheck %s + +#include <typeinfo> + +namespace Test1 { +struct A { virtual void f(); }; + +// CHECK-LABEL: define hidden noundef nonnull align 8 dereferenceable(16) ptr @_ZN5Test19gettypeidEPNS_1AE( +// CHECK-SAME: ptr noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null +// CHECK-NEXT: br i1 [[TMP1]], label %[[TYPEID_BAD_TYPEID:.*]], label %[[TYPEID_END:.*]] +// CHECK: [[TYPEID_BAD_TYPEID]]: +// CHECK-NEXT: call void @__cxa_bad_typeid() #[[ATTR3:[0-9]+]] +// CHECK-NEXT: unreachable +// CHECK: [[TYPEID_END]]: +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"_ZTSN5Test11AE") +// CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]]) +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 -1 +// CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8 +// CHECK-NEXT: ret ptr [[TMP4]] +// +const std::type_info &gettypeid(A *a) { + return typeid(*a); +} + +} diff --git a/llvm/include/llvm/Analysis/TypeMetadataUtils.h b/llvm/include/llvm/Analysis/TypeMetadataUtils.h index bdb477b54b532d0..87da08dba34c745 100644 --- a/llvm/include/llvm/Analysis/TypeMetadataUtils.h +++ b/llvm/include/llvm/Analysis/TypeMetadataUtils.h @@ -51,6 +51,8 @@ void findDevirtualizableCallsForTypeTest( SmallVectorImpl<CallInst *> &Assumes, const CallInst *CI, DominatorTree &DT); +bool hasTypeIdLoadForTypeTest(const CallInst *CI); + /// Given a call to the intrinsic \@llvm.type.checked.load, find all /// devirtualizable call sites based on the call and return them in DevirtCalls. void findDevirtualizableCallsForTypeCheckedLoad( diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h index c01de4a289a69a0..b5dbfdd24657d6c 100644 --- a/llvm/include/llvm/AsmParser/LLParser.h +++ b/llvm/include/llvm/AsmParser/LLParser.h @@ -427,6 +427,7 @@ namespace llvm { bool parseTypeIdEntry(unsigned ID); bool parseTypeIdSummary(TypeIdSummary &TIS); bool parseTypeIdCompatibleVtableEntry(unsigned ID); + bool parseTypeIdMayBeAccessed(unsigned ID); bool parseTypeTestResolution(TypeTestResolution &TTRes); bool parseOptionalWpdResolutions( std::map<uint64_t, WholeProgramDevirtResolution> &WPDResMap); diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h index 7b47bc88ddb25ff..c2bdab430b68947 100644 --- a/llvm/include/llvm/AsmParser/LLToken.h +++ b/llvm/include/llvm/AsmParser/LLToken.h @@ -422,6 +422,7 @@ enum Kind { kw_args, kw_typeid, kw_typeidCompatibleVTable, + kw_typeidMayBeAccessed, kw_summary, kw_typeTestRes, kw_kind, diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 9eb38c3e4482910..41cb7a5922088c4 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -335,6 +335,7 @@ enum GlobalValueSummarySymtabCodes { // CallStackRadixTreeBuilder class in ProfileData/MemProf.h for format. // [n x entry] FS_CONTEXT_RADIX_TREE_ARRAY = 32, + FS_RTTI = 33, }; enum MetadataCodes { diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h index 3c586a1dd21d823..717bb37685f529a 100644 --- a/llvm/include/llvm/IR/ModuleSummaryIndex.h +++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -643,6 +643,19 @@ class GlobalValueSummary { /// Return the list of values referenced by this global value definition. ArrayRef<ValueInfo> refs() const { return RefEdgeList; } + /// Erase all reference whose name is equal to Name. + bool eraseRef(StringRef Name) { + bool Erased = false; + erase_if(RefEdgeList, [&](ValueInfo VI) { + if (VI.name() == Name) { + Erased = true; + return true; + } + return false; + }); + return Erased; + } + /// If this is an alias summary, returns the summary of the aliased object (a /// global variable or function), otherwise returns itself. GlobalValueSummary *getBaseObject(); @@ -1365,6 +1378,9 @@ class ModuleSummaryIndex { std::map<StringRef, TypeIdCompatibleVtableInfo, std::less<>> TypeIdCompatibleVtableMap; + /// Type identifiers that may be accessed at run time. + SmallVector<StringRef, 0> TypeIdMayBeAccessed; + /// Mapping from original ID to GUID. If original ID can map to multiple /// GUIDs, it will be mapped to 0. DenseMap<GlobalValue::GUID, GlobalValue::GUID> OidGuidMap; @@ -1875,6 +1891,12 @@ class ModuleSummaryIndex { return I->second; } + void addTypeIdAccessed(StringRef TypeId) { + TypeIdMayBeAccessed.push_back(TypeId); + } + + const auto &getTypeIdAccessed() const { return TypeIdMayBeAccessed; } + /// Collect for the given module the list of functions it defines /// (GUID -> Summary). void collectDefinedFunctionsForModule(StringRef ModulePath, diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h index 242a05f7d32c025..085e6eaddc4904e 100644 --- a/llvm/include/llvm/LTO/LTO.h +++ b/llvm/include/llvm/LTO/LTO.h @@ -386,6 +386,8 @@ class LTO { private: Config Conf; + std::string TargetTriple; + struct RegularLTOState { RegularLTOState(unsigned ParallelCodeGenParallelismLevel, const Config &Conf); @@ -520,11 +522,17 @@ class LTO { const SymbolResolution *&ResI, const SymbolResolution *ResE); Error runRegularLTO(AddStreamFn AddStream); - Error runThinLTO(AddStreamFn AddStream, FileCache Cache, - const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols); + Error + runThinLTO(AddStreamFn AddStream, FileCache Cache, + const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols, + function_ref<PrevailingType(GlobalValue::GUID)> isPrevailing); Error checkPartiallySplit(); + std::string & getTargetTriple() { return TargetTriple; } + + void setTargetTriple(std::string TT) { TargetTriple = std::move(TT); } + mutable bool CalledGetMaxTasks = false; // LTO mode when using Unified LTO. diff --git a/llvm/include/llvm/Support/LibCXXABI.h b/llvm/include/llvm/Support/LibCXXABI.h new file mode 100644 index 000000000000000..37f4b43f9584563 --- /dev/null +++ b/llvm/include/llvm/Support/LibCXXABI.h @@ -0,0 +1,49 @@ +#ifndef LLVM_SUPPORT_LIBCXXABI_H +#define LLVM_SUPPORT_LIBCXXABI_H + +#include "llvm/IR/DataLayout.h" +#include "llvm/TargetParser/Triple.h" + +namespace llvm { + +class CXXABI { + + virtual const char * getVTablePrefix() = 0; + virtual const char * getTypeNamePrefix() = 0; + virtual const char * getTypeInfoPrefix() = 0; + +public: + static std::unique_ptr<CXXABI> Create(Triple &TT); + virtual ~CXXABI() {} + virtual int64_t + getOffsetFromTypeInfoSlotToAddressPoint(const DataLayout &DT) = 0; + + bool isVTable(StringRef Name) { return Name.starts_with(getVTablePrefix()); } + bool isTypeName(StringRef Name) { + return Name.starts_with(getTypeNamePrefix()); + } + bool isTypeInfo(StringRef Name) { + return Name.starts_with(getTypeInfoPrefix()); + } + + std::string getTypeNameFromTypeInfo(StringRef TypeInfo); + std::string getTypeInfoFromVTable(StringRef VTable); +}; + +class Itanium final : public CXXABI { + + const char * getVTablePrefix() override { return "_ZTV"; } + const char * getTypeNamePrefix() override { return "_ZTS"; } + const char * getTypeInfoPrefix() override { return "_ZTI"; } + +public: + virtual ~Itanium() {} + + int64_t + getOffsetFromTypeInfoSlotToAddressPoint(const DataLayout &DL) override { + return -2 * static_cast<int64_t>(DL.getPointerSize()); + } +}; + +} // namespace llvm +#endif diff --git a/llvm/include/llvm/Transforms/IPO/DeadRTTIElimination.h b/llvm/include/llvm/Transforms/IPO/DeadRTTIElimination.h new file mode 100644 index 000000000000000..906abf3d1a9ed27 --- /dev/null +++ b/llvm/include/llvm/Transforms/IPO/DeadRTTIElimination.h @@ -0,0 +1,21 @@ +#ifndef LLVM_TRANSFORMS_IPO_DEADRTTIELIMINATION_H +#define LLVM_TRANSFORMS_IPO_DEADRTTIELIMINATION_H + +#include "llvm/IR/ModuleSummaryIndex.h" +#include "llvm/Support/LibCXXABI.h" +#include "llvm/TargetParser/Triple.h" + +namespace llvm { +class DeadRTTIElimIndex { + ModuleSummaryIndex &ExportSummary; + std::unique_ptr<CXXABI> ABI; + +public: + DeadRTTIElimIndex(ModuleSummaryIndex &ExportSummary, Triple &TT) + : ExportSummary(ExportSummary), ABI(CXXABI::Create(TT)) {} + + void run(); +}; +} // namespace llvm + +#endif // LLVM_TRANSFORMS_SCALAR_DEADRTTIELIMINATION_H diff --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp index 611d4bfbc69e8fe..ec0aa81d05f8a04 100644 --- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp +++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -52,6 +52,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/LibCXXABI.h" #include <cassert> #include <cstdint> #include <vector> @@ -202,7 +203,7 @@ static void addVCallToSet( /// If this intrinsic call requires that we add information to the function /// summary, do so via the non-constant reference arguments. static void addIntrinsicToSummary( - const CallInst *CI, + ModuleSummaryIndex &Index, const CallInst *CI, SetVector<GlobalValue::GUID, std::vector<GlobalValue::GUID>> &TypeTests, SetVector<FunctionSummary::VFuncId, std::vector<FunctionSummary::VFuncId>> &TypeTestAssumeVCalls, @@ -241,6 +242,10 @@ static void addIntrinsicToSummary( addVCallToSet(Call, Guid, TypeTestAssumeVCalls, TypeTestAssumeConstVCalls); + if (Triple(CI->getModule()->getTargetTriple()).getOS() == Triple::Linux && + hasTypeIdLoadForTypeTest(CI)) + Index.addTypeIdAccessed(TypeId->getString()); + break; } @@ -431,7 +436,7 @@ static void computeFunctionSummary( if (CalledFunction) { if (CI && CalledFunction->isIntrinsic()) { addIntrinsicToSummary( - CI, TypeTests, TypeTestAssumeVCalls, TypeCheckedLoadVCalls, + Index, CI, TypeTests, TypeTestAssumeVCalls, TypeCheckedLoadVCalls, TypeTestAssumeConstVCalls, TypeCheckedLoadConstVCalls, DT); continue; } @@ -911,6 +916,61 @@ static void setLiveRoot(ModuleSummaryIndex &Index, StringRef Name) { Summary->setLive(true); } +static bool hasNonVTableUsers(const User *U, CXXABI *ABI) { + LLVM_DEBUG(dbgs() << "Check if " << *U << "has vtable users\n"); + if (isa<Instruction>(U)) { + // If the type info is used in dynamic_cast or exception handling, + // its user must be the instruction. + return true; + } + + // The virtual table type is either a struct of arrays. For example: + // @vtable = constant { [3 x ptr] } { [3 x ptr] [ ptr null, ptr @rtti, ptr @vf] } + // + // In this case, the user of @rtti is an anonymous ConstantArray. + // Therefore, if the user of the type information is anonymous, + // we need to perform a depth-first search (DFS) to locate its named users. + // + // And we also need to iterate its users if the current user is the type + // info global variable itself. + StringRef Name = U->getName(); + if (Name.empty() || ABI->isTypeInfo(Name)) { + for (const User *It : U->users()) + if (hasNonVTableUsers(It, ABI)) + return true; + return false; + } + + if (!ABI->isVTable(Name)) + return true; + + return false; +} + +static void analyzeRTTIVars(ModuleSummaryIndex &Index, const Module &M) { + Triple TT(M.getTargetTriple()); + + std::unique_ptr<CXXABI> ABI = CXXABI::Create(TT); + if (!ABI) + return; + + for (const GlobalVariable &GV : M.globals()) { + if (!ABI->isTypeInfo(GV.getName())) + continue; + + if (hasNonVTableUsers(&GV, ABI.get())) { + std::string TypeName = + ABI->getTypeNameFromTypeInfo(GV.getName()); + const GlobalVariable *TypeNameGV = M.getNamedGlobal(TypeName); + if (TypeNameGV) + Index.addTypeIdAccessed(TypeNameGV->getName()); + else + Index.addTypeIdAccessed(Index.saveString(TypeName)); + break; + } + } +} + ModuleSummaryIndex llvm::buildModuleSummaryIndex( const Module &M, std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback, @@ -1019,6 +1079,8 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex( mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("ThinLTO"))) IsThinLTO = MD->getZExtValue(); + analyzeRTTIVars(Index, M); + // Compute summaries for all functions defined in module, and save in the // index. for (const auto &F : M) { diff --git a/llvm/lib/Analysis/TypeMetadataUtils.cpp b/llvm/lib/Analysis/TypeMetadataUtils.cpp index 9ec0785eb5034d6..9271f9c3d5b0baa 100644 --- a/llvm/lib/Analysis/TypeMetadataUtils.cpp +++ b/llvm/lib/Analysis/TypeMetadataUtils.cpp @@ -17,6 +17,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" +#include "llvm/Support/LibCXXABI.h" using namespace llvm; @@ -50,6 +51,42 @@ findCallsAtConstantOffset(SmallVectorImpl<DevirtCallSite> &DevirtCalls, } } +static bool hasTypeIdLoadAtConstantOffset(const Module *M, Value *VPtr, + int64_t Offset, const CallInst *CI, + CXXABI *ABI) { + Triple TT(M->getTargetTriple()); + bool HasTypeIdLoad = false; + for (const Use &U : VPtr->uses()) { + Value *User = U.getUser(); + if (isa<BitCastInst>(User)) { + HasTypeIdLoad |= hasTypeIdLoadAtConstantOffset(M, User, Offset, CI, ABI); + } else if (isa<LoadInst>(User)) { + if (Offset == + ABI->getOffsetFromTypeInfoSlotToAddressPoint(M->getDataLayout())) + return true; + } else if (auto GEP = dyn_cast<GetElementPtrInst>(User)) { + // Take into account the GEP offset. + if (VPtr == GEP->getPointerOperand() && GEP->hasAllConstantIndices()) { + SmallVector<Value *, 8> Indices(drop_begin(GEP->operands())); + int64_t GEPOffset = M->getDataLayout().getIndexedOffsetInType( + GEP->getSourceElementType(), Indices); + HasTypeIdLoad |= + hasTypeIdLoadAtConstantOffset(M, User, Offset + GEPOffset, CI, ABI); + } + } else if (auto *Call = dyn_cast<CallInst>(User)) { + if (Call->getIntrinsicID() == llvm::Intrinsic::load_relative) { + if (auto *LoadOffset = dyn_cast<ConstantInt>(Call->getOperand(1))) { + HasTypeIdLoad |= + hasTypeIdLoadAtConstantOffset(M, User, Offset, CI, ABI); + } + } + } else { + HasTypeIdLoad = true; + } + } + return HasTypeIdLoad; +} + // Search for virtual calls that load from VPtr and add them to DevirtCalls. static void findLoadCallsAtConstantOffset( const Module *M, SmallVectorImpl<DevirtCallSite> &DevirtCalls, Value *VPtr, @@ -103,6 +140,30 @@ void llvm::findDevirtualizableCallsForTypeTest( M, DevirtCalls, CI->getArgOperand(0)->stripPointerCasts(), 0, CI, DT); } +bool llvm::hasTypeIdLoadForTypeTest(const CallInst *CI) { + assert(CI->getCalledFunction()->getIntrinsicID() == Intrinsic::type_test || + CI->getCalledFunction()->getIntrinsicID() == + Intrinsic::public_type_test); + Triple TT(CI->getModule()->getTargetTriple()); + std::unique_ptr<CXXABI> ABI = CXXABI::Create(TT); + if (!ABI) + return false; + SmallVector<CallInst *, 1> Assumes; + + const Module *M = CI->getParent()->getParent()->getParent(); + + // Find llvm.assume intrinsics for this llvm.type.test call. + for (const Use &CIU : CI->uses()) + if (auto *Assume = dyn_cast<AssumeInst>(CIU.getUser())) + Assumes.push_back(Assume); + + if (!Assumes.empty()) + return hasTypeIdLoadAtConstantOffset( + M, CI->getArgOperand(0)->stripPointerCasts(), 0, CI, ABI.get()); + + return false; +} + void llvm::findDevirtualizableCallsForTypeCheckedLoad( SmallVectorImpl<DevirtCallSite> &DevirtCalls, SmallVectorImpl<Instruction *> &LoadedPtrs, diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 5ea507c009bdc61..b6d09f0992c7994 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -826,6 +826,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(args); KEYWORD(typeid); KEYWORD(typeidCompatibleVTable); + KEYWORD(typeidMayBeAccessed); KEYWORD(summary); KEYWORD(typeTestRes); KEYWORD(kind); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index be6166f0c41694f..e33ef2e13755c54 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -1118,6 +1118,9 @@ bool LLParser::parseSummaryEntry() { case lltok::kw_typeidCompatibleVTable: result = parseTypeIdCompatibleVtableEntry(SummaryID); break; + case lltok::kw_typeidMayBeAccessed: + result = parseTypeIdMayBeAccessed(SummaryID); + break; case lltok::kw_flags: result = parseSummaryIndexFlags(); break; @@ -8918,6 +8921,33 @@ bool LLParser::parseTypeIdSummary(TypeIdSummary &TIS) { static ValueInfo EmptyVI = ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8); +bool LLParser::parseTypeIdMayBeAccessed(unsigned ID) { + assert(Lex.getKind() == lltok::kw_typeidMayBeAccessed); + Lex.Lex(); + + std::string Name; + if (parseToken(lltok::colon, "expected ':' here") || + parseToken(lltok::lparen, "expected '(' here") || + parseToken(lltok::kw_name, "expected 'name' here") || + parseToken(lltok::colon, "expected ':' here") || + parseStringConstant(Name)) + return true; + + Index->addTypeIdAccessed(Index->saveString(Name)); + + while (Lex.getKind() != lltok::rparen) { + if (parseToken(lltok::comma, "expected ',' here") || + parseStringConstant(Name)) + return true; + Index->addTypeIdAccessed(Index->saveString(Name)); + } + + if (parseToken(lltok::rparen, "expected ')' here")) + return true; + + return false; +} + /// TypeIdCompatibleVtableEntry /// ::= 'typeidCompatibleVTable' ':' '(' 'name' ':' STRINGCONSTANT ',' /// TypeIdCompatibleVtableInfo diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 56f5ff4b20e5dbf..434b3ef8a586702 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1015,6 +1015,7 @@ class ModuleSummaryIndexBitcodeReader : public BitcodeReaderBase { void parseTypeIdCompatibleVtableSummaryRecord(ArrayRef<uint64_t> Record); void parseTypeIdCompatibleVtableInfo(ArrayRef<uint64_t> Record, size_t &Slot, TypeIdCompatibleVtableInfo &TypeId); + void parseTypeIdAccessed(ArrayRef<uint64_t> Record); std::vector<FunctionSummary::ParamAccess> parseParamAccesses(ArrayRef<uint64_t> Record); SmallVector<unsigned> parseAllocInfoContext(ArrayRef<uint64_t> Record, @@ -7575,6 +7576,14 @@ void ModuleSummaryIndexBitcodeReader::parseTypeIdCompatibleVtableInfo... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/126336 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits