1*f9c275feSReid Kleckner //===-- llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp -------*- C++ -*--===// 2*f9c275feSReid Kleckner // 3*f9c275feSReid Kleckner // The LLVM Compiler Infrastructure 4*f9c275feSReid Kleckner // 5*f9c275feSReid Kleckner // This file is distributed under the University of Illinois Open Source 6*f9c275feSReid Kleckner // License. See LICENSE.TXT for details. 7*f9c275feSReid Kleckner // 8*f9c275feSReid Kleckner //===----------------------------------------------------------------------===// 9*f9c275feSReid Kleckner // 10*f9c275feSReid Kleckner // Common functionality for different debug information format backends. 11*f9c275feSReid Kleckner // LLVM currently supports DWARF and CodeView. 12*f9c275feSReid Kleckner // 13*f9c275feSReid Kleckner //===----------------------------------------------------------------------===// 14*f9c275feSReid Kleckner 15*f9c275feSReid Kleckner #include "DebugHandlerBase.h" 16*f9c275feSReid Kleckner #include "llvm/CodeGen/AsmPrinter.h" 17*f9c275feSReid Kleckner #include "llvm/CodeGen/MachineFunction.h" 18*f9c275feSReid Kleckner #include "llvm/CodeGen/MachineInstr.h" 19*f9c275feSReid Kleckner #include "llvm/CodeGen/MachineModuleInfo.h" 20*f9c275feSReid Kleckner #include "llvm/Target/TargetSubtargetInfo.h" 21*f9c275feSReid Kleckner 22*f9c275feSReid Kleckner using namespace llvm; 23*f9c275feSReid Kleckner 24*f9c275feSReid Kleckner DebugHandlerBase::DebugHandlerBase(AsmPrinter *A) : Asm(A), MMI(Asm->MMI) {} 25*f9c275feSReid Kleckner 26*f9c275feSReid Kleckner // Each LexicalScope has first instruction and last instruction to mark 27*f9c275feSReid Kleckner // beginning and end of a scope respectively. Create an inverse map that list 28*f9c275feSReid Kleckner // scopes starts (and ends) with an instruction. One instruction may start (or 29*f9c275feSReid Kleckner // end) multiple scopes. Ignore scopes that are not reachable. 30*f9c275feSReid Kleckner void DebugHandlerBase::identifyScopeMarkers() { 31*f9c275feSReid Kleckner SmallVector<LexicalScope *, 4> WorkList; 32*f9c275feSReid Kleckner WorkList.push_back(LScopes.getCurrentFunctionScope()); 33*f9c275feSReid Kleckner while (!WorkList.empty()) { 34*f9c275feSReid Kleckner LexicalScope *S = WorkList.pop_back_val(); 35*f9c275feSReid Kleckner 36*f9c275feSReid Kleckner const SmallVectorImpl<LexicalScope *> &Children = S->getChildren(); 37*f9c275feSReid Kleckner if (!Children.empty()) 38*f9c275feSReid Kleckner WorkList.append(Children.begin(), Children.end()); 39*f9c275feSReid Kleckner 40*f9c275feSReid Kleckner if (S->isAbstractScope()) 41*f9c275feSReid Kleckner continue; 42*f9c275feSReid Kleckner 43*f9c275feSReid Kleckner for (const InsnRange &R : S->getRanges()) { 44*f9c275feSReid Kleckner assert(R.first && "InsnRange does not have first instruction!"); 45*f9c275feSReid Kleckner assert(R.second && "InsnRange does not have second instruction!"); 46*f9c275feSReid Kleckner requestLabelBeforeInsn(R.first); 47*f9c275feSReid Kleckner requestLabelAfterInsn(R.second); 48*f9c275feSReid Kleckner } 49*f9c275feSReid Kleckner } 50*f9c275feSReid Kleckner } 51*f9c275feSReid Kleckner 52*f9c275feSReid Kleckner // Return Label preceding the instruction. 53*f9c275feSReid Kleckner MCSymbol *DebugHandlerBase::getLabelBeforeInsn(const MachineInstr *MI) { 54*f9c275feSReid Kleckner MCSymbol *Label = LabelsBeforeInsn.lookup(MI); 55*f9c275feSReid Kleckner assert(Label && "Didn't insert label before instruction"); 56*f9c275feSReid Kleckner return Label; 57*f9c275feSReid Kleckner } 58*f9c275feSReid Kleckner 59*f9c275feSReid Kleckner // Return Label immediately following the instruction. 60*f9c275feSReid Kleckner MCSymbol *DebugHandlerBase::getLabelAfterInsn(const MachineInstr *MI) { 61*f9c275feSReid Kleckner return LabelsAfterInsn.lookup(MI); 62*f9c275feSReid Kleckner } 63*f9c275feSReid Kleckner 64*f9c275feSReid Kleckner // Determine the relative position of the pieces described by P1 and P2. 65*f9c275feSReid Kleckner // Returns -1 if P1 is entirely before P2, 0 if P1 and P2 overlap, 66*f9c275feSReid Kleckner // 1 if P1 is entirely after P2. 67*f9c275feSReid Kleckner int DebugHandlerBase::pieceCmp(const DIExpression *P1, const DIExpression *P2) { 68*f9c275feSReid Kleckner unsigned l1 = P1->getBitPieceOffset(); 69*f9c275feSReid Kleckner unsigned l2 = P2->getBitPieceOffset(); 70*f9c275feSReid Kleckner unsigned r1 = l1 + P1->getBitPieceSize(); 71*f9c275feSReid Kleckner unsigned r2 = l2 + P2->getBitPieceSize(); 72*f9c275feSReid Kleckner if (r1 <= l2) 73*f9c275feSReid Kleckner return -1; 74*f9c275feSReid Kleckner else if (r2 <= l1) 75*f9c275feSReid Kleckner return 1; 76*f9c275feSReid Kleckner else 77*f9c275feSReid Kleckner return 0; 78*f9c275feSReid Kleckner } 79*f9c275feSReid Kleckner 80*f9c275feSReid Kleckner /// Determine whether two variable pieces overlap. 81*f9c275feSReid Kleckner bool DebugHandlerBase::piecesOverlap(const DIExpression *P1, const DIExpression *P2) { 82*f9c275feSReid Kleckner if (!P1->isBitPiece() || !P2->isBitPiece()) 83*f9c275feSReid Kleckner return true; 84*f9c275feSReid Kleckner return pieceCmp(P1, P2) == 0; 85*f9c275feSReid Kleckner } 86*f9c275feSReid Kleckner 87*f9c275feSReid Kleckner void DebugHandlerBase::beginFunction(const MachineFunction *MF) { 88*f9c275feSReid Kleckner // Grab the lexical scopes for the function, if we don't have any of those 89*f9c275feSReid Kleckner // then we're not going to be able to do anything. 90*f9c275feSReid Kleckner LScopes.initialize(*MF); 91*f9c275feSReid Kleckner if (LScopes.empty()) 92*f9c275feSReid Kleckner return; 93*f9c275feSReid Kleckner 94*f9c275feSReid Kleckner // Make sure that each lexical scope will have a begin/end label. 95*f9c275feSReid Kleckner identifyScopeMarkers(); 96*f9c275feSReid Kleckner 97*f9c275feSReid Kleckner // Calculate history for local variables. 98*f9c275feSReid Kleckner assert(DbgValues.empty() && "DbgValues map wasn't cleaned!"); 99*f9c275feSReid Kleckner calculateDbgValueHistory(MF, Asm->MF->getSubtarget().getRegisterInfo(), 100*f9c275feSReid Kleckner DbgValues); 101*f9c275feSReid Kleckner 102*f9c275feSReid Kleckner // Request labels for the full history. 103*f9c275feSReid Kleckner for (const auto &I : DbgValues) { 104*f9c275feSReid Kleckner const auto &Ranges = I.second; 105*f9c275feSReid Kleckner if (Ranges.empty()) 106*f9c275feSReid Kleckner continue; 107*f9c275feSReid Kleckner 108*f9c275feSReid Kleckner // The first mention of a function argument gets the CurrentFnBegin 109*f9c275feSReid Kleckner // label, so arguments are visible when breaking at function entry. 110*f9c275feSReid Kleckner const DILocalVariable *DIVar = Ranges.front().first->getDebugVariable(); 111*f9c275feSReid Kleckner if (DIVar->isParameter() && 112*f9c275feSReid Kleckner getDISubprogram(DIVar->getScope())->describes(MF->getFunction())) { 113*f9c275feSReid Kleckner LabelsBeforeInsn[Ranges.front().first] = Asm->getFunctionBegin(); 114*f9c275feSReid Kleckner if (Ranges.front().first->getDebugExpression()->isBitPiece()) { 115*f9c275feSReid Kleckner // Mark all non-overlapping initial pieces. 116*f9c275feSReid Kleckner for (auto I = Ranges.begin(); I != Ranges.end(); ++I) { 117*f9c275feSReid Kleckner const DIExpression *Piece = I->first->getDebugExpression(); 118*f9c275feSReid Kleckner if (std::all_of(Ranges.begin(), I, 119*f9c275feSReid Kleckner [&](DbgValueHistoryMap::InstrRange Pred) { 120*f9c275feSReid Kleckner return !piecesOverlap(Piece, Pred.first->getDebugExpression()); 121*f9c275feSReid Kleckner })) 122*f9c275feSReid Kleckner LabelsBeforeInsn[I->first] = Asm->getFunctionBegin(); 123*f9c275feSReid Kleckner else 124*f9c275feSReid Kleckner break; 125*f9c275feSReid Kleckner } 126*f9c275feSReid Kleckner } 127*f9c275feSReid Kleckner } 128*f9c275feSReid Kleckner 129*f9c275feSReid Kleckner for (const auto &Range : Ranges) { 130*f9c275feSReid Kleckner requestLabelBeforeInsn(Range.first); 131*f9c275feSReid Kleckner if (Range.second) 132*f9c275feSReid Kleckner requestLabelAfterInsn(Range.second); 133*f9c275feSReid Kleckner } 134*f9c275feSReid Kleckner } 135*f9c275feSReid Kleckner 136*f9c275feSReid Kleckner PrevInstLoc = DebugLoc(); 137*f9c275feSReid Kleckner PrevLabel = Asm->getFunctionBegin(); 138*f9c275feSReid Kleckner } 139*f9c275feSReid Kleckner 140*f9c275feSReid Kleckner void DebugHandlerBase::beginInstruction(const MachineInstr *MI) { 141*f9c275feSReid Kleckner if (!MMI->hasDebugInfo()) 142*f9c275feSReid Kleckner return; 143*f9c275feSReid Kleckner 144*f9c275feSReid Kleckner assert(CurMI == nullptr); 145*f9c275feSReid Kleckner CurMI = MI; 146*f9c275feSReid Kleckner 147*f9c275feSReid Kleckner // Insert labels where requested. 148*f9c275feSReid Kleckner DenseMap<const MachineInstr *, MCSymbol *>::iterator I = 149*f9c275feSReid Kleckner LabelsBeforeInsn.find(MI); 150*f9c275feSReid Kleckner 151*f9c275feSReid Kleckner // No label needed. 152*f9c275feSReid Kleckner if (I == LabelsBeforeInsn.end()) 153*f9c275feSReid Kleckner return; 154*f9c275feSReid Kleckner 155*f9c275feSReid Kleckner // Label already assigned. 156*f9c275feSReid Kleckner if (I->second) 157*f9c275feSReid Kleckner return; 158*f9c275feSReid Kleckner 159*f9c275feSReid Kleckner if (!PrevLabel) { 160*f9c275feSReid Kleckner PrevLabel = MMI->getContext().createTempSymbol(); 161*f9c275feSReid Kleckner Asm->OutStreamer->EmitLabel(PrevLabel); 162*f9c275feSReid Kleckner } 163*f9c275feSReid Kleckner I->second = PrevLabel; 164*f9c275feSReid Kleckner } 165*f9c275feSReid Kleckner 166*f9c275feSReid Kleckner void DebugHandlerBase::endInstruction() { 167*f9c275feSReid Kleckner if (!MMI->hasDebugInfo()) 168*f9c275feSReid Kleckner return; 169*f9c275feSReid Kleckner 170*f9c275feSReid Kleckner assert(CurMI != nullptr); 171*f9c275feSReid Kleckner // Don't create a new label after DBG_VALUE instructions. 172*f9c275feSReid Kleckner // They don't generate code. 173*f9c275feSReid Kleckner if (!CurMI->isDebugValue()) 174*f9c275feSReid Kleckner PrevLabel = nullptr; 175*f9c275feSReid Kleckner 176*f9c275feSReid Kleckner DenseMap<const MachineInstr *, MCSymbol *>::iterator I = 177*f9c275feSReid Kleckner LabelsAfterInsn.find(CurMI); 178*f9c275feSReid Kleckner CurMI = nullptr; 179*f9c275feSReid Kleckner 180*f9c275feSReid Kleckner // No label needed. 181*f9c275feSReid Kleckner if (I == LabelsAfterInsn.end()) 182*f9c275feSReid Kleckner return; 183*f9c275feSReid Kleckner 184*f9c275feSReid Kleckner // Label already assigned. 185*f9c275feSReid Kleckner if (I->second) 186*f9c275feSReid Kleckner return; 187*f9c275feSReid Kleckner 188*f9c275feSReid Kleckner // We need a label after this instruction. 189*f9c275feSReid Kleckner if (!PrevLabel) { 190*f9c275feSReid Kleckner PrevLabel = MMI->getContext().createTempSymbol(); 191*f9c275feSReid Kleckner Asm->OutStreamer->EmitLabel(PrevLabel); 192*f9c275feSReid Kleckner } 193*f9c275feSReid Kleckner I->second = PrevLabel; 194*f9c275feSReid Kleckner } 195*f9c275feSReid Kleckner 196*f9c275feSReid Kleckner void DebugHandlerBase::endFunction(const MachineFunction *MF) { 197*f9c275feSReid Kleckner DbgValues.clear(); 198*f9c275feSReid Kleckner LabelsBeforeInsn.clear(); 199*f9c275feSReid Kleckner LabelsAfterInsn.clear(); 200*f9c275feSReid Kleckner } 201