1 //===----- llvm/CodeGen/GlobalISel/LostDebugLocObserver.cpp -----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 /// Tracks DebugLocs between checkpoints and verifies that they are transferred. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h" 14 15 using namespace llvm; 16 17 #define LOC_DEBUG(X) DEBUG_WITH_TYPE(DebugType.str().c_str(), X) 18 19 void LostDebugLocObserver::analyzeDebugLocations() { 20 if (LostDebugLocs.empty()) { 21 LOC_DEBUG(dbgs() << ".. No debug info was present\n"); 22 return; 23 } 24 if (PotentialMIsForDebugLocs.empty()) { 25 LOC_DEBUG( 26 dbgs() << ".. No instructions to carry debug info (dead code?)\n"); 27 return; 28 } 29 30 LOC_DEBUG(dbgs() << ".. Searching " << PotentialMIsForDebugLocs.size() 31 << " instrs for " << LostDebugLocs.size() << " locations\n"); 32 SmallPtrSet<MachineInstr *, 4> FoundIn; 33 for (MachineInstr *MI : PotentialMIsForDebugLocs) { 34 if (!MI->getDebugLoc()) 35 continue; 36 // Check this first in case there's a matching line-0 location on both input 37 // and output. 38 if (MI->getDebugLoc().getLine() == 0) { 39 LOC_DEBUG( 40 dbgs() << ".. Assuming line-0 location covers remainder (if any)\n"); 41 return; 42 } 43 if (LostDebugLocs.erase(MI->getDebugLoc())) { 44 LOC_DEBUG(dbgs() << ".. .. found " << MI->getDebugLoc() << " in " << *MI); 45 FoundIn.insert(MI); 46 continue; 47 } 48 } 49 if (LostDebugLocs.empty()) 50 return; 51 52 NumLostDebugLocs += LostDebugLocs.size(); 53 LOC_DEBUG({ 54 dbgs() << ".. Lost locations:\n"; 55 for (const DebugLoc &Loc : LostDebugLocs) { 56 dbgs() << ".. .. "; 57 Loc.print(dbgs()); 58 dbgs() << "\n"; 59 } 60 dbgs() << ".. MIs with matched locations:\n"; 61 for (MachineInstr *MI : FoundIn) 62 if (PotentialMIsForDebugLocs.erase(MI)) 63 dbgs() << ".. .. " << *MI; 64 dbgs() << ".. Remaining MIs with unmatched/no locations:\n"; 65 for (const MachineInstr *MI : PotentialMIsForDebugLocs) 66 dbgs() << ".. .. " << *MI; 67 }); 68 } 69 70 void LostDebugLocObserver::checkpoint(bool CheckDebugLocs) { 71 if (CheckDebugLocs) 72 analyzeDebugLocations(); 73 PotentialMIsForDebugLocs.clear(); 74 LostDebugLocs.clear(); 75 } 76 77 void LostDebugLocObserver::createdInstr(MachineInstr &MI) { 78 PotentialMIsForDebugLocs.insert(&MI); 79 } 80 81 static bool irTranslatorNeverAddsLocations(unsigned Opcode) { 82 switch (Opcode) { 83 default: 84 return false; 85 case TargetOpcode::G_CONSTANT: 86 case TargetOpcode::G_FCONSTANT: 87 case TargetOpcode::G_IMPLICIT_DEF: 88 case TargetOpcode::G_GLOBAL_VALUE: 89 return true; 90 } 91 } 92 93 void LostDebugLocObserver::erasingInstr(MachineInstr &MI) { 94 if (irTranslatorNeverAddsLocations(MI.getOpcode())) 95 return; 96 97 PotentialMIsForDebugLocs.erase(&MI); 98 if (MI.getDebugLoc()) 99 LostDebugLocs.insert(MI.getDebugLoc()); 100 } 101 102 void LostDebugLocObserver::changingInstr(MachineInstr &MI) { 103 if (irTranslatorNeverAddsLocations(MI.getOpcode())) 104 return; 105 106 PotentialMIsForDebugLocs.erase(&MI); 107 if (MI.getDebugLoc()) 108 LostDebugLocs.insert(MI.getDebugLoc()); 109 } 110 111 void LostDebugLocObserver::changedInstr(MachineInstr &MI) { 112 PotentialMIsForDebugLocs.insert(&MI); 113 } 114