diff options
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 |