From 8ec4db5e17f654670cd0d5e43e3a57a9b39b4f9d Mon Sep 17 00:00:00 2001 From: Abdullah Mohammad Amin <67847674+UltimateForce21@users.noreply.github.com> Date: Thu, 28 Aug 2025 13:41:38 -0400 Subject: [PATCH] Stateful variable-location annotations in Disassembler::PrintInstructions() (follow-up to #147460) (#152887) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Context** Follow-up to [#147460](https://github.com/llvm/llvm-project/pull/147460), which added the ability to surface register-resident variable locations. This PR moves the annotation logic out of `Instruction::Dump()` and into `Disassembler::PrintInstructions()`, and adds lightweight state tracking so we only print changes at range starts and when variables go out of scope. --- ## What this does While iterating the instructions for a function, we maintain a “live variable map” keyed by `lldb::user_id_t` (the `Variable`’s ID) to remember each variable’s last emitted location string. For each instruction: - **New (or newly visible) variable** → print `name = ` once at the start of its DWARF location range, cache it. - **Location changed** (e.g., DWARF range switched to a different register/const) → print the updated mapping. - **Out of scope** (was tracked previously but not found for the current PC) → print `name = ` and drop it. This produces **concise, stateful annotations** that highlight variable lifetime transitions without spamming every line. --- ## Why in `PrintInstructions()`? - Keeps `Instruction` stateless and avoids changing the `Instruction::Dump()` virtual API. - Makes it straightforward to diff state across instructions (`prev → current`) inside the single driver loop. --- ## How it works (high-level) 1. For the current PC, get in-scope variables via `StackFrame::GetInScopeVariableList(/*get_parent=*/true)`. 2. For each `Variable`, query `DWARFExpressionList::GetExpressionEntryAtAddress(func_load_addr, current_pc)` (added in #144238). 3. If the entry exists, call `DumpLocation(..., eDescriptionLevelBrief, abi)` to get a short, ABI-aware location string (e.g., `DW_OP_reg3 RBX → RBX`). 4. Compare against the last emitted location in the live map: - If not present → emit `name = ` and record it. - If different → emit updated mapping and record it. 5. After processing current in-scope variables, compute the set difference vs. the previous map and emit `name = ` for any that disappeared. Internally: - We respect file↔load address translation already provided by `DWARFExpressionList`. - We reuse the ABI to map LLVM register numbers to arch register names. --- ## Example output (x86_64, simplified) ``` -> 0x55c6f5f6a140 <+0>: cmpl $0x2, %edi ; argc = RDI, argv = RSI 0x55c6f5f6a143 <+3>: jl 0x55c6f5f6a176 ; <+54> at d_original_example.c:6:3 0x55c6f5f6a145 <+5>: pushq %r15 0x55c6f5f6a147 <+7>: pushq %r14 0x55c6f5f6a149 <+9>: pushq %rbx 0x55c6f5f6a14a <+10>: movq %rsi, %rbx 0x55c6f5f6a14d <+13>: movl %edi, %r14d 0x55c6f5f6a150 <+16>: movl $0x1, %r15d ; argc = R14 0x55c6f5f6a156 <+22>: nopw %cs:(%rax,%rax) ; i = R15, argv = RBX 0x55c6f5f6a160 <+32>: movq (%rbx,%r15,8), %rdi 0x55c6f5f6a164 <+36>: callq 0x55c6f5f6a030 ; symbol stub for: puts 0x55c6f5f6a169 <+41>: incq %r15 0x55c6f5f6a16c <+44>: cmpq %r15, %r14 0x55c6f5f6a16f <+47>: jne 0x55c6f5f6a160 ; <+32> at d_original_example.c:5:10 0x55c6f5f6a171 <+49>: popq %rbx ; i = 0x55c6f5f6a172 <+50>: popq %r14 ; argv = RSI 0x55c6f5f6a174 <+52>: popq %r15 ; argc = RDI 0x55c6f5f6a176 <+54>: xorl %eax, %eax 0x55c6f5f6a178 <+56>: retq ``` Only transitions are shown: the start of a location, changes, and end-of-lifetime. --- ## Scope & limitations (by design) - Handles **simple locations** first (registers, const-in-register cases surfaced by `DumpLocation`). - **Memory/composite locations** are out of scope for this PR. - Annotations appear **only at range boundaries** (start/change/end) to minimize noise. - Output is **target-independent**; register names come from the target ABI. ## Implementation notes - All annotation printing now happens in `Disassembler::PrintInstructions()`. - Uses `std::unordered_map` as the live map. - No persistent state across calls; the map is rebuilt while walking instruction by instruction. - **No changes** to the `Instruction` interface. --- ## Requested feedback - Placement and wording of the `` marker. - Whether we should optionally gate this behind a setting (currently always on when disassembling with an `ExecutionContext`). - Preference for immediate inclusion of tests vs. follow-up patch. --- Thanks for reviewing! Happy to adjust behavior/format based on feedback. --------- Co-authored-by: Jonas Devlieghere Co-authored-by: Adrian Prantl --- lldb/include/lldb/Core/Disassembler.h | 18 +- .../include/lldb/Expression/DWARFExpression.h | 3 +- .../Commands/CommandObjectDisassemble.cpp | 8 + .../Commands/CommandObjectDisassemble.h | 1 + lldb/source/Commands/Options.td | 2 + lldb/source/Core/Disassembler.cpp | 175 +++++- lldb/source/Expression/DWARFExpression.cpp | 8 +- lldb/source/Target/StackFrame.cpp | 26 +- .../disassembler-variables/Makefile | 32 + .../TestVariableAnnotationsDisassembler.py | 108 ++++ .../d_original_example.s | 461 +++++++++++++++ .../disassembler-variables/live_across_call.s | 371 ++++++++++++ .../disassembler-variables/loop_reg_rotate.s | 557 ++++++++++++++++++ .../disassembler-variables/regs_fp_params.s | 304 ++++++++++ .../disassembler-variables/regs_int_params.s | 312 ++++++++++ .../regs_mixed_params.s | 375 ++++++++++++ .../seed_reg_const_undef.s | 289 +++++++++ llvm/include/llvm/DebugInfo/DIContext.h | 1 + .../DWARF/DWARFExpressionPrinter.cpp | 163 +++-- 19 files changed, 3119 insertions(+), 95 deletions(-) create mode 100644 lldb/test/API/functionalities/disassembler-variables/Makefile create mode 100644 lldb/test/API/functionalities/disassembler-variables/TestVariableAnnotationsDisassembler.py create mode 100644 lldb/test/API/functionalities/disassembler-variables/d_original_example.s create mode 100644 lldb/test/API/functionalities/disassembler-variables/live_across_call.s create mode 100644 lldb/test/API/functionalities/disassembler-variables/loop_reg_rotate.s create mode 100644 lldb/test/API/functionalities/disassembler-variables/regs_fp_params.s create mode 100644 lldb/test/API/functionalities/disassembler-variables/regs_int_params.s create mode 100644 lldb/test/API/functionalities/disassembler-variables/regs_mixed_params.s create mode 100644 lldb/test/API/functionalities/disassembler-variables/seed_reg_const_undef.s diff --git a/lldb/include/lldb/Core/Disassembler.h b/lldb/include/lldb/Core/Disassembler.h index 50a5d8783584..6a21470b2472 100644 --- a/lldb/include/lldb/Core/Disassembler.h +++ b/lldb/include/lldb/Core/Disassembler.h @@ -169,7 +169,7 @@ public: virtual bool IsAuthenticated() = 0; - bool CanSetBreakpoint (); + bool CanSetBreakpoint(); virtual size_t Decode(const Disassembler &disassembler, const DataExtractor &data, @@ -282,7 +282,7 @@ std::function FetchImmOp(int64_t &imm); std::function MatchOpType(Instruction::Operand::Type type); -} +} // namespace OperandMatchers class InstructionList { public: @@ -316,20 +316,19 @@ public: /// @param[in] ignore_calls /// It true, then fine the first branch instruction that isn't /// a function call (a branch that calls and returns to the next - /// instruction). If false, find the instruction index of any + /// instruction). If false, find the instruction index of any /// branch in the list. - /// + /// /// @param[out] found_calls - /// If non-null, this will be set to true if any calls were found in + /// If non-null, this will be set to true if any calls were found in /// extending the range. - /// + /// /// @return /// The instruction index of the first branch that is at or past - /// \a start. Returns UINT32_MAX if no matching branches are + /// \a start. Returns UINT32_MAX if no matching branches are /// found. //------------------------------------------------------------------ - uint32_t GetIndexOfNextBranchInstruction(uint32_t start, - bool ignore_calls, + uint32_t GetIndexOfNextBranchInstruction(uint32_t start, bool ignore_calls, bool *found_calls) const; uint32_t GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr, @@ -399,6 +398,7 @@ public: eOptionMarkPCAddress = (1u << 3), // Mark the disassembly line the contains the PC eOptionShowControlFlowKind = (1u << 4), + eOptionVariableAnnotations = (1u << 5), }; enum HexImmediateStyle { diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h index 8fcc5d37b91c..1f8464cf5cf8 100644 --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -159,7 +159,8 @@ public: return data.GetByteSize() > 0; } - void DumpLocation(Stream *s, lldb::DescriptionLevel level, ABI *abi) const; + void DumpLocation(Stream *s, lldb::DescriptionLevel level, ABI *abi, + llvm::DIDumpOptions options = {}) const; bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op) const; diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp index f8e4ff9f08b6..c0553d2c6c8b 100644 --- a/lldb/source/Commands/CommandObjectDisassemble.cpp +++ b/lldb/source/Commands/CommandObjectDisassemble.cpp @@ -154,6 +154,10 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue( } } break; + case 'v': + enable_variable_annotations = true; + break; + case '\x01': force = true; break; @@ -180,6 +184,7 @@ void CommandObjectDisassemble::CommandOptions::OptionParsingStarting( end_addr = LLDB_INVALID_ADDRESS; symbol_containing_addr = LLDB_INVALID_ADDRESS; raw = false; + enable_variable_annotations = false; plugin_name.clear(); Target *target = @@ -529,6 +534,9 @@ void CommandObjectDisassemble::DoExecute(Args &command, if (m_options.raw) options |= Disassembler::eOptionRawOuput; + if (m_options.enable_variable_annotations) + options |= Disassembler::eOptionVariableAnnotations; + llvm::Expected> ranges = GetRangesForSelectedMode(result); if (!ranges) { diff --git a/lldb/source/Commands/CommandObjectDisassemble.h b/lldb/source/Commands/CommandObjectDisassemble.h index 4fbcd72d1c04..eed44adce5ff 100644 --- a/lldb/source/Commands/CommandObjectDisassemble.h +++ b/lldb/source/Commands/CommandObjectDisassemble.h @@ -78,6 +78,7 @@ public: // in SetOptionValue if anything the selects a location is set. lldb::addr_t symbol_containing_addr = 0; bool force = false; + bool enable_variable_annotations = false; }; CommandObjectDisassemble(CommandInterpreter &interpreter); diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index 7bdd6cfcfcc9..3dbf65b0c02f 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -366,6 +366,8 @@ let Command = "disassemble" in { Desc<"Disassemble function containing this address.">; def disassemble_options_force : Option<"force", "\\x01">, Groups<[2,3,4,5,7]>, Desc<"Force disassembly of large functions.">; + def disassemble_options_variable : Option<"variable", "v">, + Desc<"Enable variable disassembly annotations for this invocation.">; } let Command = "diagnostics dump" in { diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index e0a7d6934570..9b0b604d6caa 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -26,7 +26,11 @@ #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/Variable.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/ABI.h" #include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" @@ -41,6 +45,8 @@ #include "lldb/lldb-private-enumerations.h" #include "lldb/lldb-private-interfaces.h" #include "lldb/lldb-private-types.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/TargetParser/Triple.h" @@ -376,6 +382,147 @@ void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch, } } + // Add variable location annotations to the disassembly output. + // + // For each instruction, this block attempts to resolve in-scope variables + // and determine if the current PC falls within their + // DWARF location entry. If so, it prints a simplified annotation using the + // variable name and its resolved location (e.g., "var = reg; " ). + // + // Annotations are only included if the variable has a valid DWARF location + // entry, and the location string is non-empty after filtering. Decoding + // errors and DWARF opcodes are intentionally omitted to keep the output + // concise and user-friendly. + // + // The goal is to give users helpful live variable hints alongside the + // disassembled instruction stream, similar to how debug information + // enhances source-level debugging. + + struct VarState { + std::string name; ///< Display name. + std::string last_loc; ///< Last printed location (empty means ). + bool seen_this_inst = false; + }; + + // Track live variables across instructions. + llvm::DenseMap live_vars; + + // Stateful annotator: updates live_vars and returns only what should be + // printed for THIS instruction. + auto annotate_static = [&](Instruction &inst, Target &target, + ModuleSP module_sp) -> std::vector { + std::vector events; + + // Reset per-instruction seen flags. + for (auto &kv : live_vars) + kv.second.seen_this_inst = false; + + const Address &iaddr = inst.GetAddress(); + if (!module_sp) { + // Everything previously live becomes . + for (auto I = live_vars.begin(), E = live_vars.end(); I != E;) { + auto Cur = I++; + events.push_back( + llvm::formatv("{0} = ", Cur->second.name).str()); + live_vars.erase(Cur); + } + return events; + } + + // Resolve innermost block at this *file* address. + SymbolContext sc; + const lldb::SymbolContextItem mask = + eSymbolContextFunction | eSymbolContextBlock; + if (!module_sp->ResolveSymbolContextForAddress(iaddr, mask, sc) || + !sc.function) { + // No function context: everything dies here. + for (auto I = live_vars.begin(), E = live_vars.end(); I != E;) { + auto Cur = I++; + events.push_back( + llvm::formatv("{0} = ", Cur->second.name).str()); + live_vars.erase(Cur); + } + return events; + } + + Block *B = sc.block; ///< Innermost block containing iaddr. + VariableList var_list; + if (B) { + auto filter = [](Variable *v) -> bool { return v && !v->IsArtificial(); }; + + B->AppendVariables(/*can_create*/ true, + /*get_parent_variables*/ true, + /*stop_if_block_is_inlined_function*/ false, + /*filter*/ filter, + /*variable_list*/ &var_list); + } + + const lldb::addr_t pc_file = iaddr.GetFileAddress(); + const lldb::addr_t func_file = sc.function->GetAddress().GetFileAddress(); + + // ABI from Target (pretty reg names if plugin exists). Safe to be null. + lldb::ProcessSP no_process; + lldb::ABISP abi_sp = ABI::FindPlugin(no_process, target.GetArchitecture()); + ABI *abi = abi_sp.get(); + + llvm::DIDumpOptions opts; + opts.ShowAddresses = false; + if (abi) + opts.PrintRegisterOnly = true; + + for (size_t i = 0, e = var_list.GetSize(); i != e; ++i) { + lldb::VariableSP v = var_list.GetVariableAtIndex(i); + if (!v || v->IsArtificial()) + continue; + + const char *nm = v->GetName().AsCString(); + llvm::StringRef name = nm ? nm : ""; + + lldb_private::DWARFExpressionList &exprs = v->LocationExpressionList(); + if (!exprs.IsValid()) + continue; + + auto entry_or_err = exprs.GetExpressionEntryAtAddress(func_file, pc_file); + if (!entry_or_err) + continue; + + auto entry = *entry_or_err; + + StreamString loc_ss; + entry.expr->DumpLocation(&loc_ss, eDescriptionLevelBrief, abi, opts); + llvm::StringRef loc = llvm::StringRef(loc_ss.GetString()).trim(); + if (loc.empty()) + continue; + + auto ins = live_vars.insert( + {v->GetID(), VarState{name.str(), loc.str(), /*seen*/ true}}); + if (ins.second) { + // Newly live. + events.push_back(llvm::formatv("{0} = {1}", name, loc).str()); + } else { + VarState &vs = ins.first->second; + vs.seen_this_inst = true; + if (vs.last_loc != loc) { + vs.last_loc = loc.str(); + events.push_back(llvm::formatv("{0} = {1}", vs.name, loc).str()); + } + } + } + + // Anything previously live that we didn't see a location for at this inst + // is now . + for (auto I = live_vars.begin(), E = live_vars.end(); I != E;) { + auto Cur = I++; + if (!Cur->second.seen_this_inst) { + events.push_back( + llvm::formatv("{0} = ", Cur->second.name).str()); + live_vars.erase(Cur); + } + } + + return events; + }; + previous_symbol = nullptr; SourceLine previous_line; for (size_t i = 0; i < num_instructions_found; ++i) { @@ -540,10 +687,26 @@ void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch, const bool show_bytes = (options & eOptionShowBytes) != 0; const bool show_control_flow_kind = (options & eOptionShowControlFlowKind) != 0; - inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, + + StreamString inst_line; + + inst->Dump(&inst_line, max_opcode_byte_size, true, show_bytes, show_control_flow_kind, &exe_ctx, &sc, &prev_sc, nullptr, address_text_size); + + if ((options & eOptionVariableAnnotations) && target_sp) { + auto annotations = annotate_static(*inst, *target_sp, module_sp); + if (!annotations.empty()) { + const size_t annotation_column = 100; + inst_line.FillLastLineToColumn(annotation_column, ' '); + inst_line.PutCString("; "); + inst_line.PutCString(llvm::join(annotations, ", ")); + } + } + + strm.PutCString(inst_line.GetString()); strm.EOL(); + } else { break; } @@ -724,9 +887,7 @@ bool Instruction::DumpEmulation(const ArchSpec &arch) { return false; } -bool Instruction::CanSetBreakpoint () { - return !HasDelaySlot(); -} +bool Instruction::CanSetBreakpoint() { return !HasDelaySlot(); } bool Instruction::HasDelaySlot() { // Default is false. @@ -1073,10 +1234,8 @@ void InstructionList::Append(lldb::InstructionSP &inst_sp) { m_instructions.push_back(inst_sp); } -uint32_t -InstructionList::GetIndexOfNextBranchInstruction(uint32_t start, - bool ignore_calls, - bool *found_calls) const { +uint32_t InstructionList::GetIndexOfNextBranchInstruction( + uint32_t start, bool ignore_calls, bool *found_calls) const { size_t num_instructions = m_instructions.size(); uint32_t next_branch = UINT32_MAX; diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index ed4e4e4e341a..df56bcf5eb43 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -67,7 +67,8 @@ void DWARFExpression::UpdateValue(uint64_t const_value, } void DWARFExpression::DumpLocation(Stream *s, lldb::DescriptionLevel level, - ABI *abi) const { + ABI *abi, + llvm::DIDumpOptions options) const { auto *MCRegInfo = abi ? &abi->GetMCRegisterInfo() : nullptr; auto GetRegName = [&MCRegInfo](uint64_t DwarfRegNum, bool IsEH) -> llvm::StringRef { @@ -79,10 +80,9 @@ void DWARFExpression::DumpLocation(Stream *s, lldb::DescriptionLevel level, return llvm::StringRef(RegName); return {}; }; - llvm::DIDumpOptions DumpOpts; - DumpOpts.GetNameForDWARFReg = GetRegName; + options.GetNameForDWARFReg = GetRegName; llvm::DWARFExpression E(m_data.GetAsLLVM(), m_data.GetAddressByteSize()); - llvm::printDwarfExpression(&E, s->AsRawOstream(), DumpOpts, nullptr); + llvm::printDwarfExpression(&E, s->AsRawOstream(), options, nullptr); } RegisterKind DWARFExpression::GetRegisterKind() const { return m_reg_kind; } diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 40049d40aa41..f27004c2d134 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -266,6 +266,7 @@ bool StackFrame::ChangePC(addr_t pc) { const char *StackFrame::Disassemble() { std::lock_guard guard(m_mutex); + if (!m_disassembly.Empty()) return m_disassembly.GetData(); @@ -440,10 +441,10 @@ VariableList *StackFrame::GetVariableList(bool get_file_globals, const bool get_child_variables = true; const bool can_create = true; const bool stop_if_child_block_is_inlined_function = true; - frame_block->AppendBlockVariables(can_create, get_child_variables, - stop_if_child_block_is_inlined_function, - [](Variable *v) { return true; }, - m_variable_list_sp.get()); + frame_block->AppendBlockVariables( + can_create, get_child_variables, + stop_if_child_block_is_inlined_function, + [](Variable *v) { return true; }, m_variable_list_sp.get()); } } @@ -1227,10 +1228,12 @@ StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp, VariableList *var_list = GetVariableList(true, nullptr); if (var_list) { // Make sure the variable is a frame variable - const uint32_t var_idx = var_list->FindIndexForVariable(variable_sp.get()); + const uint32_t var_idx = + var_list->FindIndexForVariable(variable_sp.get()); const uint32_t num_variables = var_list->GetSize(); if (var_idx < num_variables) { - valobj_sp = m_variable_list_value_objects.GetValueObjectAtIndex(var_idx); + valobj_sp = + m_variable_list_value_objects.GetValueObjectAtIndex(var_idx); if (!valobj_sp) { if (m_variable_list_value_objects.GetSize() < num_variables) m_variable_list_value_objects.Resize(num_variables); @@ -1764,11 +1767,9 @@ lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg, if (clobbered_reg_matcher(operands[0])) { origin_operand = &operands[1]; - } - else if (clobbered_reg_matcher(operands[1])) { + } else if (clobbered_reg_matcher(operands[1])) { origin_operand = &operands[0]; - } - else { + } else { continue; } @@ -1794,8 +1795,7 @@ lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg, if (!source_path) { continue; } - source_path = - GetValueForDereferincingOffset(frame, source_path, offset); + source_path = GetValueForDereferincingOffset(frame, source_path, offset); } if (source_path) { @@ -1805,7 +1805,7 @@ lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg, return ValueObjectSP(); } -} +} // namespace lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg, int64_t offset) { diff --git a/lldb/test/API/functionalities/disassembler-variables/Makefile b/lldb/test/API/functionalities/disassembler-variables/Makefile new file mode 100644 index 000000000000..3d4bcd22fa65 --- /dev/null +++ b/lldb/test/API/functionalities/disassembler-variables/Makefile @@ -0,0 +1,32 @@ +# List all assembler inputs stable test fixtures. +ASM_SOURCES := \ + d_original_example.s \ + regs_int_params.s \ + regs_fp_params.s \ + regs_mixed_params.s \ + live_across_call.s \ + loop_reg_rotate.s \ + seed_reg_const_undef.s + +ASM_OBJS := $(ASM_SOURCES:.s=.o) + +# Provide a tiny dummy so the harness can link an exe without ASM_OBJS. +C_SOURCES := dummy_main.c + +# Generating the dummy source on demand. +dummy_main.c: + @echo 'int main(void){return 0;}' > $@ + +# Assemble .s → .o using the configured compiler. +%.o: %.s + $(CC) -c -x assembler $< -o $@ + +# Default target: build all .o fixtures and the dummy exe. +.PHONY: all +all: $(ASM_OBJS) $(EXE) + +# Keeping things tidy. +clean:: + $(RM) -f $(ASM_OBJS) dummy_main.c + +include Makefile.rules diff --git a/lldb/test/API/functionalities/disassembler-variables/TestVariableAnnotationsDisassembler.py b/lldb/test/API/functionalities/disassembler-variables/TestVariableAnnotationsDisassembler.py new file mode 100644 index 000000000000..e6f26bf8fd38 --- /dev/null +++ b/lldb/test/API/functionalities/disassembler-variables/TestVariableAnnotationsDisassembler.py @@ -0,0 +1,108 @@ +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldb +import os +import re + + +class TestVariableAnnotationsDisassembler(TestBase): + def _build_obj(self, obj_name: str) -> str: + # Let the Makefile build all .o’s (pattern rule). Then grab the one we need. + self.build() + obj = self.getBuildArtifact(obj_name) + self.assertTrue(os.path.exists(obj), f"missing object: {obj}") + return obj + + def _create_target(self, path): + target = self.dbg.CreateTarget(path) + self.assertTrue(target, f"failed to create target for {path}") + return target + + def _disassemble_verbose_symbol(self, symname): + self.runCmd(f"disassemble -n {symname} -v", check=True) + return self.res.GetOutput() + + def test_d_original_example_O1(self): + obj = self._build_obj("d_original_example.o") + target = self._create_target(obj) + out = self._disassemble_verbose_symbol("main") + print(out) + self.assertIn("argc = ", out) + self.assertIn("argv = ", out) + self.assertIn("i = ", out) + self.assertNotIn("", out) + + @no_debug_info_test + def test_regs_int_params(self): + obj = self._build_obj("regs_int_params.o") + target = self._create_target(obj) + out = self._disassemble_verbose_symbol("regs_int_params") + print(out) + self.assertRegex(out, r"\ba\s*=\s*(DW_OP_reg5\b|RDI\b)") + self.assertRegex(out, r"\bb\s*=\s*(DW_OP_reg4\b|RSI\b)") + self.assertRegex(out, r"\bc\s*=\s*(DW_OP_reg1\b|RDX\b)") + self.assertRegex(out, r"\bd\s*=\s*(DW_OP_reg2\b|RCX\b)") + self.assertRegex(out, r"\be\s*=\s*(DW_OP_reg8\b|R8\b)") + self.assertRegex(out, r"\bf\s*=\s*(DW_OP_reg9\b|R9\b)") + self.assertNotIn("", out) + + @no_debug_info_test + def test_regs_fp_params(self): + obj = self._build_obj("regs_fp_params.o") + target = self._create_target(obj) + out = self._disassemble_verbose_symbol("regs_fp_params") + print(out) + self.assertRegex(out, r"\ba\s*=\s*(DW_OP_reg17\b|XMM0\b)") + self.assertRegex(out, r"\bb\s*=\s*(DW_OP_reg18\b|XMM1\b)") + self.assertRegex(out, r"\bc\s*=\s*(DW_OP_reg19\b|XMM2\b)") + self.assertRegex(out, r"\bd\s*=\s*(DW_OP_reg20\b|XMM3\b)") + self.assertRegex(out, r"\be\s*=\s*(DW_OP_reg21\b|XMM4\b)") + self.assertRegex(out, r"\bf\s*=\s*(DW_OP_reg22\b|XMM5\b)") + self.assertNotIn("", out) + + @no_debug_info_test + def test_regs_mixed_params(self): + obj = self._build_obj("regs_mixed_params.o") + target = self._create_target(obj) + out = self._disassemble_verbose_symbol("regs_mixed_params") + print(out) + self.assertRegex(out, r"\ba\s*=\s*(DW_OP_reg5\b|RDI\b)") + self.assertRegex(out, r"\bb\s*=\s*(DW_OP_reg4\b|RSI\b)") + self.assertRegex(out, r"\bx\s*=\s*(DW_OP_reg17\b|XMM0\b|DW_OP_reg\d+\b)") + self.assertRegex(out, r"\by\s*=\s*(DW_OP_reg18\b|XMM1\b|DW_OP_reg\d+\b)") + self.assertRegex(out, r"\bc\s*=\s*(DW_OP_reg1\b|RDX\b)") + self.assertRegex(out, r"\bz\s*=\s*(DW_OP_reg19\b|XMM2\b|DW_OP_reg\d+\b)") + self.assertNotIn("", out) + + @no_debug_info_test + def test_live_across_call(self): + obj = self._build_obj("live_across_call.o") + target = self._create_target(obj) + out = self._disassemble_verbose_symbol("live_across_call") + print(out) + self.assertRegex(out, r"\bx\s*=\s*(DW_OP_reg5\b|RDI\b)") + self.assertIn("call", out) + self.assertRegex(out, r"\br\s*=\s*(DW_OP_reg0\b|RAX\b|DW_OP_reg\d+\b)") + self.assertNotIn("", out) + + @no_debug_info_test + def test_loop_reg_rotate(self): + obj = self._build_obj("loop_reg_rotate.o") + target = self._create_target(obj) + out = self._disassemble_verbose_symbol("loop_reg_rotate") + print(out) + self.assertRegex(out, r"\bn\s*=\s*(DW_OP_reg\d+\b|R[A-Z0-9]+)") + self.assertRegex(out, r"\bseed\s*=\s*(DW_OP_reg\d+\b|R[A-Z0-9]+)") + self.assertRegex(out, r"\bk\s*=\s*(DW_OP_reg\d+\b|R[A-Z0-9]+)") + self.assertRegex(out, r"\bj\s*=\s*(DW_OP_reg\d+\b|R[A-Z0-9]+)") + self.assertRegex(out, r"\bi\s*=\s*(DW_OP_reg\d+\b|R[A-Z0-9]+)") + self.assertNotIn("", out) + + @no_debug_info_test + def test_seed_reg_const_undef(self): + obj = self._build_obj("seed_reg_const_undef.o") + target = self._create_target(obj) + out = self._disassemble_verbose_symbol("main") + print(out) + self.assertRegex(out, r"\b(i|argc)\s*=\s*(DW_OP_reg\d+\b|R[A-Z0-9]+)") + self.assertNotIn("", out) diff --git a/lldb/test/API/functionalities/disassembler-variables/d_original_example.s b/lldb/test/API/functionalities/disassembler-variables/d_original_example.s new file mode 100644 index 000000000000..c38742cfc683 --- /dev/null +++ b/lldb/test/API/functionalities/disassembler-variables/d_original_example.s @@ -0,0 +1,461 @@ +/* Original C (for context): +* #include +* +* int main(int argc, char **argv) { +* for (int i = 1; i < argc; ++i) +* puts(argv[i]); +* return 0; +* } +*/ + .file "d_original_example.c" + .text + .globl main # -- Begin function main + .p2align 4 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 0 "." "d_original_example.c" md5 0x25192a1d5a6018cf37d369f9004fab00 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: main:argc <- $edi + #DEBUG_VALUE: main:argv <- $rsi + #DEBUG_VALUE: i <- 1 + .loc 0 4 21 prologue_end # d_original_example.c:4:21 + cmpl $2, %edi +.Ltmp0: + .loc 0 4 3 is_stmt 0 # d_original_example.c:4:3 + jl .LBB0_4 +.Ltmp1: +# %bb.1: # %for.body.preheader + #DEBUG_VALUE: main:argc <- $edi + #DEBUG_VALUE: main:argv <- $rsi + #DEBUG_VALUE: i <- 1 + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + pushq %r15 + pushq %r14 + pushq %rbx + pushq %rax + .cfi_offset %rbx, -40 + .cfi_offset %r14, -32 + .cfi_offset %r15, -24 + movq %rsi, %rbx +.Ltmp2: + .loc 0 4 21 # d_original_example.c:4:21 + movl %edi, %r14d +.Ltmp3: + #DEBUG_VALUE: main:argc <- $r14d + .loc 0 0 21 # d_original_example.c:0:21 + movl $1, %r15d +.Ltmp4: + .p2align 4 +.LBB0_2: # %for.body + # =>This Inner Loop Header: Depth=1 + #DEBUG_VALUE: main:argc <- $r14d + #DEBUG_VALUE: main:argv <- $rbx + #DEBUG_VALUE: i <- $r15 + .loc 0 5 10 is_stmt 1 # d_original_example.c:5:10 + movq (%rbx,%r15,8), %rdi + .loc 0 5 5 is_stmt 0 # d_original_example.c:5:5 + callq puts@PLT +.Ltmp5: + .loc 0 4 29 is_stmt 1 # d_original_example.c:4:29 + incq %r15 +.Ltmp6: + #DEBUG_VALUE: i <- $r15 + .loc 0 4 21 is_stmt 0 # d_original_example.c:4:21 + cmpq %r15, %r14 +.Ltmp7: + .loc 0 4 3 # d_original_example.c:4:3 + jne .LBB0_2 +.Ltmp8: +# %bb.3: + #DEBUG_VALUE: main:argc <- $r14d + #DEBUG_VALUE: main:argv <- $rbx + #DEBUG_VALUE: i <- $r15 + .loc 0 0 3 # d_original_example.c:0:3 + addq $8, %rsp + popq %rbx +.Ltmp9: + #DEBUG_VALUE: main:argv <- [DW_OP_LLVM_entry_value 1] $rsi + popq %r14 +.Ltmp10: + #DEBUG_VALUE: main:argc <- [DW_OP_LLVM_entry_value 1] $edi + popq %r15 + popq %rbp + .cfi_def_cfa %rsp, 8 + .cfi_restore %rbx + .cfi_restore %r14 + .cfi_restore %r15 + .cfi_restore %rbp +.Ltmp11: +.LBB0_4: # %for.cond.cleanup + #DEBUG_VALUE: main:argc <- [DW_OP_LLVM_entry_value 1] $edi + #DEBUG_VALUE: main:argv <- [DW_OP_LLVM_entry_value 1] $rsi + .loc 0 6 3 is_stmt 1 # d_original_example.c:6:3 + xorl %eax, %eax + retq +.Ltmp12: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + .file 1 "/usr/include" "stdio.h" md5 0xf31eefcc3f15835fc5a4023a625cf609 + # -- End function + .section .debug_loclists,"",@progbits + .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length +.Ldebug_list_header_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 3 # Offset entry count +.Lloclists_table_base0: + .long .Ldebug_loc0-.Lloclists_table_base0 + .long .Ldebug_loc1-.Lloclists_table_base0 + .long .Ldebug_loc2-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp3-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp3-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp10-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 94 # super-register DW_OP_reg14 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp10-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 85 # super-register DW_OP_reg5 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_loc1: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp4-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 84 # DW_OP_reg4 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp4-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp9-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 83 # DW_OP_reg3 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp9-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 84 # DW_OP_reg4 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_loc2: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp4-.Lfunc_begin0 # ending offset + .byte 3 # Loc expr size + .byte 17 # DW_OP_consts + .byte 1 # 1 + .byte 159 # DW_OP_stack_value + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp4-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp8-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 95 # DW_OP_reg15 + .byte 0 # DW_LLE_end_of_list +.Ldebug_list_header_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .ascii "\214\001" # DW_AT_loclists_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 39 # DW_AT_prototyped + .byte 25 # DW_FORM_flag_present + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 11 # DW_TAG_lexical_block + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 72 # DW_TAG_call_site + .byte 0 # DW_CHILDREN_no + .byte 127 # DW_AT_call_origin + .byte 19 # DW_FORM_ref4 + .byte 125 # DW_AT_call_return_pc + .byte 27 # DW_FORM_addrx + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 5 # DW_FORM_data2 + .byte 39 # DW_AT_prototyped + .byte 25 # DW_FORM_flag_present + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 11 # Abbreviation Code + .byte 38 # DW_TAG_const_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x7f DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 29 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .long .Lloclists_table_base0 # DW_AT_loclists_base + .byte 2 # Abbrev [2] 0x27:0x38 DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + # DW_AT_call_all_calls + .byte 6 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + # DW_AT_prototyped + .long 110 # DW_AT_type + # DW_AT_external + .byte 3 # Abbrev [3] 0x36:0x9 DW_TAG_formal_parameter + .byte 0 # DW_AT_location + .byte 7 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long 110 # DW_AT_type + .byte 3 # Abbrev [3] 0x3f:0x9 DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 8 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long 128 # DW_AT_type + .byte 4 # Abbrev [4] 0x48:0x10 DW_TAG_lexical_block + .byte 0 # DW_AT_low_pc + .long .Ltmp8-.Lfunc_begin0 # DW_AT_high_pc + .byte 5 # Abbrev [5] 0x4e:0x9 DW_TAG_variable + .byte 2 # DW_AT_location + .byte 9 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .long 110 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 6 # Abbrev [6] 0x58:0x6 DW_TAG_call_site + .long 95 # DW_AT_call_origin + .byte 1 # DW_AT_call_return_pc + .byte 0 # End Of Children Mark + .byte 7 # Abbrev [7] 0x5f:0xf DW_TAG_subprogram + .byte 3 # DW_AT_name + .byte 1 # DW_AT_decl_file + .short 661 # DW_AT_decl_line + # DW_AT_prototyped + .long 110 # DW_AT_type + # DW_AT_declaration + # DW_AT_external + .byte 8 # Abbrev [8] 0x68:0x5 DW_TAG_formal_parameter + .long 114 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 9 # Abbrev [9] 0x6e:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 10 # Abbrev [10] 0x72:0x5 DW_TAG_pointer_type + .long 119 # DW_AT_type + .byte 11 # Abbrev [11] 0x77:0x5 DW_TAG_const_type + .long 124 # DW_AT_type + .byte 9 # Abbrev [9] 0x7c:0x4 DW_TAG_base_type + .byte 5 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 10 # Abbrev [10] 0x80:0x5 DW_TAG_pointer_type + .long 133 # DW_AT_type + .byte 10 # Abbrev [10] 0x85:0x5 DW_TAG_pointer_type + .long 124 # DW_AT_type + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 44 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 22.0.0git (https://github.com/UltimateForce21/llvm-project.git 79c0a9e1e7da0f727c41d27c9c6ff8a28bb7d06f)" # string offset=0 +.Linfo_string1: + .asciz "d_original_example.c" # string offset=119 +.Linfo_string2: + .asciz "." # string offset=140 +.Linfo_string3: + .asciz "puts" # string offset=142 +.Linfo_string4: + .asciz "int" # string offset=147 +.Linfo_string5: + .asciz "char" # string offset=151 +.Linfo_string6: + .asciz "main" # string offset=156 +.Linfo_string7: + .asciz "argc" # string offset=161 +.Linfo_string8: + .asciz "argv" # string offset=166 +.Linfo_string9: + .asciz "i" # string offset=171 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .long .Linfo_string9 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 + .quad .Ltmp5 +.Ldebug_addr_end0: + .ident "clang version 22.0.0git (https://github.com/UltimateForce21/llvm-project.git 79c0a9e1e7da0f727c41d27c9c6ff8a28bb7d06f)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/lldb/test/API/functionalities/disassembler-variables/live_across_call.s b/lldb/test/API/functionalities/disassembler-variables/live_across_call.s new file mode 100644 index 000000000000..cd9f08afe6fd --- /dev/null +++ b/lldb/test/API/functionalities/disassembler-variables/live_across_call.s @@ -0,0 +1,371 @@ +/* Original C (for context): +* // Declare a real external call so the compiler must respect ABI clobbers. +* extern int leaf(int) __attribute__((noinline)); +* +* __attribute__((noinline)) +* int live_across_call(int x) { +* volatile int a = x; // a starts in a GPR (from arg) +* asm volatile("" :: "r"(a)); // keep 'a' live in a register +* int r = leaf(a); // 'a' is live across the call +* asm volatile("" :: "r"(a), "r"(r));// still live afterwards +* return a + r; +* } +*/ + .file "live_across_call.c" + .text + .globl live_across_call # -- Begin function live_across_call + .p2align 4 + .type live_across_call,@function +live_across_call: # @live_across_call +.Lfunc_begin0: + .file 0 "." "live_across_call.c" md5 0x351c37295026edf0d468774d35f47e5e + .loc 0 5 0 # live_across_call.c:5:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: live_across_call:x <- $edi + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + subq $16, %rsp +.Ltmp0: + .loc 0 6 16 prologue_end # live_across_call.c:6:16 + movl %edi, -4(%rbp) + .loc 0 7 26 # live_across_call.c:7:26 + movl -4(%rbp), %eax + .loc 0 7 3 is_stmt 0 # live_across_call.c:7:3 + #APP + #NO_APP + .loc 0 8 16 is_stmt 1 # live_across_call.c:8:16 + movl -4(%rbp), %edi +.Ltmp1: + #DEBUG_VALUE: live_across_call:x <- [DW_OP_LLVM_entry_value 1] $edi + .loc 0 8 11 is_stmt 0 # live_across_call.c:8:11 + callq leaf@PLT +.Ltmp2: + #DEBUG_VALUE: live_across_call:r <- $eax + .loc 0 9 26 is_stmt 1 # live_across_call.c:9:26 + movl -4(%rbp), %ecx + .loc 0 9 3 is_stmt 0 # live_across_call.c:9:3 + #APP + #NO_APP + .loc 0 10 12 is_stmt 1 # live_across_call.c:10:12 + addl -4(%rbp), %eax +.Ltmp3: + .loc 0 10 3 epilogue_begin is_stmt 0 # live_across_call.c:10:3 + addq $16, %rsp + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp4: +.Lfunc_end0: + .size live_across_call, .Lfunc_end0-live_across_call + .cfi_endproc + # -- End function + .section .debug_loclists,"",@progbits + .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length +.Ldebug_list_header_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 2 # Offset entry count +.Lloclists_table_base0: + .long .Ldebug_loc0-.Lloclists_table_base0 + .long .Ldebug_loc1-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 85 # super-register DW_OP_reg5 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_loc1: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp2-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp3-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 80 # super-register DW_OP_reg0 + .byte 0 # DW_LLE_end_of_list +.Ldebug_list_header_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .ascii "\214\001" # DW_AT_loclists_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 39 # DW_AT_prototyped + .byte 25 # DW_FORM_flag_present + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 72 # DW_TAG_call_site + .byte 0 # DW_CHILDREN_no + .byte 127 # DW_AT_call_origin + .byte 19 # DW_FORM_ref4 + .byte 125 # DW_AT_call_return_pc + .byte 27 # DW_FORM_addrx + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 39 # DW_AT_prototyped + .byte 25 # DW_FORM_flag_present + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 53 # DW_TAG_volatile_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x66 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 29 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .long .Lloclists_table_base0 # DW_AT_loclists_base + .byte 2 # Abbrev [2] 0x27:0x33 DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + # DW_AT_call_all_calls + .byte 5 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + # DW_AT_prototyped + .long 104 # DW_AT_type + # DW_AT_external + .byte 3 # Abbrev [3] 0x36:0x9 DW_TAG_formal_parameter + .byte 0 # DW_AT_location + .byte 7 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + .long 104 # DW_AT_type + .byte 4 # Abbrev [4] 0x3f:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 124 + .byte 6 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 108 # DW_AT_type + .byte 5 # Abbrev [5] 0x4a:0x9 DW_TAG_variable + .byte 1 # DW_AT_location + .byte 8 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .long 104 # DW_AT_type + .byte 6 # Abbrev [6] 0x53:0x6 DW_TAG_call_site + .long 90 # DW_AT_call_origin + .byte 1 # DW_AT_call_return_pc + .byte 0 # End Of Children Mark + .byte 7 # Abbrev [7] 0x5a:0xe DW_TAG_subprogram + .byte 3 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + # DW_AT_prototyped + .long 104 # DW_AT_type + # DW_AT_declaration + # DW_AT_external + .byte 8 # Abbrev [8] 0x62:0x5 DW_TAG_formal_parameter + .long 104 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 9 # Abbrev [9] 0x68:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 10 # Abbrev [10] 0x6c:0x5 DW_TAG_volatile_type + .long 104 # DW_AT_type + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 40 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 22.0.0git (https://github.com/UltimateForce21/llvm-project.git 79c0a9e1e7da0f727c41d27c9c6ff8a28bb7d06f)" # string offset=0 +.Linfo_string1: + .asciz "live_across_call.c" # string offset=119 +.Linfo_string2: + .asciz "." # string offset=138 +.Linfo_string3: + .asciz "leaf" # string offset=140 +.Linfo_string4: + .asciz "int" # string offset=145 +.Linfo_string5: + .asciz "live_across_call" # string offset=149 +.Linfo_string6: + .asciz "a" # string offset=166 +.Linfo_string7: + .asciz "x" # string offset=168 +.Linfo_string8: + .asciz "r" # string offset=170 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 + .quad .Ltmp2 +.Ldebug_addr_end0: + .ident "clang version 22.0.0git (https://github.com/UltimateForce21/llvm-project.git 79c0a9e1e7da0f727c41d27c9c6ff8a28bb7d06f)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/lldb/test/API/functionalities/disassembler-variables/loop_reg_rotate.s b/lldb/test/API/functionalities/disassembler-variables/loop_reg_rotate.s new file mode 100644 index 000000000000..c01e2b28fd2b --- /dev/null +++ b/lldb/test/API/functionalities/disassembler-variables/loop_reg_rotate.s @@ -0,0 +1,557 @@ +/* Original C (for context): +* __attribute__((noinline)) +* int loop_reg_rotate(int n, int seed) { +* volatile int acc = seed; // keep as a named local +* int i = 0, j = 1, k = 2; // extra pressure but not enough to spill +* +* for (int t = 0; t < n; ++t) { +* // Mix uses so the allocator may reshuffle regs for 'acc' +* acc = acc + i; +* asm volatile("" :: "r"(acc)); // pin 'acc' live here +* acc = acc ^ j; +* asm volatile("" :: "r"(acc)); // and here +* acc = acc + k; +* i ^= acc; j += acc; k ^= j; +* } +* +* asm volatile("" :: "r"(acc)); +* return acc + i + j + k; +* } +*/ + .file "loop_reg_rotate.c" + .text + .globl loop_reg_rotate # -- Begin function loop_reg_rotate + .p2align 4 + .type loop_reg_rotate,@function +loop_reg_rotate: # @loop_reg_rotate +.Lfunc_begin0: + .file 0 "." "loop_reg_rotate.c" md5 0x388f52de76e9442230e689fb9be1b4ef + .loc 0 2 0 # loop_reg_rotate.c:2:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: loop_reg_rotate:n <- $edi + #DEBUG_VALUE: loop_reg_rotate:seed <- $esi + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp +.Ltmp0: + .loc 0 3 16 prologue_end # loop_reg_rotate.c:3:16 + movl %esi, -4(%rbp) +.Ltmp1: + #DEBUG_VALUE: loop_reg_rotate:i <- 0 + #DEBUG_VALUE: loop_reg_rotate:j <- 1 + #DEBUG_VALUE: loop_reg_rotate:k <- 2 + #DEBUG_VALUE: t <- 0 + .loc 0 6 21 # loop_reg_rotate.c:6:21 + testl %edi, %edi +.Ltmp2: + .loc 0 6 3 is_stmt 0 # loop_reg_rotate.c:6:3 + jle .LBB0_1 +.Ltmp3: +# %bb.3: # %for.body.preheader + #DEBUG_VALUE: loop_reg_rotate:n <- $edi + #DEBUG_VALUE: loop_reg_rotate:seed <- $esi + #DEBUG_VALUE: loop_reg_rotate:i <- 0 + #DEBUG_VALUE: loop_reg_rotate:j <- 1 + #DEBUG_VALUE: loop_reg_rotate:k <- 2 + #DEBUG_VALUE: t <- 0 + .loc 0 0 3 # loop_reg_rotate.c:0:3 + xorl %eax, %eax + movl $1, %edx + movl $2, %ecx +.Ltmp4: + .p2align 4 +.LBB0_4: # %for.body + # =>This Inner Loop Header: Depth=1 + #DEBUG_VALUE: loop_reg_rotate:n <- [DW_OP_LLVM_entry_value 1] $edi + #DEBUG_VALUE: loop_reg_rotate:seed <- [DW_OP_LLVM_entry_value 1] $esi + #DEBUG_VALUE: t <- [DW_OP_LLVM_arg 0, DW_OP_LLVM_arg 1, DW_OP_minus, DW_OP_consts 18446744073709551615, DW_OP_div, DW_OP_stack_value] undef, undef + #DEBUG_VALUE: loop_reg_rotate:k <- $ecx + #DEBUG_VALUE: loop_reg_rotate:j <- $edx + #DEBUG_VALUE: loop_reg_rotate:i <- $eax + .loc 0 8 9 is_stmt 1 # loop_reg_rotate.c:8:9 + addl %eax, -4(%rbp) + .loc 0 9 28 # loop_reg_rotate.c:9:28 + movl -4(%rbp), %esi + .loc 0 9 5 is_stmt 0 # loop_reg_rotate.c:9:5 + #APP + #NO_APP + .loc 0 10 9 is_stmt 1 # loop_reg_rotate.c:10:9 + xorl %edx, -4(%rbp) + .loc 0 11 28 # loop_reg_rotate.c:11:28 + movl -4(%rbp), %esi + .loc 0 11 5 is_stmt 0 # loop_reg_rotate.c:11:5 + #APP + #NO_APP + .loc 0 12 9 is_stmt 1 # loop_reg_rotate.c:12:9 + addl %ecx, -4(%rbp) + .loc 0 13 7 # loop_reg_rotate.c:13:7 + xorl -4(%rbp), %eax +.Ltmp5: + #DEBUG_VALUE: loop_reg_rotate:i <- $eax + .loc 0 13 17 is_stmt 0 # loop_reg_rotate.c:13:17 + addl -4(%rbp), %edx +.Ltmp6: + #DEBUG_VALUE: loop_reg_rotate:j <- $edx + .loc 0 13 27 # loop_reg_rotate.c:13:27 + xorl %edx, %ecx +.Ltmp7: + #DEBUG_VALUE: loop_reg_rotate:k <- $ecx + #DEBUG_VALUE: t <- [DW_OP_LLVM_arg 0, DW_OP_LLVM_arg 1, DW_OP_minus, DW_OP_consts 18446744073709551615, DW_OP_div, DW_OP_consts 1, DW_OP_plus, DW_OP_stack_value] undef, undef + .loc 0 6 21 is_stmt 1 # loop_reg_rotate.c:6:21 + decl %edi +.Ltmp8: + .loc 0 6 3 is_stmt 0 # loop_reg_rotate.c:6:3 + jne .LBB0_4 + jmp .LBB0_2 +.Ltmp9: +.LBB0_1: + #DEBUG_VALUE: loop_reg_rotate:n <- $edi + #DEBUG_VALUE: loop_reg_rotate:seed <- $esi + #DEBUG_VALUE: loop_reg_rotate:i <- 0 + #DEBUG_VALUE: loop_reg_rotate:j <- 1 + #DEBUG_VALUE: loop_reg_rotate:k <- 2 + #DEBUG_VALUE: t <- 0 + .loc 0 0 3 # loop_reg_rotate.c:0:3 + movl $2, %ecx + movl $1, %edx + xorl %eax, %eax +.Ltmp10: +.LBB0_2: # %for.cond.cleanup + #DEBUG_VALUE: loop_reg_rotate:n <- [DW_OP_LLVM_entry_value 1] $edi + #DEBUG_VALUE: loop_reg_rotate:seed <- [DW_OP_LLVM_entry_value 1] $esi + .loc 0 16 26 is_stmt 1 # loop_reg_rotate.c:16:26 + movl -4(%rbp), %esi + .loc 0 16 3 is_stmt 0 # loop_reg_rotate.c:16:3 + #APP + #NO_APP + .loc 0 17 14 is_stmt 1 # loop_reg_rotate.c:17:14 + addl %edx, %eax + .loc 0 17 18 is_stmt 0 # loop_reg_rotate.c:17:18 + addl %ecx, %eax + .loc 0 17 22 # loop_reg_rotate.c:17:22 + addl -4(%rbp), %eax + .loc 0 17 3 epilogue_begin # loop_reg_rotate.c:17:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp11: +.Lfunc_end0: + .size loop_reg_rotate, .Lfunc_end0-loop_reg_rotate + .cfi_endproc + # -- End function + .section .debug_loclists,"",@progbits + .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length +.Ldebug_list_header_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 6 # Offset entry count +.Lloclists_table_base0: + .long .Ldebug_loc0-.Lloclists_table_base0 + .long .Ldebug_loc1-.Lloclists_table_base0 + .long .Ldebug_loc2-.Lloclists_table_base0 + .long .Ldebug_loc3-.Lloclists_table_base0 + .long .Ldebug_loc4-.Lloclists_table_base0 + .long .Ldebug_loc5-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp4-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp4-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp9-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 85 # super-register DW_OP_reg5 + .byte 159 # DW_OP_stack_value + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp9-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp10-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp10-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 85 # super-register DW_OP_reg5 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_loc1: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp4-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 84 # super-register DW_OP_reg4 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp4-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp9-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 84 # super-register DW_OP_reg4 + .byte 159 # DW_OP_stack_value + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp9-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp10-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 84 # super-register DW_OP_reg4 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp10-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 84 # super-register DW_OP_reg4 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_loc2: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp4-.Lfunc_begin0 # ending offset + .byte 3 # Loc expr size + .byte 17 # DW_OP_consts + .byte 0 # 0 + .byte 159 # DW_OP_stack_value + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp4-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp9-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 80 # super-register DW_OP_reg0 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp9-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp10-.Lfunc_begin0 # ending offset + .byte 3 # Loc expr size + .byte 17 # DW_OP_consts + .byte 0 # 0 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_loc3: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp4-.Lfunc_begin0 # ending offset + .byte 3 # Loc expr size + .byte 17 # DW_OP_consts + .byte 1 # 1 + .byte 159 # DW_OP_stack_value + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp4-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp9-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 81 # super-register DW_OP_reg1 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp9-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp10-.Lfunc_begin0 # ending offset + .byte 3 # Loc expr size + .byte 17 # DW_OP_consts + .byte 1 # 1 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_loc4: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp4-.Lfunc_begin0 # ending offset + .byte 3 # Loc expr size + .byte 17 # DW_OP_consts + .byte 2 # 2 + .byte 159 # DW_OP_stack_value + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp4-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp9-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 82 # super-register DW_OP_reg2 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp9-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp10-.Lfunc_begin0 # ending offset + .byte 3 # Loc expr size + .byte 17 # DW_OP_consts + .byte 2 # 2 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_loc5: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp4-.Lfunc_begin0 # ending offset + .byte 3 # Loc expr size + .byte 17 # DW_OP_consts + .byte 0 # 0 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_list_header_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .ascii "\214\001" # DW_AT_loclists_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 39 # DW_AT_prototyped + .byte 25 # DW_FORM_flag_present + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 11 # DW_TAG_lexical_block + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 53 # DW_TAG_volatile_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x7d DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 29 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .long .Lloclists_table_base0 # DW_AT_loclists_base + .byte 2 # Abbrev [2] 0x27:0x58 DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + # DW_AT_call_all_calls + .byte 3 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + # DW_AT_prototyped + .long 127 # DW_AT_type + # DW_AT_external + .byte 3 # Abbrev [3] 0x36:0x9 DW_TAG_formal_parameter + .byte 0 # DW_AT_location + .byte 6 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 127 # DW_AT_type + .byte 3 # Abbrev [3] 0x3f:0x9 DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 7 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 127 # DW_AT_type + .byte 4 # Abbrev [4] 0x48:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 124 + .byte 5 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long 131 # DW_AT_type + .byte 5 # Abbrev [5] 0x53:0x9 DW_TAG_variable + .byte 2 # DW_AT_location + .byte 8 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .long 127 # DW_AT_type + .byte 5 # Abbrev [5] 0x5c:0x9 DW_TAG_variable + .byte 3 # DW_AT_location + .byte 9 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .long 127 # DW_AT_type + .byte 5 # Abbrev [5] 0x65:0x9 DW_TAG_variable + .byte 4 # DW_AT_location + .byte 10 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .long 127 # DW_AT_type + .byte 6 # Abbrev [6] 0x6e:0x10 DW_TAG_lexical_block + .byte 1 # DW_AT_low_pc + .long .Ltmp9-.Ltmp1 # DW_AT_high_pc + .byte 5 # Abbrev [5] 0x74:0x9 DW_TAG_variable + .byte 5 # DW_AT_location + .byte 11 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 127 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark + .byte 7 # Abbrev [7] 0x7f:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 8 # Abbrev [8] 0x83:0x5 DW_TAG_volatile_type + .long 127 # DW_AT_type + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 52 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 22.0.0git (https://github.com/UltimateForce21/llvm-project.git 79c0a9e1e7da0f727c41d27c9c6ff8a28bb7d06f)" # string offset=0 +.Linfo_string1: + .asciz "loop_reg_rotate.c" # string offset=119 +.Linfo_string2: + .asciz "." # string offset=137 +.Linfo_string3: + .asciz "loop_reg_rotate" # string offset=139 +.Linfo_string4: + .asciz "int" # string offset=155 +.Linfo_string5: + .asciz "acc" # string offset=159 +.Linfo_string6: + .asciz "n" # string offset=163 +.Linfo_string7: + .asciz "seed" # string offset=165 +.Linfo_string8: + .asciz "i" # string offset=170 +.Linfo_string9: + .asciz "j" # string offset=172 +.Linfo_string10: + .asciz "k" # string offset=174 +.Linfo_string11: + .asciz "t" # string offset=176 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .long .Linfo_string9 + .long .Linfo_string10 + .long .Linfo_string11 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 + .quad .Ltmp1 +.Ldebug_addr_end0: + .ident "clang version 22.0.0git (https://github.com/UltimateForce21/llvm-project.git 79c0a9e1e7da0f727c41d27c9c6ff8a28bb7d06f)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/lldb/test/API/functionalities/disassembler-variables/regs_fp_params.s b/lldb/test/API/functionalities/disassembler-variables/regs_fp_params.s new file mode 100644 index 000000000000..502ab151e0c5 --- /dev/null +++ b/lldb/test/API/functionalities/disassembler-variables/regs_fp_params.s @@ -0,0 +1,304 @@ +/* Original C (for context): +* __attribute__((noinline)) +* double regs_fp_params(double a, double b, double c, double d, double e, double f) { +* asm volatile("" :: "x"(a), "x"(b), "x"(c), "x"(d), "x"(e), "x"(f)); +* return a + b + c + d + e + f; +* }*/ + .file "regs_fp_params.c" + .text + .globl regs_fp_params # -- Begin function regs_fp_params + .p2align 4 + .type regs_fp_params,@function +regs_fp_params: # @regs_fp_params +.Lfunc_begin0: + .file 0 "." "regs_fp_params.c" md5 0xdd883927454b0ea1cdce7b3c16c6a643 + .loc 0 2 0 # regs_fp_params.c:2:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: regs_fp_params:a <- $xmm0 + #DEBUG_VALUE: regs_fp_params:b <- $xmm1 + #DEBUG_VALUE: regs_fp_params:c <- $xmm2 + #DEBUG_VALUE: regs_fp_params:d <- $xmm3 + #DEBUG_VALUE: regs_fp_params:e <- $xmm4 + #DEBUG_VALUE: regs_fp_params:f <- $xmm5 + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp +.Ltmp0: + .loc 0 3 3 prologue_end # regs_fp_params.c:3:3 + #APP + #NO_APP + .loc 0 4 12 # regs_fp_params.c:4:12 + addsd %xmm1, %xmm0 +.Ltmp1: + #DEBUG_VALUE: regs_fp_params:a <- [DW_OP_LLVM_entry_value 1] $xmm0 + .loc 0 4 16 is_stmt 0 # regs_fp_params.c:4:16 + addsd %xmm2, %xmm0 + .loc 0 4 20 # regs_fp_params.c:4:20 + addsd %xmm3, %xmm0 + .loc 0 4 24 # regs_fp_params.c:4:24 + addsd %xmm4, %xmm0 + .loc 0 4 28 # regs_fp_params.c:4:28 + addsd %xmm5, %xmm0 + .loc 0 4 3 epilogue_begin # regs_fp_params.c:4:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp2: +.Lfunc_end0: + .size regs_fp_params, .Lfunc_end0-regs_fp_params + .cfi_endproc + # -- End function + .section .debug_loclists,"",@progbits + .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length +.Ldebug_list_header_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 1 # Offset entry count +.Lloclists_table_base0: + .long .Ldebug_loc0-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 97 # DW_OP_reg17 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 97 # DW_OP_reg17 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_list_header_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .ascii "\214\001" # DW_AT_loclists_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 39 # DW_AT_prototyped + .byte 25 # DW_FORM_flag_present + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x6b DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 29 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .long .Lloclists_table_base0 # DW_AT_loclists_base + .byte 2 # Abbrev [2] 0x27:0x4b DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + # DW_AT_call_all_calls + .byte 3 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + # DW_AT_prototyped + .long 114 # DW_AT_type + # DW_AT_external + .byte 3 # Abbrev [3] 0x36:0x9 DW_TAG_formal_parameter + .byte 0 # DW_AT_location + .byte 5 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 4 # Abbrev [4] 0x3f:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 98 + .byte 6 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 4 # Abbrev [4] 0x49:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 99 + .byte 7 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 4 # Abbrev [4] 0x53:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 100 + .byte 8 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 4 # Abbrev [4] 0x5d:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 101 + .byte 9 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 4 # Abbrev [4] 0x67:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 102 + .byte 10 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x72:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 4 # DW_AT_encoding + .byte 8 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 48 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 22.0.0git (https://github.com/UltimateForce21/llvm-project.git 79c0a9e1e7da0f727c41d27c9c6ff8a28bb7d06f)" # string offset=0 +.Linfo_string1: + .asciz "regs_fp_params.c" # string offset=119 +.Linfo_string2: + .asciz "." # string offset=136 +.Linfo_string3: + .asciz "regs_fp_params" # string offset=138 +.Linfo_string4: + .asciz "double" # string offset=153 +.Linfo_string5: + .asciz "a" # string offset=160 +.Linfo_string6: + .asciz "b" # string offset=162 +.Linfo_string7: + .asciz "c" # string offset=164 +.Linfo_string8: + .asciz "d" # string offset=166 +.Linfo_string9: + .asciz "e" # string offset=168 +.Linfo_string10: + .asciz "f" # string offset=170 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .long .Linfo_string9 + .long .Linfo_string10 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 +.Ldebug_addr_end0: + .ident "clang version 22.0.0git (https://github.com/UltimateForce21/llvm-project.git 79c0a9e1e7da0f727c41d27c9c6ff8a28bb7d06f)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/lldb/test/API/functionalities/disassembler-variables/regs_int_params.s b/lldb/test/API/functionalities/disassembler-variables/regs_int_params.s new file mode 100644 index 000000000000..0b2a60e2b4d5 --- /dev/null +++ b/lldb/test/API/functionalities/disassembler-variables/regs_int_params.s @@ -0,0 +1,312 @@ +/* Original C (for context): +* __attribute__((noinline)) +* int regs_int_params(int a, int b, int c, int d, int e, int f) { +* // Keep all params in regs; avoid spilling to the stack. +* // The compiler will usually keep a..f in the 6 integer-arg regs. +* asm volatile("" :: "r"(a), "r"(b), "r"(c), "r"(d), "r"(e), "r"(f)); +* return a + b + c + d + e + f; +* } +*/ + .file "regs_int_params.c" + .text + .globl regs_int_params # -- Begin function regs_int_params + .p2align 4 + .type regs_int_params,@function +regs_int_params: # @regs_int_params +.Lfunc_begin0: + .file 0 "." "regs_int_params.c" md5 0xcf39432098ab893043cc8b4606354bd2 + .loc 0 2 0 # regs_int_params.c:2:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: regs_int_params:a <- $edi + #DEBUG_VALUE: regs_int_params:b <- $esi + #DEBUG_VALUE: regs_int_params:c <- $edx + #DEBUG_VALUE: regs_int_params:d <- $ecx + #DEBUG_VALUE: regs_int_params:e <- $r8d + #DEBUG_VALUE: regs_int_params:f <- $r9d + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + # kill: def $r9d killed $r9d def $r9 + # kill: def $r8d killed $r8d def $r8 + # kill: def $ecx killed $ecx def $rcx + # kill: def $edx killed $edx def $rdx + # kill: def $esi killed $esi def $rsi + # kill: def $edi killed $edi def $rdi +.Ltmp0: + .loc 0 5 3 prologue_end # regs_int_params.c:5:3 + #APP + #NO_APP + .loc 0 6 12 # regs_int_params.c:6:12 + addl %edi, %esi +.Ltmp1: + #DEBUG_VALUE: regs_int_params:b <- [DW_OP_LLVM_entry_value 1] $esi + .loc 0 6 16 is_stmt 0 # regs_int_params.c:6:16 + leal (%rdx,%rcx), %eax + .loc 0 6 20 # regs_int_params.c:6:20 + addl %esi, %eax + .loc 0 6 28 # regs_int_params.c:6:28 + addl %r8d, %eax + addl %r9d, %eax + .loc 0 6 3 epilogue_begin # regs_int_params.c:6:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp2: +.Lfunc_end0: + .size regs_int_params, .Lfunc_end0-regs_int_params + .cfi_endproc + # -- End function + .section .debug_loclists,"",@progbits + .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length +.Ldebug_list_header_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 1 # Offset entry count +.Lloclists_table_base0: + .long .Ldebug_loc0-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 84 # super-register DW_OP_reg4 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 84 # super-register DW_OP_reg4 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_list_header_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .ascii "\214\001" # DW_AT_loclists_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 39 # DW_AT_prototyped + .byte 25 # DW_FORM_flag_present + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x6b DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 29 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .long .Lloclists_table_base0 # DW_AT_loclists_base + .byte 2 # Abbrev [2] 0x27:0x4b DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + # DW_AT_call_all_calls + .byte 3 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + # DW_AT_prototyped + .long 114 # DW_AT_type + # DW_AT_external + .byte 3 # Abbrev [3] 0x36:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .byte 5 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 4 # Abbrev [4] 0x40:0x9 DW_TAG_formal_parameter + .byte 0 # DW_AT_location + .byte 6 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 3 # Abbrev [3] 0x49:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 81 + .byte 7 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 3 # Abbrev [3] 0x53:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 82 + .byte 8 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 3 # Abbrev [3] 0x5d:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 88 + .byte 9 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 3 # Abbrev [3] 0x67:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 89 + .byte 10 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x72:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 48 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 22.0.0git (https://github.com/UltimateForce21/llvm-project.git 79c0a9e1e7da0f727c41d27c9c6ff8a28bb7d06f)" # string offset=0 +.Linfo_string1: + .asciz "regs_int_params.c" # string offset=119 +.Linfo_string2: + .asciz "." # string offset=137 +.Linfo_string3: + .asciz "regs_int_params" # string offset=139 +.Linfo_string4: + .asciz "int" # string offset=155 +.Linfo_string5: + .asciz "a" # string offset=159 +.Linfo_string6: + .asciz "b" # string offset=161 +.Linfo_string7: + .asciz "c" # string offset=163 +.Linfo_string8: + .asciz "d" # string offset=165 +.Linfo_string9: + .asciz "e" # string offset=167 +.Linfo_string10: + .asciz "f" # string offset=169 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .long .Linfo_string9 + .long .Linfo_string10 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 +.Ldebug_addr_end0: + .ident "clang version 22.0.0git (https://github.com/UltimateForce21/llvm-project.git 79c0a9e1e7da0f727c41d27c9c6ff8a28bb7d06f)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/lldb/test/API/functionalities/disassembler-variables/regs_mixed_params.s b/lldb/test/API/functionalities/disassembler-variables/regs_mixed_params.s new file mode 100644 index 000000000000..691180b42f24 --- /dev/null +++ b/lldb/test/API/functionalities/disassembler-variables/regs_mixed_params.s @@ -0,0 +1,375 @@ +/* Original C (for context): +* __attribute__((noinline)) +* double regs_mixed_params(int a, int b, double x, double y, int c, double z) { +* // Keep everything live; avoid spills. +* asm volatile("" :: "r"(a), "r"(b), "x"(x), "x"(y), "r"(c), "x"(z)); +* // Some mixing so values stay in regs long enough to annotate. +* double r = (double)(a + b + c) + x + y + z; +* asm volatile("" :: "x"(r), "r"(a), "x"(x)); +* return r; +* } +*/ + .file "regs_mixed_params.c" + .file 0 "." "regs_mixed_params.c" md5 0x73c4bda40238ae460aaecb3a6a2603cf + .text + .globl regs_mixed_params # -- Begin function regs_mixed_params + .p2align 4 + .type regs_mixed_params,@function +regs_mixed_params: # @regs_mixed_params +.Lfunc_begin0: + .loc 0 2 0 # regs_mixed_params.c:2:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: regs_mixed_params:a <- $edi + #DEBUG_VALUE: regs_mixed_params:b <- $esi + #DEBUG_VALUE: regs_mixed_params:x <- $xmm0 + #DEBUG_VALUE: regs_mixed_params:y <- $xmm1 + #DEBUG_VALUE: regs_mixed_params:c <- $edx + #DEBUG_VALUE: regs_mixed_params:z <- $xmm2 + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp +.Ltmp0: + .loc 0 4 3 prologue_end # regs_mixed_params.c:4:3 + #APP + #NO_APP + .loc 0 6 25 # regs_mixed_params.c:6:25 + addl %edi, %esi +.Ltmp1: + #DEBUG_VALUE: regs_mixed_params:b <- [DW_OP_LLVM_entry_value 1] $esi + .loc 0 6 29 is_stmt 0 # regs_mixed_params.c:6:29 + addl %edx, %esi + .loc 0 6 14 # regs_mixed_params.c:6:14 + cvtsi2sd %esi, %xmm4 + .loc 0 6 34 # regs_mixed_params.c:6:34 + movapd %xmm0, %xmm3 + addsd %xmm4, %xmm3 + .loc 0 6 38 # regs_mixed_params.c:6:38 + addsd %xmm1, %xmm3 + .loc 0 6 42 # regs_mixed_params.c:6:42 + addsd %xmm2, %xmm3 +.Ltmp2: + #DEBUG_VALUE: regs_mixed_params:r <- $xmm3 + .loc 0 7 3 is_stmt 1 # regs_mixed_params.c:7:3 + #APP + #NO_APP + .loc 0 8 3 # regs_mixed_params.c:8:3 + movapd %xmm3, %xmm0 +.Ltmp3: + #DEBUG_VALUE: regs_mixed_params:x <- [DW_OP_LLVM_entry_value 1] $xmm0 + .loc 0 8 3 epilogue_begin is_stmt 0 # regs_mixed_params.c:8:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp4: +.Lfunc_end0: + .size regs_mixed_params, .Lfunc_end0-regs_mixed_params + .cfi_endproc + # -- End function + .section .debug_loclists,"",@progbits + .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length +.Ldebug_list_header_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 3 # Offset entry count +.Lloclists_table_base0: + .long .Ldebug_loc0-.Lloclists_table_base0 + .long .Ldebug_loc1-.Lloclists_table_base0 + .long .Ldebug_loc2-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 84 # super-register DW_OP_reg4 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 84 # super-register DW_OP_reg4 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_loc1: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp3-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 97 # DW_OP_reg17 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp3-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 97 # DW_OP_reg17 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_loc2: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp2-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 100 # DW_OP_reg20 + .byte 0 # DW_LLE_end_of_list +.Ldebug_list_header_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .ascii "\214\001" # DW_AT_loclists_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 39 # DW_AT_prototyped + .byte 25 # DW_FORM_flag_present + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x77 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 29 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .long .Lloclists_table_base0 # DW_AT_loclists_base + .byte 2 # Abbrev [2] 0x27:0x4 DW_TAG_base_type + .byte 3 # DW_AT_name + .byte 4 # DW_AT_encoding + .byte 8 # DW_AT_byte_size + .byte 3 # Abbrev [3] 0x2b:0x53 DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + # DW_AT_call_all_calls + .byte 4 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + # DW_AT_prototyped + .long 39 # DW_AT_type + # DW_AT_external + .byte 4 # Abbrev [4] 0x3a:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .byte 5 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 126 # DW_AT_type + .byte 5 # Abbrev [5] 0x44:0x9 DW_TAG_formal_parameter + .byte 0 # DW_AT_location + .byte 7 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 126 # DW_AT_type + .byte 5 # Abbrev [5] 0x4d:0x9 DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 8 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 39 # DW_AT_type + .byte 4 # Abbrev [4] 0x56:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 98 + .byte 9 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 39 # DW_AT_type + .byte 4 # Abbrev [4] 0x60:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 81 + .byte 10 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 126 # DW_AT_type + .byte 4 # Abbrev [4] 0x6a:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 99 + .byte 11 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 39 # DW_AT_type + .byte 6 # Abbrev [6] 0x74:0x9 DW_TAG_variable + .byte 2 # DW_AT_location + .byte 12 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 39 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 2 # Abbrev [2] 0x7e:0x4 DW_TAG_base_type + .byte 6 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 56 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 22.0.0git (https://github.com/UltimateForce21/llvm-project.git 79c0a9e1e7da0f727c41d27c9c6ff8a28bb7d06f)" # string offset=0 +.Linfo_string1: + .asciz "regs_mixed_params.c" # string offset=119 +.Linfo_string2: + .asciz "." # string offset=139 +.Linfo_string3: + .asciz "double" # string offset=141 +.Linfo_string4: + .asciz "regs_mixed_params" # string offset=148 +.Linfo_string5: + .asciz "a" # string offset=166 +.Linfo_string6: + .asciz "int" # string offset=168 +.Linfo_string7: + .asciz "b" # string offset=172 +.Linfo_string8: + .asciz "x" # string offset=174 +.Linfo_string9: + .asciz "y" # string offset=176 +.Linfo_string10: + .asciz "c" # string offset=178 +.Linfo_string11: + .asciz "z" # string offset=180 +.Linfo_string12: + .asciz "r" # string offset=182 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .long .Linfo_string9 + .long .Linfo_string10 + .long .Linfo_string11 + .long .Linfo_string12 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 +.Ldebug_addr_end0: + .ident "clang version 22.0.0git (https://github.com/UltimateForce21/llvm-project.git 79c0a9e1e7da0f727c41d27c9c6ff8a28bb7d06f)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/lldb/test/API/functionalities/disassembler-variables/seed_reg_const_undef.s b/lldb/test/API/functionalities/disassembler-variables/seed_reg_const_undef.s new file mode 100644 index 000000000000..f85b8a712cbb --- /dev/null +++ b/lldb/test/API/functionalities/disassembler-variables/seed_reg_const_undef.s @@ -0,0 +1,289 @@ +/* Original C (for context): +* __attribute__((noinline)) +* int main(int argc, char **argv) { +* int i = argc; // i in a reg (DW_OP_regN) +* asm volatile("" :: "r"(i)); // keep i live here +* i = 0; // i becomes const 0 (DW_OP_constu 0, stack_value) +* asm volatile("" :: "r"(i)); // keep the const range materialized +* return 0; // i ends -> after its range +* } +*/ + + .file "seed_reg_const_undef.c" + .text + .globl main # -- Begin function main + .p2align 4 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 0 "." "seed_reg_const_undef.c" md5 0x5e8dbf089d1bd72d395da802210b3138 + .loc 0 3 0 # seed_reg_const_undef.c:3:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: main:argc <- $edi + #DEBUG_VALUE: main:argv <- $rsi + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp +.Ltmp0: + #DEBUG_VALUE: main:i <- $edi + .loc 0 5 3 prologue_end # seed_reg_const_undef.c:5:3 + #APP + #NO_APP +.Ltmp1: + #DEBUG_VALUE: main:i <- 0 + .loc 0 7 3 # seed_reg_const_undef.c:7:3 + xorl %eax, %eax + #APP + #NO_APP + .loc 0 8 3 # seed_reg_const_undef.c:8:3 + xorl %eax, %eax + .loc 0 8 3 epilogue_begin is_stmt 0 # seed_reg_const_undef.c:8:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp2: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .section .debug_loclists,"",@progbits + .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length +.Ldebug_list_header_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 1 # Offset entry count +.Lloclists_table_base0: + .long .Ldebug_loc0-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp0-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 3 # Loc expr size + .byte 17 # DW_OP_consts + .byte 0 # 0 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_list_header_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .ascii "\214\001" # DW_AT_loclists_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 39 # DW_AT_prototyped + .byte 25 # DW_FORM_flag_present + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x5b DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 29 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .long .Lloclists_table_base0 # DW_AT_loclists_base + .byte 2 # Abbrev [2] 0x27:0x2d DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + # DW_AT_call_all_calls + .byte 3 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + # DW_AT_prototyped + .long 84 # DW_AT_type + # DW_AT_external + .byte 3 # Abbrev [3] 0x36:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .byte 5 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long 84 # DW_AT_type + .byte 3 # Abbrev [3] 0x40:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 84 + .byte 6 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long 88 # DW_AT_type + .byte 4 # Abbrev [4] 0x4a:0x9 DW_TAG_variable + .byte 0 # DW_AT_location + .byte 8 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .long 84 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x54:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 6 # Abbrev [6] 0x58:0x5 DW_TAG_pointer_type + .long 93 # DW_AT_type + .byte 6 # Abbrev [6] 0x5d:0x5 DW_TAG_pointer_type + .long 98 # DW_AT_type + .byte 5 # Abbrev [5] 0x62:0x4 DW_TAG_base_type + .byte 7 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 40 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 22.0.0git (https://github.com/UltimateForce21/llvm-project.git 79c0a9e1e7da0f727c41d27c9c6ff8a28bb7d06f)" # string offset=0 +.Linfo_string1: + .asciz "seed_reg_const_undef.c" # string offset=119 +.Linfo_string2: + .asciz "." # string offset=142 +.Linfo_string3: + .asciz "main" # string offset=144 +.Linfo_string4: + .asciz "int" # string offset=149 +.Linfo_string5: + .asciz "argc" # string offset=153 +.Linfo_string6: + .asciz "argv" # string offset=158 +.Linfo_string7: + .asciz "char" # string offset=163 +.Linfo_string8: + .asciz "i" # string offset=168 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 +.Ldebug_addr_end0: + .ident "clang version 22.0.0git (https://github.com/UltimateForce21/llvm-project.git 79c0a9e1e7da0f727c41d27c9c6ff8a28bb7d06f)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/llvm/include/llvm/DebugInfo/DIContext.h b/llvm/include/llvm/DebugInfo/DIContext.h index 0347f90c236d..e7e87bbfebf3 100644 --- a/llvm/include/llvm/DebugInfo/DIContext.h +++ b/llvm/include/llvm/DebugInfo/DIContext.h @@ -209,6 +209,7 @@ struct DIDumpOptions { bool IsEH = false; bool DumpNonSkeleton = false; bool ShowAggregateErrors = false; + bool PrintRegisterOnly = false; std::string JsonErrSummaryFile; std::function GetNameForDWARFReg; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp b/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp index ebcd4dda5048..078ebf4e7c03 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp @@ -48,13 +48,52 @@ static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS, DIDumpOptions DumpOpts, const DWARFExpression *Expr, DWARFUnit *U) { if (Op->isError()) { - OS << ""; + if (!DumpOpts.PrintRegisterOnly) + OS << ""; return false; } - StringRef Name = OperationEncodingString(Op->getCode()); - assert(!Name.empty() && "DW_OP has no name!"); - OS << Name; + // In "register-only" mode, still show simple constant-valued locations. + // This lets clients print annotations like "i = 0" when the location is + // a constant (e.g. DW_OP_constu/consts ... DW_OP_stack_value). + // We continue to suppress all other non-register ops in this mode. + if (DumpOpts.PrintRegisterOnly) { + // First, try pretty-printing registers (existing behavior below also does + // this, but we need to short-circuit here to avoid printing opcode names). + if ((Op->getCode() >= DW_OP_breg0 && Op->getCode() <= DW_OP_breg31) || + (Op->getCode() >= DW_OP_reg0 && Op->getCode() <= DW_OP_reg31) || + Op->getCode() == DW_OP_bregx || Op->getCode() == DW_OP_regx || + Op->getCode() == DW_OP_regval_type) { + if (prettyPrintRegisterOp(U, OS, DumpOpts, Op->getCode(), + Op->getRawOperands())) + return true; + // If we couldn't pretty-print, fall through and suppress. + } + + // Show constants (decimal), suppress everything else. + if (Op->getCode() == DW_OP_constu) { + OS << (uint64_t)Op->getRawOperand(0); + return true; + } + if (Op->getCode() == DW_OP_consts) { + OS << (int64_t)Op->getRawOperand(0); + return true; + } + if (Op->getCode() >= DW_OP_lit0 && Op->getCode() <= DW_OP_lit31) { + OS << (unsigned)(Op->getCode() - DW_OP_lit0); + return true; + } + if (Op->getCode() == DW_OP_stack_value) + return true; // metadata; don't print a token + + return true; // suppress other opcodes silently in register-only mode + } + + if (!DumpOpts.PrintRegisterOnly) { + StringRef Name = OperationEncodingString(Op->getCode()); + assert(!Name.empty() && "DW_OP has no name!"); + OS << Name; + } if ((Op->getCode() >= DW_OP_breg0 && Op->getCode() <= DW_OP_breg31) || (Op->getCode() >= DW_OP_reg0 && Op->getCode() <= DW_OP_reg31) || @@ -64,48 +103,51 @@ static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS, Op->getRawOperands())) return true; - for (unsigned Operand = 0; Operand < Op->getDescription().Op.size(); - ++Operand) { - unsigned Size = Op->getDescription().Op[Operand]; - unsigned Signed = Size & DWARFExpression::Operation::SignBit; + if (!DumpOpts.PrintRegisterOnly) { + for (unsigned Operand = 0; Operand < Op->getDescription().Op.size(); + ++Operand) { + unsigned Size = Op->getDescription().Op[Operand]; + unsigned Signed = Size & DWARFExpression::Operation::SignBit; - if (Size == DWARFExpression::Operation::SizeSubOpLEB) { - StringRef SubName = - SubOperationEncodingString(Op->getCode(), Op->getRawOperand(Operand)); - assert(!SubName.empty() && "DW_OP SubOp has no name!"); - OS << " " << SubName; - } else if (Size == DWARFExpression::Operation::BaseTypeRef && U) { - // For DW_OP_convert the operand may be 0 to indicate that conversion to - // the generic type should be done. The same holds for DW_OP_reinterpret, - // which is currently not supported. - if (Op->getCode() == DW_OP_convert && Op->getRawOperand(Operand) == 0) - OS << " 0x0"; - else - prettyPrintBaseTypeRef(U, OS, DumpOpts, Op->getRawOperands(), Operand); - } else if (Size == DWARFExpression::Operation::WasmLocationArg) { - assert(Operand == 1); - switch (Op->getRawOperand(0)) { - case 0: - case 1: - case 2: - case 3: // global as uint32 - case 4: - OS << format(" 0x%" PRIx64, Op->getRawOperand(Operand)); - break; - default: - assert(false); + if (Size == DWARFExpression::Operation::SizeSubOpLEB) { + StringRef SubName = SubOperationEncodingString( + Op->getCode(), Op->getRawOperand(Operand)); + assert(!SubName.empty() && "DW_OP SubOp has no name!"); + OS << " " << SubName; + } else if (Size == DWARFExpression::Operation::BaseTypeRef && U) { + // For DW_OP_convert the operand may be 0 to indicate that conversion to + // the generic type should be done. The same holds for + // DW_OP_reinterpret, which is currently not supported. + if (Op->getCode() == DW_OP_convert && Op->getRawOperand(Operand) == 0) + OS << " 0x0"; + else + prettyPrintBaseTypeRef(U, OS, DumpOpts, Op->getRawOperands(), + Operand); + } else if (Size == DWARFExpression::Operation::WasmLocationArg) { + assert(Operand == 1); + switch (Op->getRawOperand(0)) { + case 0: + case 1: + case 2: + case 3: // global as uint32 + case 4: + OS << format(" 0x%" PRIx64, Op->getRawOperand(Operand)); + break; + default: + assert(false); + } + } else if (Size == DWARFExpression::Operation::SizeBlock) { + uint64_t Offset = Op->getRawOperand(Operand); + for (unsigned i = 0; i < Op->getRawOperand(Operand - 1); ++i) + OS << format(" 0x%02x", + static_cast(Expr->getData()[Offset++])); + } else { + if (Signed) + OS << format(" %+" PRId64, (int64_t)Op->getRawOperand(Operand)); + else if (Op->getCode() != DW_OP_entry_value && + Op->getCode() != DW_OP_GNU_entry_value) + OS << format(" 0x%" PRIx64, Op->getRawOperand(Operand)); } - } else if (Size == DWARFExpression::Operation::SizeBlock) { - uint64_t Offset = Op->getRawOperand(Operand); - for (unsigned i = 0; i < Op->getRawOperand(Operand - 1); ++i) - OS << format(" 0x%02x", - static_cast(Expr->getData()[Offset++])); - } else { - if (Signed) - OS << format(" %+" PRId64, (int64_t)Op->getRawOperand(Operand)); - else if (Op->getCode() != DW_OP_entry_value && - Op->getCode() != DW_OP_GNU_entry_value) - OS << format(" 0x%" PRIx64, Op->getRawOperand(Operand)); } } return true; @@ -120,29 +162,30 @@ void printDwarfExpression(const DWARFExpression *E, raw_ostream &OS, for (auto &Op : *E) { DumpOpts.IsEH = IsEH; - if (!printOp(&Op, OS, DumpOpts, E, U)) { + if (!printOp(&Op, OS, DumpOpts, E, U) && !DumpOpts.PrintRegisterOnly) { uint64_t FailOffset = Op.getEndOffset(); while (FailOffset < E->getData().size()) OS << format(" %02x", static_cast(E->getData()[FailOffset++])); return; } + if (!DumpOpts.PrintRegisterOnly) { + if (Op.getCode() == DW_OP_entry_value || + Op.getCode() == DW_OP_GNU_entry_value) { + OS << "("; + EntryValExprSize = Op.getRawOperand(0); + EntryValStartOffset = Op.getEndOffset(); + continue; + } - if (Op.getCode() == DW_OP_entry_value || - Op.getCode() == DW_OP_GNU_entry_value) { - OS << "("; - EntryValExprSize = Op.getRawOperand(0); - EntryValStartOffset = Op.getEndOffset(); - continue; + if (EntryValExprSize) { + EntryValExprSize -= Op.getEndOffset() - EntryValStartOffset; + if (EntryValExprSize == 0) + OS << ")"; + } + + if (Op.getEndOffset() < E->getData().size()) + OS << ", "; } - - if (EntryValExprSize) { - EntryValExprSize -= Op.getEndOffset() - EntryValStartOffset; - if (EntryValExprSize == 0) - OS << ")"; - } - - if (Op.getEndOffset() < E->getData().size()) - OS << ", "; } }