blob: eda63d603daaeb6568a5c795189a840352753153 [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
151Declaration &
152InlineFunctionInfo::GetCallSite ()
153{
154 return m_call_decl;
155}
156
157const Declaration &
158InlineFunctionInfo::GetCallSite () const
159{
160 return m_call_decl;
161}
162
163
164Mangled&
165InlineFunctionInfo::GetMangled()
166{
167 return m_mangled;
168}
169
170const Mangled&
171InlineFunctionInfo::GetMangled() const
172{
173 return m_mangled;
174}
175
176size_t
177InlineFunctionInfo::MemorySize() const
178{
179 return FunctionInfo::MemorySize() + m_mangled.MemorySize();
180}
181
182//----------------------------------------------------------------------
183//
184//----------------------------------------------------------------------
185Function::Function
186(
187 CompileUnit *comp_unit,
188 lldb::user_id_t func_uid,
189 lldb::user_id_t type_uid,
190 const Mangled &mangled,
191 Type * type,
192 const AddressRange& range
193) :
194 UserID(func_uid),
195 m_comp_unit(comp_unit),
196 m_type_uid(type_uid),
197 m_type(type),
198 m_mangled(mangled),
199 m_blocks(this, range),
200 m_frame_base(),
201 m_flags(),
202 m_prologue_byte_size(0)
203{
204 assert(comp_unit != NULL);
205}
206
207Function::Function
208(
209 CompileUnit *comp_unit,
210 lldb::user_id_t func_uid,
211 lldb::user_id_t type_uid,
212 const char *mangled,
213 Type *type,
214 const AddressRange &range
215) :
216 UserID(func_uid),
217 m_comp_unit(comp_unit),
218 m_type_uid(type_uid),
219 m_type(type),
220 m_mangled(mangled, true),
221 m_blocks(this, range),
222 m_frame_base(),
223 m_flags(),
224 m_prologue_byte_size(0)
225{
226 assert(comp_unit != NULL);
227}
228
229
230Function::~Function()
231{
232}
233
234const AddressRange &
235Function::GetAddressRange()
236{
237 return GetBlocks(true).GetAddressRange();
238}
239
Jim Inghamb75b4662010-08-20 01:15:01 +0000240bool
241Function::IsInlined()
242{
243 Block *root_block = GetBlocks(true).GetBlockByID(Block::RootID);
244 if (root_block)
245 {
246 if (root_block->InlinedFunctionInfo() != NULL)
247 return true;
248 }
249 return false;
250
251}
252void
253Function::GetStartLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
254{
255 line_no = 0;
256 source_file.Clear();
257
258 if (m_comp_unit == NULL)
259 return;
260
261 if (m_type != NULL && m_type->GetDeclaration().GetLine() != 0)
262 {
263 source_file = m_type->GetDeclaration().GetFile();
264 line_no = m_type->GetDeclaration().GetLine();
265 }
266 else
267 {
268 LineTable *line_table = m_comp_unit->GetLineTable();
269 if (line_table == NULL)
270 return;
271
272 LineEntry line_entry;
273 if (line_table->FindLineEntryByAddress (GetAddressRange().GetBaseAddress(), line_entry, NULL))
274 {
275 line_no = line_entry.line;
276 source_file = line_entry.file;
277 }
278 }
279}
280
281void
282Function::GetEndLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
283{
284 line_no = 0;
285 source_file.Clear();
286
287 // The -1 is kind of cheesy, but I want to get the last line entry for the given function, not the
288 // first entry of the next.
289 Address scratch_addr(GetAddressRange().GetBaseAddress());
290 scratch_addr.SetOffset (scratch_addr.GetOffset() + GetAddressRange().GetByteSize() - 1);
291
292 LineTable *line_table = m_comp_unit->GetLineTable();
293 if (line_table == NULL)
294 return;
295
296 LineEntry line_entry;
297 if (line_table->FindLineEntryByAddress (scratch_addr, line_entry, NULL))
298 {
299 line_no = line_entry.line;
300 source_file = line_entry.file;
301 }
302}
303
Chris Lattner24943d22010-06-08 16:52:24 +0000304BlockList &
305Function::GetBlocks(bool can_create)
306{
307 if (m_blocks.IsEmpty() && can_create)
308 {
309 SymbolContext sc;
310 CalculateSymbolContext(&sc);
311 assert(sc.module_sp);
312 sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc);
313 }
314 return m_blocks;
315}
316
317CompileUnit*
318Function::GetCompileUnit()
319{
320 return m_comp_unit;
321}
322
323const CompileUnit*
324Function::GetCompileUnit() const
325{
326 return m_comp_unit;
327}
328
Greg Clayton12bec712010-06-28 21:30:43 +0000329
330void
331Function::GetDescription(Stream *s, lldb::DescriptionLevel level, Process *process)
332{
333 Type* func_type = GetType();
334 *s << '"' << func_type->GetName() << "\", id = " << (const UserID&)*this;
335 *s << ", range = ";
336 GetAddressRange().Dump(s, process, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
337}
338
Chris Lattner24943d22010-06-08 16:52:24 +0000339void
340Function::Dump(Stream *s, bool show_context) const
341{
342 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
343 s->Indent();
344 *s << "Function" << (const UserID&)*this;
345
346 m_mangled.Dump(s);
347
348// FunctionInfo::Dump(s);
349 if (m_type)
350 {
351 *s << ", type = " << (void*)m_type;
352 /// << " (";
353 ///m_type->DumpTypeName(s);
354 ///s->PutChar(')');
355 }
356 else if (m_type_uid != LLDB_INVALID_UID)
357 *s << ", type_uid = " << m_type_uid;
358
359 s->EOL();
360 // Dump the root object
361 if (!m_blocks.IsEmpty())
362 m_blocks.Dump(s, Block::RootID, INT_MAX, show_context);
363}
364
365
366void
367Function::CalculateSymbolContext(SymbolContext* sc)
368{
369 sc->function = this;
370 m_comp_unit->CalculateSymbolContext(sc);
371}
372
373void
374Function::DumpSymbolContext(Stream *s)
375{
376 m_comp_unit->DumpSymbolContext(s);
377 s->Printf(", Function{0x%8.8x}", GetID());
378}
379
380size_t
381Function::MemorySize () const
382{
383 size_t mem_size = sizeof(Function) + m_blocks.MemorySize();
384 return mem_size;
385}
386
387Type*
388Function::GetType()
389{
390 return m_type;
391}
392
393const Type*
394Function::GetType() const
395{
396 return m_type;
397}
398
399Type
400Function::GetReturnType ()
401{
402 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType()));
403 assert (clang_type->isFunctionType());
404 clang::FunctionType *function_type = dyn_cast<clang::FunctionType> (clang_type);
405 clang::QualType fun_return_qualtype = function_type->getResultType();
406
Greg Clayton1674b122010-07-21 22:12:05 +0000407 const ConstString fun_return_name(ClangASTType::GetClangTypeName(fun_return_qualtype.getAsOpaquePtr()));
Chris Lattner24943d22010-06-08 16:52:24 +0000408
409 SymbolContext sc;
410 CalculateSymbolContext (&sc);
411 // Null out everything below the CompUnit 'cause we don't actually know these.
412
Greg Clayton960d6a42010-08-03 00:35:52 +0000413 size_t bit_size = ClangASTType::GetClangTypeBitWidth ((GetType()->GetClangASTContext().getASTContext()), fun_return_qualtype.getAsOpaquePtr());
Chris Lattner24943d22010-06-08 16:52:24 +0000414 Type return_type (0, GetType()->GetSymbolFile(), fun_return_name, bit_size, sc.comp_unit, 0, Type::eTypeUIDSynthetic, Declaration(), fun_return_qualtype.getAsOpaquePtr());
415 return return_type;
416}
417
418int
419Function::GetArgumentCount ()
420{
421 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType()));
422 assert (clang_type->isFunctionType());
423 if (!clang_type->isFunctionProtoType())
424 return -1;
425
426 const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
427 if (function_proto_type != NULL)
428 return function_proto_type->getNumArgs();
429
430 return 0;
431}
432
433const Type
434Function::GetArgumentTypeAtIndex (size_t idx)
435{
436 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType()));
437 assert (clang_type->isFunctionType());
438 if (!clang_type->isFunctionProtoType())
439 return Type();
440
441 const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
442 if (function_proto_type != NULL)
443 {
444 unsigned num_args = function_proto_type->getNumArgs();
445 if (idx >= num_args)
446 return Type();
447 clang::QualType arg_qualtype = (function_proto_type->arg_type_begin())[idx];
448
Greg Clayton1674b122010-07-21 22:12:05 +0000449 const ConstString arg_return_name(ClangASTType::GetClangTypeName(arg_qualtype.getAsOpaquePtr()));
Chris Lattner24943d22010-06-08 16:52:24 +0000450 SymbolContext sc;
451 CalculateSymbolContext (&sc);
452 // Null out everything below the CompUnit 'cause we don't actually know these.
453
Greg Clayton960d6a42010-08-03 00:35:52 +0000454 size_t bit_size = ClangASTType::GetClangTypeBitWidth ((GetType()->GetClangASTContext().getASTContext()), arg_qualtype.getAsOpaquePtr());
Chris Lattner24943d22010-06-08 16:52:24 +0000455 Type arg_type (0, GetType()->GetSymbolFile(), arg_return_name, bit_size, sc.comp_unit, 0, Type::eTypeUIDSynthetic, Declaration(), arg_qualtype.getAsOpaquePtr());
456 return arg_type;
457 }
458
459 return Type();
460}
461
462const char *
463Function::GetArgumentNameAtIndex (size_t idx)
464{
465 clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetOpaqueClangQualType())->getTypePtr();
466 assert (clang_type->isFunctionType());
467 if (!clang_type->isFunctionProtoType())
468 return NULL;
469 return NULL;
470}
471
472bool
473Function::IsVariadic ()
474{
475 const clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetOpaqueClangQualType())->getTypePtr();
476 assert (clang_type->isFunctionType());
477 if (!clang_type->isFunctionProtoType())
478 return false;
479
480 const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
481 if (function_proto_type != NULL)
482 {
483 return function_proto_type->isVariadic();
484 }
485
486 return false;
487}
488
489uint32_t
490Function::GetPrologueByteSize ()
491{
492 if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize))
493 {
494 m_flags.Set(flagsCalculatedPrologueSize);
495 LineTable* line_table = m_comp_unit->GetLineTable ();
496 if (line_table)
497 {
498 LineEntry line_entry;
499 if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), line_entry))
500 m_prologue_byte_size = line_entry.range.GetByteSize();
501 }
502 }
503 return m_prologue_byte_size;
504}
505
506
507