//===----- llvm/CodeGen/GlobalISel/LostDebugLocObserver.cpp -----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // /// Tracks DebugLocs between checkpoints and verifies that they are transferred. // //===----------------------------------------------------------------------===// #include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h" using namespace llvm; #define LOC_DEBUG(X) DEBUG_WITH_TYPE(DebugType.str().c_str(), X) void LostDebugLocObserver::analyzeDebugLocations() { if (LostDebugLocs.empty()) { LOC_DEBUG(dbgs() << ".. No debug info was present\n"); return; } if (PotentialMIsForDebugLocs.empty()) { LOC_DEBUG( dbgs() << ".. No instructions to carry debug info (dead code?)\n"); return; } LOC_DEBUG(dbgs() << ".. Searching " << PotentialMIsForDebugLocs.size() << " instrs for " << LostDebugLocs.size() << " locations\n"); SmallPtrSet FoundIn; for (MachineInstr *MI : PotentialMIsForDebugLocs) { if (!MI->getDebugLoc()) continue; // Check this first in case there's a matching line-0 location on both input // and output. if (MI->getDebugLoc().getLine() == 0) { LOC_DEBUG( dbgs() << ".. Assuming line-0 location covers remainder (if any)\n"); return; } if (LostDebugLocs.erase(MI->getDebugLoc())) { LOC_DEBUG(dbgs() << ".. .. found " << MI->getDebugLoc() << " in " << *MI); FoundIn.insert(MI); continue; } } if (LostDebugLocs.empty()) return; NumLostDebugLocs += LostDebugLocs.size(); LOC_DEBUG({ dbgs() << ".. Lost locations:\n"; for (const DebugLoc &Loc : LostDebugLocs) { dbgs() << ".. .. "; Loc.print(dbgs()); dbgs() << "\n"; } dbgs() << ".. MIs with matched locations:\n"; for (MachineInstr *MI : FoundIn) if (PotentialMIsForDebugLocs.erase(MI)) dbgs() << ".. .. " << *MI; dbgs() << ".. Remaining MIs with unmatched/no locations:\n"; for (const MachineInstr *MI : PotentialMIsForDebugLocs) dbgs() << ".. .. " << *MI; }); } void LostDebugLocObserver::checkpoint(bool CheckDebugLocs) { if (CheckDebugLocs) analyzeDebugLocations(); PotentialMIsForDebugLocs.clear(); LostDebugLocs.clear(); } void LostDebugLocObserver::createdInstr(MachineInstr &MI) { PotentialMIsForDebugLocs.insert(&MI); } static bool irTranslatorNeverAddsLocations(unsigned Opcode) { switch (Opcode) { default: return false; case TargetOpcode::G_CONSTANT: case TargetOpcode::G_FCONSTANT: case TargetOpcode::G_IMPLICIT_DEF: case TargetOpcode::G_GLOBAL_VALUE: return true; } } void LostDebugLocObserver::erasingInstr(MachineInstr &MI) { if (irTranslatorNeverAddsLocations(MI.getOpcode())) return; PotentialMIsForDebugLocs.erase(&MI); if (MI.getDebugLoc()) LostDebugLocs.insert(MI.getDebugLoc()); } void LostDebugLocObserver::changingInstr(MachineInstr &MI) { if (irTranslatorNeverAddsLocations(MI.getOpcode())) return; PotentialMIsForDebugLocs.erase(&MI); if (MI.getDebugLoc()) LostDebugLocs.insert(MI.getDebugLoc()); } void LostDebugLocObserver::changedInstr(MachineInstr &MI) { PotentialMIsForDebugLocs.insert(&MI); }