Skip to content

Commit e5d844b

Browse files
committed
[Bitcode] Ensure DIArgList in bitcode has no null or forward metadata refs
This patch fixes an issue in which ConstantAsMetadata arguments to a DIArglist, as well as the Constant values referenced by that metadata, would not be always be emitted correctly into bitcode. This patch fixes this issue firstly by searching for ConstantAsMetadata in DIArgLists (previously we would only search for them when directly wrapped in MetadataAsValue), and secondly by enumerating all of a DIArgList's arguments directly prior to enumerating the DIArgList itself. This patch also adds a number of asserts, and no longer treats the arguments to a DIArgList as optional fields when reading/writing to bitcode. Differential Revision: https://reviews.llvm.org/D100572
1 parent be2277f commit e5d844b

File tree

5 files changed

+81
-26
lines changed

5 files changed

+81
-26
lines changed

llvm/lib/Bitcode/Reader/MetadataLoader.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2078,8 +2078,15 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
20782078
case bitc::METADATA_ARG_LIST: {
20792079
SmallVector<ValueAsMetadata *, 4> Elts;
20802080
Elts.reserve(Record.size());
2081-
for (uint64_t Elt : Record)
2082-
Elts.push_back(dyn_cast_or_null<ValueAsMetadata>(getMDOrNull(Elt)));
2081+
for (uint64_t Elt : Record) {
2082+
Metadata *MD = getMD(Elt);
2083+
if (isa<MDNode>(MD) && cast<MDNode>(MD)->isTemporary())
2084+
return error(
2085+
"Invalid record: DIArgList should not contain forward refs");
2086+
if (!isa<ValueAsMetadata>(MD))
2087+
return error("Invalid record");
2088+
Elts.push_back(cast<ValueAsMetadata>(MD));
2089+
}
20832090

20842091
MetadataList.assignValue(DIArgList::get(Context, Elts), NextMetadataNo);
20852092
NextMetadataNo++;

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1876,7 +1876,7 @@ void ModuleBitcodeWriter::writeDIArgList(const DIArgList *N,
18761876
unsigned Abbrev) {
18771877
Record.reserve(N->getArgs().size());
18781878
for (ValueAsMetadata *MD : N->getArgs())
1879-
Record.push_back(VE.getMetadataOrNullID(MD));
1879+
Record.push_back(VE.getMetadataID(MD));
18801880

18811881
Stream.EmitRecord(bitc::METADATA_ARG_LIST, Record, Abbrev);
18821882
Record.clear();

llvm/lib/Bitcode/Writer/ValueEnumerator.cpp

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,6 @@ struct OrderMap {
7878

7979
} // end anonymous namespace
8080

81-
/// Look for a value that might be wrapped as metadata, e.g. a value in a
82-
/// metadata operand. Returns nullptr for a non-wrapped input value if
83-
/// OnlyWrapped is true, or it returns the input value as-is if false.
84-
static const Value *skipMetadataWrapper(const Value *V, bool OnlyWrapped) {
85-
if (const auto *MAV = dyn_cast<MetadataAsValue>(V))
86-
if (const auto *VAM = dyn_cast<ValueAsMetadata>(MAV->getMetadata()))
87-
return VAM->getValue();
88-
return OnlyWrapped ? nullptr : V;
89-
}
90-
9181
static void orderValue(const Value *V, OrderMap &OM) {
9282
if (OM.lookup(V).first)
9383
return;
@@ -139,16 +129,25 @@ static OrderMap orderModule(const Module &M) {
139129
// these before global values, as these will be read before setting the
140130
// global values' initializers. The latter matters for constants which have
141131
// uses towards other constants that are used as initializers.
132+
auto orderConstantValue = [&OM](const Value *V) {
133+
if ((isa<Constant>(V) && !isa<GlobalValue>(V)) || isa<InlineAsm>(V))
134+
orderValue(V, OM);
135+
};
142136
for (const Function &F : M) {
143137
if (F.isDeclaration())
144138
continue;
145139
for (const BasicBlock &BB : F)
146140
for (const Instruction &I : BB)
147141
for (const Value *V : I.operands()) {
148-
if (const Value *Op = skipMetadataWrapper(V, true)) {
149-
if ((isa<Constant>(*Op) && !isa<GlobalValue>(*Op)) ||
150-
isa<InlineAsm>(*Op))
151-
orderValue(Op, OM);
142+
if (const auto *MAV = dyn_cast<MetadataAsValue>(V)) {
143+
if (const auto *VAM =
144+
dyn_cast<ValueAsMetadata>(MAV->getMetadata())) {
145+
orderConstantValue(VAM->getValue());
146+
} else if (const auto *AL =
147+
dyn_cast<DIArgList>(MAV->getMetadata())) {
148+
for (const auto *VAM : AL->getArgs())
149+
orderConstantValue(VAM->getValue());
150+
}
152151
}
153152
}
154153
}
@@ -448,10 +447,17 @@ ValueEnumerator::ValueEnumerator(const Module &M,
448447
continue;
449448
}
450449

451-
// Local metadata is enumerated during function-incorporation.
452-
if (isa<LocalAsMetadata>(MD->getMetadata()) ||
453-
isa<DIArgList>(MD->getMetadata()))
450+
// Local metadata is enumerated during function-incorporation, but
451+
// any ConstantAsMetadata arguments in a DIArgList should be examined
452+
// now.
453+
if (isa<LocalAsMetadata>(MD->getMetadata()))
454+
continue;
455+
if (auto *AL = dyn_cast<DIArgList>(MD->getMetadata())) {
456+
for (auto *VAM : AL->getArgs())
457+
if (isa<ConstantAsMetadata>(VAM))
458+
EnumerateMetadata(&F, VAM);
454459
continue;
460+
}
455461

456462
EnumerateMetadata(&F, MD->getMetadata());
457463
}
@@ -620,6 +626,11 @@ void ValueEnumerator::EnumerateFunctionLocalMetadata(
620626
EnumerateFunctionLocalMetadata(getMetadataFunctionID(&F), Local);
621627
}
622628

629+
void ValueEnumerator::EnumerateFunctionLocalListMetadata(
630+
const Function &F, const DIArgList *ArgList) {
631+
EnumerateFunctionLocalListMetadata(getMetadataFunctionID(&F), ArgList);
632+
}
633+
623634
void ValueEnumerator::dropFunctionFromMetadata(
624635
MetadataMapType::value_type &FirstMD) {
625636
SmallVector<const MDNode *, 64> Worklist;
@@ -730,7 +741,7 @@ const MDNode *ValueEnumerator::enumerateMetadataImpl(unsigned F, const Metadata
730741
return nullptr;
731742
}
732743

733-
/// EnumerateFunctionLocalMetadataa - Incorporate function-local metadata
744+
/// EnumerateFunctionLocalMetadata - Incorporate function-local metadata
734745
/// information reachable from the metadata.
735746
void ValueEnumerator::EnumerateFunctionLocalMetadata(
736747
unsigned F, const LocalAsMetadata *Local) {
@@ -750,6 +761,39 @@ void ValueEnumerator::EnumerateFunctionLocalMetadata(
750761
EnumerateValue(Local->getValue());
751762
}
752763

764+
/// EnumerateFunctionLocalListMetadata - Incorporate function-local metadata
765+
/// information reachable from the metadata.
766+
void ValueEnumerator::EnumerateFunctionLocalListMetadata(
767+
unsigned F, const DIArgList *ArgList) {
768+
assert(F && "Expected a function");
769+
770+
// Check to see if it's already in!
771+
MDIndex &Index = MetadataMap[ArgList];
772+
if (Index.ID) {
773+
assert(Index.F == F && "Expected the same function");
774+
return;
775+
}
776+
777+
for (ValueAsMetadata *VAM : ArgList->getArgs()) {
778+
if (isa<LocalAsMetadata>(VAM)) {
779+
assert(MetadataMap.count(VAM) &&
780+
"LocalAsMetadata should be enumerated before DIArgList");
781+
assert(MetadataMap[VAM].F == F &&
782+
"Expected LocalAsMetadata in the same function");
783+
} else {
784+
assert(isa<ConstantAsMetadata>(VAM) &&
785+
"Expected LocalAsMetadata or ConstantAsMetadata");
786+
assert(ValueMap.count(VAM->getValue()) &&
787+
"Constant should be enumerated beforeDIArgList");
788+
EnumerateMetadata(F, VAM);
789+
}
790+
}
791+
792+
MDs.push_back(ArgList);
793+
Index.F = F;
794+
Index.ID = MDs.size();
795+
}
796+
753797
static unsigned getMetadataTypeOrder(const Metadata *MD) {
754798
// Strings are emitted in bulk and must come first.
755799
if (isa<MDString>(MD))
@@ -1072,7 +1116,7 @@ void ValueEnumerator::incorporateFunction(const Function &F) {
10721116
// DIArgList entries must come after function-local metadata, as it is not
10731117
// possible to forward-reference them.
10741118
for (const DIArgList *ArgList : ArgListMDVector)
1075-
EnumerateMetadata(&F, ArgList);
1119+
EnumerateFunctionLocalListMetadata(F, ArgList);
10761120
}
10771121

10781122
void ValueEnumerator::purgeFunction() {

llvm/lib/Bitcode/Writer/ValueEnumerator.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ namespace llvm {
2727

2828
class BasicBlock;
2929
class Comdat;
30+
class DIArgList;
3031
class Function;
3132
class Instruction;
3233
class LocalAsMetadata;
@@ -286,6 +287,9 @@ class ValueEnumerator {
286287
void EnumerateFunctionLocalMetadata(const Function &F,
287288
const LocalAsMetadata *Local);
288289
void EnumerateFunctionLocalMetadata(unsigned F, const LocalAsMetadata *Local);
290+
void EnumerateFunctionLocalListMetadata(const Function &F,
291+
const DIArgList *ArgList);
292+
void EnumerateFunctionLocalListMetadata(unsigned F, const DIArgList *Arglist);
289293
void EnumerateNamedMDNode(const NamedMDNode *NMD);
290294
void EnumerateValue(const Value *V);
291295
void EnumerateType(Type *T);

llvm/test/DebugInfo/Generic/debug_value_list.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@ target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16
88
target triple = "x86_64-pc-windows-msvc19.16.27034"
99

1010
; CHECK-COUNT-3: llvm.dbg.value(
11-
; CHECK-SAME: metadata !DIArgList(i32 %a, i32 %b)
11+
; CHECK-SAME: metadata !DIArgList(i32 %a, i32 %b, i32 5)
1212
; CHECK-SAME: metadata !16,
13-
; CHECK-SAME: metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus)
13+
; 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)
1414
define dso_local i32 @"?foo@@YAHHH@Z"(i32 %a, i32 %b) local_unnamed_addr !dbg !8 {
1515
entry:
1616
call void @llvm.dbg.value(metadata !DIArgList(i32 %b), metadata !14, metadata !DIExpression(DW_OP_LLVM_arg, 0)), !dbg !17
1717
call void @llvm.dbg.value(metadata !DIArgList(i32 %a), metadata !15, metadata !DIExpression(DW_OP_LLVM_arg, 0)), !dbg !17
1818
call void @llvm.dbg.value(
19-
metadata !DIArgList(i32 %a, i32 %b),
19+
metadata !DIArgList(i32 %a, i32 %b, i32 5),
2020
metadata !16,
21-
metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus)), !dbg !17
21+
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
2222
%mul = mul nsw i32 %b, %a, !dbg !18
2323
ret i32 %mul, !dbg !18
2424
}

0 commit comments

Comments
 (0)