diff options
Diffstat (limited to 'llvm/lib/IR/BasicBlock.cpp')
-rw-r--r-- | llvm/lib/IR/BasicBlock.cpp | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp index 0a8fddb..3ac5faf 100644 --- a/llvm/lib/IR/BasicBlock.cpp +++ b/llvm/lib/IR/BasicBlock.cpp @@ -829,6 +829,89 @@ void BasicBlock::spliceDebugInfoEmptyBlock(BasicBlock::iterator Dest, 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. |