diff --git a/llvm/include/llvm/IR/AutoUpgrade.h b/llvm/include/llvm/IR/AutoUpgrade.h index 540d60afc5a01..420671905aee1 100644 --- a/llvm/include/llvm/IR/AutoUpgrade.h +++ b/llvm/include/llvm/IR/AutoUpgrade.h @@ -63,6 +63,10 @@ namespace llvm { /// module is modified. LLVM_ABI bool UpgradeModuleFlags(Module &M); + /// Upgrade the cfi.functions metadata node by calculating and inserting + /// the GUID for each function entry if it's missing. + LLVM_ABI bool UpgradeCFIFunctionsMetadata(Module &M); + /// Convert legacy nvvm.annotations metadata to appropriate function /// attributes. LLVM_ABI void UpgradeNVVMAnnotations(Module &M); diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h index 0eaca276c48d2..ae99593d16b6b 100644 --- a/llvm/include/llvm/IR/ModuleSummaryIndex.h +++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -1573,7 +1573,7 @@ class ModuleSummaryIndex { // in the way some record are interpreted, like flags for instance. // Note that incrementing this may require changes in both BitcodeReader.cpp // and BitcodeWriter.cpp. - static constexpr uint64_t BitcodeSummaryVersion = 13; + static constexpr uint64_t BitcodeSummaryVersion = 14; // Regular LTO module name for ASM writer static constexpr const char *getRegularLTOModuleName() { diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index eb228825b9051..75e6add0ec76f 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -476,6 +476,7 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) { llvm::UpgradeDebugInfo(*M); UpgradeModuleFlags(*M); + UpgradeCFIFunctionsMetadata(*M); UpgradeNVVMAnnotations(*M); UpgradeSectionAttributes(*M); copyModuleAttrToFunctions(*M); diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 835497db8c052..35c417d8d26c2 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -3979,6 +3979,8 @@ Error BitcodeReader::materializeMetadata() { } } + UpgradeCFIFunctionsMetadata(*TheModule); + DeferredMetadataInfo.clear(); return Error::success(); } @@ -8149,24 +8151,42 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) { case bitc::FS_CFI_FUNCTION_DEFS: { auto &CfiFunctionDefs = TheIndex.cfiFunctionDefs(); - for (unsigned I = 0; I != Record.size(); I += 2) { - StringRef Name(Strtab.data() + Record[I], - static_cast(Record[I + 1])); - GlobalValue::GUID GUID = GlobalValue::getGUIDAssumingExternalLinkage( - GlobalValue::dropLLVMManglingEscape(Name)); - CfiFunctionDefs.addSymbolWithThinLTOGUID(Name, GUID); + if (Version < 14) { + for (unsigned I = 0; I != Record.size(); I += 2) { + StringRef Name(Strtab.data() + Record[I], + static_cast(Record[I + 1])); + GlobalValue::GUID GUID = GlobalValue::getGUIDAssumingExternalLinkage( + GlobalValue::dropLLVMManglingEscape(Name)); + CfiFunctionDefs.addSymbolWithThinLTOGUID(Name, GUID); + } + } else { + for (unsigned I = 0; I != Record.size(); I += 3) { + GlobalValue::GUID ThinLTOGUID = Record[I]; + StringRef Name(Strtab.data() + Record[I + 1], + static_cast(Record[I + 2])); + CfiFunctionDefs.addSymbolWithThinLTOGUID(Name, ThinLTOGUID); + } } break; } case bitc::FS_CFI_FUNCTION_DECLS: { auto &CfiFunctionDecls = TheIndex.cfiFunctionDecls(); - for (unsigned I = 0; I != Record.size(); I += 2) { - StringRef Name(Strtab.data() + Record[I], - static_cast(Record[I + 1])); - GlobalValue::GUID GUID = GlobalValue::getGUIDAssumingExternalLinkage( - GlobalValue::dropLLVMManglingEscape(Name)); - CfiFunctionDecls.addSymbolWithThinLTOGUID(Name, GUID); + if (Version < 14) { + for (unsigned I = 0; I != Record.size(); I += 2) { + StringRef Name(Strtab.data() + Record[I], + static_cast(Record[I + 1])); + GlobalValue::GUID GUID = GlobalValue::getGUIDAssumingExternalLinkage( + GlobalValue::dropLLVMManglingEscape(Name)); + CfiFunctionDecls.addSymbolWithThinLTOGUID(Name, GUID); + } + } else { + for (unsigned I = 0; I != Record.size(); I += 3) { + GlobalValue::GUID ThinLTOGUID = Record[I]; + StringRef Name(Strtab.data() + Record[I + 1], + static_cast(Record[I + 2])); + CfiFunctionDecls.addSymbolWithThinLTOGUID(Name, ThinLTOGUID); + } } break; } diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 115be64779157..f4857461ca58e 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -5323,21 +5323,23 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { getReferencedTypeIds(FS, ReferencedTypeIds); } - SmallVector Functions; + SmallVector, 4> Functions; auto EmitCfiFunctions = [&](const CfiFunctionIndex &CfiIndex, bitc::GlobalValueSummarySymtabCodes Code) { if (CfiIndex.empty()) return; for (GlobalValue::GUID GUID : DefOrUseGUIDs) { auto Names = CfiIndex.getNamesForGUID(GUID); - llvm::append_range(Functions, Names); + for (StringRef Name : Names) + Functions.push_back({Name, GUID}); } if (Functions.empty()) return; llvm::sort(Functions); - for (const auto &S : Functions) { - NameVals.push_back(StrtabBuilder.add(S)); - NameVals.push_back(S.size()); + for (const auto &Record : Functions) { + NameVals.push_back(Record.second); + NameVals.push_back(StrtabBuilder.add(Record.first)); + NameVals.push_back(Record.first.size()); } Stream.EmitRecord(Code, NameVals); NameVals.clear(); diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp index 88d0885d18da3..44076e0ce2442 100644 --- a/llvm/lib/IR/AutoUpgrade.cpp +++ b/llvm/lib/IR/AutoUpgrade.cpp @@ -26,6 +26,7 @@ #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Function.h" +#include "llvm/IR/GlobalValue.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstVisitor.h" #include "llvm/IR/Instruction.h" @@ -6359,6 +6360,50 @@ bool llvm::UpgradeModuleFlags(Module &M) { return Changed; } +bool llvm::UpgradeCFIFunctionsMetadata(Module &M) { + NamedMDNode *CFIConsts = M.getNamedMetadata("cfi.functions"); + // If this metadata has operands, we expect all of them to be either from + // before or from after the format change handled here, so we can bail out + // fast if the first (if any) operands is of the new format. + auto MatchesVersion = [](const MDNode *Op) { + return Op->getNumOperands() >= 3 && + isa(Op->getOperand(2)) && + cast(Op->getOperand(2)) + ->getType() + ->isIntegerTy(64); + }; + + if (!CFIConsts || !CFIConsts->getNumOperands() || + MatchesVersion(CFIConsts->getOperand(0))) + return false; + + bool Changed = false; + for (unsigned I = 0, E = CFIConsts->getNumOperands(); I != E; ++I) { + MDNode *Op = CFIConsts->getOperand(I); + assert(!MatchesVersion(Op) && "Unexpected mix of CFIConstant formats"); + assert(Op->getNumOperands() >= 2 && + "Expected at least 2 operands - name and linkage type"); + MDString *NameMD = dyn_cast(Op->getOperand(0)); + StringRef Name = NameMD->getString(); + GlobalValue::GUID GUID = GlobalValue::getGUIDAssumingExternalLinkage( + GlobalValue::dropLLVMManglingEscape(Name)); + + SmallVector Elts; + Elts.push_back(Op->getOperand(0)); + Elts.push_back(Op->getOperand(1)); + Elts.push_back(ConstantAsMetadata::get( + ConstantInt::get(Type::getInt64Ty(M.getContext()), GUID))); + + for (unsigned J = 2, EJ = Op->getNumOperands(); J != EJ; ++J) + Elts.push_back(Op->getOperand(J)); + + CFIConsts->setOperand(I, MDNode::get(M.getContext(), Elts)); + Changed = true; + } + + return Changed; +} + void llvm::UpgradeSectionAttributes(Module &M) { auto TrimSpaces = [](StringRef Section) -> std::string { SmallVector Components; diff --git a/llvm/lib/Transforms/IPO/CrossDSOCFI.cpp b/llvm/lib/Transforms/IPO/CrossDSOCFI.cpp index 4c8ffeb198161..9e940015902b4 100644 --- a/llvm/lib/Transforms/IPO/CrossDSOCFI.cpp +++ b/llvm/lib/Transforms/IPO/CrossDSOCFI.cpp @@ -73,8 +73,9 @@ void CrossDSOCFI::buildCFICheck(Module &M) { NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions"); if (CfiFunctionsMD) { for (auto *Func : CfiFunctionsMD->operands()) { - assert(Func->getNumOperands() >= 2); - for (unsigned I = 2; I < Func->getNumOperands(); ++I) + assert(Func->getNumOperands() >= 3); + assert(isa(Func->getOperand(2))); + for (unsigned I = 3; I < Func->getNumOperands(); ++I) if (ConstantInt *TypeId = extractNumericTypeId(cast(Func->getOperand(I).get()))) TypeIds.insert(TypeId->getZExtValue()); diff --git a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp index bc08c73360414..a519f78f2a1a7 100644 --- a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp +++ b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp @@ -2213,8 +2213,10 @@ bool LowerTypeTestsModule::lower() { ->getUniqueInteger() .getZExtValue()); const GlobalValue::GUID GUID = - GlobalValue::getGUIDAssumingExternalLinkage( - GlobalValue::dropLLVMManglingEscape(FunctionName)); + cast(FuncMD->getOperand(2)) + ->getValue() + ->getUniqueInteger() + .getZExtValue(); // Do not emit jumptable entries for functions that are not-live and // have no live references (and are not exported with cross-DSO CFI.) if (!ExportSummary->isGUIDLive(GUID)) @@ -2285,7 +2287,7 @@ bool LowerTypeTestsModule::lower() { F->setLinkage(GlobalValue::ExternalWeakLinkage); F->eraseMetadata(LLVMContext::MD_type); - for (unsigned I = 2; I < FuncMD->getNumOperands(); ++I) + for (unsigned I = 3; I < FuncMD->getNumOperands(); ++I) F->addMetadata(LLVMContext::MD_type, *cast(FuncMD->getOperand(I).get())); } diff --git a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp index 3a6851eb60272..c14c9b869525d 100644 --- a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -436,6 +436,11 @@ void splitAndWriteThinLTOBitcode( Linkage = CFL_Declaration; Elts.push_back(ConstantAsMetadata::get( llvm::ConstantInt::get(Type::getInt8Ty(Ctx), Linkage))); + // TODO: use F->getGUID() once #184065 is relanded. + GlobalValue::GUID GUID = GlobalValue::getGUIDAssumingExternalLinkage( + GlobalValue::dropLLVMManglingEscape(V->getName())); + Elts.push_back(ConstantAsMetadata::get( + llvm::ConstantInt::get(Type::getInt64Ty(Ctx), GUID))); append_range(Elts, Types); CfiFunctionMDs.push_back(MDTuple::get(Ctx, Elts)); } diff --git a/llvm/test/Bitcode/Inputs/cfi-functions-upgrade.bc b/llvm/test/Bitcode/Inputs/cfi-functions-upgrade.bc new file mode 100644 index 0000000000000..37322512a66a5 Binary files /dev/null and b/llvm/test/Bitcode/Inputs/cfi-functions-upgrade.bc differ diff --git a/llvm/test/Bitcode/Inputs/cfi-summary-upgrade.bc b/llvm/test/Bitcode/Inputs/cfi-summary-upgrade.bc new file mode 100644 index 0000000000000..c9bc5dc071810 Binary files /dev/null and b/llvm/test/Bitcode/Inputs/cfi-summary-upgrade.bc differ diff --git a/llvm/test/Bitcode/cfi-functions-upgrade.ll b/llvm/test/Bitcode/cfi-functions-upgrade.ll new file mode 100644 index 0000000000000..e9ff3dc9c5872 --- /dev/null +++ b/llvm/test/Bitcode/cfi-functions-upgrade.ll @@ -0,0 +1,24 @@ +; RUN: llvm-bcanalyzer -dump %S/Inputs/cfi-summary-upgrade.bc | FileCheck %s --check-prefix=OLD-SUMMARY +; RUN: llvm-dis < %S/Inputs/cfi-summary-upgrade.bc | FileCheck %s --check-prefix=UPGRADED-SUMMARY + +; RUN: llvm-bcanalyzer -dump %S/Inputs/cfi-functions-upgrade.bc | FileCheck %s --check-prefix=OLD-METADATA +; RUN: llvm-dis < %S/Inputs/cfi-functions-upgrade.bc | llvm-as | llvm-bcanalyzer -dump | FileCheck %s --check-prefix=UPGRADED-METADATA + +; OLD-SUMMARY: +; OLD-SUMMARY: +; OLD-SUMMARY: + +; This just tests that the old summary got loaded successfully. llvm-dis does't +; have a representation for the 2 cfi tables. +; UPGRADED-SUMMARY: ^0 = module: +; UPGRADED-SUMMARY: ^1 = gv: (guid: 6699318081062747564, +; UPGRADED-SUMMARY: ^2 = gv: (guid: 14771895114995649345, +; UPGRADED-SUMMARY: ^3 = typeid: (name: "typeid1", + +; This tests a roundtrip of old metadata -> new metadata. +; OLD-METADATA: + +; UPGRADED-METADATA: diff --git a/llvm/test/Bitcode/summary_version.ll b/llvm/test/Bitcode/summary_version.ll index bbfdd8987e5d9..fbc8bdbee0a16 100644 --- a/llvm/test/Bitcode/summary_version.ll +++ b/llvm/test/Bitcode/summary_version.ll @@ -2,7 +2,7 @@ ; RUN: opt -module-summary %s -o - | llvm-bcanalyzer -dump | FileCheck %s ; CHECK: +; CHECK: diff --git a/llvm/test/ThinLTO/X86/cfi-icall-only-defuse.ll b/llvm/test/ThinLTO/X86/cfi-icall-only-defuse.ll index 41fb17d574985..5a18fb92e7024 100644 --- a/llvm/test/ThinLTO/X86/cfi-icall-only-defuse.ll +++ b/llvm/test/ThinLTO/X86/cfi-icall-only-defuse.ll @@ -40,7 +40,7 @@ define i8 @f(i1 %i, ptr %p) { !0 = !{i64 0, !"t1"} ; FOOBAZ: +; FOOBAZ: ; FOOBAZ: ; FOOBAZ: ; FOOBAZ: ; BARQUX: +; BARQUX: ; BARQUX: ; BARQUX: ; BARQUX: