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