blob: 51c449acd93d4b9f47018babc791d733808e8599 [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"
13#include "lldb/Symbol/CompileUnit.h"
14#include "lldb/Symbol/LineTable.h"
15#include "lldb/Symbol/SymbolVendor.h"
16#include "lldb/Symbol/ClangASTContext.h"
17#include "clang/AST/Type.h"
18#include "clang/AST/CanonicalType.h"
19
20using namespace lldb_private;
21
22//----------------------------------------------------------------------
23// Basic function information is contained in the FunctionInfo class.
24// It is designed to contain the name, linkage name, and declaration
25// location.
26//----------------------------------------------------------------------
27FunctionInfo::FunctionInfo (const char *name, const Declaration *decl_ptr) :
28 m_name(name),
29 m_declaration(decl_ptr)
30{
31}
32
33
34FunctionInfo::FunctionInfo (const ConstString& name, const Declaration *decl_ptr) :
35 m_name(name),
36 m_declaration(decl_ptr)
37{
38}
39
40
41FunctionInfo::~FunctionInfo()
42{
43}
44
45void
46FunctionInfo::Dump(Stream *s) const
47{
48 if (m_name)
49 *s << ", name = \"" << m_name << "\"";
50 m_declaration.Dump(s);
51}
52
53
54int
55FunctionInfo::Compare(const FunctionInfo& a, const FunctionInfo& b)
56{
57 int result = ConstString::Compare(a.GetName(), b.GetName());
58 if (result)
59 return result;
60
61 return Declaration::Compare(a.m_declaration, b.m_declaration);
62}
63
64
65Declaration&
66FunctionInfo::GetDeclaration()
67{
68 return m_declaration;
69}
70
71const Declaration&
72FunctionInfo::GetDeclaration() const
73{
74 return m_declaration;
75}
76
77const ConstString&
78FunctionInfo::GetName() const
79{
80 return m_name;
81}
82
83size_t
84FunctionInfo::MemorySize() const
85{
86 return m_name.MemorySize() + m_declaration.MemorySize();
87}
88
89
90InlineFunctionInfo::InlineFunctionInfo
91(
92 const char *name,
93 const char *mangled,
94 const Declaration *decl_ptr,
95 const Declaration *call_decl_ptr
96) :
97 FunctionInfo(name, decl_ptr),
98 m_mangled(mangled, true),
99 m_call_decl (call_decl_ptr)
100{
101}
102
103InlineFunctionInfo::InlineFunctionInfo
104(
105 const ConstString& name,
106 const Mangled &mangled,
107 const Declaration *decl_ptr,
108 const Declaration *call_decl_ptr
109) :
110 FunctionInfo(name, decl_ptr),
111 m_mangled(mangled),
112 m_call_decl (call_decl_ptr)
113{
114}
115
116InlineFunctionInfo::~InlineFunctionInfo()
117{
118}
119
120int
121InlineFunctionInfo::Compare(const InlineFunctionInfo& a, const InlineFunctionInfo& b)
122{
123
124 int result = FunctionInfo::Compare(a, b);
125 if (result)
126 return result;
127 // only compare the mangled names if both have them
128 return Mangled::Compare(a.m_mangled, a.m_mangled);
129}
130
131void
132InlineFunctionInfo::Dump(Stream *s) const
133{
134 FunctionInfo::Dump(s);
135 if (m_mangled)
136 m_mangled.Dump(s);
137}
138
139void
140InlineFunctionInfo::DumpStopContext (Stream *s) const
141{
142// s->Indent("[inlined] ");
143 s->Indent();
144 if (m_mangled)
145 s->PutCString (m_mangled.GetName().AsCString());
146 else
147 s->PutCString (m_name.AsCString());
148}
149
150Declaration &
151InlineFunctionInfo::GetCallSite ()
152{
153 return m_call_decl;
154}
155
156const Declaration &
157InlineFunctionInfo::GetCallSite () const
158{
159 return m_call_decl;
160}
161
162
163Mangled&
164InlineFunctionInfo::GetMangled()
165{
166 return m_mangled;
167}
168
169const Mangled&
170InlineFunctionInfo::GetMangled() const
171{
172 return m_mangled;
173}
174
175size_t
176InlineFunctionInfo::MemorySize() const
177{
178 return FunctionInfo::MemorySize() + m_mangled.MemorySize();
179}
180
181//----------------------------------------------------------------------
182//
183//----------------------------------------------------------------------
184Function::Function
185(
186 CompileUnit *comp_unit,
187 lldb::user_id_t func_uid,
188 lldb::user_id_t type_uid,
189 const Mangled &mangled,
190 Type * type,
191 const AddressRange& range
192) :
193 UserID(func_uid),
194 m_comp_unit(comp_unit),
195 m_type_uid(type_uid),
196 m_type(type),
197 m_mangled(mangled),
198 m_blocks(this, range),
199 m_frame_base(),
200 m_flags(),
201 m_prologue_byte_size(0)
202{
203 assert(comp_unit != NULL);
204}
205
206Function::Function
207(
208 CompileUnit *comp_unit,
209 lldb::user_id_t func_uid,
210 lldb::user_id_t type_uid,
211 const char *mangled,
212 Type *type,
213 const AddressRange &range
214) :
215 UserID(func_uid),
216 m_comp_unit(comp_unit),
217 m_type_uid(type_uid),
218 m_type(type),
219 m_mangled(mangled, true),
220 m_blocks(this, range),
221 m_frame_base(),
222 m_flags(),
223 m_prologue_byte_size(0)
224{
225 assert(comp_unit != NULL);
226}
227
228
229Function::~Function()
230{
231}
232
233const AddressRange &
234Function::GetAddressRange()
235{
236 return GetBlocks(true).GetAddressRange();
237}
238
239BlockList &
240Function::GetBlocks(bool can_create)
241{
242 if (m_blocks.IsEmpty() && can_create)
243 {
244 SymbolContext sc;
245 CalculateSymbolContext(&sc);
246 assert(sc.module_sp);
247 sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc);
248 }
249 return m_blocks;
250}
251
252CompileUnit*
253Function::GetCompileUnit()
254{
255 return m_comp_unit;
256}
257
258const CompileUnit*
259Function::GetCompileUnit() const
260{
261 return m_comp_unit;
262}
263
264void
265Function::Dump(Stream *s, bool show_context) const
266{
267 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
268 s->Indent();
269 *s << "Function" << (const UserID&)*this;
270
271 m_mangled.Dump(s);
272
273// FunctionInfo::Dump(s);
274 if (m_type)
275 {
276 *s << ", type = " << (void*)m_type;
277 /// << " (";
278 ///m_type->DumpTypeName(s);
279 ///s->PutChar(')');
280 }
281 else if (m_type_uid != LLDB_INVALID_UID)
282 *s << ", type_uid = " << m_type_uid;
283
284 s->EOL();
285 // Dump the root object
286 if (!m_blocks.IsEmpty())
287 m_blocks.Dump(s, Block::RootID, INT_MAX, show_context);
288}
289
290
291void
292Function::CalculateSymbolContext(SymbolContext* sc)
293{
294 sc->function = this;
295 m_comp_unit->CalculateSymbolContext(sc);
296}
297
298void
299Function::DumpSymbolContext(Stream *s)
300{
301 m_comp_unit->DumpSymbolContext(s);
302 s->Printf(", Function{0x%8.8x}", GetID());
303}
304
305size_t
306Function::MemorySize () const
307{
308 size_t mem_size = sizeof(Function) + m_blocks.MemorySize();
309 return mem_size;
310}
311
312Type*
313Function::GetType()
314{
315 return m_type;
316}
317
318const Type*
319Function::GetType() const
320{
321 return m_type;
322}
323
324Type
325Function::GetReturnType ()
326{
327 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType()));
328 assert (clang_type->isFunctionType());
329 clang::FunctionType *function_type = dyn_cast<clang::FunctionType> (clang_type);
330 clang::QualType fun_return_qualtype = function_type->getResultType();
331
332 const ConstString fun_return_name(Type::GetClangTypeName(fun_return_qualtype.getAsOpaquePtr()));
333
334 SymbolContext sc;
335 CalculateSymbolContext (&sc);
336 // Null out everything below the CompUnit 'cause we don't actually know these.
337
338 size_t bit_size = ClangASTContext::GetTypeBitSize ((GetType()->GetClangASTContext().getASTContext()), &fun_return_qualtype);
339 Type return_type (0, GetType()->GetSymbolFile(), fun_return_name, bit_size, sc.comp_unit, 0, Type::eTypeUIDSynthetic, Declaration(), fun_return_qualtype.getAsOpaquePtr());
340 return return_type;
341}
342
343int
344Function::GetArgumentCount ()
345{
346 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType()));
347 assert (clang_type->isFunctionType());
348 if (!clang_type->isFunctionProtoType())
349 return -1;
350
351 const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
352 if (function_proto_type != NULL)
353 return function_proto_type->getNumArgs();
354
355 return 0;
356}
357
358const Type
359Function::GetArgumentTypeAtIndex (size_t idx)
360{
361 clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType()));
362 assert (clang_type->isFunctionType());
363 if (!clang_type->isFunctionProtoType())
364 return Type();
365
366 const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
367 if (function_proto_type != NULL)
368 {
369 unsigned num_args = function_proto_type->getNumArgs();
370 if (idx >= num_args)
371 return Type();
372 clang::QualType arg_qualtype = (function_proto_type->arg_type_begin())[idx];
373
374 const ConstString arg_return_name(Type::GetClangTypeName(arg_qualtype.getAsOpaquePtr()));
375 SymbolContext sc;
376 CalculateSymbolContext (&sc);
377 // Null out everything below the CompUnit 'cause we don't actually know these.
378
379 size_t bit_size = ClangASTContext::GetTypeBitSize ((GetType()->GetClangASTContext().getASTContext()), &arg_qualtype);
380 Type arg_type (0, GetType()->GetSymbolFile(), arg_return_name, bit_size, sc.comp_unit, 0, Type::eTypeUIDSynthetic, Declaration(), arg_qualtype.getAsOpaquePtr());
381 return arg_type;
382 }
383
384 return Type();
385}
386
387const char *
388Function::GetArgumentNameAtIndex (size_t idx)
389{
390 clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetOpaqueClangQualType())->getTypePtr();
391 assert (clang_type->isFunctionType());
392 if (!clang_type->isFunctionProtoType())
393 return NULL;
394 return NULL;
395}
396
397bool
398Function::IsVariadic ()
399{
400 const clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetOpaqueClangQualType())->getTypePtr();
401 assert (clang_type->isFunctionType());
402 if (!clang_type->isFunctionProtoType())
403 return false;
404
405 const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
406 if (function_proto_type != NULL)
407 {
408 return function_proto_type->isVariadic();
409 }
410
411 return false;
412}
413
414uint32_t
415Function::GetPrologueByteSize ()
416{
417 if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize))
418 {
419 m_flags.Set(flagsCalculatedPrologueSize);
420 LineTable* line_table = m_comp_unit->GetLineTable ();
421 if (line_table)
422 {
423 LineEntry line_entry;
424 if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), line_entry))
425 m_prologue_byte_size = line_entry.range.GetByteSize();
426 }
427 }
428 return m_prologue_byte_size;
429}
430
431
432