diff options
author | David Stenberg <david.stenberg@ericsson.com> | 2020-10-20 19:30:39 +0200 |
---|---|---|
committer | David Stenberg <david.stenberg@ericsson.com> | 2020-10-20 20:05:59 +0200 |
commit | 0c0fcea557e4a7cfd51216ad20aa67c82733ab52 (patch) | |
tree | 90a23ba322ba982ff4e4e7319a88dc267f7bc56c /llvm/lib/Bitcode/Writer/ValueEnumerator.cpp | |
parent | cf9e54ef49c689772112c377ecce358ec66d0e59 (diff) | |
download | llvm-0c0fcea557e4a7cfd51216ad20aa67c82733ab52.zip llvm-0c0fcea557e4a7cfd51216ad20aa67c82733ab52.tar.gz llvm-0c0fcea557e4a7cfd51216ad20aa67c82733ab52.tar.bz2 |
Handle value uses wrapped in metadata for the use-list order
When generating the use-list order, also consider value uses that are
operands which are wrapped in metadata; e.g. llvm.dbg.value operands.
This fixes PR36778. The test case is based on the reproducer from that
report.
Reviewed By: dexonsmith
Differential Revision: https://reviews.llvm.org/D53758
Diffstat (limited to 'llvm/lib/Bitcode/Writer/ValueEnumerator.cpp')
-rw-r--r-- | llvm/lib/Bitcode/Writer/ValueEnumerator.cpp | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp index 4ae25f7..bbee8b3 100644 --- a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -78,6 +78,16 @@ struct OrderMap { } // 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<MetadataAsValue>(V)) + if (const auto *VAM = dyn_cast<ValueAsMetadata>(MAV->getMetadata())) + return VAM->getValue(); + return OnlyWrapped ? nullptr : V; +} + static void orderValue(const Value *V, OrderMap &OM) { if (OM.lookup(V).first) return; @@ -123,6 +133,25 @@ static OrderMap orderModule(const Module &M) { if (!isa<GlobalValue>(U.get())) orderValue(U.get(), OM); } + + // As constants used in metadata operands are emitted as module-level + // constants, we must order them before other operands. Also, we must order + // 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. + 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<Constant>(*Op) && !isa<GlobalValue>(*Op)) || + isa<InlineAsm>(*Op)) + orderValue(Op, OM); + } + } + } OM.LastGlobalConstantID = OM.size(); // Initializers of GlobalValues are processed in |