blob: 5f9adbbbe12c4afcd3b102e91db3c7395b950f64 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- Function.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/Function.h"
11#include "lldb/Core/Module.h"
12#include "lldb/Core/Section.h"
Greg Clayton1674b122010-07-21 22:12:05 +000013#include "lldb/Symbol/ClangASTType.h"
14#include "lldb/Symbol/ClangASTContext.h"
Chris Lattner24943d22010-06-08 16:52:24 +000015#include "lldb/Symbol/CompileUnit.h"
16#include "lldb/Symbol/LineTable.h"
17#include "lldb/Symbol/SymbolVendor.h"
Chris Lattner24943d22010-06-08 16:52:24 +000018#include "clang/AST/Type.h"
19#include "clang/AST/CanonicalType.h"
20
21using namespace lldb_private;
22
23//----------------------------------------------------------------------
24// Basic function information is contained in the FunctionInfo class.
25// It is designed to contain the name, linkage name, and declaration
26// location.
27//----------------------------------------------------------------------
28FunctionInfo::FunctionInfo (const char *name, const Declaration *decl_ptr) :
29 m_name(name),
30 m_declaration(decl_ptr)
31{
32}
33
34
35FunctionInfo::FunctionInfo (const ConstString& name, const Declaration *decl_ptr) :
36 m_name(name),
37 m_declaration(decl_ptr)
38{
39}
40
41
42FunctionInfo::~FunctionInfo()
43{
44}
45
46void
47FunctionInfo::Dump(Stream *s) const
48{
49 if (m_name)
50 *s << ", name = \"" << m_name << "\"";
51 m_declaration.Dump(s);
52}
53
54
55int
56FunctionInfo::Compare(const FunctionInfo& a, const FunctionInfo& b)
57{
58 int result = ConstString::Compare(a.GetName(), b.GetName());
59 if (result)
60 return result;
61
62 return Declaration::Compare(a.m_declaration, b.m_declaration);
63}
64
65
66Declaration&
67FunctionInfo::GetDeclaration()
68{
69 return m_declaration;
70}
71
72const Declaration&
73FunctionInfo::GetDeclaration() const
74{
75 return m_declaration;
76}
77
78const ConstString&
79FunctionInfo::GetName() const
80{
81 return m_name;
82}
83
84size_t
85FunctionInfo::MemorySize() const
86{
87 return m_name.MemorySize() + m_declaration.MemorySize();
88}
89
90
91InlineFunctionInfo::InlineFunctionInfo
92(
93 const char *name,
94 const char *mangled,
95 const Declaration *decl_ptr,
96 const Declaration *call_decl_ptr
97) :
98 FunctionInfo(name, decl_ptr),
99 m_mangled(mangled, true),
100 m_call_decl (call_decl_ptr)
101{
102}
103
104InlineFunctionInfo::InlineFunctionInfo
105(
106 const ConstString& name,
107 const Mangled &mangled,
108 const Declaration *decl_ptr,
109 const Declaration *call_decl_ptr
110) :
111 FunctionInfo(name, decl_ptr),
112 m_mangled(mangled),
113 m_call_decl (call_decl_ptr)
114{
115}
116
117InlineFunctionInfo::~InlineFunctionInfo()
118{
119}
120
121int
122InlineFunctionInfo::Compare(const InlineFunctionInfo& a, const InlineFunctionInfo& b)
123{
124
125 int result = FunctionInfo::Compare(a, b);
126 if (result)
127 return result;
128 // only compare the mangled names if both have them
129 return Mangled::Compare(a.m_mangled, a.m_mangled);
130}
131
132void
133InlineFunctionInfo::Dump(Stream *s) const
134{
135 FunctionInfo::Dump(s);
136 if (m_mangled)
137 m_mangled.Dump(s);
138}
139
140void
141InlineFunctionInfo::DumpStopContext (Stream *s) const
142{
143// s->Indent("[inlined] ");
144 s->Indent();
145 if (m_mangled)
146 s->PutCString (m_mangled.GetName().AsCString());
147 else
148 s->PutCString (m_name.AsCString());
149}
150
Greg Clayton33ed1702010-08-24 00:45:41 +0000151
152const ConstString &
153InlineFunctionInfo::GetName () const
154{
155 if (m_mangled)
156 return m_mangled.GetName();
157 return m_name;
158}
159
160
Chris Lattner24943d22010-06-08 16:52:24 +0000161Declaration &
162InlineFunctionInfo::GetCallSite ()
163{
164 return m_call_decl;
165}
166
167const Declaration &
168InlineFunctionInfo::GetCallSite () const
169{
170 return m_call_decl;
171}
172
173
174Mangled&
175InlineFunctionInfo::GetMangled()
176{
177 return m_mangled;
178}
179
180const Mangled&
181InlineFunctionInfo::GetMangled() const
182{
183 return m_mangled;
184}
185
186size_t
187InlineFunctionInfo::MemorySize() const
188{
189 return FunctionInfo::MemorySize() + m_mangled.MemorySize();
190}
191
192//----------------------------------------------------------------------
193//
194//----------------------------------------------------------------------
195Function::Function
196(
197 CompileUnit *comp_unit,
198 lldb::user_id_t func_uid,
199 lldb::user_id_t type_uid,
200 const Mangled &mangled,
201 Type * type,
202 const AddressRange& range
203) :
Greg Clayton75ccf502010-08-21 02:22:51 +0000204 UserID (func_uid),
205 m_comp_unit (comp_unit),
206 m_type_uid (type_uid),
207 m_type (type),
208 m_mangled (mangled),
209 m_block (func_uid),
210 m_range (range),
211 m_frame_base (),
212 m_flags (),
213 m_prologue_byte_size (0)
Chris Lattner24943d22010-06-08 16:52:24 +0000214{
Greg Clayton75ccf502010-08-21 02:22:51 +0000215 m_block.SetParentScope(this);
Chris Lattner24943d22010-06-08 16:52:24 +0000216 assert(comp_unit != NULL);
217}
218
219Function::Function
220(
221 CompileUnit *comp_unit,
222 lldb::user_id_t func_uid,
223 lldb::user_id_t type_uid,
224 const char *mangled,
225 Type *type,
226 const AddressRange &range
227) :
Greg Clayton75ccf502010-08-21 02:22:51 +0000228 UserID (func_uid),
229 m_comp_unit (comp_unit),
230 m_type_uid (type_uid),
231 m_type (type),
232 m_mangled (mangled, true),
233 m_block (func_uid),
234 m_range (range),
235 m_frame_base (),
236 m_flags (),
237 m_prologue_byte_size (0)
Chris Lattner24943d22010-06-08 16:52:24 +0000238{
Greg Clayton75ccf502010-08-21 02:22:51 +0000239 m_block.SetParentScope(this);
Chris Lattner24943d22010-06-08 16:52:24 +0000240 assert(comp_unit != NULL);
241}
242
243
244Function::~Function()
245{
246}
247
Jim Inghamb75b4662010-08-20 01:15:01 +0000248void
249Function::GetStartLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
250{
251 line_no = 0;
252 source_file.Clear();
253
254 if (m_comp_unit == NULL)
255 return;
256
257 if (m_type != NULL && m_type->GetDeclaration().GetLine() != 0)
258 {
259 source_file = m_type->GetDeclaration().GetFile();
260 line_no = m_type->GetDeclaration().GetLine();
261 }
262 else
263 {
264 LineTable *line_table = m_comp_unit->GetLineTable();
265 if (line_table == NULL)
266 return;
267
268 LineEntry line_entry;
269 if (line_table->FindLineEntryByAddress (GetAddressRange().GetBaseAddress(), line_entry, NULL))
270 {
271 line_no = line_entry.line;
272 source_file = line_entry.file;
273 }
274 }
275}
276
277void
278Function::GetEndLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
279{
280 line_no = 0;
281 source_file.Clear();
282
283 // The -1 is kind of cheesy, but I want to get the last line entry for the given function, not the
284 // first entry of the next.
285 Address scratch_addr(GetAddressRange().GetBaseAddress());
286 scratch_addr.SetOffset (scratch_addr.GetOffset() + GetAddressRange().GetByteSize() - 1);
287
288 LineTable *line_table = m_comp_unit->GetLineTable();
289 if (line_table == NULL)
290 return;
291
292 LineEntry line_entry;
293 if (line_table->FindLineEntryByAddress (scratch_addr, line_entry, NULL))
294 {
295 line_no = line_entry.line;
296 source_file = line_entry.file;
297 }
298}
299
Greg Clayton75ccf502010-08-21 02:22:51 +0000300Block &
301Function::GetBlock (bool can_create)
Chris Lattner24943d22010-06-08 16:52:24 +0000302{
Greg Clayton75ccf502010-08-21 02:22:51 +0000303 if (!m_block.BlockInfoHasBeenParsed() && can_create)
Chris Lattner24943d22010-06-08 16:52:24 +0000304 {
305 SymbolContext sc;
306 CalculateSymbolContext(&sc);
307 assert(sc.module_sp);
308 sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc);
Greg Clayton75ccf502010-08-21 02:22:51 +0000309 m_block.SetBlockInfoHasBeenParsed (true, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000310 }
Greg Clayton75ccf502010-08-21 02:22:51 +0000311 return m_block;
Chris Lattner24943d22010-06-08 16:52:24 +0000312}
313
314CompileUnit*
315Function::GetCompileUnit()
316{
317 return m_comp_unit;
318}
319
320const CompileUnit*
321Function::GetCompileUnit() const
322{
323 return m_comp_unit;
324}
325
Greg Clayton12bec712010-06-28 21:30:43 +0000326
327void
328Function::GetDescription(Stream *s, lldb::DescriptionLevel level, Process *process)
329{
330 Type* func_type = GetType();
331 *s << '"' << func_type->GetName() << "\", id = " << (const UserID&)*this;
332 *s << ", range = ";
333 GetAddressRange().Dump(s, process, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
334}
335
Chris Lattner24943d22010-06-08 16:52:24 +0000336void
337Function::Dump(Stream *s, bool show_context) const
338{
339 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
340 s->Indent();
341 *s << "Function" << (const UserID&)*this;
342
343 m_mangled.Dump(s);
344
345// FunctionInfo::Dump(s);
346 if (m_type)
347 {
348 *s << ", type = " << (void*)m_type;
349 /// << " (";
350 ///m_type->DumpTypeName(s);
351 ///s->PutChar(')');
352 }
353 else if (m_type_uid != LLDB_INVALID_UID)
354 *s << ", type_uid = " << m_type_uid;
355
356 s->EOL();
357 // Dump the root object
Greg Clayton75ccf502010-08-21 02:22:51 +0000358 if (m_block.BlockInfoHasBeenParsed ())
359 m_block.Dump(s, m_range.GetBaseAddress().GetFileAddress(), INT_MAX, show_context);
Chris Lattner24943d22010-06-08 16:52:24 +0000360}
361
362
363void
364Function::CalculateSymbolContext(SymbolContext* sc)
365{
366 sc->function = this;
367 m_comp_unit->CalculateSymbolContext(sc);
368}
369
370void
371Function::DumpSymbolContext(Stream *s)
372{
373 m_comp_unit->DumpSymbolContext(s);
374 s->Printf(", Function{0x%8.8x}", GetID());
375}
376
377size_t
378Function::MemorySize () const
379{
Greg Clayton75ccf502010-08-21 02:22:51 +0000380 size_t mem_size = sizeof(Function) + m_block.MemorySize();
Chris Lattner24943d22010-06-08 16:52:24 +0000381 return mem_size;
382}
383
384Type*
385Function::GetType()
386{
387 return m_type;
388}
389
390const Type*
391Function::GetType() const
392{
393 return m_type;
394}
395
396Type
397Function::GetReturnType ()
398{
399 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType()));
400 assert (clang_type->isFunctionType());
401 clang::FunctionType *function_type = dyn_cast<clang::FunctionType> (clang_type);
402 clang::QualType fun_return_qualtype = function_type->getResultType();
403
Greg Clayton1674b122010-07-21 22:12:05 +0000404 const ConstString fun_return_name(ClangASTType::GetClangTypeName(fun_return_qualtype.getAsOpaquePtr()));
Chris Lattner24943d22010-06-08 16:52:24 +0000405
406 SymbolContext sc;
407 CalculateSymbolContext (&sc);
408 // Null out everything below the CompUnit 'cause we don't actually know these.
409
Greg Clayton960d6a42010-08-03 00:35:52 +0000410 size_t bit_size = ClangASTType::GetClangTypeBitWidth ((GetType()->GetClangASTContext().getASTContext()), fun_return_qualtype.getAsOpaquePtr());
Chris Lattner24943d22010-06-08 16:52:24 +0000411 Type return_type (0, GetType()->GetSymbolFile(), fun_return_name, bit_size, sc.comp_unit, 0, Type::eTypeUIDSynthetic, Declaration(), fun_return_qualtype.getAsOpaquePtr());
412 return return_type;
413}
414
415int
416Function::GetArgumentCount ()
417{
418 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType()));
419 assert (clang_type->isFunctionType());
420 if (!clang_type->isFunctionProtoType())
421 return -1;
422
423 const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
424 if (function_proto_type != NULL)
425 return function_proto_type->getNumArgs();
426
427 return 0;
428}
429
430const Type
431Function::GetArgumentTypeAtIndex (size_t idx)
432{
433 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType()));
434 assert (clang_type->isFunctionType());
435 if (!clang_type->isFunctionProtoType())
436 return Type();
437
438 const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
439 if (function_proto_type != NULL)
440 {
441 unsigned num_args = function_proto_type->getNumArgs();
442 if (idx >= num_args)
443 return Type();
444 clang::QualType arg_qualtype = (function_proto_type->arg_type_begin())[idx];
445
Greg Clayton1674b122010-07-21 22:12:05 +0000446 const ConstString arg_return_name(ClangASTType::GetClangTypeName(arg_qualtype.getAsOpaquePtr()));
Chris Lattner24943d22010-06-08 16:52:24 +0000447 SymbolContext sc;
448 CalculateSymbolContext (&sc);
449 // Null out everything below the CompUnit 'cause we don't actually know these.
450
Greg Clayton960d6a42010-08-03 00:35:52 +0000451 size_t bit_size = ClangASTType::GetClangTypeBitWidth ((GetType()->GetClangASTContext().getASTContext()), arg_qualtype.getAsOpaquePtr());
Chris Lattner24943d22010-06-08 16:52:24 +0000452 Type arg_type (0, GetType()->GetSymbolFile(), arg_return_name, bit_size, sc.comp_unit, 0, Type::eTypeUIDSynthetic, Declaration(), arg_qualtype.getAsOpaquePtr());
453 return arg_type;
454 }
455
456 return Type();
457}
458
459const char *
460Function::GetArgumentNameAtIndex (size_t idx)
461{
462 clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetOpaqueClangQualType())->getTypePtr();
463 assert (clang_type->isFunctionType());
464 if (!clang_type->isFunctionProtoType())
465 return NULL;
466 return NULL;
467}
468
469bool
470Function::IsVariadic ()
471{
472 const clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetOpaqueClangQualType())->getTypePtr();
473 assert (clang_type->isFunctionType());
474 if (!clang_type->isFunctionProtoType())
475 return false;
476
477 const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
478 if (function_proto_type != NULL)
479 {
480 return function_proto_type->isVariadic();
481 }
482
483 return false;
484}
485
486uint32_t
487Function::GetPrologueByteSize ()
488{
489 if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize))
490 {
491 m_flags.Set(flagsCalculatedPrologueSize);
492 LineTable* line_table = m_comp_unit->GetLineTable ();
493 if (line_table)
494 {
495 LineEntry line_entry;
496 if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), line_entry))
497 m_prologue_byte_size = line_entry.range.GetByteSize();
498 }
499 }
500 return m_prologue_byte_size;
501}
502
503
504