From: Stephen Tozer Date: Wed, 10 Mar 2021 14:34:47 +0000 (+0000) Subject: Revert "[DebugInfo] Add DWARF emission for DBG_VALUE_LIST" X-Git-Tag: llvmorg-14-init~12768 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=429c6ecbb302e2beedd8694378ae5be456206209;p=platform%2Fupstream%2Fllvm.git Revert "[DebugInfo] Add DWARF emission for DBG_VALUE_LIST" This reverts commit 0da27ba56c9f5e3f534a65401962301189eac342. This revision was causing an error on the sanitizer-x86_64-linux-autoconf build. --- diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index d557476..dbe7028 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -918,6 +918,9 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { OS << V->getName(); OS << " <- "; + // The second operand is only an offset if it's an immediate. + bool MemLoc = MI->isIndirectDebugValue(); + auto Offset = StackOffset::getFixed(MemLoc ? MI->getOperand(1).getImm() : 0); const DIExpression *Expr = MI->getDebugExpression(); if (Expr->getNumElements()) { OS << '['; @@ -931,71 +934,56 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { } // Register or immediate value. Register 0 means undef. - for (const MachineOperand &Op : MI->debug_operands()) { - if (&Op != MI->debug_operands().begin()) - OS << ", "; - switch (Op.getType()) { - case MachineOperand::MO_FPImmediate: { - APFloat APF = APFloat(Op.getFPImm()->getValueAPF()); - if (Op.getFPImm()->getType()->isFloatTy()) { - OS << (double)APF.convertToFloat(); - } else if (Op.getFPImm()->getType()->isDoubleTy()) { - OS << APF.convertToDouble(); - } else { - // There is no good way to print long double. Convert a copy to - // double. Ah well, it's only a comment. - bool ignored; - APF.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, - &ignored); - OS << "(long double) " << APF.convertToDouble(); - } - break; - } - case MachineOperand::MO_Immediate: { - OS << Op.getImm(); - break; + if (MI->getDebugOperand(0).isFPImm()) { + APFloat APF = APFloat(MI->getDebugOperand(0).getFPImm()->getValueAPF()); + if (MI->getDebugOperand(0).getFPImm()->getType()->isFloatTy()) { + OS << (double)APF.convertToFloat(); + } else if (MI->getDebugOperand(0).getFPImm()->getType()->isDoubleTy()) { + OS << APF.convertToDouble(); + } else { + // There is no good way to print long double. Convert a copy to + // double. Ah well, it's only a comment. + bool ignored; + APF.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, + &ignored); + OS << "(long double) " << APF.convertToDouble(); } - case MachineOperand::MO_CImmediate: { - Op.getCImm()->getValue().print(OS, false /*isSigned*/); - break; + } else if (MI->getDebugOperand(0).isImm()) { + OS << MI->getDebugOperand(0).getImm(); + } else if (MI->getDebugOperand(0).isCImm()) { + MI->getDebugOperand(0).getCImm()->getValue().print(OS, false /*isSigned*/); + } else if (MI->getDebugOperand(0).isTargetIndex()) { + auto Op = MI->getDebugOperand(0); + OS << "!target-index(" << Op.getIndex() << "," << Op.getOffset() << ")"; + // NOTE: Want this comment at start of line, don't emit with AddComment. + AP.OutStreamer->emitRawComment(OS.str()); + return true; + } else { + Register Reg; + if (MI->getDebugOperand(0).isReg()) { + Reg = MI->getDebugOperand(0).getReg(); + } else { + assert(MI->getDebugOperand(0).isFI() && "Unknown operand type"); + const TargetFrameLowering *TFI = AP.MF->getSubtarget().getFrameLowering(); + Offset += TFI->getFrameIndexReference( + *AP.MF, MI->getDebugOperand(0).getIndex(), Reg); + MemLoc = true; } - case MachineOperand::MO_TargetIndex: { - OS << "!target-index(" << Op.getIndex() << "," << Op.getOffset() << ")"; + if (Reg == 0) { + // Suppress offset, it is not meaningful here. + OS << "undef"; // NOTE: Want this comment at start of line, don't emit with AddComment. AP.OutStreamer->emitRawComment(OS.str()); - break; - } - case MachineOperand::MO_Register: - case MachineOperand::MO_FrameIndex: { - Register Reg; - Optional Offset; - if (Op.isReg()) { - Reg = Op.getReg(); - } else { - const TargetFrameLowering *TFI = - AP.MF->getSubtarget().getFrameLowering(); - Offset = TFI->getFrameIndexReference(*AP.MF, Op.getIndex(), Reg); - } - if (!Reg) { - // Suppress offset, it is not meaningful here. - OS << "undef"; - break; - } - // The second operand is only an offset if it's an immediate. - if (MI->isIndirectDebugValue()) - Offset = StackOffset::getFixed(MI->getDebugOffset().getImm()); - if (Offset) - OS << '['; - OS << printReg(Reg, AP.MF->getSubtarget().getRegisterInfo()); - if (Offset) - OS << '+' << Offset->getFixed() << ']'; - break; - } - default: - llvm_unreachable("Unknown operand type"); + return true; } + if (MemLoc) + OS << '['; + OS << printReg(Reg, AP.MF->getSubtarget().getRegisterInfo()); } + if (MemLoc) + OS << '+' << Offset.getFixed() << ']'; + // NOTE: Want this comment at start of line, don't emit with AddComment. AP.OutStreamer->emitRawComment(OS.str()); return true; diff --git a/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp b/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp index bb24f14..a30720c 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp @@ -37,6 +37,22 @@ namespace { using EntryIndex = DbgValueHistoryMap::EntryIndex; } +// If @MI is a DBG_VALUE with debug value described by a +// defined register, returns the number of this register. +// In the other case, returns 0. +static Register isDescribedByReg(const MachineInstr &MI) { + assert(MI.isDebugValue()); + assert(MI.getNumOperands() == 4); + // If the location of variable is an entry value (DW_OP_LLVM_entry_value) + // do not consider it as a register location. + if (MI.getDebugExpression()->isEntryValue()) + return 0; + // If location of variable is described using a register (directly or + // indirectly), this register is always a first operand. + return MI.getDebugOperand(0).isReg() ? MI.getDebugOperand(0).getReg() + : Register(); +} + void InstructionOrdering::initialize(const MachineFunction &MF) { // We give meta instructions the same ordinal as the preceding instruction // because this class is written for the task of comparing positions of @@ -317,44 +333,24 @@ static void addRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo, } /// Create a clobbering entry and end all open debug value entries -/// for \p Var that are described by \p RegNo using that entry. Inserts into \p -/// FellowRegisters the set of Registers that were also used to describe \p Var -/// alongside \p RegNo. +/// for \p Var that are described by \p RegNo using that entry. static void clobberRegEntries(InlinedEntity Var, unsigned RegNo, const MachineInstr &ClobberingInstr, DbgValueEntriesMap &LiveEntries, - DbgValueHistoryMap &HistMap, - SmallVectorImpl &FellowRegisters) { + DbgValueHistoryMap &HistMap) { EntryIndex ClobberIndex = HistMap.startClobber(Var, ClobberingInstr); + // Close all entries whose values are described by the register. SmallVector IndicesToErase; - // If a given register appears in a live DBG_VALUE_LIST for Var alongside the - // clobbered register, and never appears in a live DBG_VALUE* for Var without - // the clobbered register, then it is no longer linked to the variable. - SmallSet MaybeRemovedRegisters; - SmallSet KeepRegisters; for (auto Index : LiveEntries[Var]) { auto &Entry = HistMap.getEntry(Var, Index); assert(Entry.isDbgValue() && "Not a DBG_VALUE in LiveEntries"); - if (Entry.getInstr()->isDebugEntryValue()) - continue; - if (Entry.getInstr()->hasDebugOperandForReg(RegNo)) { + if (isDescribedByReg(*Entry.getInstr()) == RegNo) { IndicesToErase.push_back(Index); Entry.endEntry(ClobberIndex); - for (auto &MO : Entry.getInstr()->debug_operands()) - if (MO.isReg() && MO.getReg() && MO.getReg() != RegNo) - MaybeRemovedRegisters.insert(MO.getReg()); - } else { - for (auto &MO : Entry.getInstr()->debug_operands()) - if (MO.isReg() && MO.getReg()) - KeepRegisters.insert(MO.getReg()); } } - for (Register Reg : MaybeRemovedRegisters) - if (!KeepRegisters.contains(Reg)) - FellowRegisters.push_back(Reg); - // Drop all entries that have ended. for (auto Index : IndicesToErase) LiveEntries[Var].erase(Index); @@ -382,24 +378,17 @@ static void handleNewDebugValue(InlinedEntity Var, const MachineInstr &DV, IndicesToErase.push_back(Index); Entry.endEntry(NewIndex); } - if (!DV.isDebugEntryValue()) - for (const MachineOperand &Op : DV.debug_operands()) - if (Op.isReg() && Op.getReg()) - TrackedRegs[Op.getReg()] |= !Overlaps; + if (Register Reg = isDescribedByReg(DV)) + TrackedRegs[Reg] |= !Overlaps; } // If the new debug value is described by a register, add tracking of // that register if it is not already tracked. - if (!DV.isDebugEntryValue()) { - for (const MachineOperand &Op : DV.debug_operands()) { - if (Op.isReg() && Op.getReg()) { - Register NewReg = Op.getReg(); - if (!TrackedRegs.count(NewReg)) - addRegDescribedVar(RegVars, NewReg, Var); - LiveEntries[Var].insert(NewIndex); - TrackedRegs[NewReg] = true; - } - } + if (Register NewReg = isDescribedByReg(DV)) { + if (!TrackedRegs.count(NewReg)) + addRegDescribedVar(RegVars, NewReg, Var); + LiveEntries[Var].insert(NewIndex); + TrackedRegs[NewReg] = true; } // Drop tracking of registers that are no longer used. @@ -422,16 +411,9 @@ static void clobberRegisterUses(RegDescribedVarsMap &RegVars, DbgValueEntriesMap &LiveEntries, const MachineInstr &ClobberingInstr) { // Iterate over all variables described by this register and add this - // instruction to their history, clobbering it. All registers that also - // describe the clobbered variables (i.e. in variadic debug values) will have - // those Variables removed from their DescribedVars. - for (const auto &Var : I->second) { - SmallVector FellowRegisters; - clobberRegEntries(Var, I->first, ClobberingInstr, LiveEntries, HistMap, - FellowRegisters); - for (Register RegNo : FellowRegisters) - dropRegDescribedVar(RegVars, RegNo, Var); - } + // instruction to their history, clobbering it. + for (const auto &Var : I->second) + clobberRegEntries(Var, I->first, ClobberingInstr, LiveEntries, HistMap); RegVars.erase(I); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp index b9a9e1c..68a4bfb 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp @@ -35,8 +35,7 @@ Optional DbgVariableLocation::extractFromMachineInstruction( const MachineInstr &Instruction) { DbgVariableLocation Location; - // Variables calculated from multiple locations can't be represented here. - if (Instruction.getNumDebugOperands() != 1) + if (!Instruction.isDebugValue()) return None; if (!Instruction.getDebugOperand(0).isReg()) return None; @@ -47,15 +46,6 @@ DbgVariableLocation::extractFromMachineInstruction( int64_t Offset = 0; const DIExpression *DIExpr = Instruction.getDebugExpression(); auto Op = DIExpr->expr_op_begin(); - // We can handle a DBG_VALUE_LIST iff it has exactly one location operand that - // appears exactly once at the start of the expression. - if (Instruction.isDebugValueList()) { - if (Instruction.getNumDebugOperands() == 1 && - Op->getOp() == dwarf::DW_OP_LLVM_arg) - ++Op; - else - return None; - } while (Op != DIExpr->expr_op_end()) { switch (Op->getOp()) { case dwarf::DW_OP_constu: { @@ -271,8 +261,7 @@ void DebugHandlerBase::beginFunction(const MachineFunction *MF) { continue; auto IsDescribedByReg = [](const MachineInstr *MI) { - return any_of(MI->debug_operands(), - [](auto &MO) { return MO.isReg() && MO.getReg(); }); + return MI->getDebugOperand(0).isReg() && MI->getDebugOperand(0).getReg(); }; // The first mention of a function argument gets the CurrentFnBegin label, diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h index 525b839..36278f2 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h +++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h @@ -34,10 +34,10 @@ struct TargetIndexLocation { } }; -/// A single location or constant within a variable location description, with -/// either a single entry (with an optional DIExpression) used for a DBG_VALUE, -/// or a list of entries used for a DBG_VALUE_LIST. -class DbgValueLocEntry { +/// A single location or constant. +class DbgValueLoc { + /// Any complex address location expression for this DbgValueLoc. + const DIExpression *Expression; /// Type of entry that this represents. enum EntryType { @@ -64,16 +64,24 @@ class DbgValueLocEntry { }; public: - DbgValueLocEntry(int64_t i) : EntryKind(E_Integer) { Constant.Int = i; } - DbgValueLocEntry(const ConstantFP *CFP) : EntryKind(E_ConstantFP) { + DbgValueLoc(const DIExpression *Expr, int64_t i) + : Expression(Expr), EntryKind(E_Integer) { + Constant.Int = i; + } + DbgValueLoc(const DIExpression *Expr, const ConstantFP *CFP) + : Expression(Expr), EntryKind(E_ConstantFP) { Constant.CFP = CFP; } - DbgValueLocEntry(const ConstantInt *CIP) : EntryKind(E_ConstantInt) { + DbgValueLoc(const DIExpression *Expr, const ConstantInt *CIP) + : Expression(Expr), EntryKind(E_ConstantInt) { Constant.CIP = CIP; } - DbgValueLocEntry(MachineLocation Loc) : EntryKind(E_Location), Loc(Loc) {} - DbgValueLocEntry(TargetIndexLocation Loc) - : EntryKind(E_TargetIndexLocation), TIL(Loc) {} + DbgValueLoc(const DIExpression *Expr, MachineLocation Loc) + : Expression(Expr), EntryKind(E_Location), Loc(Loc) { + assert(cast(Expr)->isValid()); + } + DbgValueLoc(const DIExpression *Expr, TargetIndexLocation Loc) + : Expression(Expr), EntryKind(E_TargetIndexLocation), TIL(Loc) {} bool isLocation() const { return EntryKind == E_Location; } bool isTargetIndexLocation() const { @@ -87,7 +95,11 @@ public: const ConstantInt *getConstantInt() const { return Constant.CIP; } MachineLocation getLoc() const { return Loc; } TargetIndexLocation getTargetIndexLocation() const { return TIL; } - friend bool operator==(const DbgValueLocEntry &, const DbgValueLocEntry &); + bool isFragment() const { return getExpression()->isFragment(); } + bool isEntryVal() const { return getExpression()->isEntryValue(); } + const DIExpression *getExpression() const { return Expression; } + friend bool operator==(const DbgValueLoc &, const DbgValueLoc &); + friend bool operator<(const DbgValueLoc &, const DbgValueLoc &); #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void dump() const { if (isLocation()) { @@ -99,77 +111,6 @@ public: Constant.CIP->dump(); else if (isConstantFP()) Constant.CFP->dump(); - } -#endif -}; - -/// The location of a single variable, composed of an expression and 0 or more -/// DbgValueLocEntries. -class DbgValueLoc { - /// Any complex address location expression for this DbgValueLoc. - const DIExpression *Expression; - - SmallVector ValueLocEntries; - - bool IsVariadic; - -public: - DbgValueLoc(const DIExpression *Expr, ArrayRef Locs) - : Expression(Expr), ValueLocEntries(Locs.begin(), Locs.end()), - IsVariadic(true) { -#ifndef NDEBUG - // Currently, DBG_VALUE_VAR expressions must use stack_value. - assert(Expr && Expr->isValid() && - is_contained(Locs, dwarf::DW_OP_stack_value)); - for (DbgValueLocEntry &Entry : ValueLocEntries) { - assert(!Entry.isConstantFP() && !Entry.isConstantInt() && - "Constant values should only be present in non-variadic " - "DBG_VALUEs."); - } -#endif - } - - DbgValueLoc(const DIExpression *Expr, ArrayRef Locs, - bool IsVariadic) - : Expression(Expr), ValueLocEntries(Locs.begin(), Locs.end()), - IsVariadic(IsVariadic) { -#ifndef NDEBUG - assert(cast(Expr)->isValid() || - !any_of(Locs, [](auto LE) { return LE.isLocation(); })); - if (!IsVariadic) { - assert(ValueLocEntries.size() == 1); - } else { - // Currently, DBG_VALUE_VAR expressions must use stack_value. - assert(Expr && Expr->isValid() && - is_contained(Expr->getElements(), dwarf::DW_OP_stack_value)); - for (DbgValueLocEntry &Entry : ValueLocEntries) { - assert(!Entry.isConstantFP() && !Entry.isConstantInt() && - "Constant values should only be present in non-variadic " - "DBG_VALUEs."); - } - } -#endif - } - - DbgValueLoc(const DIExpression *Expr, DbgValueLocEntry Loc) - : Expression(Expr), ValueLocEntries(1, Loc), IsVariadic(false) { - assert(((Expr && Expr->isValid()) || !Loc.isLocation()) && - "DBG_VALUE with a machine location must have a valid expression."); - } - - bool isFragment() const { return getExpression()->isFragment(); } - bool isEntryVal() const { return getExpression()->isEntryValue(); } - bool isVariadic() const { return IsVariadic; } - const DIExpression *getExpression() const { return Expression; } - const ArrayRef getLocEntries() const { - return ValueLocEntries; - } - friend bool operator==(const DbgValueLoc &, const DbgValueLoc &); - friend bool operator<(const DbgValueLoc &, const DbgValueLoc &); -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - LLVM_DUMP_METHOD void dump() const { - for (DbgValueLocEntry DV : ValueLocEntries) - DV.dump(); if (Expression) Expression->dump(); } @@ -239,32 +180,30 @@ public: DwarfCompileUnit &TheCU); }; -/// Compare two DbgValueLocEntries for equality. -inline bool operator==(const DbgValueLocEntry &A, const DbgValueLocEntry &B) { +/// Compare two DbgValueLocs for equality. +inline bool operator==(const DbgValueLoc &A, + const DbgValueLoc &B) { if (A.EntryKind != B.EntryKind) return false; + if (A.Expression != B.Expression) + return false; + switch (A.EntryKind) { - case DbgValueLocEntry::E_Location: + case DbgValueLoc::E_Location: return A.Loc == B.Loc; - case DbgValueLocEntry::E_TargetIndexLocation: + case DbgValueLoc::E_TargetIndexLocation: return A.TIL == B.TIL; - case DbgValueLocEntry::E_Integer: + case DbgValueLoc::E_Integer: return A.Constant.Int == B.Constant.Int; - case DbgValueLocEntry::E_ConstantFP: + case DbgValueLoc::E_ConstantFP: return A.Constant.CFP == B.Constant.CFP; - case DbgValueLocEntry::E_ConstantInt: + case DbgValueLoc::E_ConstantInt: return A.Constant.CIP == B.Constant.CIP; } llvm_unreachable("unhandled EntryKind"); } -/// Compare two DbgValueLocs for equality. -inline bool operator==(const DbgValueLoc &A, const DbgValueLoc &B) { - return A.ValueLocEntries == B.ValueLocEntries && - A.Expression == B.Expression && A.IsVariadic == B.IsVariadic; -} - /// Compare two fragments based on their offset. inline bool operator<(const DbgValueLoc &A, const DbgValueLoc &B) { diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index cba36ab..3d378df 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -728,95 +728,36 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV, // Check if variable has a single location description. if (auto *DVal = DV.getValueLoc()) { - if (!DVal->isVariadic()) { - const DbgValueLocEntry *Entry = DVal->getLocEntries().begin(); - if (Entry->isLocation()) { - addVariableAddress(DV, *VariableDie, Entry->getLoc()); - } else if (Entry->isInt()) { - auto *Expr = DV.getSingleExpression(); - if (Expr && Expr->getNumElements()) { - DIELoc *Loc = new (DIEValueAllocator) DIELoc; - DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); - // If there is an expression, emit raw unsigned bytes. - DwarfExpr.addFragmentOffset(Expr); - DwarfExpr.addUnsignedConstant(Entry->getInt()); - DwarfExpr.addExpression(Expr); - addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize()); - if (DwarfExpr.TagOffset) - addUInt(*VariableDie, dwarf::DW_AT_LLVM_tag_offset, - dwarf::DW_FORM_data1, *DwarfExpr.TagOffset); - } else - addConstantValue(*VariableDie, Entry->getInt(), DV.getType()); - } else if (Entry->isConstantFP()) { - addConstantFPValue(*VariableDie, Entry->getConstantFP()); - } else if (Entry->isConstantInt()) { - addConstantValue(*VariableDie, Entry->getConstantInt(), DV.getType()); - } else if (Entry->isTargetIndexLocation()) { + if (DVal->isLocation()) + addVariableAddress(DV, *VariableDie, DVal->getLoc()); + else if (DVal->isInt()) { + auto *Expr = DV.getSingleExpression(); + if (Expr && Expr->getNumElements()) { DIELoc *Loc = new (DIEValueAllocator) DIELoc; DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); - const DIBasicType *BT = dyn_cast( - static_cast(DV.getVariable()->getType())); - DwarfDebug::emitDebugLocValue(*Asm, BT, *DVal, DwarfExpr); + // If there is an expression, emit raw unsigned bytes. + DwarfExpr.addFragmentOffset(Expr); + DwarfExpr.addUnsignedConstant(DVal->getInt()); + DwarfExpr.addExpression(Expr); addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize()); - } - return VariableDie; + if (DwarfExpr.TagOffset) + addUInt(*VariableDie, dwarf::DW_AT_LLVM_tag_offset, + dwarf::DW_FORM_data1, *DwarfExpr.TagOffset); + + } else + addConstantValue(*VariableDie, DVal->getInt(), DV.getType()); + } else if (DVal->isConstantFP()) { + addConstantFPValue(*VariableDie, DVal->getConstantFP()); + } else if (DVal->isConstantInt()) { + addConstantValue(*VariableDie, DVal->getConstantInt(), DV.getType()); + } else if (DVal->isTargetIndexLocation()) { + DIELoc *Loc = new (DIEValueAllocator) DIELoc; + DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); + const DIBasicType *BT = dyn_cast( + static_cast(DV.getVariable()->getType())); + DwarfDebug::emitDebugLocValue(*Asm, BT, *DVal, DwarfExpr); + addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize()); } - // If any of the location entries are registers with the value 0, then the - // location is undefined. - if (any_of(DVal->getLocEntries(), [](const DbgValueLocEntry &Entry) { - return Entry.isLocation() && !Entry.getLoc().getReg(); - })) - return VariableDie; - const DIExpression *Expr = DV.getSingleExpression(); - assert(Expr && "Variadic Debug Value must have an Expression."); - DIELoc *Loc = new (DIEValueAllocator) DIELoc; - DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); - DwarfExpr.addFragmentOffset(Expr); - DIExpressionCursor Cursor(Expr); - const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo(); - - // Declare the TargetMachine locally so we don't need to capture `this` in - // the lambda. - TargetMachine &TM = Asm->TM; - auto AddEntry = [&DwarfExpr, &TRI, &TM](const DbgValueLocEntry &Entry, - DIExpressionCursor &Cursor) { - if (Entry.isLocation()) { - if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, - Entry.getLoc().getReg())) - return false; - } else if (Entry.isInt()) { - // If there is an expression, emit raw unsigned bytes. - DwarfExpr.addUnsignedConstant(Entry.getInt()); - } else if (Entry.isConstantFP()) { - APInt RawBytes = Entry.getConstantFP()->getValueAPF().bitcastToAPInt(); - DwarfExpr.addUnsignedConstant(RawBytes); - } else if (Entry.isConstantInt()) { - APInt RawBytes = Entry.getConstantInt()->getValue(); - DwarfExpr.addUnsignedConstant(RawBytes); - } else if (Entry.isTargetIndexLocation()) { - TargetIndexLocation Loc = Entry.getTargetIndexLocation(); - // TODO TargetIndexLocation is a target-independent. Currently only the - // WebAssembly-specific encoding is supported. - assert(TM.getTargetTriple().isWasm()); - DwarfExpr.addWasmLocation(Loc.Index, static_cast(Loc.Offset)); - } else { - llvm_unreachable("Unsupported Entry type."); - } - return true; - }; - - DwarfExpr.addExpression( - std::move(Cursor), - [&AddEntry, &DVal](unsigned Idx, DIExpressionCursor &Cursor) -> bool { - return AddEntry(DVal->getLocEntries()[Idx], Cursor); - }); - - // Now attach the location information to the DIE. - addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize()); - if (DwarfExpr.TagOffset) - addUInt(*VariableDie, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1, - *DwarfExpr.TagOffset); - return VariableDie; } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 9e20527..beed2a5 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -235,27 +235,29 @@ 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(); - const bool IsVariadic = MI->isDebugValueList(); - assert(MI->getNumOperands() >= 3); - SmallVector 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!"); - } - return DbgValueLoc(Expr, DbgValueLocEntries, IsVariadic); + 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())); + } + 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!"); } void DbgVariable::initializeDbgValue(const MachineInstr *DbgValue) { @@ -643,7 +645,7 @@ static void finishCallSiteParams(ValT Val, const DIExpression *Expr, assert((!CombinedExpr || CombinedExpr->isValid()) && "Combined debug expression is invalid"); - DbgValueLoc DbgLocVal(CombinedExpr, DbgValueLocEntry(Val)); + DbgValueLoc DbgLocVal(CombinedExpr, Val); DbgCallSiteParam CSParm(Param.ParamReg, DbgLocVal); Params.push_back(CSParm); ++NumCSParams; @@ -1611,9 +1613,7 @@ 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 (MBB->pred_empty() && - all_of(DbgValue->debug_operands(), - [](const MachineOperand &Op) { return Op.isImm(); })) + if (DbgValue->getDebugOperand(0).isImm() && MBB->pred_empty()) return true; // Test if the location terminates before the end of the scope. @@ -2486,95 +2486,51 @@ void DwarfDebug::emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, auto *DIExpr = Value.getExpression(); DIExpressionCursor ExprCursor(DIExpr); DwarfExpr.addFragmentOffset(DIExpr); - - // 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(); + // 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(); DwarfExpr.setLocation(Location, DIExpr); + DIExpressionCursor Cursor(DIExpr); - DwarfExpr.beginEntryValueExpression(ExprCursor); + if (DIExpr->isEntryValue()) + DwarfExpr.beginEntryValueExpression(Cursor); const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo(); - 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(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; - } - } else { - llvm_unreachable("Invalid Entry for a DW_AT_location expression."); - } - return true; - }; - - if (!Value.isVariadic()) { - if (!EmitValueLocEntry(Value.getLocEntries()[0], ExprCursor)) + 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(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); + return; + } + 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"); } - - // 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); - }); + DwarfExpr.addExpression(std::move(ExprCursor)); } void DebugLocEntry::finalize(const AsmPrinter &AP, diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp index 8dc2601..ef61e2e 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -302,12 +302,6 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI, } DwarfRegs.clear(); - // If we need to mask out a subregister, do it now, unless the next - // operation would emit an OpPiece anyway. - auto NextOp = ExprCursor.peek(); - if (SubRegisterSizeInBits && NextOp && - (NextOp->getOp() != dwarf::DW_OP_LLVM_fragment)) - maskSubRegister(); return true; } @@ -360,14 +354,6 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI, else addBReg(Reg.DwarfRegNo, SignedOffset); DwarfRegs.clear(); - - // If we need to mask out a subregister, do it now, unless the next - // operation would emit an OpPiece anyway. - auto NextOp = ExprCursor.peek(); - if (SubRegisterSizeInBits && NextOp && - (NextOp->getOp() != dwarf::DW_OP_LLVM_fragment)) - maskSubRegister(); - return true; } @@ -465,19 +451,16 @@ static bool isMemoryLocation(DIExpressionCursor ExprCursor) { void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, unsigned FragmentOffsetInBits) { - addExpression(std::move(ExprCursor), - [](unsigned Idx, DIExpressionCursor &Cursor) -> bool { - llvm_unreachable("unhandled opcode found in expression"); - }); -} - -void DwarfExpression::addExpression( - DIExpressionCursor &&ExprCursor, - std::function InsertArg) { // Entry values can currently only cover the initial register location, // and not any other parts of the following DWARF expression. assert(!IsEmittingEntryValue && "Can't emit entry value around expression"); + // If we need to mask out a subregister, do it now, unless the next + // operation would emit an OpPiece anyway. + auto N = ExprCursor.peek(); + if (SubRegisterSizeInBits && N && (N->getOp() != dwarf::DW_OP_LLVM_fragment)) + maskSubRegister(); + Optional PrevConvertOp = None; while (ExprCursor) { @@ -493,12 +476,6 @@ void DwarfExpression::addExpression( } switch (OpNum) { - case dwarf::DW_OP_LLVM_arg: - if (!InsertArg(Op->getArg(0), ExprCursor)) { - LocationKind = Unknown; - return; - } - break; case dwarf::DW_OP_LLVM_fragment: { unsigned SizeInBits = Op->getArg(1); unsigned FragmentOffset = Op->getArg(0); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h index 2e5edf1..0d55144 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -347,9 +347,6 @@ public: /// fragment inside the entire variable. void addExpression(DIExpressionCursor &&Expr, unsigned FragmentOffsetInBits = 0); - void - addExpression(DIExpressionCursor &&Expr, - std::function InsertArg); /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to /// the fragment described by \c Expr. diff --git a/llvm/test/DebugInfo/X86/dbg_value_list_clobbers.mir b/llvm/test/DebugInfo/X86/dbg_value_list_clobbers.mir deleted file mode 100644 index 601067a..0000000 --- a/llvm/test/DebugInfo/X86/dbg_value_list_clobbers.mir +++ /dev/null @@ -1,84 +0,0 @@ -# RUN: llc %s --start-after=livedebugvalues -filetype=obj -o - \ -# RUN: | llvm-dwarfdump - -name locala -o - | FileCheck %s -# -# Test that clobbers between DBG_VALUE_LIST and DBG_VALUE instructions work as -# expected. Comments and test directives inline. - ---- | - target triple = "x86_64-unknown-linux-gnu" - define dso_local i32 @fun() local_unnamed_addr !dbg !7 { - entry: - ret i32 0 - } - - !llvm.dbg.cu = !{!0} - !llvm.module.flags = !{!3, !4, !5} - !llvm.ident = !{!6} - - !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 11.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) - !1 = !DIFile(filename: "example.c", directory: "/") - !2 = !{} - !3 = !{i32 7, !"Dwarf Version", i32 4} - !4 = !{i32 2, !"Debug Info Version", i32 3} - !5 = !{i32 1, !"wchar_size", i32 4} - !6 = !{!"clang version 11.0.0"} - !8 = !DISubroutineType(types: !9) - !9 = !{!10} - !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) - !11 = !{!12} - !22 = !DISubroutineType(types: !23) - !23 = !{!10, !10} - ; --- Important metadata --- - !7 = distinct !DISubprogram(name: "fun", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) - !15 = !DILocation(line: 1, column: 1, scope: !7) - !12 = !DILocalVariable(name: "locala", scope: !7, file: !1, line: 1, type: !10) - -... ---- -name: fun -body: | - bb.0.entry: - ; This test checks that we see expected location ranges for a single variable. - ; CHECK: {{.*}} DW_TAG_variable - ; CHECK-NEXT: DW_AT_location {{.*}} - - DBG_VALUE_LIST !12, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_stack_value), $eax, debug-location !15 - ; CHECK-NEXT: [{{.*}}): DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_stack_value - - $edi = MOV32ri 1 - DBG_VALUE_LIST !12, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_stack_value), $esi, debug-location !15 - ; CHECK-NEXT: [{{.*}}): DW_OP_breg4 RSI+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_stack_value - - $eax = MOV32ri 2 - DBG_VALUE $eax, $noreg, !12, !DIExpression(), debug-location !15 - ; CHECK-NEXT: [{{.*}}): DW_OP_reg0 RAX - - $ecx = MOV32ri 3 - DBG_VALUE_LIST !12, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_stack_value), $eax, $ecx, debug-location !15 - ; CHECK-NEXT: [{{.*}}): DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_breg2 RCX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_plus, DW_OP_stack_value - - ; Check that a reg clobber prevents identical locations merging. - $ecx = MOV32ri 4 - $ecx = MOV32ri 5 - DBG_VALUE_LIST !12, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_stack_value), $eax, $ecx, debug-location !15 - ; CHECK-NEXT: [{{.*}}): DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_breg2 RCX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_plus, DW_OP_stack_value - - ; Check that fragments are composed correctly. - $ecx = MOV32ri 6 - DBG_VALUE_LIST !12, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 16), $eax, debug-location !15 - DBG_VALUE_LIST !12, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_stack_value, DW_OP_LLVM_fragment, 16, 16), $ecx, debug-location !15 - ; CHECK-NEXT: [{{.*}}): DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_stack_value, DW_OP_piece 0x2, DW_OP_breg2 RCX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_stack_value, DW_OP_piece 0x2 - - ; Check that fragments clobber preceeding overlap. - $edi = MOV32ri 7 - DBG_VALUE_LIST !12, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_stack_value, DW_OP_LLVM_fragment, 16, 16), $edi, debug-location !15 - ; CHECK-NEXT: [{{.*}}): DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_stack_value, DW_OP_piece 0x2, DW_OP_breg5 RDI+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_stack_value, DW_OP_piece 0x2 - - ; Check that a (non-zero-offset) fragment works. - $ecx = MOV32ri 8 - $ecx = MOV32ri 9 - DBG_VALUE_LIST !12, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_stack_value, DW_OP_LLVM_fragment, 16, 16), $eax, $ecx, debug-location !15 - ; CHECK-NEXT: [{{.*}}): DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_stack_value, DW_OP_piece 0x2, DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_breg2 RCX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_plus, DW_OP_stack_value, DW_OP_piece 0x2 - - RETQ debug-location !15 -... diff --git a/llvm/test/DebugInfo/X86/dbg_value_list_emission.mir b/llvm/test/DebugInfo/X86/dbg_value_list_emission.mir deleted file mode 100644 index e3380cb..0000000 --- a/llvm/test/DebugInfo/X86/dbg_value_list_emission.mir +++ /dev/null @@ -1,101 +0,0 @@ -# RUN: llc %s --start-after=livedebugvalues -filetype=obj -o - \ -# RUN: | llvm-dwarfdump - -name local* -regex \ -# RUN: | FileCheck %s -# -# Test that we produce correct DWARF from DBG_VALUE_LIST instructions. -# Comments and test directives inline. - ---- | - target triple = "x86_64-unknown-linux-gnu" - define dso_local i32 @fun() local_unnamed_addr !dbg !7 { - entry: - ret i32 0 - } - - !llvm.dbg.cu = !{!0} - !llvm.module.flags = !{!3, !4, !5} - !llvm.ident = !{!6} - - !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 11.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) - !1 = !DIFile(filename: "example.c", directory: "/") - !2 = !{} - !3 = !{i32 7, !"Dwarf Version", i32 4} - !4 = !{i32 2, !"Debug Info Version", i32 3} - !5 = !{i32 1, !"wchar_size", i32 4} - !6 = !{!"clang version 11.0.0"} - !8 = !DISubroutineType(types: !9) - !9 = !{!10} - !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) - !11 = !{!12, !13, !25} - !22 = !DISubroutineType(types: !23) - !23 = !{!10, !10} - ; --- Important metadata --- - !7 = distinct !DISubprogram(name: "fun", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) - !15 = !DILocation(line: 1, column: 1, scope: !7) - !12 = !DILocalVariable(name: "locala", scope: !7, file: !1, line: 1, type: !10) - !13 = !DILocalVariable(name: "localb", scope: !7, file: !1, line: 2, type: !10) - !25 = !DILocalVariable(name: "localc", scope: !7, file: !1, line: 3, type: !10) - !26 = !DILocalVariable(name: "locald", scope: !7, file: !1, line: 4, type: !10) - !27 = !DILocalVariable(name: "locale", scope: !7, file: !1, line: 5, type: !10) - !28 = !DILocalVariable(name: "localf", scope: !7, file: !1, line: 6, type: !10) - !29 = !DILocalVariable(name: "localg", scope: !7, file: !1, line: 6, type: !10) - !30 = !DILocalVariable(name: "localh", scope: !7, file: !1, line: 6, type: !10) - -... ---- -name: fun -body: | - bb.0.entry: - ; NOTE: By design, all DBG_VALUE_LIST instructions describe stack_value - ; locations, so they are always created with a DW_OP_stack_value op. - ; - ; (1) Check a single reg arg works. - DBG_VALUE_LIST !12, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_stack_value), $eax, debug-location !15 - ; CHECK: DW_TAG_variable - ; CHECK-NEXT: (DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_stack_value) - ; CHECK-NEXT: DW_AT_name ("locala") - - ; (2) Check multiple reg args work. - DBG_VALUE_LIST !13, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_stack_value), $eax, $edi, debug-location !15 - ; CHECK: DW_TAG_variable - ; CHECK-NEXT: (DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_breg5 RDI+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_plus, DW_OP_stack_value) - ; CHECK-NEXT: DW_AT_name ("localb") - - ; (3) Check that multiple references to one reg arg works. - DBG_VALUE_LIST !25, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 0, DW_OP_minus, DW_OP_stack_value), $eax, debug-location !15 - ; CHECK: DW_TAG_variable - ; CHECK-NEXT: (DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_minus, DW_OP_stack_value) - ; CHECK-NEXT: DW_AT_name ("localc") - - ; (4) Check constant and reg args work together. - DBG_VALUE_LIST !26, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_mul, DW_OP_stack_value), $eax, 5, debug-location !15 - ; CHECK: DW_TAG_variable - ; CHECK-NEXT: (DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_lit5, DW_OP_mul, DW_OP_stack_value) - ; CHECK-NEXT: DW_AT_name ("locald") - - ; (5) Check that arg deref works. - DBG_VALUE_LIST !27, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_deref, DW_OP_stack_value), $eax, debug-location !15 - ; CHECK: DW_TAG_variable - ; CHECK-NEXT: (DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_deref, DW_OP_stack_value) - ; CHECK-NEXT: DW_AT_name ("locale") - - ; (6) Check that fragments work. - DBG_VALUE_LIST !28, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 16), $eax, debug-location !15 - ; CHECK: DW_TAG_variable - ; CHECK-NEXT: (DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_stack_value, DW_OP_piece 0x2) - ; CHECK-NEXT: DW_AT_name ("localf") - - ; (7) Check that constant register offsets are correctly folded. - DBG_VALUE_LIST !29, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_plus_uconst, 5, DW_OP_LLVM_arg, 1, DW_OP_plus_uconst, 17, DW_OP_plus, DW_OP_stack_value), $eax, $edi, debug-location !15 - ; CHECK: DW_TAG_variable - ; CHECK-NEXT: (DW_OP_breg0 RAX+5, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_breg5 RDI+17, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_plus, DW_OP_stack_value) - ; CHECK-NEXT: DW_AT_name ("localg") - - ; (8) Check that a single $noreg location invalidates the entire entry. - DBG_VALUE_LIST !30, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_stack_value), $eax, $noreg, debug-location !15 - ; CHECK: DW_TAG_variable - ; CHECK-NEXT: DW_AT_name ("localh") - ; CHECK-NOT: DW_AT_location - - RETQ debug-location !15 -...