blob: e89782dd3c280db78df1955629cd19eec596f45b [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
Greg Claytonc67b7d12010-09-10 01:30:46 +000021using namespace lldb;
Chris Lattner24943d22010-06-08 16:52:24 +000022using namespace lldb_private;
23
24//----------------------------------------------------------------------
25// Basic function information is contained in the FunctionInfo class.
26// It is designed to contain the name, linkage name, and declaration
27// location.
28//----------------------------------------------------------------------
29FunctionInfo::FunctionInfo (const char *name, const Declaration *decl_ptr) :
30 m_name(name),
31 m_declaration(decl_ptr)
32{
33}
34
35
36FunctionInfo::FunctionInfo (const ConstString& name, const Declaration *decl_ptr) :
37 m_name(name),
38 m_declaration(decl_ptr)
39{
40}
41
42
43FunctionInfo::~FunctionInfo()
44{
45}
46
47void
Greg Clayton1924e242010-09-15 05:51:24 +000048FunctionInfo::Dump(Stream *s, bool show_fullpaths) const
Chris Lattner24943d22010-06-08 16:52:24 +000049{
50 if (m_name)
51 *s << ", name = \"" << m_name << "\"";
Greg Clayton1924e242010-09-15 05:51:24 +000052 m_declaration.Dump(s, show_fullpaths);
Chris Lattner24943d22010-06-08 16:52:24 +000053}
54
55
56int
57FunctionInfo::Compare(const FunctionInfo& a, const FunctionInfo& b)
58{
59 int result = ConstString::Compare(a.GetName(), b.GetName());
60 if (result)
61 return result;
62
63 return Declaration::Compare(a.m_declaration, b.m_declaration);
64}
65
66
67Declaration&
68FunctionInfo::GetDeclaration()
69{
70 return m_declaration;
71}
72
73const Declaration&
74FunctionInfo::GetDeclaration() const
75{
76 return m_declaration;
77}
78
79const ConstString&
80FunctionInfo::GetName() const
81{
82 return m_name;
83}
84
85size_t
86FunctionInfo::MemorySize() const
87{
88 return m_name.MemorySize() + m_declaration.MemorySize();
89}
90
91
92InlineFunctionInfo::InlineFunctionInfo
93(
94 const char *name,
95 const char *mangled,
96 const Declaration *decl_ptr,
97 const Declaration *call_decl_ptr
98) :
99 FunctionInfo(name, decl_ptr),
100 m_mangled(mangled, true),
101 m_call_decl (call_decl_ptr)
102{
103}
104
105InlineFunctionInfo::InlineFunctionInfo
106(
107 const ConstString& name,
108 const Mangled &mangled,
109 const Declaration *decl_ptr,
110 const Declaration *call_decl_ptr
111) :
112 FunctionInfo(name, decl_ptr),
113 m_mangled(mangled),
114 m_call_decl (call_decl_ptr)
115{
116}
117
118InlineFunctionInfo::~InlineFunctionInfo()
119{
120}
121
122int
123InlineFunctionInfo::Compare(const InlineFunctionInfo& a, const InlineFunctionInfo& b)
124{
125
126 int result = FunctionInfo::Compare(a, b);
127 if (result)
128 return result;
129 // only compare the mangled names if both have them
130 return Mangled::Compare(a.m_mangled, a.m_mangled);
131}
132
133void
Greg Clayton1924e242010-09-15 05:51:24 +0000134InlineFunctionInfo::Dump(Stream *s, bool show_fullpaths) const
Chris Lattner24943d22010-06-08 16:52:24 +0000135{
Greg Clayton1924e242010-09-15 05:51:24 +0000136 FunctionInfo::Dump(s, show_fullpaths);
Chris Lattner24943d22010-06-08 16:52:24 +0000137 if (m_mangled)
138 m_mangled.Dump(s);
139}
140
141void
142InlineFunctionInfo::DumpStopContext (Stream *s) const
143{
144// s->Indent("[inlined] ");
145 s->Indent();
146 if (m_mangled)
147 s->PutCString (m_mangled.GetName().AsCString());
148 else
149 s->PutCString (m_name.AsCString());
150}
151
Greg Clayton33ed1702010-08-24 00:45:41 +0000152
153const ConstString &
154InlineFunctionInfo::GetName () const
155{
156 if (m_mangled)
157 return m_mangled.GetName();
158 return m_name;
159}
160
161
Chris Lattner24943d22010-06-08 16:52:24 +0000162Declaration &
163InlineFunctionInfo::GetCallSite ()
164{
165 return m_call_decl;
166}
167
168const Declaration &
169InlineFunctionInfo::GetCallSite () const
170{
171 return m_call_decl;
172}
173
174
175Mangled&
176InlineFunctionInfo::GetMangled()
177{
178 return m_mangled;
179}
180
181const Mangled&
182InlineFunctionInfo::GetMangled() const
183{
184 return m_mangled;
185}
186
187size_t
188InlineFunctionInfo::MemorySize() const
189{
190 return FunctionInfo::MemorySize() + m_mangled.MemorySize();
191}
192
193//----------------------------------------------------------------------
194//
195//----------------------------------------------------------------------
196Function::Function
197(
198 CompileUnit *comp_unit,
199 lldb::user_id_t func_uid,
200 lldb::user_id_t type_uid,
201 const Mangled &mangled,
202 Type * type,
203 const AddressRange& range
204) :
Greg Clayton75ccf502010-08-21 02:22:51 +0000205 UserID (func_uid),
206 m_comp_unit (comp_unit),
207 m_type_uid (type_uid),
208 m_type (type),
209 m_mangled (mangled),
210 m_block (func_uid),
211 m_range (range),
212 m_frame_base (),
213 m_flags (),
214 m_prologue_byte_size (0)
Chris Lattner24943d22010-06-08 16:52:24 +0000215{
Greg Clayton75ccf502010-08-21 02:22:51 +0000216 m_block.SetParentScope(this);
Chris Lattner24943d22010-06-08 16:52:24 +0000217 assert(comp_unit != NULL);
218}
219
220Function::Function
221(
222 CompileUnit *comp_unit,
223 lldb::user_id_t func_uid,
224 lldb::user_id_t type_uid,
225 const char *mangled,
226 Type *type,
227 const AddressRange &range
228) :
Greg Clayton75ccf502010-08-21 02:22:51 +0000229 UserID (func_uid),
230 m_comp_unit (comp_unit),
231 m_type_uid (type_uid),
232 m_type (type),
233 m_mangled (mangled, true),
234 m_block (func_uid),
235 m_range (range),
236 m_frame_base (),
237 m_flags (),
238 m_prologue_byte_size (0)
Chris Lattner24943d22010-06-08 16:52:24 +0000239{
Greg Clayton75ccf502010-08-21 02:22:51 +0000240 m_block.SetParentScope(this);
Chris Lattner24943d22010-06-08 16:52:24 +0000241 assert(comp_unit != NULL);
242}
243
244
245Function::~Function()
246{
247}
248
Jim Inghamb75b4662010-08-20 01:15:01 +0000249void
250Function::GetStartLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
251{
252 line_no = 0;
253 source_file.Clear();
254
255 if (m_comp_unit == NULL)
256 return;
257
258 if (m_type != NULL && m_type->GetDeclaration().GetLine() != 0)
259 {
260 source_file = m_type->GetDeclaration().GetFile();
261 line_no = m_type->GetDeclaration().GetLine();
262 }
263 else
264 {
265 LineTable *line_table = m_comp_unit->GetLineTable();
266 if (line_table == NULL)
267 return;
268
269 LineEntry line_entry;
270 if (line_table->FindLineEntryByAddress (GetAddressRange().GetBaseAddress(), line_entry, NULL))
271 {
272 line_no = line_entry.line;
273 source_file = line_entry.file;
274 }
275 }
276}
277
278void
279Function::GetEndLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
280{
281 line_no = 0;
282 source_file.Clear();
283
284 // The -1 is kind of cheesy, but I want to get the last line entry for the given function, not the
285 // first entry of the next.
286 Address scratch_addr(GetAddressRange().GetBaseAddress());
287 scratch_addr.SetOffset (scratch_addr.GetOffset() + GetAddressRange().GetByteSize() - 1);
288
289 LineTable *line_table = m_comp_unit->GetLineTable();
290 if (line_table == NULL)
291 return;
292
293 LineEntry line_entry;
294 if (line_table->FindLineEntryByAddress (scratch_addr, line_entry, NULL))
295 {
296 line_no = line_entry.line;
297 source_file = line_entry.file;
298 }
299}
300
Greg Clayton75ccf502010-08-21 02:22:51 +0000301Block &
302Function::GetBlock (bool can_create)
Chris Lattner24943d22010-06-08 16:52:24 +0000303{
Greg Clayton75ccf502010-08-21 02:22:51 +0000304 if (!m_block.BlockInfoHasBeenParsed() && can_create)
Chris Lattner24943d22010-06-08 16:52:24 +0000305 {
306 SymbolContext sc;
307 CalculateSymbolContext(&sc);
308 assert(sc.module_sp);
309 sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc);
Greg Clayton75ccf502010-08-21 02:22:51 +0000310 m_block.SetBlockInfoHasBeenParsed (true, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000311 }
Greg Clayton75ccf502010-08-21 02:22:51 +0000312 return m_block;
Chris Lattner24943d22010-06-08 16:52:24 +0000313}
314
315CompileUnit*
316Function::GetCompileUnit()
317{
318 return m_comp_unit;
319}
320
321const CompileUnit*
322Function::GetCompileUnit() const
323{
324 return m_comp_unit;
325}
326
Greg Clayton12bec712010-06-28 21:30:43 +0000327
328void
Greg Claytoneea26402010-09-14 23:36:40 +0000329Function::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target)
Greg Clayton12bec712010-06-28 21:30:43 +0000330{
331 Type* func_type = GetType();
Greg Claytonc67b7d12010-09-10 01:30:46 +0000332 *s << "id = " << (const UserID&)*this << ", name = \"" << func_type->GetName() << "\", range = ";
333
334 Address::DumpStyle fallback_style;
335 if (level == eDescriptionLevelVerbose)
336 fallback_style = Address::DumpStyleModuleWithFileAddress;
337 else
338 fallback_style = Address::DumpStyleFileAddress;
Greg Claytoneea26402010-09-14 23:36:40 +0000339 GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, fallback_style);
Greg Clayton12bec712010-06-28 21:30:43 +0000340}
341
Chris Lattner24943d22010-06-08 16:52:24 +0000342void
343Function::Dump(Stream *s, bool show_context) const
344{
345 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
346 s->Indent();
347 *s << "Function" << (const UserID&)*this;
348
349 m_mangled.Dump(s);
350
351// FunctionInfo::Dump(s);
352 if (m_type)
353 {
354 *s << ", type = " << (void*)m_type;
355 /// << " (";
356 ///m_type->DumpTypeName(s);
357 ///s->PutChar(')');
358 }
359 else if (m_type_uid != LLDB_INVALID_UID)
360 *s << ", type_uid = " << m_type_uid;
361
362 s->EOL();
363 // Dump the root object
Greg Clayton75ccf502010-08-21 02:22:51 +0000364 if (m_block.BlockInfoHasBeenParsed ())
365 m_block.Dump(s, m_range.GetBaseAddress().GetFileAddress(), INT_MAX, show_context);
Chris Lattner24943d22010-06-08 16:52:24 +0000366}
367
368
369void
370Function::CalculateSymbolContext(SymbolContext* sc)
371{
372 sc->function = this;
373 m_comp_unit->CalculateSymbolContext(sc);
374}
375
376void
377Function::DumpSymbolContext(Stream *s)
378{
379 m_comp_unit->DumpSymbolContext(s);
380 s->Printf(", Function{0x%8.8x}", GetID());
381}
382
383size_t
384Function::MemorySize () const
385{
Greg Clayton75ccf502010-08-21 02:22:51 +0000386 size_t mem_size = sizeof(Function) + m_block.MemorySize();
Chris Lattner24943d22010-06-08 16:52:24 +0000387 return mem_size;
388}
389
390Type*
391Function::GetType()
392{
393 return m_type;
394}
395
396const Type*
397Function::GetType() const
398{
399 return m_type;
400}
401
402Type
403Function::GetReturnType ()
404{
Greg Clayton462d4142010-09-29 01:12:09 +0000405 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetClangType()));
Chris Lattner24943d22010-06-08 16:52:24 +0000406 assert (clang_type->isFunctionType());
407 clang::FunctionType *function_type = dyn_cast<clang::FunctionType> (clang_type);
408 clang::QualType fun_return_qualtype = function_type->getResultType();
409
Greg Clayton1674b122010-07-21 22:12:05 +0000410 const ConstString fun_return_name(ClangASTType::GetClangTypeName(fun_return_qualtype.getAsOpaquePtr()));
Chris Lattner24943d22010-06-08 16:52:24 +0000411
412 SymbolContext sc;
413 CalculateSymbolContext (&sc);
414 // Null out everything below the CompUnit 'cause we don't actually know these.
415
Greg Clayton960d6a42010-08-03 00:35:52 +0000416 size_t bit_size = ClangASTType::GetClangTypeBitWidth ((GetType()->GetClangASTContext().getASTContext()), fun_return_qualtype.getAsOpaquePtr());
Greg Clayton4b407112010-09-30 21:49:03 +0000417 Type return_type (0, GetType()->GetSymbolFile(), fun_return_name, bit_size, sc.comp_unit, 0, Type::eEncodingIsSyntheticUID, Declaration(), fun_return_qualtype.getAsOpaquePtr(), false);
Chris Lattner24943d22010-06-08 16:52:24 +0000418 return return_type;
419}
420
421int
422Function::GetArgumentCount ()
423{
Greg Clayton462d4142010-09-29 01:12:09 +0000424 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetClangType()));
Chris Lattner24943d22010-06-08 16:52:24 +0000425 assert (clang_type->isFunctionType());
426 if (!clang_type->isFunctionProtoType())
427 return -1;
428
429 const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
430 if (function_proto_type != NULL)
431 return function_proto_type->getNumArgs();
432
433 return 0;
434}
435
436const Type
437Function::GetArgumentTypeAtIndex (size_t idx)
438{
Greg Clayton462d4142010-09-29 01:12:09 +0000439 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetClangType()));
Chris Lattner24943d22010-06-08 16:52:24 +0000440 assert (clang_type->isFunctionType());
441 if (!clang_type->isFunctionProtoType())
442 return Type();
443
444 const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
445 if (function_proto_type != NULL)
446 {
447 unsigned num_args = function_proto_type->getNumArgs();
448 if (idx >= num_args)
449 return Type();
450 clang::QualType arg_qualtype = (function_proto_type->arg_type_begin())[idx];
451
Greg Clayton1674b122010-07-21 22:12:05 +0000452 const ConstString arg_return_name(ClangASTType::GetClangTypeName(arg_qualtype.getAsOpaquePtr()));
Chris Lattner24943d22010-06-08 16:52:24 +0000453 SymbolContext sc;
454 CalculateSymbolContext (&sc);
455 // Null out everything below the CompUnit 'cause we don't actually know these.
456
Greg Clayton960d6a42010-08-03 00:35:52 +0000457 size_t bit_size = ClangASTType::GetClangTypeBitWidth ((GetType()->GetClangASTContext().getASTContext()), arg_qualtype.getAsOpaquePtr());
Greg Clayton4b407112010-09-30 21:49:03 +0000458 Type arg_type (0, GetType()->GetSymbolFile(), arg_return_name, bit_size, sc.comp_unit, 0, Type::eEncodingIsSyntheticUID, Declaration(), arg_qualtype.getAsOpaquePtr(), false);
Chris Lattner24943d22010-06-08 16:52:24 +0000459 return arg_type;
460 }
461
462 return Type();
463}
464
465const char *
466Function::GetArgumentNameAtIndex (size_t idx)
467{
Greg Clayton462d4142010-09-29 01:12:09 +0000468 clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetClangType())->getTypePtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000469 assert (clang_type->isFunctionType());
470 if (!clang_type->isFunctionProtoType())
471 return NULL;
472 return NULL;
473}
474
475bool
476Function::IsVariadic ()
477{
Greg Clayton462d4142010-09-29 01:12:09 +0000478 const clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetClangType())->getTypePtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000479 assert (clang_type->isFunctionType());
480 if (!clang_type->isFunctionProtoType())
481 return false;
482
483 const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
484 if (function_proto_type != NULL)
485 {
486 return function_proto_type->isVariadic();
487 }
488
489 return false;
490}
491
492uint32_t
493Function::GetPrologueByteSize ()
494{
495 if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize))
496 {
497 m_flags.Set(flagsCalculatedPrologueSize);
498 LineTable* line_table = m_comp_unit->GetLineTable ();
499 if (line_table)
500 {
501 LineEntry line_entry;
502 if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), line_entry))
Greg Clayton2b8732c2010-11-11 20:13:30 +0000503 {
504 // We need to take the delta of the end of the first line entry
505 // as a file address and the start file address of the function
506 // in case the first line entry doesn't start at the beginning
507 // of the function.
508 const addr_t func_start_file_addr = m_range.GetBaseAddress().GetFileAddress();
509 const addr_t line_entry_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress() + line_entry.range.GetByteSize();
510 if (line_entry_end_file_addr > func_start_file_addr)
511 m_prologue_byte_size = line_entry_end_file_addr - func_start_file_addr;
512 }
Chris Lattner24943d22010-06-08 16:52:24 +0000513 }
514 }
515 return m_prologue_byte_size;
516}
517
518
519