Index: include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- include/llvm/IR/ModuleSummaryIndex.h +++ include/llvm/IR/ModuleSummaryIndex.h @@ -329,6 +329,8 @@ std::unique_ptr TIdInfo; + llvm::Optional PersonalityInfo; + public: FunctionSummary(GVFlags Flags, unsigned NumInsts, FFlags FunFlags, std::vector Refs, std::vector CGEdges, @@ -364,6 +366,10 @@ /// Return the list of pairs. ArrayRef calls() const { return CallGraphEdgeList; } + llvm::Optional getPersonality() { return PersonalityInfo; } + + void setPersonality(ValueInfo Personality) { PersonalityInfo = Personality; } + /// Returns the list of type identifiers used by this function in /// llvm.type.test intrinsics other than by an llvm.assume intrinsic, /// represented as GUIDs. Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -737,7 +737,8 @@ std::vector makeCallList(ArrayRef Record, bool IsOldProfileFormat, bool HasProfile); - Error parseEntireSummary(unsigned ID); + Error parseEntireSummary(unsigned ID, + DenseMap &PersonalityMap); Error parseModuleStringTable(); std::pair @@ -4879,6 +4880,7 @@ SmallVector Record; DenseMap ValueIdToLinkageMap; + DenseMap PersonalityMap; unsigned ValueId = 0; // Read the index for this module. @@ -4925,7 +4927,7 @@ SeenValueSymbolTable = true; } SeenGlobalValSummary = true; - if (Error Err = parseEntireSummary(Entry.ID)) + if (Error Err = parseEntireSummary(Entry.ID, PersonalityMap)) return Err; break; case bitc::MODULE_STRTAB_BLOCK_ID: @@ -4987,6 +4989,13 @@ std::tie(Name, GVRecord) = readNameFromStrtab(Record); if (GVRecord.size() <= 3) return error("Invalid record"); + + // Remember personality routine if exist. If non-zero, the value in + // GVRecord is index of the personality function routine plus 1. + if (BitCode == bitc::MODULE_CODE_FUNCTION) + if (GVRecord.size() >= 15 && GVRecord[14] != 0) + PersonalityMap[ValueId] = GVRecord[14] - 1; + uint64_t RawLinkage = GVRecord[3]; GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage); if (!UseStrtab) { @@ -5033,7 +5042,8 @@ // Eagerly parse the entire summary block. This populates the GlobalValueSummary // objects in the index. -Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) { +Error ModuleSummaryIndexBitcodeReader::parseEntireSummary( + unsigned ID, DenseMap &PersonalityMap) { if (Stream.EnterSubBlock(ID)) return error("Invalid record"); SmallVector Record; @@ -5149,6 +5159,9 @@ auto VIAndOriginalGUID = getValueInfoFromValueId(ValueID); FS->setModulePath(addThisModule()->first()); FS->setOriginalName(VIAndOriginalGUID.second); + auto It = PersonalityMap.find(ValueID); + if (It != PersonalityMap.end()) + FS->setPersonality(getValueInfoFromValueId(It->second).first); TheIndex.addGlobalValueSummary(VIAndOriginalGUID.first, std::move(FS)); break; } Index: lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- lib/Transforms/IPO/FunctionImport.cpp +++ lib/Transforms/IPO/FunctionImport.cpp @@ -457,9 +457,12 @@ for (auto &Summary : VI.getSummaryList()) { for (auto Ref : Summary->refs()) visit(Ref); - if (auto *FS = dyn_cast(Summary.get())) + if (auto *FS = dyn_cast(Summary.get())) { for (auto Call : FS->calls()) visit(Call.first); + if (Optional P = FS->getPersonality()) + visit(*P); + } if (auto *AS = dyn_cast(Summary.get())) { auto AliaseeGUID = AS->getAliasee().getOriginalName(); ValueInfo AliaseeVI = Index.getValueInfo(AliaseeGUID); Index: test/ThinLTO/X86/Inputs/personality.ll =================================================================== --- test/ThinLTO/X86/Inputs/personality.ll +++ test/ThinLTO/X86/Inputs/personality.ll @@ -0,0 +1,10 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux-gnu" + +define void @bar() personality i32 (i32, i32, i64, i8*, i8*)* @personality_routine { + ret void +} + +define protected i32 @personality_routine(i32, i32, i64, i8*, i8*) { + ret i32 0 +} Index: test/ThinLTO/X86/personality.ll =================================================================== --- test/ThinLTO/X86/personality.ll +++ test/ThinLTO/X86/personality.ll @@ -0,0 +1,41 @@ +; RUN: opt -module-summary %s -o %t1.bc +; RUN: opt -module-summary %S/Inputs/personality.ll -o %t2.bc + +; RUN: llvm-lto2 run -o %t.o %t1.bc %t2.bc -save-temps \ +; RUN: -r %t2.bc,bar,p \ +; RUN: -r %t2.bc,personality_routine,p \ +; RUN: -r %t1.bc,foo,p \ +; RUN: -r %t1.bc,personality_routine,l \ +; RUN: -r %t1.bc,main,xp \ +; RUN: -r %t1.bc,bar,l +; RUN: llvm-readobj -t %t.o.1 | FileCheck %s --check-prefix=BINDING + +; BINDING: Symbol { +; BINDING: Name: personality_routine +; BINDING-NEXT: Value: +; BINDING-NEXT: Size: +; BINDING-NEXT: Binding: Global +; BINDING-NEXT: Type: Function +; BINDING-NEXT: Other [ +; BINDING-NEXT: STV_PROTECTED +; BINDING-NEXT: ] +; BINDING-NEXT: Section: .text +; BINDING-NEXT: } + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux-gnu" + +declare protected i32 @personality_routine(i32, i32, i64, i8*, i8*) +declare void @bar() + +define void @foo() personality i32 (i32, i32, i64, i8*, i8*)* @personality_routine { + ret void +} + +define i32 @main() { +entry: + call void @foo() + call void @bar() + ret i32 0 +} +