diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -2078,8 +2078,15 @@ case bitc::METADATA_ARG_LIST: { SmallVector Elts; Elts.reserve(Record.size()); - for (uint64_t Elt : Record) - Elts.push_back(dyn_cast_or_null(getMDOrNull(Elt))); + for (uint64_t Elt : Record) { + Metadata *MD = getMD(Elt); + if (isa(MD) && cast(MD)->isTemporary()) + return error( + "Invalid record: DIArgList should not contain forward refs"); + if (!isa(MD)) + return error("Invalid record"); + Elts.push_back(cast(MD)); + } MetadataList.assignValue(DIArgList::get(Context, Elts), NextMetadataNo); NextMetadataNo++; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1876,7 +1876,7 @@ unsigned Abbrev) { Record.reserve(N->getArgs().size()); for (ValueAsMetadata *MD : N->getArgs()) - Record.push_back(VE.getMetadataOrNullID(MD)); + Record.push_back(VE.getMetadataID(MD)); Stream.EmitRecord(bitc::METADATA_ARG_LIST, Record, Abbrev); Record.clear(); diff --git a/llvm/lib/Bitcode/Writer/ValueEnumerator.h b/llvm/lib/Bitcode/Writer/ValueEnumerator.h --- a/llvm/lib/Bitcode/Writer/ValueEnumerator.h +++ b/llvm/lib/Bitcode/Writer/ValueEnumerator.h @@ -27,6 +27,7 @@ class BasicBlock; class Comdat; +class DIArgList; class Function; class Instruction; class LocalAsMetadata; @@ -286,6 +287,9 @@ void EnumerateFunctionLocalMetadata(const Function &F, const LocalAsMetadata *Local); void EnumerateFunctionLocalMetadata(unsigned F, const LocalAsMetadata *Local); + void EnumerateFunctionLocalListMetadata(const Function &F, + const DIArgList *ArgList); + void EnumerateFunctionLocalListMetadata(unsigned F, const DIArgList *Arglist); void EnumerateNamedMDNode(const NamedMDNode *NMD); void EnumerateValue(const Value *V); void EnumerateType(Type *T); diff --git a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp --- a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -78,16 +78,6 @@ } // end anonymous namespace -/// Look for a value that might be wrapped as metadata, e.g. a value in a -/// metadata operand. Returns nullptr for a non-wrapped input value if -/// OnlyWrapped is true, or it returns the input value as-is if false. -static const Value *skipMetadataWrapper(const Value *V, bool OnlyWrapped) { - if (const auto *MAV = dyn_cast(V)) - if (const auto *VAM = dyn_cast(MAV->getMetadata())) - return VAM->getValue(); - return OnlyWrapped ? nullptr : V; -} - static void orderValue(const Value *V, OrderMap &OM) { if (OM.lookup(V).first) return; @@ -139,16 +129,25 @@ // these before global values, as these will be read before setting the // global values' initializers. The latter matters for constants which have // uses towards other constants that are used as initializers. + auto orderConstantValue = [&OM](const Value *V) { + if ((isa(V) && !isa(V)) || isa(V)) + orderValue(V, OM); + }; for (const Function &F : M) { if (F.isDeclaration()) continue; for (const BasicBlock &BB : F) for (const Instruction &I : BB) for (const Value *V : I.operands()) { - if (const Value *Op = skipMetadataWrapper(V, true)) { - if ((isa(*Op) && !isa(*Op)) || - isa(*Op)) - orderValue(Op, OM); + if (const auto *MAV = dyn_cast(V)) { + if (const auto *VAM = + dyn_cast(MAV->getMetadata())) { + orderConstantValue(VAM->getValue()); + } else if (const auto *AL = + dyn_cast(MAV->getMetadata())) { + for (const auto *VAM : AL->getArgs()) + orderConstantValue(VAM->getValue()); + } } } } @@ -448,10 +447,17 @@ continue; } - // Local metadata is enumerated during function-incorporation. - if (isa(MD->getMetadata()) || - isa(MD->getMetadata())) + // Local metadata is enumerated during function-incorporation, but + // any ConstantAsMetadata arguments in a DIArgList should be examined + // now. + if (isa(MD->getMetadata())) + continue; + if (auto *AL = dyn_cast(MD->getMetadata())) { + for (auto *VAM : AL->getArgs()) + if (isa(VAM)) + EnumerateMetadata(&F, VAM); continue; + } EnumerateMetadata(&F, MD->getMetadata()); } @@ -620,6 +626,11 @@ EnumerateFunctionLocalMetadata(getMetadataFunctionID(&F), Local); } +void ValueEnumerator::EnumerateFunctionLocalListMetadata( + const Function &F, const DIArgList *ArgList) { + EnumerateFunctionLocalListMetadata(getMetadataFunctionID(&F), ArgList); +} + void ValueEnumerator::dropFunctionFromMetadata( MetadataMapType::value_type &FirstMD) { SmallVector Worklist; @@ -730,7 +741,7 @@ return nullptr; } -/// EnumerateFunctionLocalMetadataa - Incorporate function-local metadata +/// EnumerateFunctionLocalMetadata - Incorporate function-local metadata /// information reachable from the metadata. void ValueEnumerator::EnumerateFunctionLocalMetadata( unsigned F, const LocalAsMetadata *Local) { @@ -750,6 +761,39 @@ EnumerateValue(Local->getValue()); } +/// EnumerateFunctionLocalListMetadata - Incorporate function-local metadata +/// information reachable from the metadata. +void ValueEnumerator::EnumerateFunctionLocalListMetadata( + unsigned F, const DIArgList *ArgList) { + assert(F && "Expected a function"); + + // Check to see if it's already in! + MDIndex &Index = MetadataMap[ArgList]; + if (Index.ID) { + assert(Index.F == F && "Expected the same function"); + return; + } + + for (ValueAsMetadata *VAM : ArgList->getArgs()) { + if (isa(VAM)) { + assert(MetadataMap.count(VAM) && + "LocalAsMetadata should be enumerated before DIArgList"); + assert(MetadataMap[VAM].F == F && + "Expected LocalAsMetadata in the same function"); + } else { + assert(isa(VAM) && + "Expected LocalAsMetadata or ConstantAsMetadata"); + assert(ValueMap.count(VAM->getValue()) && + "Constant should be enumerated beforeDIArgList"); + EnumerateMetadata(F, VAM); + } + } + + MDs.push_back(ArgList); + Index.F = F; + Index.ID = MDs.size(); +} + static unsigned getMetadataTypeOrder(const Metadata *MD) { // Strings are emitted in bulk and must come first. if (isa(MD)) @@ -1072,7 +1116,7 @@ // DIArgList entries must come after function-local metadata, as it is not // possible to forward-reference them. for (const DIArgList *ArgList : ArgListMDVector) - EnumerateMetadata(&F, ArgList); + EnumerateFunctionLocalListMetadata(F, ArgList); } void ValueEnumerator::purgeFunction() { diff --git a/llvm/test/DebugInfo/Generic/debug_value_list.ll b/llvm/test/DebugInfo/Generic/debug_value_list.ll --- a/llvm/test/DebugInfo/Generic/debug_value_list.ll +++ b/llvm/test/DebugInfo/Generic/debug_value_list.ll @@ -8,17 +8,17 @@ target triple = "x86_64-pc-windows-msvc19.16.27034" ; CHECK-COUNT-3: llvm.dbg.value( -; CHECK-SAME: metadata !DIArgList(i32 %a, i32 %b) +; CHECK-SAME: metadata !DIArgList(i32 %a, i32 %b, i32 5) ; CHECK-SAME: metadata !16, -; CHECK-SAME: metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus) +; CHECK-SAME: metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_LLVM_arg, 2, DW_OP_plus) define dso_local i32 @"?foo@@YAHHH@Z"(i32 %a, i32 %b) local_unnamed_addr !dbg !8 { entry: call void @llvm.dbg.value(metadata !DIArgList(i32 %b), metadata !14, metadata !DIExpression(DW_OP_LLVM_arg, 0)), !dbg !17 call void @llvm.dbg.value(metadata !DIArgList(i32 %a), metadata !15, metadata !DIExpression(DW_OP_LLVM_arg, 0)), !dbg !17 call void @llvm.dbg.value( - metadata !DIArgList(i32 %a, i32 %b), + metadata !DIArgList(i32 %a, i32 %b, i32 5), metadata !16, - metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus)), !dbg !17 + metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_LLVM_arg, 2, DW_OP_plus)), !dbg !17 %mul = mul nsw i32 %b, %a, !dbg !18 ret i32 %mul, !dbg !18 }