Function.cpp revision 12bec71b323dc520f0e985a86e09c4712559e115
1//===-- 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
264
265void
266Function::GetDescription(Stream *s, lldb::DescriptionLevel level, Process *process)
267{
268    Type* func_type = GetType();
269    *s << '"' << func_type->GetName() << "\", id = " << (const UserID&)*this;
270    *s << ", range = ";
271    GetAddressRange().Dump(s, process, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
272}
273
274void
275Function::Dump(Stream *s, bool show_context) const
276{
277    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
278    s->Indent();
279    *s << "Function" << (const UserID&)*this;
280
281    m_mangled.Dump(s);
282
283//  FunctionInfo::Dump(s);
284    if (m_type)
285    {
286        *s << ", type = " << (void*)m_type;
287        /// << " (";
288        ///m_type->DumpTypeName(s);
289        ///s->PutChar(')');
290    }
291    else if (m_type_uid != LLDB_INVALID_UID)
292        *s << ", type_uid = " << m_type_uid;
293
294    s->EOL();
295    // Dump the root object
296    if (!m_blocks.IsEmpty())
297        m_blocks.Dump(s, Block::RootID, INT_MAX, show_context);
298}
299
300
301void
302Function::CalculateSymbolContext(SymbolContext* sc)
303{
304    sc->function = this;
305    m_comp_unit->CalculateSymbolContext(sc);
306}
307
308void
309Function::DumpSymbolContext(Stream *s)
310{
311    m_comp_unit->DumpSymbolContext(s);
312    s->Printf(", Function{0x%8.8x}", GetID());
313}
314
315size_t
316Function::MemorySize () const
317{
318    size_t mem_size = sizeof(Function) + m_blocks.MemorySize();
319    return mem_size;
320}
321
322Type*
323Function::GetType()
324{
325    return m_type;
326}
327
328const Type*
329Function::GetType() const
330{
331    return m_type;
332}
333
334Type
335Function::GetReturnType ()
336{
337    clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType()));
338    assert (clang_type->isFunctionType());
339    clang::FunctionType *function_type = dyn_cast<clang::FunctionType> (clang_type);
340    clang::QualType fun_return_qualtype = function_type->getResultType();
341
342    const ConstString fun_return_name(Type::GetClangTypeName(fun_return_qualtype.getAsOpaquePtr()));
343
344    SymbolContext sc;
345    CalculateSymbolContext (&sc);
346    // Null out everything below the CompUnit 'cause we don't actually know these.
347
348    size_t bit_size = ClangASTContext::GetTypeBitSize ((GetType()->GetClangASTContext().getASTContext()), &fun_return_qualtype);
349    Type return_type (0, GetType()->GetSymbolFile(), fun_return_name, bit_size, sc.comp_unit, 0, Type::eTypeUIDSynthetic, Declaration(), fun_return_qualtype.getAsOpaquePtr());
350    return return_type;
351}
352
353int
354Function::GetArgumentCount ()
355{
356    clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType()));
357    assert (clang_type->isFunctionType());
358    if (!clang_type->isFunctionProtoType())
359        return -1;
360
361    const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
362    if (function_proto_type != NULL)
363        return function_proto_type->getNumArgs();
364
365    return 0;
366}
367
368const Type
369Function::GetArgumentTypeAtIndex (size_t idx)
370{
371    clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetOpaqueClangQualType()));
372   assert (clang_type->isFunctionType());
373   if (!clang_type->isFunctionProtoType())
374        return Type();
375
376    const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
377    if (function_proto_type != NULL)
378    {
379        unsigned num_args = function_proto_type->getNumArgs();
380        if (idx >= num_args)
381            return Type();
382        clang::QualType arg_qualtype = (function_proto_type->arg_type_begin())[idx];
383
384        const ConstString arg_return_name(Type::GetClangTypeName(arg_qualtype.getAsOpaquePtr()));
385        SymbolContext sc;
386        CalculateSymbolContext (&sc);
387        // Null out everything below the CompUnit 'cause we don't actually know these.
388
389        size_t bit_size = ClangASTContext::GetTypeBitSize ((GetType()->GetClangASTContext().getASTContext()), &arg_qualtype);
390        Type arg_type (0, GetType()->GetSymbolFile(), arg_return_name, bit_size, sc.comp_unit, 0, Type::eTypeUIDSynthetic, Declaration(), arg_qualtype.getAsOpaquePtr());
391        return arg_type;
392    }
393
394    return Type();
395}
396
397const char *
398Function::GetArgumentNameAtIndex (size_t idx)
399{
400   clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetOpaqueClangQualType())->getTypePtr();
401   assert (clang_type->isFunctionType());
402   if (!clang_type->isFunctionProtoType())
403       return NULL;
404    return NULL;
405}
406
407bool
408Function::IsVariadic ()
409{
410   const clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetOpaqueClangQualType())->getTypePtr();
411   assert (clang_type->isFunctionType());
412   if (!clang_type->isFunctionProtoType())
413        return false;
414
415    const clang::FunctionProtoType *function_proto_type = dyn_cast<clang::FunctionProtoType>(clang_type);
416    if (function_proto_type != NULL)
417    {
418        return function_proto_type->isVariadic();
419    }
420
421    return false;
422}
423
424uint32_t
425Function::GetPrologueByteSize ()
426{
427    if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize))
428    {
429        m_flags.Set(flagsCalculatedPrologueSize);
430        LineTable* line_table = m_comp_unit->GetLineTable ();
431        if (line_table)
432        {
433            LineEntry line_entry;
434            if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), line_entry))
435                m_prologue_byte_size = line_entry.range.GetByteSize();
436        }
437    }
438    return m_prologue_byte_size;
439}
440
441
442
443