[llvm-branch-commits] [lldb] [lldb][Fortran] Added support for base types to DWARFASTParserFortran (PR #223406)
Iasonas Karaprodromidis via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Sep 18 07:59:55 PDT 2026
https://github.com/Iasonaskrpr updated https://github.com/llvm/llvm-project/pull/223406
>From a41ea60ce903dc6c53ccfbcd97654380e8b44014 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Mon, 14 Sep 2026 16:28:33 +0300
Subject: [PATCH] [lldb][Fortran] Added support for base types to
DWARFASTParserFortran, tests for DWARFASTParserFortran and a method to get
the parser from TypeSystemFortran
---
.../DWARF/DWARFASTParserFortran.cpp | 131 ++++++++++-
.../SymbolFile/DWARF/DWARFASTParserFortran.h | 18 +-
.../TypeSystem/Fortran/TypeSystemFortran.cpp | 8 +
.../TypeSystem/Fortran/TypeSystemFortran.h | 3 +
.../unittests/SymbolFile/DWARF/CMakeLists.txt | 2 +
.../DWARF/DWARFASTParserFortranTests.cpp | 209 ++++++++++++++++++
6 files changed, 366 insertions(+), 5 deletions(-)
create mode 100644 lldb/unittests/SymbolFile/DWARF/DWARFASTParserFortranTests.cpp
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
index b0606a4e9ca81..c40ce396b1377 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
@@ -12,20 +12,143 @@
//===----------------------------------------------------------------------===//
#include "DWARFASTParserFortran.h"
+#include "DWARFDIE.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFDeclContext.h"
+#include "DWARFDefines.h"
+#include "LogChannelDWARF.h"
+#include "SymbolFileDWARF.h"
+#include "SymbolFileDWARFDebugMap.h"
+#include "UniqueDWARFASTType.h"
+
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/ValueObject/ValueObject.h"
using namespace lldb;
using namespace lldb_private;
+using namespace lldb_private::plugin::dwarf;
+using namespace llvm::dwarf;
-DWARFASTParserFortran::DWARFASTParserFortran()
- : lldb_private::plugin::dwarf::DWARFASTParser(Kind::DWARFASTParserFortran) {
-}
+DWARFASTParserFortran::DWARFASTParserFortran(
+ lldb_private::TypeSystemFortran &m_ast)
+ : lldb_private::plugin::dwarf::DWARFASTParser(Kind::DWARFASTParserFortran),
+ m_ast(m_ast) {}
DWARFASTParserFortran::~DWARFASTParserFortran() {}
+TypeSP DWARFASTParserFortran::UpdateSymbolContextScopeForType(
+ const SymbolContext &sc, const DWARFDIE &die, TypeSP type_sp) {
+ if (!type_sp)
+ return type_sp;
+
+ DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
+ dw_tag_t sc_parent_tag = sc_parent_die.Tag();
+
+ SymbolContextScope *symbol_context_scope = nullptr;
+ if (sc_parent_tag == DW_TAG_compile_unit ||
+ sc_parent_tag == DW_TAG_partial_unit) {
+ symbol_context_scope = sc.comp_unit;
+ } else if (sc.function != nullptr && sc_parent_die) {
+ symbol_context_scope =
+ sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
+ if (symbol_context_scope == nullptr)
+ symbol_context_scope = sc.function;
+ } else {
+ symbol_context_scope = sc.module_sp.get();
+ }
+
+ if (symbol_context_scope != nullptr)
+ type_sp->SetSymbolContextScope(symbol_context_scope);
+ return type_sp;
+}
+
lldb::TypeSP DWARFASTParserFortran::ParseTypeFromDWARF(
const lldb_private::SymbolContext &sc,
const lldb_private::plugin::dwarf::DWARFDIE &die, bool *type_is_new_ptr) {
- return lldb::TypeSP();
+ TypeSP type_sp;
+ if (type_is_new_ptr)
+ *type_is_new_ptr = false;
+ Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
+
+ if (die) {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ if (log) {
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "DWARFASTParserFortran::ParseTypeFromDWARF (die = 0x%8.8x) %s name"
+ "= "
+ "'%s')",
+ die.GetOffset(), plugin::dwarf::DW_TAG_value_to_name(die.Tag()),
+ die.GetName());
+ }
+ Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE());
+ if (!type_ptr) {
+ if (type_is_new_ptr)
+ *type_is_new_ptr = true;
+
+ const dw_tag_t tag = die.Tag();
+ ConstString type_name;
+ const char *type_name_cstr = nullptr;
+ CompilerType compiler_type;
+ DWARFAttributes attributes;
+ DWARFFormValue form_value;
+ Declaration decl;
+ uint32_t encoding = 0;
+ switch (tag) {
+ case DW_TAG_base_type: {
+ dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
+ attributes = die.GetAttributes();
+ uint64_t bit_size = 0;
+ for (size_t idx = 0; idx < attributes.Size(); idx++) {
+ if (attributes.ExtractFormValueAtIndex(idx, form_value)) {
+ switch (attributes.AttributeAtIndex(idx)) {
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ if (type_name_cstr &&
+ type_name_cstr[0]) { // Check for null AND empty string
+ type_name.SetString(llvm::StringRef(type_name_cstr).upper());
+ } else {
+ type_name.SetCString("UNKNOWN_FORTRAN_TYPE");
+ }
+ break;
+ case DW_AT_encoding:
+ encoding = form_value.Unsigned();
+ break;
+ case DW_AT_byte_size:
+ bit_size = form_value.Unsigned() * 8;
+ break;
+ case DW_AT_bit_size:
+ bit_size = form_value.Unsigned();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ compiler_type = m_ast.CreateBaseType(encoding, bit_size, type_name);
+ type_sp =
+ dwarf->MakeType(die.GetID(), type_name, (bit_size + 7) / 8, nullptr,
+ LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
+ compiler_type, Type::ResolveState::Full);
+ } break;
+ default:
+ if (log) {
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log, "[{0:x16}]: unhandled type tag {1:x4} ({2})",
+ die.GetOffset(), tag, DW_TAG_value_to_name(tag));
+ }
+ break;
+ }
+ UpdateSymbolContextScopeForType(sc, die, type_sp);
+ if (type_sp.get())
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+
+ } else if (type_ptr != DIE_IS_BEING_PARSED) {
+ type_sp = type_ptr->shared_from_this();
+ }
+ }
+ return type_sp;
}
lldb_private::Function *DWARFASTParserFortran::ParseFunctionFromDWARF(
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h
index 4fbbd76ad4cb2..2afa12ae232ed 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h
@@ -26,10 +26,23 @@ class ExecutionContext;
class DWARFASTParserFortran
: public lldb_private::plugin::dwarf::DWARFASTParser {
public:
- DWARFASTParserFortran();
+ DWARFASTParserFortran(lldb_private::TypeSystemFortran &m_ast);
~DWARFASTParserFortran() override;
+ // LLVM RTTI support
+ static bool classof(const DWARFASTParser *Parser) {
+ return Parser->GetKind() == Kind::DWARFASTParserFortran;
+ }
+
+ /// If \p type_sp is valid, calculate and set its symbol context scope, and
+ /// update the type list for its backing symbol file.
+ ///
+ /// Returns \p type_sp.
+ lldb::TypeSP UpdateSymbolContextScopeForType(
+ const lldb_private::SymbolContext &sc,
+ const lldb_private::plugin::dwarf::DWARFDIE &die, lldb::TypeSP type_sp);
+
lldb::TypeSP
ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
const lldb_private::plugin::dwarf::DWARFDIE &die,
@@ -72,6 +85,9 @@ class DWARFASTParserFortran
lldb_private::plugin::dwarf::DWARFDIE die) override {
return {};
}
+
+private:
+ lldb_private::TypeSystemFortran &m_ast;
};
#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFASTPARSERFORTRAN_H
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
index 007029757c9a5..d7f5a0437d1dc 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
@@ -9,6 +9,8 @@
#include "TypeSystemFortran.h"
#include "FortranTypes.h"
+#include "Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h"
+
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Symbol/SymbolFile.h"
@@ -38,6 +40,12 @@ void TypeSystemFortran::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}
+plugin::dwarf::DWARFASTParser *TypeSystemFortran::GetDWARFParser() {
+ if (!m_dwarf_ast_parser_up)
+ m_dwarf_ast_parser_up = std::make_unique<DWARFASTParserFortran>(*this);
+ return m_dwarf_ast_parser_up.get();
+}
+
TypeSystemSP TypeSystemFortran::CreateInstance(LanguageType language,
Module *module, Target *target) {
if (Language::LanguageIsFortran(language))
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
index 46a4a4a74c584..5be3d3c170331 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
@@ -35,6 +35,8 @@ class TypeSystemFortran : public TypeSystem {
static void Terminate();
+ plugin::dwarf::DWARFASTParser *GetDWARFParser() override;
+
static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language,
Module *module, Target *target);
@@ -474,6 +476,7 @@ class TypeSystemFortran : public TypeSystem {
// of the types
mutable llvm::SmallVector<std::unique_ptr<plugin::fortran::FortranType>>
m_types;
+ std::unique_ptr<plugin::dwarf::DWARFASTParser> m_dwarf_ast_parser_up;
TypeSystemFortran(const TypeSystemFortran &) = delete;
const TypeSystemFortran &operator=(const TypeSystemFortran &) = delete;
diff --git a/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt b/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
index 185cad60f74d9..09d9032252b65 100644
--- a/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
+++ b/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
@@ -1,5 +1,6 @@
add_lldb_unittest(SymbolFileDWARFTests
DWARFASTParserClangTests.cpp
+ DWARFASTParserFortranTests.cpp
DWARFDebugNamesIndexTest.cpp
DWARFDIETest.cpp
DWARFIndexCachingTest.cpp
@@ -19,6 +20,7 @@ add_lldb_unittest(SymbolFileDWARFTests
lldbPluginSymbolFileDWARF
lldbPluginSymbolFilePDB
lldbPluginTypeSystemClang
+ lldbPluginTypeSystemFortran
lldbPluginPlatformMacOSX
lldbUtilityHelpers
lldbSymbolHelpers
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserFortranTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserFortranTests.cpp
new file mode 100644
index 0000000000000..4189a43d7a374
--- /dev/null
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserFortranTests.cpp
@@ -0,0 +1,209 @@
+//===-- DWARFASTParserFortranTests.cpp ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h"
+#include "Plugins/SymbolFile/DWARF/DWARFCompileUnit.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
+#include "TestingSupport/Symbol/YAMLModuleTester.h"
+#include "TestingSupport/TestUtilities.h"
+#include "lldb/Core/Debugger.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::plugin::dwarf;
+using namespace llvm::dwarf;
+
+namespace {
+
+class TypeSystemFortranHolder {
+ std::shared_ptr<TypeSystemFortran> m_ast;
+
+public:
+ TypeSystemFortranHolder() : m_ast(std::make_shared<TypeSystemFortran>()) {}
+ TypeSystemFortran *GetAST() const { return m_ast.get(); }
+};
+
+class DWARFASTParserFortranTests : public testing::Test {
+ void SetUp() override {
+ std::call_once(TestUtilities::g_debugger_initialize_flag, []() {
+ Debugger::Initialize(nullptr);
+ TypeSystemFortran::Initialize();
+ });
+ }
+};
+
+/// Helper structure for DWARFASTParserFortran tests that want to parse DWARF
+/// generated using yaml2obj. On construction parses the supplied YAML data
+/// into a DWARF module and thereafter vends a DWARFASTParserFortran and
+/// TypeSystemFortran that are guaranteed to live for the duration of this
+/// object.
+class DWARFASTParserFortranYAMLTester {
+public:
+ DWARFASTParserFortranYAMLTester(llvm::StringRef yaml_data)
+ : m_module_tester(yaml_data) {}
+
+ DWARFDIE GetCUDIE() {
+ DWARFUnit *unit = m_module_tester.GetDwarfUnit();
+ assert(unit);
+
+ const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
+ assert(cu_entry->Tag() == DW_TAG_compile_unit);
+
+ return DWARFDIE(unit, cu_entry);
+ }
+
+ DWARFASTParserFortran &GetParser() {
+ auto *parser = GetTypeSystem().GetDWARFParser();
+
+ assert(llvm::isa_and_nonnull<DWARFASTParserFortran>(parser));
+
+ return *llvm::cast<DWARFASTParserFortran>(parser);
+ }
+
+ TypeSystemFortran &GetTypeSystem() {
+ ModuleSP module_sp = m_module_tester.GetModule();
+ assert(module_sp);
+
+ SymbolFile *symfile = module_sp->GetSymbolFile();
+ assert(symfile);
+
+ TypeSystemSP ts_sp = llvm::cantFail(symfile->GetTypeSystemForLanguage(
+ lldb::LanguageType::eLanguageTypeFortran90));
+
+ assert(llvm::isa_and_nonnull<TypeSystemFortran>(ts_sp.get()));
+
+ return llvm::cast<TypeSystemFortran>(*ts_sp);
+ }
+
+private:
+ YAMLModuleTester m_module_tester;
+};
+} // namespace
+
+TEST_F(DWARFASTParserFortranTests, EnsureBaseTypeParsingWorks) {
+ const char *yamldata = R"(
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+DWARF:
+ debug_abbrev:
+ - Table:
+ - Code: 0x00000001
+ Tag: DW_TAG_compile_unit
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_language
+ Form: DW_FORM_data2
+ - Code: 0x00000002
+ Tag: DW_TAG_base_type
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_encoding
+ Form: DW_FORM_data1
+ - Attribute: DW_AT_byte_size
+ Form: DW_FORM_data1
+ debug_info:
+ - Version: 4
+ AddrSize: 8
+ Entries:
+ - AbbrCode: 0x00000001
+ Values:
+ - Value: 0x000000000000000E # DW_LANG_Fortran95
+ # integer(kind=4)
+ - AbbrCode: 0x00000002
+ Values:
+ - CStr: 'integer(kind=4)'
+ - Value: 0x0000000000000005 # DW_ATE_signed
+ - Value: 0x0000000000000004
+ # integer(kind=8)
+ - AbbrCode: 0x00000002
+ Values:
+ - CStr: 'integer(kind=8)'
+ - Value: 0x0000000000000005 # DW_ATE_signed
+ - Value: 0x0000000000000008
+ # real(kind=4)
+ - AbbrCode: 0x00000002
+ Values:
+ - CStr: 'real(kind=4)'
+ - Value: 0x0000000000000004 # DW_ATE_float
+ - Value: 0x0000000000000004
+ # complex(kind=4)
+ - AbbrCode: 0x00000002
+ Values:
+ - CStr: 'complex(kind=4)'
+ - Value: 0x0000000000000003 # DW_ATE_complex_float
+ - Value: 0x0000000000000008
+ # logical(kind=4)
+ - AbbrCode: 0x00000002
+ Values:
+ - CStr: 'logical(kind=4)'
+ - Value: 0x0000000000000002 # DW_ATE_boolean
+ - Value: 0x0000000000000004
+)";
+
+ DWARFASTParserFortranYAMLTester tester(yamldata);
+ DWARFDIE cu_die = tester.GetCUDIE();
+
+ struct ExpectedTypeInfo {
+ const char *name;
+ uint64_t byte_size;
+ lldb::BasicType basic_type;
+ };
+
+ const std::vector<ExpectedTypeInfo> expected_types = {
+ {"INTEGER", 4, lldb::eBasicTypeInt},
+ {"INTEGER(KIND=8)", 8, lldb::eBasicTypeLongLong},
+ {"REAL", 4, lldb::eBasicTypeFloat},
+ {"COMPLEX", 8, lldb::eBasicTypeFloatComplex},
+ {"LOGICAL", 4, lldb::eBasicTypeBool},
+ };
+
+ size_t type_idx = 0;
+ for (DWARFDIE child_die : cu_die.children()) {
+ ASSERT_EQ(child_die.Tag(), DW_TAG_base_type);
+ ASSERT_LT(type_idx, expected_types.size());
+
+ const auto &expected = expected_types[type_idx++];
+ SymbolContext sc;
+
+ bool is_new_type = false;
+ lldb::TypeSP type_sp =
+ tester.GetParser().ParseTypeFromDWARF(sc, child_die, &is_new_type);
+
+ ASSERT_NE(type_sp, nullptr);
+ EXPECT_TRUE(is_new_type);
+
+ EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName().GetString(),
+ expected.name);
+
+ llvm::Expected<uint64_t> size_or_err = type_sp->GetByteSize(nullptr);
+ ASSERT_FALSE(!size_or_err);
+ EXPECT_EQ(*size_or_err, expected.byte_size);
+
+ EXPECT_EQ(type_sp->GetForwardCompilerType().GetBasicTypeEnumeration(),
+ expected.basic_type);
+
+ bool is_new_type_cached = true;
+ lldb::TypeSP cached_type_sp = tester.GetParser().ParseTypeFromDWARF(
+ sc, child_die, &is_new_type_cached);
+
+ ASSERT_NE(cached_type_sp, nullptr);
+ EXPECT_FALSE(is_new_type_cached);
+ EXPECT_EQ(type_sp, cached_type_sp);
+ }
+
+ // Ensure all expected DIEs were iterated
+ EXPECT_EQ(type_idx, expected_types.size());
+}
More information about the llvm-branch-commits
mailing list