diff options
| author | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2015-03-14 20:19:36 +0000 |
|---|---|---|
| committer | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2015-03-14 20:19:36 +0000 |
| commit | d6d70e753dd6061d5796937b1e05fbe54f4692f8 (patch) | |
| tree | da5e5b5de4f1d6aad38b138b36e6b5ce049e7a84 /llvm/lib/IR/AsmWriter.cpp | |
| parent | 096b1da29d21cda6c8950e477010777019ed0e88 (diff) | |
| download | bcm5719-llvm-d6d70e753dd6061d5796937b1e05fbe54f4692f8.tar.gz bcm5719-llvm-d6d70e753dd6061d5796937b1e05fbe54f4692f8.zip | |
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
Diffstat (limited to 'llvm/lib/IR/AsmWriter.cpp')
| -rw-r--r-- | llvm/lib/IR/AsmWriter.cpp | 118 |
1 files changed, 85 insertions, 33 deletions
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 0fcfe23d2a2..509fb423ff7 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -275,6 +275,15 @@ static const Module *getModuleFromVal(const Value *V) { if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) return GV->getParent(); + + if (const auto *MAV = dyn_cast<MetadataAsValue>(V)) { + for (const User *U : MAV->users()) + if (isa<Instruction>(U)) + if (const Module *M = getModuleFromVal(U)) + return M; + return nullptr; + } + return nullptr; } @@ -525,6 +534,7 @@ private: /// TheFunction - The function for which we are holding slot numbers. const Function* TheFunction; bool FunctionProcessed; + bool ShouldInitializeAllMetadata; /// mMap - The slot map for the module level data. ValueMap mMap; @@ -542,10 +552,20 @@ private: DenseMap<AttributeSet, unsigned> asMap; unsigned asNext; public: - /// Construct from a module - explicit SlotTracker(const Module *M); + /// Construct from a module. + /// + /// If \c ShouldInitializeAllMetadata, initializes all metadata in all + /// functions, giving correct numbering for metadata referenced only from + /// within a function (even if no functions have been initialized). + explicit SlotTracker(const Module *M, + bool ShouldInitializeAllMetadata = false); /// Construct from a function, starting out in incorp state. - explicit SlotTracker(const Function *F); + /// + /// If \c ShouldInitializeAllMetadata, initializes all metadata in all + /// functions, giving correct numbering for metadata referenced only from + /// within a function (even if no functions have been initialized). + explicit SlotTracker(const Function *F, + bool ShouldInitializeAllMetadata = false); /// Return the slot number of the specified value in it's type /// plane. If something is not in the SlotTracker, return -1. @@ -606,6 +626,9 @@ private: /// Add all of the functions arguments, basic blocks, and instructions. void processFunction(); + /// Add all of the metadata from a function. + void processFunctionMetadata(const Function &F); + /// Add all of the metadata from an instruction. void processInstructionMetadata(const Instruction &I); @@ -648,15 +671,18 @@ static SlotTracker *createSlotTracker(const Value *V) { // Module level constructor. Causes the contents of the Module (sans functions) // to be added to the slot table. -SlotTracker::SlotTracker(const Module *M) - : TheModule(M), TheFunction(nullptr), FunctionProcessed(false), mNext(0), +SlotTracker::SlotTracker(const Module *M, bool ShouldInitializeAllMetadata) + : TheModule(M), TheFunction(nullptr), FunctionProcessed(false), + ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), mNext(0), fNext(0), mdnNext(0), asNext(0) {} // Function level constructor. Causes the contents of the Module and the one // function provided to be added to the slot table. -SlotTracker::SlotTracker(const Function *F) +SlotTracker::SlotTracker(const Function *F, bool ShouldInitializeAllMetadata) : TheModule(F ? F->getParent() : nullptr), TheFunction(F), - FunctionProcessed(false), mNext(0), fNext(0), mdnNext(0), asNext(0) {} + FunctionProcessed(false), + ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), mNext(0), + fNext(0), mdnNext(0), asNext(0) {} inline void SlotTracker::initialize() { if (TheModule) { @@ -695,6 +721,9 @@ void SlotTracker::processModule() { // Add all the unnamed functions to the table. CreateModuleSlot(I); + if (ShouldInitializeAllMetadata) + processFunctionMetadata(*I); + // Add all the function attributes to the table. // FIXME: Add attributes of other objects? AttributeSet FnAttrs = I->getAttributes().getFnAttributes(); @@ -750,6 +779,12 @@ void SlotTracker::processFunction() { ST_DEBUG("end processFunction!\n"); } +void SlotTracker::processFunctionMetadata(const Function &F) { + for (auto &BB : F) + for (auto &I : BB) + processInstructionMetadata(I); +} + void SlotTracker::processInstructionMetadata(const Instruction &I) { // Process metadata used directly by intrinsics. if (const CallInst *CI = dyn_cast<CallInst>(&I)) @@ -3134,11 +3169,24 @@ void Type::print(raw_ostream &OS) const { } } +static bool isReferencingMDNode(const Instruction &I) { + if (const auto *CI = dyn_cast<CallInst>(&I)) + if (Function *F = CI->getCalledFunction()) + if (F->isIntrinsic()) + for (auto &Op : I.operands()) + if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op)) + if (isa<MDNode>(V->getMetadata())) + return true; + return false; +} + void Value::print(raw_ostream &ROS) const { formatted_raw_ostream OS(ROS); if (const Instruction *I = dyn_cast<Instruction>(this)) { const Function *F = I->getParent() ? I->getParent()->getParent() : nullptr; - SlotTracker SlotTable(F); + SlotTracker SlotTable( + F, + /* ShouldInitializeAllMetadata */ isReferencingMDNode(*I)); AssemblyWriter W(OS, SlotTable, getModuleFromVal(I), nullptr); W.printInstruction(*I); } else if (const BasicBlock *BB = dyn_cast<BasicBlock>(this)) { @@ -3146,7 +3194,8 @@ void Value::print(raw_ostream &ROS) const { AssemblyWriter W(OS, SlotTable, getModuleFromVal(BB), nullptr); W.printBasicBlock(BB); } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(this)) { - SlotTracker SlotTable(GV->getParent()); + SlotTracker SlotTable(GV->getParent(), + /* ShouldInitializeAllMetadata */ isa<Function>(GV)); AssemblyWriter W(OS, SlotTable, GV->getParent(), nullptr); if (const GlobalVariable *V = dyn_cast<GlobalVariable>(GV)) W.printGlobal(V); @@ -3155,7 +3204,7 @@ void Value::print(raw_ostream &ROS) const { else W.printAlias(cast<GlobalAlias>(GV)); } else if (const MetadataAsValue *V = dyn_cast<MetadataAsValue>(this)) { - V->getMetadata()->print(ROS); + V->getMetadata()->print(ROS, getModuleFromVal(V)); } else if (const Constant *C = dyn_cast<Constant>(this)) { TypePrinting TypePrinter; TypePrinter.print(C->getType(), OS); @@ -3171,8 +3220,9 @@ void Value::print(raw_ostream &ROS) const { void Value::printAsOperand(raw_ostream &O, bool PrintType, const Module *M) const { // Fast path: Don't construct and populate a TypePrinting object if we // won't be needing any types printed. - if (!PrintType && ((!isa<Constant>(this) && !isa<MetadataAsValue>(this)) || - hasName() || isa<GlobalValue>(this))) { + bool IsMetadata = isa<MetadataAsValue>(this); + if (!PrintType && ((!isa<Constant>(this) && !IsMetadata) || hasName() || + isa<GlobalValue>(this))) { WriteAsOperandInternal(O, this, nullptr, nullptr, M); return; } @@ -3188,33 +3238,35 @@ void Value::printAsOperand(raw_ostream &O, bool PrintType, const Module *M) cons O << ' '; } - WriteAsOperandInternal(O, this, &TypePrinter, nullptr, M); + SlotTracker Machine(M, /* ShouldInitializeAllMetadata */ IsMetadata); + WriteAsOperandInternal(O, this, &TypePrinter, &Machine, M); } -void Metadata::print(raw_ostream &ROS) const { +static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD, + const Module *M, bool OnlyAsOperand) { formatted_raw_ostream OS(ROS); - if (auto *N = dyn_cast<MDNode>(this)) { - SlotTracker SlotTable(static_cast<Function *>(nullptr)); - AssemblyWriter W(OS, SlotTable, nullptr, nullptr); - W.printMDNodeBody(N); + auto *N = dyn_cast<MDNode>(&MD); + TypePrinting TypePrinter; + SlotTracker Machine(M, /* ShouldInitializeAllMetadata */ N); + if (M) + TypePrinter.incorporateTypes(*M); + + WriteAsOperandInternal(OS, &MD, &TypePrinter, &Machine, M, + /* FromValue */ true); + if (OnlyAsOperand || !N) return; - } - printAsOperand(OS); + + OS << " = "; + WriteMDNodeBodyInternal(OS, N, &TypePrinter, &Machine, M); } -void Metadata::printAsOperand(raw_ostream &ROS, bool PrintType, - const Module *M) const { - formatted_raw_ostream OS(ROS); +void Metadata::printAsOperand(raw_ostream &OS, const Module *M) const { + printMetadataImpl(OS, *this, M, /* OnlyAsOperand */ true); +} - std::unique_ptr<TypePrinting> TypePrinter; - if (PrintType) { - TypePrinter.reset(new TypePrinting); - if (M) - TypePrinter->incorporateTypes(*M); - } - WriteAsOperandInternal(OS, this, TypePrinter.get(), nullptr, M, - /* FromValue */ true); +void Metadata::print(raw_ostream &OS, const Module *M) const { + printMetadataImpl(OS, *this, M, /* OnlyAsOperand */ false); } // Value::dump - allow easy printing of Values from the debugger. @@ -3238,7 +3290,7 @@ LLVM_DUMP_METHOD void NamedMDNode::dump() const { print(dbgs()); } LLVM_DUMP_METHOD -void Metadata::dump() const { - print(dbgs()); +void Metadata::dump(const Module *M) const { + print(dbgs(), M); dbgs() << '\n'; } |

