diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-12-18 20:30:12 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2024-04-19 21:12:03 +0000 |
| commit | c9157d925c489f07ba9c0b2ce47e5149b75969a5 (patch) | |
| tree | 08bc4a3d9cad3f9ebffa558ddf140b9d9257b219 /contrib/llvm-project/llvm/lib/IR/BasicBlock.cpp | |
| parent | 2a66844f606a35d68ad8a8061f4bea204274b3bc (diff) | |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/IR/BasicBlock.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/IR/BasicBlock.cpp | 650 |
1 files changed, 633 insertions, 17 deletions
diff --git a/contrib/llvm-project/llvm/lib/IR/BasicBlock.cpp b/contrib/llvm-project/llvm/lib/IR/BasicBlock.cpp index 14e1787c2b14..03b74b0480f0 100644 --- a/contrib/llvm-project/llvm/lib/IR/BasicBlock.cpp +++ b/contrib/llvm-project/llvm/lib/IR/BasicBlock.cpp @@ -16,16 +16,191 @@ #include "llvm/ADT/Statistic.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugProgramInstruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Type.h" +#include "llvm/Support/CommandLine.h" + +#include "LLVMContextImpl.h" using namespace llvm; #define DEBUG_TYPE "ir" STATISTIC(NumInstrRenumberings, "Number of renumberings across all blocks"); +cl::opt<bool> + UseNewDbgInfoFormat("experimental-debuginfo-iterators", + cl::desc("Enable communicating debuginfo positions " + "through iterators, eliminating intrinsics"), + cl::init(false)); + +DPMarker *BasicBlock::createMarker(Instruction *I) { + assert(IsNewDbgInfoFormat && + "Tried to create a marker in a non new debug-info block!"); + if (I->DbgMarker) + return I->DbgMarker; + DPMarker *Marker = new DPMarker(); + Marker->MarkedInstr = I; + I->DbgMarker = Marker; + return Marker; +} + +DPMarker *BasicBlock::createMarker(InstListType::iterator It) { + assert(IsNewDbgInfoFormat && + "Tried to create a marker in a non new debug-info block!"); + if (It != end()) + return createMarker(&*It); + DPMarker *DPM = getTrailingDPValues(); + if (DPM) + return DPM; + DPM = new DPMarker(); + setTrailingDPValues(DPM); + return DPM; +} + +void BasicBlock::convertToNewDbgValues() { + // Is the command line option set? + if (!UseNewDbgInfoFormat) + return; + + IsNewDbgInfoFormat = true; + + // Iterate over all instructions in the instruction list, collecting dbg.value + // instructions and converting them to DPValues. Once we find a "real" + // instruction, attach all those DPValues to a DPMarker in that instruction. + SmallVector<DPValue *, 4> DPVals; + for (Instruction &I : make_early_inc_range(InstList)) { + assert(!I.DbgMarker && "DbgMarker already set on old-format instrs?"); + if (DbgVariableIntrinsic *DVI = dyn_cast<DbgVariableIntrinsic>(&I)) { + if (isa<DbgAssignIntrinsic>(DVI)) + continue; + + // Convert this dbg.value to a DPValue. + DPValue *Value = new DPValue(DVI); + DPVals.push_back(Value); + DVI->eraseFromParent(); + continue; + } + + // Create a marker to store DPValues in. Technically we don't need to store + // one marker per instruction, but that's a future optimisation. + createMarker(&I); + DPMarker *Marker = I.DbgMarker; + + for (DPValue *DPV : DPVals) + Marker->insertDPValue(DPV, false); + + DPVals.clear(); + } +} + +void BasicBlock::convertFromNewDbgValues() { + invalidateOrders(); + IsNewDbgInfoFormat = false; + + // Iterate over the block, finding instructions annotated with DPMarkers. + // Convert any attached DPValues to dbg.values and insert ahead of the + // instruction. + for (auto &Inst : *this) { + if (!Inst.DbgMarker) + continue; + + DPMarker &Marker = *Inst.DbgMarker; + for (DPValue &DPV : Marker.getDbgValueRange()) + InstList.insert(Inst.getIterator(), + DPV.createDebugIntrinsic(getModule(), nullptr)); + + Marker.eraseFromParent(); + }; + + // Assume no trailing DPValues: we could technically create them at the end + // of the block, after a terminator, but this would be non-cannonical and + // indicates that something else is broken somewhere. + assert(!getTrailingDPValues()); +} + +bool BasicBlock::validateDbgValues(bool Assert, bool Msg, raw_ostream *OS) { + bool RetVal = false; + if (!OS) + OS = &errs(); + + // Helper lambda for reporting failures: via assertion, printing, and return + // value. + auto TestFailure = [Assert, Msg, &RetVal, OS](bool Val, const char *Text) { + // Did the test fail? + if (Val) + return; + + // If we're asserting, then fire off an assertion. + if (Assert) + llvm_unreachable(Text); + + if (Msg) + *OS << Text << "\n"; + RetVal = true; + }; + + // We should have the same debug-format as the parent function. + TestFailure(getParent()->IsNewDbgInfoFormat == IsNewDbgInfoFormat, + "Parent function doesn't have the same debug-info format"); + + // Only validate if we are using the new format. + if (!IsNewDbgInfoFormat) + return RetVal; + + // Match every DPMarker to every Instruction and vice versa, and + // verify that there are no invalid DPValues. + for (auto It = begin(); It != end(); ++It) { + if (!It->DbgMarker) + continue; + + // Validate DebugProgramMarkers. + DPMarker *CurrentDebugMarker = It->DbgMarker; + + // If this is a marker, it should match the instruction and vice versa. + TestFailure(CurrentDebugMarker->MarkedInstr == &*It, + "Debug Marker points to incorrect instruction?"); + + // Now validate any DPValues in the marker. + for (DPValue &DPV : CurrentDebugMarker->getDbgValueRange()) { + // Validate DebugProgramValues. + TestFailure(DPV.getMarker() == CurrentDebugMarker, + "Not pointing at correct next marker!"); + + // Verify that no DbgValues appear prior to PHIs. + TestFailure( + !isa<PHINode>(It), + "DebugProgramValues must not appear before PHI nodes in a block!"); + } + } + + // Except transiently when removing + re-inserting the block terminator, there + // should be no trailing DPValues. + TestFailure(!getTrailingDPValues(), "Trailing DPValues in block"); + return RetVal; +} + +#ifndef NDEBUG +void BasicBlock::dumpDbgValues() const { + for (auto &Inst : *this) { + if (!Inst.DbgMarker) + continue; + + dbgs() << "@ " << Inst.DbgMarker << " "; + Inst.DbgMarker->dump(); + }; +} +#endif + +void BasicBlock::setIsNewDbgInfoFormat(bool NewFlag) { + if (NewFlag && !IsNewDbgInfoFormat) + convertToNewDbgValues(); + else if (!NewFlag && IsNewDbgInfoFormat) + convertFromNewDbgValues(); +} + ValueSymbolTable *BasicBlock::getValueSymbolTable() { if (Function *F = getParent()) return F->getValueSymbolTable(); @@ -42,11 +217,13 @@ template <> void llvm::invalidateParentIListOrdering(BasicBlock *BB) { // Explicit instantiation of SymbolTableListTraits since some of the methods // are not in the public header file... -template class llvm::SymbolTableListTraits<Instruction>; +template class llvm::SymbolTableListTraits<Instruction, + ilist_iterator_bits<true>>; BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent, BasicBlock *InsertBefore) - : Value(Type::getLabelTy(C), Value::BasicBlockVal), Parent(nullptr) { + : Value(Type::getLabelTy(C), Value::BasicBlockVal), + IsNewDbgInfoFormat(false), Parent(nullptr) { if (NewParent) insertInto(NewParent, InsertBefore); @@ -55,12 +232,16 @@ BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent, "Cannot insert block before another block with no function!"); setName(Name); + if (NewParent) + setIsNewDbgInfoFormat(NewParent->IsNewDbgInfoFormat); } void BasicBlock::insertInto(Function *NewParent, BasicBlock *InsertBefore) { assert(NewParent && "Expected a parent"); assert(!Parent && "Already has a parent"); + setIsNewDbgInfoFormat(NewParent->IsNewDbgInfoFormat); + if (InsertBefore) NewParent->insert(InsertBefore->getIterator(), this); else @@ -90,6 +271,11 @@ BasicBlock::~BasicBlock() { assert(getParent() == nullptr && "BasicBlock still linked into the program!"); dropAllReferences(); + for (auto &Inst : *this) { + if (!Inst.DbgMarker) + continue; + Inst.DbgMarker->eraseFromParent(); + } InstList.clear(); } @@ -220,6 +406,16 @@ const Instruction* BasicBlock::getFirstNonPHI() const { return nullptr; } +BasicBlock::const_iterator BasicBlock::getFirstNonPHIIt() const { + const Instruction *I = getFirstNonPHI(); + BasicBlock::const_iterator It = I->getIterator(); + // Set the head-inclusive bit to indicate that this iterator includes + // any debug-info at the start of the block. This is a no-op unless the + // appropriate CMake flag is set. + It.setHeadBit(true); + return It; +} + const Instruction *BasicBlock::getFirstNonPHIOrDbg(bool SkipPseudoOp) const { for (const Instruction &I : *this) { if (isa<PHINode>(I) || isa<DbgInfoIntrinsic>(I)) @@ -257,6 +453,10 @@ BasicBlock::const_iterator BasicBlock::getFirstInsertionPt() const { const_iterator InsertPt = FirstNonPHI->getIterator(); if (InsertPt->isEHPad()) ++InsertPt; + // Set the head-inclusive bit to indicate that this iterator includes + // any debug-info at the start of the block. This is a no-op unless the + // appropriate CMake flag is set. + InsertPt.setHeadBit(true); return InsertPt; } @@ -396,8 +596,9 @@ bool BasicBlock::isLegalToHoistInto() const { // If the block has no successors, there can be no instructions to hoist. assert(Term->getNumSuccessors() > 0); - // Instructions should not be hoisted across exception handling boundaries. - return !Term->isExceptionalTerminator(); + // Instructions should not be hoisted across special terminators, which may + // have side effects or return values. + return !Term->isSpecialTerminator(); } bool BasicBlock::isEntryBlock() const { @@ -419,7 +620,7 @@ BasicBlock *BasicBlock::splitBasicBlock(iterator I, const Twine &BBName, this->getNextNode()); // Save DebugLoc of split point before invalidating iterator. - DebugLoc Loc = I->getDebugLoc(); + DebugLoc Loc = I->getStableDebugLoc(); // Move all of the specified instructions from the original basic block into // the new basic block. New->splice(New->end(), this, I, end()); @@ -475,18 +676,6 @@ BasicBlock *BasicBlock::splitBasicBlockBefore(iterator I, const Twine &BBName) { return New; } -void BasicBlock::splice(BasicBlock::iterator ToIt, BasicBlock *FromBB, - BasicBlock::iterator FromBeginIt, - BasicBlock::iterator FromEndIt) { -#ifdef EXPENSIVE_CHECKS - // Check that FromBeginIt is befor FromEndIt. - auto FromBBEnd = FromBB->end(); - for (auto It = FromBeginIt; It != FromEndIt; ++It) - assert(It != FromBBEnd && "FromBeginIt not before FromEndIt!"); -#endif // EXPENSIVE_CHECKS - getInstList().splice(ToIt, FromBB->getInstList(), FromBeginIt, FromEndIt); -} - BasicBlock::iterator BasicBlock::erase(BasicBlock::iterator FromIt, BasicBlock::iterator ToIt) { return InstList.erase(FromIt, ToIt); @@ -558,6 +747,420 @@ void BasicBlock::renumberInstructions() { NumInstrRenumberings++; } +void BasicBlock::flushTerminatorDbgValues() { + // If we erase the terminator in a block, any DPValues will sink and "fall + // off the end", existing after any terminator that gets inserted. With + // dbg.value intrinsics we would just insert the terminator at end() and + // the dbg.values would come before the terminator. With DPValues, we must + // do this manually. + // To get out of this unfortunate form, whenever we insert a terminator, + // check whether there's anything trailing at the end and move those DPValues + // in front of the terminator. + + // Do nothing if we're not in new debug-info format. + if (!IsNewDbgInfoFormat) + return; + + // If there's no terminator, there's nothing to do. + Instruction *Term = getTerminator(); + if (!Term) + return; + + // Are there any dangling DPValues? + DPMarker *TrailingDPValues = getTrailingDPValues(); + if (!TrailingDPValues) + return; + + // Transfer DPValues from the trailing position onto the terminator. + Term->DbgMarker->absorbDebugValues(*TrailingDPValues, false); + TrailingDPValues->eraseFromParent(); + deleteTrailingDPValues(); +} + +void BasicBlock::spliceDebugInfoEmptyBlock(BasicBlock::iterator Dest, + BasicBlock *Src, + BasicBlock::iterator First, + BasicBlock::iterator Last) { + // Imagine the folowing: + // + // bb1: + // dbg.value(... + // ret i32 0 + // + // If an optimisation pass attempts to splice the contents of the block from + // BB1->begin() to BB1->getTerminator(), then the dbg.value will be + // transferred to the destination. + // However, in the "new" DPValue format for debug-info, that range is empty: + // begin() returns an iterator to the terminator, as there will only be a + // single instruction in the block. We must piece together from the bits set + // in the iterators whether there was the intention to transfer any debug + // info. + + // If we're not in "new" debug-info format, do nothing. + if (!IsNewDbgInfoFormat) + return; + + assert(First == Last); + bool InsertAtHead = Dest.getHeadBit(); + bool ReadFromHead = First.getHeadBit(); + + // If the source block is completely empty, including no terminator, then + // transfer any trailing DPValues that are still hanging around. This can + // occur when a block is optimised away and the terminator has been moved + // somewhere else. + if (Src->empty()) { + assert(Dest != end() && + "Transferring trailing DPValues to another trailing position"); + DPMarker *SrcTrailingDPValues = Src->getTrailingDPValues(); + if (!SrcTrailingDPValues) + return; + + DPMarker *M = Dest->DbgMarker; + M->absorbDebugValues(*SrcTrailingDPValues, InsertAtHead); + SrcTrailingDPValues->eraseFromParent(); + Src->deleteTrailingDPValues(); + return; + } + + // There are instructions in this block; if the First iterator was + // with begin() / getFirstInsertionPt() then the caller intended debug-info + // at the start of the block to be transferred. + if (!Src->empty() && First == Src->begin() && ReadFromHead) + Dest->DbgMarker->absorbDebugValues(*First->DbgMarker, InsertAtHead); + + return; +} + +void BasicBlock::spliceDebugInfo(BasicBlock::iterator Dest, BasicBlock *Src, + BasicBlock::iterator First, + BasicBlock::iterator Last) { + /* Do a quick normalisation before calling the real splice implementation. We + might be operating on a degenerate basic block that has no instructions + in it, a legitimate transient state. In that case, Dest will be end() and + any DPValues temporarily stored in the TrailingDPValues map in LLVMContext. + We might illustrate it thus: + + Dest + | + this-block: ~~~~~~~~ + Src-block: ++++B---B---B---B:::C + | | + First Last + + However: does the caller expect the "~" DPValues to end up before or after + the spliced segment? This is communciated in the "Head" bit of Dest, which + signals whether the caller called begin() or end() on this block. + + If the head bit is set, then all is well, we leave DPValues trailing just + like how dbg.value instructions would trail after instructions spliced to + the beginning of this block. + + If the head bit isn't set, then try to jam the "~" DPValues onto the front + of the First instruction, then splice like normal, which joins the "~" + DPValues with the "+" DPValues. However if the "+" DPValues are supposed to + be left behind in Src, then: + * detach the "+" DPValues, + * move the "~" DPValues onto First, + * splice like normal, + * replace the "+" DPValues onto the Last position. + Complicated, but gets the job done. */ + + // If we're inserting at end(), and not in front of dangling DPValues, then + // move the DPValues onto "First". They'll then be moved naturally in the + // splice process. + DPMarker *MoreDanglingDPValues = nullptr; + DPMarker *OurTrailingDPValues = getTrailingDPValues(); + if (Dest == end() && !Dest.getHeadBit() && OurTrailingDPValues) { + // Are the "+" DPValues not supposed to move? If so, detach them + // temporarily. + if (!First.getHeadBit() && First->hasDbgValues()) { + MoreDanglingDPValues = Src->getMarker(First); + MoreDanglingDPValues->removeFromParent(); + } + + if (First->hasDbgValues()) { + DPMarker *CurMarker = Src->getMarker(First); + // Place them at the front, it would look like this: + // Dest + // | + // this-block: + // Src-block: ~~~~~~~~++++B---B---B---B:::C + // | | + // First Last + CurMarker->absorbDebugValues(*OurTrailingDPValues, true); + OurTrailingDPValues->eraseFromParent(); + } else { + // No current marker, create one and absorb in. (FIXME: we can avoid an + // allocation in the future). + DPMarker *CurMarker = Src->createMarker(&*First); + CurMarker->absorbDebugValues(*OurTrailingDPValues, false); + OurTrailingDPValues->eraseFromParent(); + } + deleteTrailingDPValues(); + First.setHeadBit(true); + } + + // Call the main debug-info-splicing implementation. + spliceDebugInfoImpl(Dest, Src, First, Last); + + // Do we have some "+" DPValues hanging around that weren't supposed to move, + // and we detached to make things easier? + if (!MoreDanglingDPValues) + return; + + // FIXME: we could avoid an allocation here sometimes. + DPMarker *LastMarker = Src->createMarker(Last); + LastMarker->absorbDebugValues(*MoreDanglingDPValues, true); + MoreDanglingDPValues->eraseFromParent(); +} + +void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, + BasicBlock::iterator First, + BasicBlock::iterator Last) { + // Find out where to _place_ these dbg.values; if InsertAtHead is specified, + // this will be at the start of Dest's debug value range, otherwise this is + // just Dest's marker. + bool InsertAtHead = Dest.getHeadBit(); + bool ReadFromHead = First.getHeadBit(); + // Use this flag to signal the abnormal case, where we don't want to copy the + // DPValues ahead of the "Last" position. + bool ReadFromTail = !Last.getTailBit(); + bool LastIsEnd = (Last == Src->end()); + + /* + Here's an illustration of what we're about to do. We have two blocks, this + and Src, and two segments of list. Each instruction is marked by a capital + while potential DPValue debug-info is marked out by "-" characters and a few + other special characters (+:=) where I want to highlight what's going on. + + Dest + | + this-block: A----A----A ====A----A----A----A---A---A + Src-block ++++B---B---B---B:::C + | | + First Last + + The splice method is going to take all the instructions from First up to + (but not including) Last and insert them in _front_ of Dest, forming one + long list. All the DPValues attached to instructions _between_ First and + Last need no maintenence. However, we have to do special things with the + DPValues marked with the +:= characters. We only have three positions: + should the "+" DPValues be transferred, and if so to where? Do we move the + ":" DPValues? Would they go in front of the "=" DPValues, or should the "=" + DPValues go before "+" DPValues? + + We're told which way it should be by the bits carried in the iterators. The + "Head" bit indicates whether the specified position is supposed to be at the + front of the attached DPValues (true) or not (false). The Tail bit is true + on the other end of a range: is the range intended to include DPValues up to + the end (false) or not (true). + + FIXME: the tail bit doesn't need to be distinct from the head bit, we could + combine them. + + Here are some examples of different configurations: + + Dest.Head = true, First.Head = true, Last.Tail = false + + this-block: A----A----A++++B---B---B---B:::====A----A----A----A---A---A + | | + First Dest + + Wheras if we didn't want to read from the Src list, + + Dest.Head = true, First.Head = false, Last.Tail = false + + this-block: A----A----AB---B---B---B:::====A----A----A----A---A---A + | | + First Dest + + Or if we didn't want to insert at the head of Dest: + + Dest.Head = false, First.Head = false, Last.Tail = false + + this-block: A----A----A====B---B---B---B:::A----A----A----A---A---A + | | + First Dest + + Tests for these various configurations can be found in the unit test file + BasicBlockDbgInfoTest.cpp. + + */ + + // Detach the marker at Dest -- this lets us move the "====" DPValues around. + DPMarker *DestMarker = nullptr; + if (Dest != end()) { + DestMarker = getMarker(Dest); + DestMarker->removeFromParent(); + createMarker(&*Dest); + } + + // If we're moving the tail range of DPValues (":::"), absorb them into the + // front of the DPValues at Dest. + if (ReadFromTail && Src->getMarker(Last)) { + DPMarker *OntoDest = getMarker(Dest); + DPMarker *FromLast = Src->getMarker(Last); + OntoDest->absorbDebugValues(*FromLast, true); + if (LastIsEnd) { + FromLast->eraseFromParent(); + Src->deleteTrailingDPValues(); + } + } + + // If we're _not_ reading from the head of First, i.e. the "++++" DPValues, + // move their markers onto Last. They remain in the Src block. No action + // needed. + if (!ReadFromHead && First->hasDbgValues()) { + DPMarker *OntoLast = Src->createMarker(Last); + DPMarker *FromFirst = Src->createMarker(First); + OntoLast->absorbDebugValues(*FromFirst, + true); // Always insert at head of it. + } + + // Finally, do something with the "====" DPValues we detached. + if (DestMarker) { + if (InsertAtHead) { + // Insert them at the end of the DPValues at Dest. The "::::" DPValues + // might be in front of them. + DPMarker *NewDestMarker = getMarker(Dest); + NewDestMarker->absorbDebugValues(*DestMarker, false); + } else { + // Insert them right at the start of the range we moved, ahead of First + // and the "++++" DPValues. + DPMarker *FirstMarker = getMarker(First); + FirstMarker->absorbDebugValues(*DestMarker, true); + } + DestMarker->eraseFromParent(); + } else if (Dest == end() && !InsertAtHead) { + // In the rare circumstance where we insert at end(), and we did not + // generate the iterator with begin() / getFirstInsertionPt(), it means + // any trailing debug-info at the end of the block would "normally" have + // been pushed in front of "First". Move it there now. + DPMarker *FirstMarker = getMarker(First); + DPMarker *TrailingDPValues = getTrailingDPValues(); + if (TrailingDPValues) { + FirstMarker->absorbDebugValues(*TrailingDPValues, true); + TrailingDPValues->eraseFromParent(); + deleteTrailingDPValues(); + } + } +} + +void BasicBlock::splice(iterator Dest, BasicBlock *Src, iterator First, + iterator Last) { + assert(Src->IsNewDbgInfoFormat == IsNewDbgInfoFormat); + +#ifdef EXPENSIVE_CHECKS + // Check that First is before Last. + auto FromBBEnd = Src->end(); + for (auto It = First; It != Last; ++It) + assert(It != FromBBEnd && "FromBeginIt not before FromEndIt!"); +#endif // EXPENSIVE_CHECKS + + // Lots of horrible special casing for empty transfers: the dbg.values between + // two positions could be spliced in dbg.value mode. + if (First == Last) { + spliceDebugInfoEmptyBlock(Dest, Src, First, Last); + return; + } + + // Handle non-instr debug-info specific juggling. + if (IsNewDbgInfoFormat) + spliceDebugInfo(Dest, Src, First, Last); + + // And move the instructions. + getInstList().splice(Dest, Src->getInstList(), First, Last); + + flushTerminatorDbgValues(); +} + +void BasicBlock::insertDPValueAfter(DPValue *DPV, Instruction *I) { + assert(IsNewDbgInfoFormat); + assert(I->getParent() == this); + + iterator NextIt = std::next(I->getIterator()); + DPMarker *NextMarker = getMarker(NextIt); + if (!NextMarker) + NextMarker = createMarker(NextIt); + NextMarker->insertDPValue(DPV, true); +} + +void BasicBlock::insertDPValueBefore(DPValue *DPV, + InstListType::iterator Where) { + // We should never directly insert at the end of the block, new DPValues + // shouldn't be generated at times when there's no terminator. + assert(Where != end()); + assert(Where->getParent() == this); + if (!Where->DbgMarker) + createMarker(Where); + bool InsertAtHead = Where.getHeadBit(); + Where->DbgMarker->insertDPValue(DPV, InsertAtHead); +} + +DPMarker *BasicBlock::getNextMarker(Instruction *I) { + return getMarker(std::next(I->getIterator())); +} + +DPMarker *BasicBlock::getMarker(InstListType::iterator It) { + if (It == end()) { + DPMarker *DPM = getTrailingDPValues(); + return DPM; + } + return It->DbgMarker; +} + +void BasicBlock::reinsertInstInDPValues( + Instruction *I, std::optional<DPValue::self_iterator> Pos) { + // "I" was originally removed from a position where it was + // immediately in front of Pos. Any DPValues on that position then "fell down" + // onto Pos. "I" has been re-inserted at the front of that wedge of DPValues, + // shuffle them around to represent the original positioning. To illustrate: + // + // Instructions: I1---I---I0 + // DPValues: DDD DDD + // + // Instruction "I" removed, + // + // Instructions: I1------I0 + // DPValues: DDDDDD + // ^Pos + // + // Instruction "I" re-inserted (now): + // + // Instructions: I1---I------I0 + // DPValues: DDDDDD + // ^Pos + // + // After this method completes: + // + // Instructions: I1---I---I0 + // DPValues: DDD DDD + + // This happens if there were no DPValues on I0. Are there now DPValues there? + if (!Pos) { + DPMarker *NextMarker = getNextMarker(I); + if (!NextMarker) + return; + if (NextMarker->StoredDPValues.empty()) + return; + // There are DPMarkers there now -- they fell down from "I". + DPMarker *ThisMarker = createMarker(I); + ThisMarker->absorbDebugValues(*NextMarker, false); + return; + } + + // Is there even a range of DPValues to move? + DPMarker *DPM = (*Pos)->getMarker(); + auto Range = make_range(DPM->StoredDPValues.begin(), (*Pos)); + if (Range.begin() == Range.end()) + return; + + // Otherwise: splice. + DPMarker *ThisMarker = createMarker(I); + assert(ThisMarker->StoredDPValues.empty()); + ThisMarker->absorbDebugValues(Range, *DPM, true); +} + #ifndef NDEBUG /// In asserts builds, this checks the numbering. In non-asserts builds, it /// is defined as a no-op inline function in BasicBlock.h. @@ -572,3 +1175,16 @@ void BasicBlock::validateInstrOrdering() const { } } #endif + +void BasicBlock::setTrailingDPValues(DPMarker *foo) { + getContext().pImpl->setTrailingDPValues(this, foo); +} + +DPMarker *BasicBlock::getTrailingDPValues() { + return getContext().pImpl->getTrailingDPValues(this); +} + +void BasicBlock::deleteTrailingDPValues() { + getContext().pImpl->deleteTrailingDPValues(this); +} + |
