[LLDB][NativePDB] Add local constant support (#180612)

This is mostly to support Swift `let`, but I found a way to get MSVC to
emit a local `S_CONSTANT` (see test).

I saw the note about `MakeConstantLocalExpression` at
2e34fecf02/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp (L2177)
but couldn't repro with local or global (emitted as `S_LDATA32` in both
cases).
This commit is contained in:
Leonard Grey 2026-02-12 09:35:00 -05:00 committed by GitHub
parent 6da74dded0
commit 4c08780e7c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 81 additions and 25 deletions

View File

@ -2196,32 +2196,54 @@ SymbolFileNativePDB::ParseVariablesForCompileUnit(CompileUnit &comp_unit,
VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
PdbCompilandSymId var_id,
bool is_param) {
bool is_param,
bool is_constant) {
ModuleSP module = GetObjectFile()->GetModule();
Block *block = GetOrCreateBlock(scope_id);
if (!block)
return nullptr;
// Get function block.
Block *func_block = block;
while (func_block->GetParent()) {
func_block = func_block->GetParent();
CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
if (!cii)
return nullptr;
CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
VariableInfo var_info;
bool location_is_constant_data = is_constant;
if (is_constant) {
CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(var_id.offset);
assert(sym.kind() == S_CONSTANT);
ConstantSym constant(sym.kind());
cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant));
var_info.name = constant.Name;
var_info.type = constant.Type;
var_info.location = DWARFExpressionList(
module,
MakeConstantLocationExpression(constant.Type, m_index->tpi(),
constant.Value, module),
nullptr);
} else {
// Get function block.
Block *func_block = block;
while (func_block->GetParent())
func_block = func_block->GetParent();
Address addr;
func_block->GetStartAddress(addr);
var_info = GetVariableLocationInfo(*m_index, var_id, *func_block, module);
Function *func = func_block->CalculateSymbolContextFunction();
if (!func)
return nullptr;
// Use empty dwarf expr if optimized away so that it won't be filtered out
// when lookuping local variables in this scope.
if (!var_info.location.IsValid())
var_info.location =
DWARFExpressionList(module, DWARFExpression(), nullptr);
var_info.location.SetFuncFileAddress(func->GetAddress().GetFileAddress());
}
Address addr;
func_block->GetStartAddress(addr);
VariableInfo var_info =
GetVariableLocationInfo(*m_index, var_id, *func_block, module);
Function *func = func_block->CalculateSymbolContextFunction();
if (!func)
return nullptr;
// Use empty dwarf expr if optimized away so that it won't be filtered out
// when lookuping local variables in this scope.
if (!var_info.location.IsValid())
var_info.location = DWARFExpressionList(module, DWARFExpression(), nullptr);
var_info.location.SetFuncFileAddress(func->GetAddress().GetFileAddress());
CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
TypeSP type_sp = GetOrCreateType(var_info.type);
if (!type_sp)
return nullptr;
@ -2235,7 +2257,6 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
is_param ? eValueTypeVariableArgument : eValueTypeVariableLocal;
bool external = false;
bool artificial = false;
bool location_is_constant_data = false;
bool static_member = false;
Variable::RangeList scope_ranges;
VariableSP var_sp = std::make_shared<Variable>(
@ -2256,13 +2277,15 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
return var_sp;
}
VariableSP SymbolFileNativePDB::GetOrCreateLocalVariable(
PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param) {
VariableSP
SymbolFileNativePDB::GetOrCreateLocalVariable(PdbCompilandSymId scope_id,
PdbCompilandSymId var_id,
bool is_param, bool is_constant) {
auto iter = m_local_variables.find(toOpaqueUid(var_id));
if (iter != m_local_variables.end())
return iter->second;
return CreateLocalVariable(scope_id, var_id, is_param);
return CreateLocalVariable(scope_id, var_id, is_param, is_constant);
}
TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) {
@ -2390,6 +2413,13 @@ size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) {
if (variable)
variables->AddVariableIfUnique(variable);
break;
case S_CONSTANT:
variable = GetOrCreateLocalVariable(block_id, child_sym_id,
/*is_param=*/false,
/*is_constant=*/true);
if (variable)
variables->AddVariableIfUnique(variable);
break;
default:
break;
}

View File

@ -236,14 +236,16 @@ private:
Block *GetOrCreateBlock(PdbCompilandSymId block_id);
lldb::VariableSP GetOrCreateLocalVariable(PdbCompilandSymId scope_id,
PdbCompilandSymId var_id,
bool is_param);
bool is_param,
bool is_constant = false);
lldb::TypeSP GetOrCreateTypedef(PdbGlobalSymId id);
lldb::FunctionSP CreateFunction(PdbCompilandSymId func_id,
CompileUnit &comp_unit);
Block *CreateBlock(PdbCompilandSymId block_id);
lldb::VariableSP CreateLocalVariable(PdbCompilandSymId scope_id,
PdbCompilandSymId var_id, bool is_param);
PdbCompilandSymId var_id, bool is_param,
bool is_constant = false);
lldb::TypeSP CreateTypedef(PdbGlobalSymId id);
lldb::CompUnitSP CreateCompileUnit(const CompilandIndexItem &cci);
lldb::TypeSP CreateType(PdbTypeSymId type_id, CompilerType ct);

View File

@ -0,0 +1,24 @@
# REQUIRES: msvc
# Test that we can display local S_CONSTANT records.
# MSVC emits S_CONSTANT for static const locals; clang-cl does not.
# RUN: split-file %s %t
# RUN: %build --compiler=msvc --nodefaultlib -o %t.exe -- %t/main.cpp
# RUN: %lldb -f %t.exe -s %t/commands.input 2>&1 | FileCheck %s
#--- main.cpp
int main() {
static const int kConstant = 42;
return kConstant;
}
#--- commands.input
settings set stop-line-count-after 0
break set -n main
run
frame variable
quit
# CHECK: (const int) {{.*}}kConstant = 42