[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
https://github.com/llvm/llvm-project/blob/2e34fecf02962e4c8477ca88cc5ac9386a0f76bb/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp#L2177
but couldn't repro with local or global (emitted as `S_LDATA32` in both
cases).
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 7e39af7..bed1583 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -2196,32 +2196,54 @@
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 @@
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 @@
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 @@
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;
}
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
index 11b982e..4d5d9fb 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -236,14 +236,16 @@
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);
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/local-constant.test b/lldb/test/Shell/SymbolFile/NativePDB/local-constant.test
new file mode 100644
index 0000000..83d37631
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/NativePDB/local-constant.test
@@ -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