LLDB mainline
DWARFASTParserFortran.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements the DWARF AST parser for the Fortran language.
11///
12//===----------------------------------------------------------------------===//
13
15#include "DWARFDIE.h"
16#include "DWARFDebugInfo.h"
17#include "DWARFDeclContext.h"
18#include "DWARFDefines.h"
19#include "LogChannelDWARF.h"
20#include "SymbolFileDWARF.h"
22#include "UniqueDWARFASTType.h"
23
25#include "lldb/Utility/Log.h"
27
28using namespace lldb;
29using namespace lldb_private;
30using namespace lldb_private::plugin::dwarf;
31using namespace llvm::dwarf;
32
37
39
41 const SymbolContext &sc, const DWARFDIE &die, TypeSP type_sp) {
42 if (!type_sp)
43 return type_sp;
44
46 dw_tag_t sc_parent_tag = sc_parent_die.Tag();
47
48 SymbolContextScope *symbol_context_scope = nullptr;
49 if (sc_parent_tag == DW_TAG_compile_unit ||
50 sc_parent_tag == DW_TAG_partial_unit) {
51 symbol_context_scope = sc.comp_unit;
52 } else if (!sc.function && sc_parent_die) {
53 symbol_context_scope =
54 sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
55 if (symbol_context_scope == nullptr)
56 symbol_context_scope = sc.function;
57 } else {
58 symbol_context_scope = sc.module_sp.get();
59 }
60
61 if (symbol_context_scope != nullptr)
62 type_sp->SetSymbolContextScope(symbol_context_scope);
63 return type_sp;
64}
65
67 const DWARFDIE &function_die,
70 if (!function_die)
71 return;
72
73 for (DWARFDIE die : function_die.children()) {
74 if (die.Tag() != DW_TAG_formal_parameter ||
75 die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0))
76 continue;
77
78 DWARFDIE param_type_die = die.GetAttributeValueAsReferenceDIE(DW_AT_type);
79 Type *type = die.ResolveTypeUID(param_type_die);
80 if (!type)
81 break;
82
83 param_names.emplace_back(die.GetName());
84 param_types.push_back(type->GetForwardCompilerType());
85 }
86 assert(param_names.size() == param_types.size());
87}
88
91 const lldb_private::plugin::dwarf::DWARFDIE &die, bool *type_is_new_ptr) {
92 TypeSP type_sp;
93 if (type_is_new_ptr)
94 *type_is_new_ptr = false;
95
97
98 if (!die)
99 return type_sp;
101 if (log) {
102 dwarf->GetObjectFile()->GetModule()->LogMessage(
103 log,
104 "DWARFASTParserFortran::ParseTypeFromDWARF (die = 0x%8.8x) %s name"
105 "= "
106 "'%s')",
108 die.GetName());
109 }
110
111 Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE());
112
113 if (type_ptr) {
114 if (type_ptr != DIE_IS_BEING_PARSED)
115 return type_ptr->shared_from_this();
116 else
117 return TypeSP();
118 }
119
120 if (type_is_new_ptr)
121 *type_is_new_ptr = true;
122
123 ConstString type_name;
124 const char *type_name_cstr = nullptr;
125 CompilerType compiler_type;
126 DWARFAttributes attributes;
127 DWARFFormValue form_value;
128 Declaration decl;
129 // We use 0x00 as a sentinel value, it doesn't map to any DW_ATE attribute
130 llvm::dwarf::TypeKind encoding = static_cast<llvm::dwarf::TypeKind>(0x00);
131
132 switch (const dw_tag_t tag = die.Tag()) {
133 case DW_TAG_base_type: {
134 dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
135 attributes = die.GetAttributes();
136 uint64_t bit_size = 0;
137 for (size_t idx = 0; idx < attributes.Size(); idx++) {
138 if (attributes.ExtractFormValueAtIndex(idx, form_value)) {
139
140 switch (attributes.AttributeAtIndex(idx)) {
141 case DW_AT_name:
142 type_name_cstr = form_value.AsCString();
143
144 if (type_name_cstr && type_name_cstr[0] != '\0')
145 type_name.SetString(llvm::StringRef(type_name_cstr).upper());
146 else
147 type_name.SetCString("UNKNOWN_FORTRAN_TYPE");
148
149 break;
150 case DW_AT_encoding:
151 encoding = static_cast<llvm::dwarf::TypeKind>(form_value.Unsigned());
152 break;
153 case DW_AT_byte_size:
154 bit_size = form_value.Unsigned() * 8;
155 break;
156 case DW_AT_bit_size:
157 bit_size = form_value.Unsigned();
158 break;
159 default:
160 break;
161 }
162 }
163 }
164
165 compiler_type = m_ast.CreateBaseType(encoding, bit_size, type_name);
166 type_sp =
167 dwarf->MakeType(die.GetID(), type_name, llvm::divideCeil(bit_size, 8),
169 compiler_type, Type::ResolveState::Full);
170 break;
171 }
172 case DW_TAG_subprogram:
173 case DW_TAG_subroutine_type: {
174 CompilerType return_type;
175 dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
176 attributes = die.GetAttributes();
177 size_t num_attr = attributes.Size();
178
179 for (size_t i = 0; i < num_attr; ++i) {
180 if (!attributes.ExtractFormValueAtIndex(i, form_value))
181 continue;
182 switch (attributes.AttributeAtIndex(i)) {
183 case DW_AT_name: {
184 const char *type_name_cstr = form_value.AsCString();
185 if (type_name_cstr && type_name_cstr[0] != '\0')
186 type_name.SetString(type_name_cstr);
187 else
188 type_name.SetCString("UNKNOWN_FORTRAN_FUNCTION");
189
190 break;
191 }
192 case DW_AT_type: {
193 if (DWARFDIE type_die = form_value.Reference())
194 if (Type *resolved_type = die.GetDWARF()->ResolveType(type_die))
195 return_type = resolved_type->GetForwardCompilerType();
196 break;
197 }
198
199 default:
200 break;
201 }
202 }
203
204 llvm::SmallVector<CompilerType, 4> param_types;
205 llvm::SmallVector<llvm::StringRef, 4> param_names;
206 ParseFunctionParameters(die, param_types, param_names);
207
208 compiler_type = m_ast.CreateFortranFunction(type_name, param_types,
209 param_names, return_type);
210
211 type_sp = dwarf->MakeType(die.GetID(), type_name, 0, nullptr,
213 compiler_type, Type::ResolveState::Full);
214 break;
215 }
216
217 default:
218 if (log)
219 dwarf->GetObjectFile()->GetModule()->LogMessage(
220 log, "[{0:x16}]: unhandled type tag {1:x4} ({2})", die.GetOffset(),
221 tag, DW_TAG_value_to_name(tag));
222
223 break;
224 }
225
226 UpdateSymbolContextScopeForType(sc, die, type_sp);
227 if (type_sp.get())
228 dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
229
230 return type_sp;
231}
232
234 lldb_private::CompileUnit &comp_unit,
237 if (die.Tag() != DW_TAG_subprogram && die.Tag() != DW_TAG_subroutine_type)
238 return nullptr;
239
240 llvm::DWARFAddressRangesVector unused_func_ranges;
241 const char *name = nullptr;
242 const char *mangled = nullptr;
243 std::optional<int> decl_file = 0;
244 std::optional<int> decl_line = 0;
245 std::optional<int> decl_column = 0;
246 std::optional<int> call_file = 0;
247 std::optional<int> call_line = 0;
248 std::optional<int> call_column = 0;
249 DWARFExpressionList frame_base;
250 if (!die.GetDIENamesAndRanges(name, mangled, unused_func_ranges, decl_file,
251 decl_line, decl_column, call_file, call_line,
252 call_column, &frame_base))
253 return nullptr;
254
255 Mangled func_name;
256 // TODO: Once the Mangled class supports Fortran demangling, we should
257 // synthesize a demangled name here if GetDIENamesAndRanges fails to provide
258 // one.
259 if (mangled)
260 func_name.SetMangledName(ConstString(mangled));
261
262 if (name)
263 func_name.SetDemangledName(ConstString(name));
264
265 FunctionSP func_sp;
267 // Supply the type only if it has already been parsed
268 Type *func_type = dwarf->GetDIEToType().lookup(die.GetDIE());
269 assert(func_type == nullptr || func_type != DIE_IS_BEING_PARSED);
270 const user_id_t func_user_id = die.GetID();
271 Address func_addr = ranges[0].GetBaseAddress();
272
273 func_sp = std::make_shared<Function>(&comp_unit,
274 func_user_id, // UserID is the DIE offset
275 func_user_id, func_name, func_type,
276 std::move(func_addr), std::move(ranges));
277
278 if (func_sp.get() == nullptr)
279 return nullptr;
280
281 if (frame_base.IsValid())
282 func_sp->GetFrameBaseExpression() = frame_base;
283
284 comp_unit.AddFunction(func_sp);
285 return func_sp.get();
286}
287
This file defines the DWARF AST parser for the Fortran language.
#define DIE_IS_BEING_PARSED
bool CompleteTypeFromDWARF(const lldb_private::plugin::dwarf::DWARFDIE &die, lldb_private::Type *type, const lldb_private::CompilerType &compiler_type) override
void ParseFunctionParameters(const lldb_private::plugin::dwarf::DWARFDIE &function_die, llvm::SmallVectorImpl< lldb_private::CompilerType > &param_types, llvm::SmallVectorImpl< llvm::StringRef > &param_names)
lldb_private::Function * ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit, const lldb_private::plugin::dwarf::DWARFDIE &die, lldb_private::AddressRanges ranges) override
DWARFASTParserFortran(lldb_private::TypeSystemFortran &m_ast)
lldb_private::TypeSystemFortran & m_ast
lldb::TypeSP UpdateSymbolContextScopeForType(const lldb_private::SymbolContext &sc, const lldb_private::plugin::dwarf::DWARFDIE &die, lldb::TypeSP type_sp)
If type_sp is valid, calculate and set its symbol context scope, and update the type list for its bac...
lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const lldb_private::plugin::dwarf::DWARFDIE &die, bool *type_is_new_ptr) override
A section + offset based address class.
Definition Address.h:62
Block * FindBlockByID(lldb::user_id_t block_id)
Definition Block.cpp:113
A class that describes a compilation unit.
Definition CompileUnit.h:43
void AddFunction(lldb::FunctionSP &function_sp)
Add a function to this compile unit.
Generic representation of a type in a programming language.
A uniqued constant string class.
Definition ConstString.h:40
void SetCString(const char *cstr)
Set the C string value.
void SetString(llvm::StringRef s)
"lldb/Expression/DWARFExpressionList.h" Encapsulates a range map from file address range to a single ...
bool IsValid() const
Return true if the location expression contains data.
A class that describes the declaration location of a lldb object.
Definition Declaration.h:24
A class that describes a function.
Definition Function.h:386
Block & GetBlock(bool can_create)
Get accessor for the block list.
Definition Function.cpp:401
A class that handles mangled names.
Definition Mangled.h:36
void SetDemangledName(ConstString name)
Definition Mangled.h:161
void SetMangledName(ConstString name)
Definition Mangled.h:163
"lldb/Symbol/SymbolContextScope.h" Inherit from this if your object is part of a symbol context and c...
Defines a symbol context baton that can be handed other debug core functions.
Function * function
The Function for a given query.
lldb::ModuleSP module_sp
The Module for a given query.
CompileUnit * comp_unit
The CompileUnit for a given query.
CompilerType GetForwardCompilerType()
@ eEncodingIsUID
This type is the type whose UID is m_encoding_uid.
dw_attr_t AttributeAtIndex(uint32_t i) const
bool ExtractFormValueAtIndex(uint32_t i, DWARFFormValue &form_value) const
DWARFAttributes GetAttributes(Recurse recurse=Recurse::yes) const
bool GetDIENamesAndRanges(const char *&name, const char *&mangled, llvm::DWARFAddressRangesVector &ranges, std::optional< int > &decl_file, std::optional< int > &decl_line, std::optional< int > &decl_column, std::optional< int > &call_file, std::optional< int > &call_line, std::optional< int > &call_column, DWARFExpressionList *frame_base) const
Definition DWARFDIE.cpp:584
DWARFDIE GetDIE(dw_offset_t die_offset) const
Definition DWARFDIE.cpp:126
llvm::iterator_range< child_iterator > children() const
The range of all the children of this DIE.
Definition DWARFDIE.cpp:601
DWARFDIE GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const
Definition DWARFDIE.cpp:134
Type * ResolveType(const DWARFDIE &die, bool assert_not_being_parsed=true, bool resolve_function_context=false)
static DWARFDIE GetParentSymbolContextDIE(const DWARFDIE &die)
llvm::dwarf::Tag dw_tag_t
Definition dwarf.h:19
#define LLDB_INVALID_UID
llvm::StringRef DW_TAG_value_to_name(dw_tag_t tag)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
std::shared_ptr< lldb_private::Function > FunctionSP
std::shared_ptr< lldb_private::Type > TypeSP
uint64_t user_id_t
Definition lldb-types.h:83