blob: c2ef05d3251e6aaaf00961f5b0a53b9ab088702b [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"
Sean Callanan9b6898f2011-07-30 02:42:06 +000020#include "llvm/Support/Casting.h"
Chris Lattner24943d22010-06-08 16:52:24 +000021
Greg Claytonc67b7d12010-09-10 01:30:46 +000022using namespace lldb;
Chris Lattner24943d22010-06-08 16:52:24 +000023using namespace lldb_private;
24
25//----------------------------------------------------------------------
26// Basic function information is contained in the FunctionInfo class.
27// It is designed to contain the name, linkage name, and declaration
28// location.
29//----------------------------------------------------------------------
30FunctionInfo::FunctionInfo (const char *name, const Declaration *decl_ptr) :
31 m_name(name),
32 m_declaration(decl_ptr)
33{
34}
35
36
37FunctionInfo::FunctionInfo (const ConstString& name, const Declaration *decl_ptr) :
38 m_name(name),
39 m_declaration(decl_ptr)
40{
41}
42
43
44FunctionInfo::~FunctionInfo()
45{
46}
47
48void
Greg Clayton1924e242010-09-15 05:51:24 +000049FunctionInfo::Dump(Stream *s, bool show_fullpaths) const
Chris Lattner24943d22010-06-08 16:52:24 +000050{
51 if (m_name)
52 *s << ", name = \"" << m_name << "\"";
Greg Clayton1924e242010-09-15 05:51:24 +000053 m_declaration.Dump(s, show_fullpaths);
Chris Lattner24943d22010-06-08 16:52:24 +000054}
55
56
57int
58FunctionInfo::Compare(const FunctionInfo& a, const FunctionInfo& b)
59{
60 int result = ConstString::Compare(a.GetName(), b.GetName());
61 if (result)
62 return result;
63
64 return Declaration::Compare(a.m_declaration, b.m_declaration);
65}
66
67
68Declaration&
69FunctionInfo::GetDeclaration()
70{
71 return m_declaration;
72}
73
74const Declaration&
75FunctionInfo::GetDeclaration() const
76{
77 return m_declaration;
78}
79
80const ConstString&
81FunctionInfo::GetName() const
82{
83 return m_name;
84}
85
86size_t
87FunctionInfo::MemorySize() const
88{
89 return m_name.MemorySize() + m_declaration.MemorySize();
90}
91
92
93InlineFunctionInfo::InlineFunctionInfo
94(
95 const char *name,
96 const char *mangled,
97 const Declaration *decl_ptr,
98 const Declaration *call_decl_ptr
99) :
100 FunctionInfo(name, decl_ptr),
101 m_mangled(mangled, true),
102 m_call_decl (call_decl_ptr)
103{
104}
105
106InlineFunctionInfo::InlineFunctionInfo
107(
108 const ConstString& name,
109 const Mangled &mangled,
110 const Declaration *decl_ptr,
111 const Declaration *call_decl_ptr
112) :
113 FunctionInfo(name, decl_ptr),
114 m_mangled(mangled),
115 m_call_decl (call_decl_ptr)
116{
117}
118
119InlineFunctionInfo::~InlineFunctionInfo()
120{
121}
122
123int
124InlineFunctionInfo::Compare(const InlineFunctionInfo& a, const InlineFunctionInfo& b)
125{
126
127 int result = FunctionInfo::Compare(a, b);
128 if (result)
129 return result;
130 // only compare the mangled names if both have them
131 return Mangled::Compare(a.m_mangled, a.m_mangled);
132}
133
134void
Greg Clayton1924e242010-09-15 05:51:24 +0000135InlineFunctionInfo::Dump(Stream *s, bool show_fullpaths) const
Chris Lattner24943d22010-06-08 16:52:24 +0000136{
Greg Clayton1924e242010-09-15 05:51:24 +0000137 FunctionInfo::Dump(s, show_fullpaths);
Chris Lattner24943d22010-06-08 16:52:24 +0000138 if (m_mangled)
139 m_mangled.Dump(s);
140}
141
142void
143InlineFunctionInfo::DumpStopContext (Stream *s) const
144{
145// s->Indent("[inlined] ");
146 s->Indent();
147 if (m_mangled)
148 s->PutCString (m_mangled.GetName().AsCString());
149 else
150 s->PutCString (m_name.AsCString());
151}
152
Greg Clayton33ed1702010-08-24 00:45:41 +0000153
154const ConstString &
155InlineFunctionInfo::GetName () const
156{
157 if (m_mangled)
158 return m_mangled.GetName();
159 return m_name;
160}
161
162
Chris Lattner24943d22010-06-08 16:52:24 +0000163Declaration &
164InlineFunctionInfo::GetCallSite ()
165{
166 return m_call_decl;
167}
168
169const Declaration &
170InlineFunctionInfo::GetCallSite () const
171{
172 return m_call_decl;
173}
174
175
176Mangled&
177InlineFunctionInfo::GetMangled()
178{
179 return m_mangled;
180}
181
182const Mangled&
183InlineFunctionInfo::GetMangled() const
184{
185 return m_mangled;
186}
187
188size_t
189InlineFunctionInfo::MemorySize() const
190{
191 return FunctionInfo::MemorySize() + m_mangled.MemorySize();
192}
193
194//----------------------------------------------------------------------
195//
196//----------------------------------------------------------------------
197Function::Function
198(
199 CompileUnit *comp_unit,
200 lldb::user_id_t func_uid,
201 lldb::user_id_t type_uid,
202 const Mangled &mangled,
203 Type * type,
204 const AddressRange& range
205) :
Greg Clayton75ccf502010-08-21 02:22:51 +0000206 UserID (func_uid),
207 m_comp_unit (comp_unit),
208 m_type_uid (type_uid),
209 m_type (type),
210 m_mangled (mangled),
211 m_block (func_uid),
212 m_range (range),
213 m_frame_base (),
214 m_flags (),
215 m_prologue_byte_size (0)
Chris Lattner24943d22010-06-08 16:52:24 +0000216{
Greg Clayton75ccf502010-08-21 02:22:51 +0000217 m_block.SetParentScope(this);
Chris Lattner24943d22010-06-08 16:52:24 +0000218 assert(comp_unit != NULL);
219}
220
221Function::Function
222(
223 CompileUnit *comp_unit,
224 lldb::user_id_t func_uid,
225 lldb::user_id_t type_uid,
226 const char *mangled,
227 Type *type,
228 const AddressRange &range
229) :
Greg Clayton75ccf502010-08-21 02:22:51 +0000230 UserID (func_uid),
231 m_comp_unit (comp_unit),
232 m_type_uid (type_uid),
233 m_type (type),
234 m_mangled (mangled, true),
235 m_block (func_uid),
236 m_range (range),
237 m_frame_base (),
238 m_flags (),
239 m_prologue_byte_size (0)
Chris Lattner24943d22010-06-08 16:52:24 +0000240{
Greg Clayton75ccf502010-08-21 02:22:51 +0000241 m_block.SetParentScope(this);
Chris Lattner24943d22010-06-08 16:52:24 +0000242 assert(comp_unit != NULL);
243}
244
245
246Function::~Function()
247{
248}
249
Jim Inghamb75b4662010-08-20 01:15:01 +0000250void
251Function::GetStartLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
252{
253 line_no = 0;
254 source_file.Clear();
255
256 if (m_comp_unit == NULL)
257 return;
258
259 if (m_type != NULL && m_type->GetDeclaration().GetLine() != 0)
260 {
261 source_file = m_type->GetDeclaration().GetFile();
262 line_no = m_type->GetDeclaration().GetLine();
263 }
264 else
265 {
266 LineTable *line_table = m_comp_unit->GetLineTable();
267 if (line_table == NULL)
268 return;
269
270 LineEntry line_entry;
271 if (line_table->FindLineEntryByAddress (GetAddressRange().GetBaseAddress(), line_entry, NULL))
272 {
273 line_no = line_entry.line;
274 source_file = line_entry.file;
275 }
276 }
277}
278
279void
280Function::GetEndLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
281{
282 line_no = 0;
283 source_file.Clear();
284
285 // The -1 is kind of cheesy, but I want to get the last line entry for the given function, not the
286 // first entry of the next.
287 Address scratch_addr(GetAddressRange().GetBaseAddress());
288 scratch_addr.SetOffset (scratch_addr.GetOffset() + GetAddressRange().GetByteSize() - 1);
289
290 LineTable *line_table = m_comp_unit->GetLineTable();
291 if (line_table == NULL)
292 return;
293
294 LineEntry line_entry;
295 if (line_table->FindLineEntryByAddress (scratch_addr, line_entry, NULL))
296 {
297 line_no = line_entry.line;
298 source_file = line_entry.file;
299 }
300}
301
Greg Clayton75ccf502010-08-21 02:22:51 +0000302Block &
303Function::GetBlock (bool can_create)
Chris Lattner24943d22010-06-08 16:52:24 +0000304{
Greg Clayton75ccf502010-08-21 02:22:51 +0000305 if (!m_block.BlockInfoHasBeenParsed() && can_create)
Chris Lattner24943d22010-06-08 16:52:24 +0000306 {
307 SymbolContext sc;
308 CalculateSymbolContext(&sc);
Greg Claytonb27e74b2011-06-24 03:47:23 +0000309 if (sc.module_sp)
310 {
311 sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc);
312 }
313 else
314 {
315 ::fprintf (stderr,
316 "unable to find module shared pointer for function '%s' in %s%s%s\n",
317 GetName().GetCString(),
318 m_comp_unit->GetDirectory().GetCString(),
319 m_comp_unit->GetDirectory() ? "/" : "",
320 m_comp_unit->GetFilename().GetCString());
321 }
Greg Clayton75ccf502010-08-21 02:22:51 +0000322 m_block.SetBlockInfoHasBeenParsed (true, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000323 }
Greg Clayton75ccf502010-08-21 02:22:51 +0000324 return m_block;
Chris Lattner24943d22010-06-08 16:52:24 +0000325}
326
327CompileUnit*
328Function::GetCompileUnit()
329{
330 return m_comp_unit;
331}
332
333const CompileUnit*
334Function::GetCompileUnit() const
335{
336 return m_comp_unit;
337}
338
Greg Clayton12bec712010-06-28 21:30:43 +0000339
340void
Greg Claytoneea26402010-09-14 23:36:40 +0000341Function::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target)
Greg Clayton12bec712010-06-28 21:30:43 +0000342{
343 Type* func_type = GetType();
Greg Claytonc67b7d12010-09-10 01:30:46 +0000344 *s << "id = " << (const UserID&)*this << ", name = \"" << func_type->GetName() << "\", range = ";
345
346 Address::DumpStyle fallback_style;
347 if (level == eDescriptionLevelVerbose)
348 fallback_style = Address::DumpStyleModuleWithFileAddress;
349 else
350 fallback_style = Address::DumpStyleFileAddress;
Greg Claytoneea26402010-09-14 23:36:40 +0000351 GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, fallback_style);
Greg Clayton12bec712010-06-28 21:30:43 +0000352}
353
Chris Lattner24943d22010-06-08 16:52:24 +0000354void
355Function::Dump(Stream *s, bool show_context) const
356{
357 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
358 s->Indent();
359 *s << "Function" << (const UserID&)*this;
360
361 m_mangled.Dump(s);
362
363// FunctionInfo::Dump(s);
364 if (m_type)
365 {
366 *s << ", type = " << (void*)m_type;
367 /// << " (";
368 ///m_type->DumpTypeName(s);
369 ///s->PutChar(')');
370 }
371 else if (m_type_uid != LLDB_INVALID_UID)
372 *s << ", type_uid = " << m_type_uid;
373
374 s->EOL();
375 // Dump the root object
Greg Clayton75ccf502010-08-21 02:22:51 +0000376 if (m_block.BlockInfoHasBeenParsed ())
377 m_block.Dump(s, m_range.GetBaseAddress().GetFileAddress(), INT_MAX, show_context);
Chris Lattner24943d22010-06-08 16:52:24 +0000378}
379
380
381void
382Function::CalculateSymbolContext(SymbolContext* sc)
383{
384 sc->function = this;
385 m_comp_unit->CalculateSymbolContext(sc);
386}
387
388void
389Function::DumpSymbolContext(Stream *s)
390{
391 m_comp_unit->DumpSymbolContext(s);
392 s->Printf(", Function{0x%8.8x}", GetID());
393}
394
395size_t
396Function::MemorySize () const
397{
Greg Clayton75ccf502010-08-21 02:22:51 +0000398 size_t mem_size = sizeof(Function) + m_block.MemorySize();
Chris Lattner24943d22010-06-08 16:52:24 +0000399 return mem_size;
400}
401
402Type*
403Function::GetType()
404{
405 return m_type;
406}
407
408const Type*
409Function::GetType() const
410{
411 return m_type;
412}
413
Greg Clayton04c9c7b2011-02-16 23:00:21 +0000414clang_type_t
415Function::GetReturnClangType ()
Chris Lattner24943d22010-06-08 16:52:24 +0000416{
Greg Clayton04c9c7b2011-02-16 23:00:21 +0000417 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetClangFullType()));
Sean Callanan9b6898f2011-07-30 02:42:06 +0000418 const clang::FunctionType *function_type = llvm::dyn_cast<clang::FunctionType> (clang_type);
Greg Clayton04c9c7b2011-02-16 23:00:21 +0000419 if (function_type)
420 return function_type->getResultType().getAsOpaquePtr();
421 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000422}
423
424int
425Function::GetArgumentCount ()
426{
Greg Clayton04c9c7b2011-02-16 23:00:21 +0000427 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetClangFullType()));
Chris Lattner24943d22010-06-08 16:52:24 +0000428 assert (clang_type->isFunctionType());
429 if (!clang_type->isFunctionProtoType())
430 return -1;
431
Sean Callanan9b6898f2011-07-30 02:42:06 +0000432 const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast<clang::FunctionProtoType>(clang_type);
Chris Lattner24943d22010-06-08 16:52:24 +0000433 if (function_proto_type != NULL)
434 return function_proto_type->getNumArgs();
435
436 return 0;
437}
438
Greg Clayton04c9c7b2011-02-16 23:00:21 +0000439clang_type_t
Chris Lattner24943d22010-06-08 16:52:24 +0000440Function::GetArgumentTypeAtIndex (size_t idx)
441{
Greg Clayton04c9c7b2011-02-16 23:00:21 +0000442 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetClangFullType()));
Sean Callanan9b6898f2011-07-30 02:42:06 +0000443 const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast<clang::FunctionProtoType>(clang_type);
Greg Clayton04c9c7b2011-02-16 23:00:21 +0000444 if (function_proto_type)
Chris Lattner24943d22010-06-08 16:52:24 +0000445 {
446 unsigned num_args = function_proto_type->getNumArgs();
447 if (idx >= num_args)
Greg Clayton04c9c7b2011-02-16 23:00:21 +0000448 return NULL;
449
450 return (function_proto_type->arg_type_begin())[idx].getAsOpaquePtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000451 }
Chris Lattner24943d22010-06-08 16:52:24 +0000452 return NULL;
453}
454
455bool
456Function::IsVariadic ()
457{
Greg Clayton04c9c7b2011-02-16 23:00:21 +0000458 const clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetClangFullType())->getTypePtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000459 assert (clang_type->isFunctionType());
460 if (!clang_type->isFunctionProtoType())
461 return false;
462
Sean Callanan9b6898f2011-07-30 02:42:06 +0000463 const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast<clang::FunctionProtoType>(clang_type);
Greg Clayton04c9c7b2011-02-16 23:00:21 +0000464 if (function_proto_type)
Chris Lattner24943d22010-06-08 16:52:24 +0000465 return function_proto_type->isVariadic();
Chris Lattner24943d22010-06-08 16:52:24 +0000466
467 return false;
468}
469
470uint32_t
471Function::GetPrologueByteSize ()
472{
473 if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize))
474 {
475 m_flags.Set(flagsCalculatedPrologueSize);
476 LineTable* line_table = m_comp_unit->GetLineTable ();
477 if (line_table)
478 {
479 LineEntry line_entry;
480 if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), line_entry))
Greg Clayton2b8732c2010-11-11 20:13:30 +0000481 {
482 // We need to take the delta of the end of the first line entry
483 // as a file address and the start file address of the function
484 // in case the first line entry doesn't start at the beginning
485 // of the function.
486 const addr_t func_start_file_addr = m_range.GetBaseAddress().GetFileAddress();
487 const addr_t line_entry_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress() + line_entry.range.GetByteSize();
488 if (line_entry_end_file_addr > func_start_file_addr)
489 m_prologue_byte_size = line_entry_end_file_addr - func_start_file_addr;
490 }
Chris Lattner24943d22010-06-08 16:52:24 +0000491 }
492 }
493 return m_prologue_byte_size;
494}
495
496
497