blob: 7c60c1b9841b5b97988a9b5bcb8583b358e0ba23 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CompileUnit.cpp -----------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Symbol/CompileUnit.h"
11#include "lldb/Symbol/LineTable.h"
12#include "lldb/Core/Module.h"
13#include "lldb/Symbol/SymbolVendor.h"
14#include "lldb/Symbol/VariableList.h"
15
16using namespace lldb;
17using namespace lldb_private;
18
19CompileUnit::CompileUnit (Module *module, void *user_data, const char *pathname, const lldb::user_id_t cu_sym_id, Language::Type language) :
20 ModuleChild(module),
21 FileSpec (pathname),
22 UserID(cu_sym_id),
23 Language (language),
24 m_user_data (user_data),
25 m_flags (0),
26 m_functions (),
27 m_support_files (),
28 m_line_table_ap (),
29 m_variables()
30{
31 assert(module != NULL);
32}
33
34CompileUnit::CompileUnit (Module *module, void *user_data, const FileSpec &fspec, const lldb::user_id_t cu_sym_id, Language::Type language) :
35 ModuleChild(module),
36 FileSpec (fspec),
37 UserID(cu_sym_id),
38 Language (language),
39 m_user_data (user_data),
40 m_flags (0),
41 m_functions (),
42 m_support_files (),
43 m_line_table_ap (),
44 m_variables()
45{
46 assert(module != NULL);
47}
48
49CompileUnit::~CompileUnit ()
50{
51}
52
53void
54CompileUnit::CalculateSymbolContext(SymbolContext* sc)
55{
56 sc->comp_unit = this;
57 GetModule()->CalculateSymbolContext(sc);
58}
59
60void
61CompileUnit::DumpSymbolContext(Stream *s)
62{
63 GetModule()->DumpSymbolContext(s);
64 s->Printf(", CompileUnit{0x%8.8x}", GetID());
65}
66
67
Greg Clayton12bec712010-06-28 21:30:43 +000068void
69CompileUnit::GetDescription(Stream *s, lldb::DescriptionLevel level) const
70{
71 *s << '"' << (const FileSpec&)*this << "\", id = " << (const UserID&)*this
72 << ", language = " << (const Language&)*this;
73}
74
Chris Lattner24943d22010-06-08 16:52:24 +000075
76//----------------------------------------------------------------------
77// Dump the current contents of this object. No functions that cause on
78// demand parsing of functions, globals, statics are called, so this
79// is a good function to call to get an idea of the current contents of
80// the CompileUnit object.
81//----------------------------------------------------------------------
82void
83CompileUnit::Dump(Stream *s, bool show_context) const
84{
85 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
86 s->Indent();
87 *s << "CompileUnit" << (const UserID&)*this
88 << ", language = " << (const Language&)*this
89 << ", file='" << (const FileSpec&)*this << "'\n";
90
91// m_types.Dump(s);
92
93 if (m_variables.get())
94 {
95 s->IndentMore();
96 m_variables->Dump(s, show_context);
97 s->IndentLess();
98 }
99
100 if (!m_functions.empty())
101 {
102 s->IndentMore();
103 std::vector<FunctionSP>::const_iterator pos;
104 std::vector<FunctionSP>::const_iterator end = m_functions.end();
105 for (pos = m_functions.begin(); pos != end; ++pos)
106 {
107 (*pos)->Dump(s, show_context);
108 }
109
110 s->IndentLess();
111 s->EOL();
112 }
113}
114
115//----------------------------------------------------------------------
116// Add a function to this compile unit
117//----------------------------------------------------------------------
118void
119CompileUnit::AddFunction(FunctionSP& funcSP)
120{
121 // TODO: order these by address
122 m_functions.push_back(funcSP);
123}
124
125FunctionSP
126CompileUnit::GetFunctionAtIndex (size_t idx)
127{
128 FunctionSP funcSP;
129 if (idx < m_functions.size())
130 funcSP = m_functions[idx];
131 return funcSP;
132}
133
134//----------------------------------------------------------------------
135// Find functions using the a Mangled::Tokens token list. This
136// function currently implements an interative approach designed to find
137// all instances of certain functions. It isn't designed to the the
138// quickest way to lookup functions as it will need to iterate through
139// all functions and see if they match, though it does provide a powerful
140// and context sensitive way to search for all functions with a certain
141// name, all functions in a namespace, or all functions of a template
142// type. See Mangled::Tokens::Parse() comments for more information.
143//
144// The function prototype will need to change to return a list of
145// results. It was originally used to help debug the Mangled class
146// and the Mangled::Tokens::MatchesQuery() function and it currently
147// will print out a list of matching results for the functions that
148// are currently in this compile unit.
149//
150// A FindFunctions method should be called prior to this that takes
151// a regular function name (const char * or ConstString as a parameter)
152// before resorting to this slower but more complete function. The
153// other FindFunctions method should be able to take advantage of any
154// accelerator tables available in the debug information (which is
155// parsed by the SymbolFile parser plug-ins and registered with each
156// Module).
157//----------------------------------------------------------------------
158//void
159//CompileUnit::FindFunctions(const Mangled::Tokens& tokens)
160//{
161// if (!m_functions.empty())
162// {
163// Stream s(stdout);
164// std::vector<FunctionSP>::const_iterator pos;
165// std::vector<FunctionSP>::const_iterator end = m_functions.end();
166// for (pos = m_functions.begin(); pos != end; ++pos)
167// {
168// const ConstString& demangled = (*pos)->Mangled().Demangled();
169// if (demangled)
170// {
171// const Mangled::Tokens& func_tokens = (*pos)->Mangled().GetTokens();
172// if (func_tokens.MatchesQuery (tokens))
173// s << "demangled MATCH found: " << demangled << "\n";
174// }
175// }
176// }
177//}
178
179FunctionSP
180CompileUnit::FindFunctionByUID (lldb::user_id_t func_uid)
181{
182 FunctionSP funcSP;
183 if (!m_functions.empty())
184 {
185 std::vector<FunctionSP>::const_iterator pos;
186 std::vector<FunctionSP>::const_iterator end = m_functions.end();
187 for (pos = m_functions.begin(); pos != end; ++pos)
188 {
189 if ((*pos)->GetID() == func_uid)
190 {
191 funcSP = *pos;
192 break;
193 }
194 }
195 }
196 return funcSP;
197}
198
199
200LineTable*
201CompileUnit::GetLineTable()
202{
203 if (m_line_table_ap.get() == NULL)
204 {
205 if (m_flags.IsClear(flagsParsedLineTable))
206 {
207 m_flags.Set(flagsParsedLineTable);
208 SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor();
209 if (symbol_vendor)
210 {
211 SymbolContext sc;
212 CalculateSymbolContext(&sc);
213 symbol_vendor->ParseCompileUnitLineTable(sc);
214 }
215 }
216 }
217 return m_line_table_ap.get();
218}
219
220void
221CompileUnit::SetLineTable(LineTable* line_table)
222{
223 if (line_table == NULL)
224 m_flags.Clear(flagsParsedLineTable);
225 else
226 m_flags.Set(flagsParsedLineTable);
227 m_line_table_ap.reset(line_table);
228}
229
230VariableListSP
231CompileUnit::GetVariableList(bool can_create)
232{
233 if (m_variables.get() == NULL && can_create)
234 {
235 SymbolContext sc;
236 CalculateSymbolContext(&sc);
237 assert(sc.module_sp);
238 sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
239 }
240
241 return m_variables;
242}
243
244uint32_t
245CompileUnit::FindLineEntry (uint32_t start_idx, uint32_t line, const FileSpec* file_spec_ptr, LineEntry *line_entry_ptr)
246{
247 uint32_t file_idx = 0;
248
249 if (file_spec_ptr)
250 {
251 file_idx = GetSupportFiles().FindFileIndex (1, *file_spec_ptr);
252 if (file_idx == UINT32_MAX)
253 return UINT32_MAX;
254 }
255 else
256 {
257 // All the line table entries actually point to the version of the Compile
258 // Unit that is in the support files (the one at 0 was artifically added.)
259 // So prefer the one further on in the support files if it exists...
260 FileSpecList &support_files = GetSupportFiles();
261 file_idx = support_files.FindFileIndex (1, support_files.GetFileSpecAtIndex(0));
262 if (file_idx == UINT32_MAX)
263 file_idx = 0;
264 }
265 LineTable *line_table = GetLineTable();
266 if (line_table)
267 return line_table->FindLineEntryIndexByFileIndex (start_idx, file_idx, line, true, line_entry_ptr);
268 return UINT32_MAX;
269}
270
271
272
273
274uint32_t
275CompileUnit::ResolveSymbolContext
276(
277 const FileSpec& file_spec,
278 uint32_t line,
279 bool check_inlines,
280 bool exact,
281 uint32_t resolve_scope,
282 SymbolContextList &sc_list
283)
284{
285 const uint32_t prev_size = sc_list.GetSize();
286 bool file_spec_matches_cu_file_spec = FileSpec::Compare(file_spec, this, !file_spec.GetDirectory().IsEmpty()) == 0;
287 if (check_inlines || file_spec_matches_cu_file_spec)
288 {
289 SymbolContext sc(GetModule());
290 sc.comp_unit = this;
291
292 uint32_t file_idx = UINT32_MAX;
293
294 // If we are looking for inline functions only and we don't
295 // find it in the support files, we are done.
296
297 if (check_inlines)
298 {
299 file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec);
300 if (file_idx == UINT32_MAX)
301 return 0;
302 }
303
304 if (line != 0)
305 {
306 LineTable *line_table = sc.comp_unit->GetLineTable();
307
308 if (line_table != NULL)
309 {
310 // We will have already looked up the file index if
311 // we are searching for inline entries.
312 if (!check_inlines)
313 file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec);
314
315 if (file_idx != UINT32_MAX)
316 {
317 uint32_t found_line;
318
319 uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_idx, line, exact, &sc.line_entry);
320 found_line = sc.line_entry.line;
321
322 while (line_idx != UINT_MAX)
323 {
324 sc_list.Append(sc);
325 line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_idx, found_line, true, &sc.line_entry);
326 }
327 }
328 }
329 }
330 else if (file_spec_matches_cu_file_spec && !check_inlines)
331 {
332 // only append the context if we aren't looking for inline call sites
333 // by file and line and if the file spec matches that of the compile unit
334 sc_list.Append(sc);
335 }
336
337 }
338 return sc_list.GetSize() - prev_size;
339}
340
341void
342CompileUnit::SetVariableList(VariableListSP &variables)
343{
344 m_variables = variables;
345}
346
347FileSpecList&
348CompileUnit::GetSupportFiles ()
349{
350 if (m_support_files.GetSize() == 0)
351 {
352 if (m_flags.IsClear(flagsParsedSupportFiles))
353 {
354 m_flags.Set(flagsParsedSupportFiles);
355 SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor();
356 if (symbol_vendor)
357 {
358 SymbolContext sc;
359 CalculateSymbolContext(&sc);
360 symbol_vendor->ParseCompileUnitSupportFiles(sc, m_support_files);
361 }
362 }
363 }
364 return m_support_files;
365}
366
367void *
368CompileUnit::GetUserData () const
369{
370 return m_user_data;
371}
372
373