diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
| commit | 344a3780b2e33f6ca763666c380202b18aab72a3 (patch) | |
| tree | f0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | |
| parent | b60736ec1405bb0a8dd40989f67ef4c93da068ab (diff) | |
vendor/llvm-project/llvmorg-13-init-16847-g88e66fa60ae5vendor/llvm-project/llvmorg-12.0.1-rc2-0-ge7dac564cd0evendor/llvm-project/llvmorg-12.0.1-0-gfed41342a82f
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 299 |
1 files changed, 214 insertions, 85 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 462682743c6a..ee14423ca3d0 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -160,6 +160,13 @@ static cl::opt<DwarfDebug::MinimizeAddrInV5> MinimizeAddrInV5Option( clEnumValN(DwarfDebug::MinimizeAddrInV5::Ranges, "Ranges", "Use rnglists for contiguous ranges if that allows " "using a pre-existing base address"), + clEnumValN(DwarfDebug::MinimizeAddrInV5::Expressions, + "Expressions", + "Use exprloc addrx+offset expressions for any " + "address with a prior base address"), + clEnumValN(DwarfDebug::MinimizeAddrInV5::Form, "Form", + "Use addrx+offset extension form for any address " + "with a prior base address"), clEnumValN(DwarfDebug::MinimizeAddrInV5::Disabled, "Disabled", "Stuff")), cl::init(DwarfDebug::MinimizeAddrInV5::Default)); @@ -228,29 +235,27 @@ const DIType *DbgVariable::getType() const { /// Get .debug_loc entry for the instruction range starting at MI. static DbgValueLoc getDebugLocValue(const MachineInstr *MI) { const DIExpression *Expr = MI->getDebugExpression(); - assert(MI->getNumOperands() == 4); - if (MI->getDebugOperand(0).isReg()) { - const auto &RegOp = MI->getDebugOperand(0); - const auto &Op1 = MI->getDebugOffset(); - // If the second operand is an immediate, this is a - // register-indirect address. - assert((!Op1.isImm() || (Op1.getImm() == 0)) && "unexpected offset"); - MachineLocation MLoc(RegOp.getReg(), Op1.isImm()); - return DbgValueLoc(Expr, MLoc); - } - if (MI->getDebugOperand(0).isTargetIndex()) { - const auto &Op = MI->getDebugOperand(0); - return DbgValueLoc(Expr, - TargetIndexLocation(Op.getIndex(), Op.getOffset())); + const bool IsVariadic = MI->isDebugValueList(); + assert(MI->getNumOperands() >= 3); + SmallVector<DbgValueLocEntry, 4> DbgValueLocEntries; + for (const MachineOperand &Op : MI->debug_operands()) { + if (Op.isReg()) { + MachineLocation MLoc(Op.getReg(), + MI->isNonListDebugValue() && MI->isDebugOffsetImm()); + DbgValueLocEntries.push_back(DbgValueLocEntry(MLoc)); + } else if (Op.isTargetIndex()) { + DbgValueLocEntries.push_back( + DbgValueLocEntry(TargetIndexLocation(Op.getIndex(), Op.getOffset()))); + } else if (Op.isImm()) + DbgValueLocEntries.push_back(DbgValueLocEntry(Op.getImm())); + else if (Op.isFPImm()) + DbgValueLocEntries.push_back(DbgValueLocEntry(Op.getFPImm())); + else if (Op.isCImm()) + DbgValueLocEntries.push_back(DbgValueLocEntry(Op.getCImm())); + else + llvm_unreachable("Unexpected debug operand in DBG_VALUE* instruction!"); } - if (MI->getDebugOperand(0).isImm()) - return DbgValueLoc(Expr, MI->getDebugOperand(0).getImm()); - if (MI->getDebugOperand(0).isFPImm()) - return DbgValueLoc(Expr, MI->getDebugOperand(0).getFPImm()); - if (MI->getDebugOperand(0).isCImm()) - return DbgValueLoc(Expr, MI->getDebugOperand(0).getCImm()); - - llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!"); + return DbgValueLoc(Expr, DbgValueLocEntries, IsVariadic); } void DbgVariable::initializeDbgValue(const MachineInstr *DbgValue) { @@ -357,11 +362,13 @@ DwarfDebug::DwarfDebug(AsmPrinter *A) DebuggerTuning = DebuggerKind::LLDB; else if (TT.isPS4CPU()) DebuggerTuning = DebuggerKind::SCE; + else if (TT.isOSAIX()) + DebuggerTuning = DebuggerKind::DBX; else DebuggerTuning = DebuggerKind::GDB; if (DwarfInlinedStrings == Default) - UseInlineStrings = TT.isNVPTX(); + UseInlineStrings = TT.isNVPTX() || tuneForDBX(); else UseInlineStrings = DwarfInlinedStrings == Enable; @@ -385,10 +392,21 @@ DwarfDebug::DwarfDebug(AsmPrinter *A) DwarfVersion = TT.isNVPTX() ? 2 : (DwarfVersion ? DwarfVersion : dwarf::DWARF_VERSION); - bool Dwarf64 = Asm->TM.Options.MCOptions.Dwarf64 && - DwarfVersion >= 3 && // DWARF64 was introduced in DWARFv3. - TT.isArch64Bit() && // DWARF64 requires 64-bit relocations. - TT.isOSBinFormatELF(); // Support only ELF for now. + bool Dwarf64 = DwarfVersion >= 3 && // DWARF64 was introduced in DWARFv3. + TT.isArch64Bit(); // DWARF64 requires 64-bit relocations. + + // Support DWARF64 + // 1: For ELF when requested. + // 2: For XCOFF64: the AIX assembler will fill in debug section lengths + // according to the DWARF64 format for 64-bit assembly, so we must use + // DWARF64 in the compiler too for 64-bit mode. + Dwarf64 &= + ((Asm->TM.Options.MCOptions.Dwarf64 || MMI->getModule()->isDwarf64()) && + TT.isOSBinFormatELF()) || + TT.isOSBinFormatXCOFF(); + + if (!Dwarf64 && TT.isArch64Bit() && TT.isOSBinFormatXCOFF()) + report_fatal_error("XCOFF requires DWARF64 for 64-bit mode!"); UseRangesSection = !NoDwarfRangesSection && !TT.isNVPTX(); @@ -627,7 +645,7 @@ static void finishCallSiteParams(ValT Val, const DIExpression *Expr, assert((!CombinedExpr || CombinedExpr->isValid()) && "Combined debug expression is invalid"); - DbgValueLoc DbgLocVal(CombinedExpr, Val); + DbgValueLoc DbgLocVal(CombinedExpr, DbgValueLocEntry(Val)); DbgCallSiteParam CSParm(Param.ParamReg, DbgLocVal); Params.push_back(CSParm); ++NumCSParams; @@ -701,7 +719,7 @@ static void interpretValues(const MachineInstr *CurMI, for (const MachineOperand &MO : MI.operands()) { if (MO.isReg() && MO.isDef() && Register::isPhysicalRegister(MO.getReg())) { - for (auto FwdReg : ForwardedRegWorklist) + for (auto &FwdReg : ForwardedRegWorklist) if (TRI.regsOverlap(FwdReg.first, MO.getReg())) Defs.insert(FwdReg.first); } @@ -750,7 +768,7 @@ static void interpretValues(const MachineInstr *CurMI, // Now that we are done handling this instruction, add items from the // temporary worklist to the real one. - for (auto New : TmpWorklistItems) + for (auto &New : TmpWorklistItems) addToFwdRegWorklist(ForwardedRegWorklist, New.first, EmptyExpr, New.second); TmpWorklistItems.clear(); } @@ -785,7 +803,7 @@ static bool interpretNextInstr(const MachineInstr *CurMI, static void collectCallSiteParameters(const MachineInstr *CallMI, ParamSet &Params) { const MachineFunction *MF = CallMI->getMF(); - auto CalleesMap = MF->getCallSitesInfo(); + const auto &CalleesMap = MF->getCallSitesInfo(); auto CallFwdRegsInfo = CalleesMap.find(CallMI); // There is no information for the call instruction. @@ -803,7 +821,7 @@ static void collectCallSiteParameters(const MachineInstr *CallMI, DIExpression::get(MF->getFunction().getContext(), {}); // Add all the forwarding registers into the ForwardedRegWorklist. - for (auto ArgReg : CallFwdRegsInfo->second) { + for (const auto &ArgReg : CallFwdRegsInfo->second) { bool InsertedReg = ForwardedRegWorklist.insert({ArgReg.Reg, {{ArgReg.Reg, EmptyExpr}}}) .second; @@ -851,7 +869,7 @@ static void collectCallSiteParameters(const MachineInstr *CallMI, // Create an expression where the register's entry value is used. DIExpression *EntryExpr = DIExpression::get( MF->getFunction().getContext(), {dwarf::DW_OP_LLVM_entry_value, 1}); - for (auto RegEntry : ForwardedRegWorklist) { + for (auto &RegEntry : ForwardedRegWorklist) { MachineLocation MLoc(RegEntry.first); finishCallSiteParams(MLoc, EntryExpr, RegEntry.second, Params); } @@ -920,8 +938,10 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, // If this is a direct call, find the callee's subprogram. // In the case of an indirect call find the register that holds // the callee. - const MachineOperand &CalleeOp = MI.getOperand(0); - if (!CalleeOp.isGlobal() && !CalleeOp.isReg()) + const MachineOperand &CalleeOp = TII->getCalleeOperand(MI); + if (!CalleeOp.isGlobal() && + (!CalleeOp.isReg() || + !Register::isPhysicalRegister(CalleeOp.getReg()))) continue; unsigned CallReg = 0; @@ -1216,6 +1236,7 @@ void DwarfDebug::beginModule(Module *M) { if (!GVMapEntry.size() || (Expr && Expr->isConstant())) GVMapEntry.push_back({nullptr, Expr}); } + DenseSet<DIGlobalVariable *> Processed; for (auto *GVE : CUNode->getGlobalVariables()) { DIGlobalVariable *GV = GVE->getVariable(); @@ -1533,6 +1554,7 @@ void DwarfDebug::collectVariableInfoFromMFTable( RegVar->initializeMMI(VI.Expr, VI.Slot); LLVM_DEBUG(dbgs() << "Created DbgVariable for " << VI.Var->getName() << "\n"); + if (DbgVariable *DbgVar = MFVars.lookup(Var)) DbgVar->addMMIEntry(*RegVar); else if (InfoHolder.addScopeVariable(Scope, RegVar.get())) { @@ -1595,7 +1617,9 @@ static bool validThroughout(LexicalScopes &LScopes, // throughout the function. This is a hack, presumably for DWARF v2 and not // necessarily correct. It would be much better to use a dbg.declare instead // if we know the constant is live throughout the scope. - if (DbgValue->getDebugOperand(0).isImm() && MBB->pred_empty()) + if (MBB->pred_empty() && + all_of(DbgValue->debug_operands(), + [](const MachineOperand &Op) { return Op.isImm(); })) return true; // Test if the location terminates before the end of the scope. @@ -1719,7 +1743,30 @@ bool DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, SmallVector<DbgValueLoc, 4> Values; for (auto &R : OpenRanges) Values.push_back(R.second); - DebugLoc.emplace_back(StartLabel, EndLabel, Values); + + // With Basic block sections, it is posssible that the StartLabel and the + // Instr are not in the same section. This happens when the StartLabel is + // the function begin label and the dbg value appears in a basic block + // that is not the entry. In this case, the range needs to be split to + // span each individual section in the range from StartLabel to EndLabel. + if (Asm->MF->hasBBSections() && StartLabel == Asm->getFunctionBegin() && + !Instr->getParent()->sameSection(&Asm->MF->front())) { + const MCSymbol *BeginSectionLabel = StartLabel; + + for (const MachineBasicBlock &MBB : *Asm->MF) { + if (MBB.isBeginSection() && &MBB != &Asm->MF->front()) + BeginSectionLabel = MBB.getSymbol(); + + if (MBB.sameSection(Instr->getParent())) { + DebugLoc.emplace_back(BeginSectionLabel, EndLabel, Values); + break; + } + if (MBB.isEndSection()) + DebugLoc.emplace_back(BeginSectionLabel, MBB.getEndSymbol(), Values); + } + } else { + DebugLoc.emplace_back(StartLabel, EndLabel, Values); + } // Attempt to coalesce the ranges of two otherwise identical // DebugLocEntries. @@ -1736,8 +1783,46 @@ bool DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, DebugLoc.pop_back(); } - return DebugLoc.size() == 1 && isSafeForSingleLocation && - validThroughout(LScopes, StartDebugMI, EndMI, getInstOrdering()); + if (!isSafeForSingleLocation || + !validThroughout(LScopes, StartDebugMI, EndMI, getInstOrdering())) + return false; + + if (DebugLoc.size() == 1) + return true; + + if (!Asm->MF->hasBBSections()) + return false; + + // Check here to see if loclist can be merged into a single range. If not, + // we must keep the split loclists per section. This does exactly what + // MergeRanges does without sections. We don't actually merge the ranges + // as the split ranges must be kept intact if this cannot be collapsed + // into a single range. + const MachineBasicBlock *RangeMBB = nullptr; + if (DebugLoc[0].getBeginSym() == Asm->getFunctionBegin()) + RangeMBB = &Asm->MF->front(); + else + RangeMBB = Entries.begin()->getInstr()->getParent(); + auto *CurEntry = DebugLoc.begin(); + auto *NextEntry = std::next(CurEntry); + while (NextEntry != DebugLoc.end()) { + // Get the last machine basic block of this section. + while (!RangeMBB->isEndSection()) + RangeMBB = RangeMBB->getNextNode(); + if (!RangeMBB->getNextNode()) + return false; + // CurEntry should end the current section and NextEntry should start + // the next section and the Values must match for these two ranges to be + // merged. + if (CurEntry->getEndSym() != RangeMBB->getEndSymbol() || + NextEntry->getBeginSym() != RangeMBB->getNextNode()->getSymbol() || + CurEntry->getValues() != NextEntry->getValues()) + return false; + RangeMBB = RangeMBB->getNextNode(); + CurEntry = NextEntry; + NextEntry = std::next(CurEntry); + } + return true; } DbgEntity *DwarfDebug::createConcreteEntity(DwarfCompileUnit &TheCU, @@ -1776,7 +1861,10 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, // Instruction ranges, specifying where IV is accessible. const auto &HistoryMapEntries = I.second; - if (HistoryMapEntries.empty()) + + // Try to find any non-empty variable location. Do not create a concrete + // entity if there are no locations. + if (!DbgValues.hasNonEmptyLocation(HistoryMapEntries)) continue; LexicalScope *Scope = nullptr; @@ -2363,12 +2451,8 @@ void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name, TheU = Skeleton; // Emit the header. - MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + Name + "_begin"); - MCSymbol *EndLabel = Asm->createTempSymbol("pub" + Name + "_end"); - Asm->emitDwarfUnitLength(EndLabel, BeginLabel, - "Length of Public " + Name + " Info"); - - Asm->OutStreamer->emitLabel(BeginLabel); + MCSymbol *EndLabel = Asm->emitDwarfUnitLength( + "pub" + Name, "Length of Public " + Name + " Info"); Asm->OutStreamer->AddComment("DWARF Version"); Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION); @@ -2469,51 +2553,93 @@ void DwarfDebug::emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, auto *DIExpr = Value.getExpression(); DIExpressionCursor ExprCursor(DIExpr); DwarfExpr.addFragmentOffset(DIExpr); - // Regular entry. - if (Value.isInt()) { - if (BT && (BT->getEncoding() == dwarf::DW_ATE_signed || - BT->getEncoding() == dwarf::DW_ATE_signed_char)) - DwarfExpr.addSignedConstant(Value.getInt()); - else - DwarfExpr.addUnsignedConstant(Value.getInt()); - } else if (Value.isLocation()) { - MachineLocation Location = Value.getLoc(); + + // If the DIExpr is is an Entry Value, we want to follow the same code path + // regardless of whether the DBG_VALUE is variadic or not. + if (DIExpr && DIExpr->isEntryValue()) { + // Entry values can only be a single register with no additional DIExpr, + // so just add it directly. + assert(Value.getLocEntries().size() == 1); + assert(Value.getLocEntries()[0].isLocation()); + MachineLocation Location = Value.getLocEntries()[0].getLoc(); DwarfExpr.setLocation(Location, DIExpr); - DIExpressionCursor Cursor(DIExpr); - if (DIExpr->isEntryValue()) - DwarfExpr.beginEntryValueExpression(Cursor); + DwarfExpr.beginEntryValueExpression(ExprCursor); const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo(); - if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg())) - return; - return DwarfExpr.addExpression(std::move(Cursor)); - } else if (Value.isTargetIndexLocation()) { - TargetIndexLocation Loc = Value.getTargetIndexLocation(); - // TODO TargetIndexLocation is a target-independent. Currently only the WebAssembly-specific - // encoding is supported. - assert(AP.TM.getTargetTriple().isWasm()); - DwarfExpr.addWasmLocation(Loc.Index, static_cast<uint64_t>(Loc.Offset)); - DwarfExpr.addExpression(std::move(ExprCursor)); - return; - } else if (Value.isConstantFP()) { - if (AP.getDwarfVersion() >= 4 && !AP.getDwarfDebug()->tuneForSCE() && - !ExprCursor) { - DwarfExpr.addConstantFP(Value.getConstantFP()->getValueAPF(), AP); + if (!DwarfExpr.addMachineRegExpression(TRI, ExprCursor, Location.getReg())) return; + return DwarfExpr.addExpression(std::move(ExprCursor)); + } + + // Regular entry. + auto EmitValueLocEntry = [&DwarfExpr, &BT, + &AP](const DbgValueLocEntry &Entry, + DIExpressionCursor &Cursor) -> bool { + if (Entry.isInt()) { + if (BT && (BT->getEncoding() == dwarf::DW_ATE_signed || + BT->getEncoding() == dwarf::DW_ATE_signed_char)) + DwarfExpr.addSignedConstant(Entry.getInt()); + else + DwarfExpr.addUnsignedConstant(Entry.getInt()); + } else if (Entry.isLocation()) { + MachineLocation Location = Entry.getLoc(); + if (Location.isIndirect()) + DwarfExpr.setMemoryLocationKind(); + + const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo(); + if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg())) + return false; + } else if (Entry.isTargetIndexLocation()) { + TargetIndexLocation Loc = Entry.getTargetIndexLocation(); + // TODO TargetIndexLocation is a target-independent. Currently only the + // WebAssembly-specific encoding is supported. + assert(AP.TM.getTargetTriple().isWasm()); + DwarfExpr.addWasmLocation(Loc.Index, static_cast<uint64_t>(Loc.Offset)); + } else if (Entry.isConstantFP()) { + if (AP.getDwarfVersion() >= 4 && !AP.getDwarfDebug()->tuneForSCE() && + !Cursor) { + DwarfExpr.addConstantFP(Entry.getConstantFP()->getValueAPF(), AP); + } else if (Entry.getConstantFP() + ->getValueAPF() + .bitcastToAPInt() + .getBitWidth() <= 64 /*bits*/) { + DwarfExpr.addUnsignedConstant( + Entry.getConstantFP()->getValueAPF().bitcastToAPInt()); + } else { + LLVM_DEBUG( + dbgs() << "Skipped DwarfExpression creation for ConstantFP of size" + << Entry.getConstantFP() + ->getValueAPF() + .bitcastToAPInt() + .getBitWidth() + << " bits\n"); + return false; + } } - if (Value.getConstantFP()->getValueAPF().bitcastToAPInt().getBitWidth() <= - 64 /*bits*/) - DwarfExpr.addUnsignedConstant( - Value.getConstantFP()->getValueAPF().bitcastToAPInt()); - else - LLVM_DEBUG( - dbgs() - << "Skipped DwarfExpression creation for ConstantFP of size" - << Value.getConstantFP()->getValueAPF().bitcastToAPInt().getBitWidth() - << " bits\n"); + return true; + }; + + if (!Value.isVariadic()) { + if (!EmitValueLocEntry(Value.getLocEntries()[0], ExprCursor)) + return; + DwarfExpr.addExpression(std::move(ExprCursor)); + return; } - DwarfExpr.addExpression(std::move(ExprCursor)); + + // If any of the location entries are registers with the value 0, then the + // location is undefined. + if (any_of(Value.getLocEntries(), [](const DbgValueLocEntry &Entry) { + return Entry.isLocation() && !Entry.getLoc().getReg(); + })) + return; + + DwarfExpr.addExpression( + std::move(ExprCursor), + [EmitValueLocEntry, &Value](unsigned Idx, + DIExpressionCursor &Cursor) -> bool { + return EmitValueLocEntry(Value.getLocEntries()[Idx], Cursor); + }); } void DebugLocEntry::finalize(const AsmPrinter &AP, @@ -3397,7 +3523,10 @@ dwarf::Form DwarfDebug::getDwarfSectionOffsetForm() const { } const MCSymbol *DwarfDebug::getSectionLabel(const MCSection *S) { - return SectionLabels.find(S)->second; + auto I = SectionLabels.find(S); + if (I == SectionLabels.end()) + return nullptr; + return I->second; } void DwarfDebug::insertSectionLabel(const MCSymbol *S) { if (SectionLabels.insert(std::make_pair(&S->getSection(), S)).second) |
