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 
20 using 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 //----------------------------------------------------------------------
27 FunctionInfo::FunctionInfo (const char *name, const Declaration *decl_ptr) :
28     m_name(name),
29     m_declaration(decl_ptr)
30 {
31 }
32 
33 
34 FunctionInfo::FunctionInfo (const ConstString& name, const Declaration *decl_ptr) :
35     m_name(name),
36     m_declaration(decl_ptr)
37 {
38 }
39 
40 
41 FunctionInfo::~FunctionInfo()
42 {
43 }
44 
45 void
46 FunctionInfo::Dump(Stream *s) const
47 {
48     if (m_name)
49         *s << ", name = \"" << m_name << "\"";
50     m_declaration.Dump(s);
51 }
52 
53 
54 int
55 FunctionInfo::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 
65 Declaration&
66 FunctionInfo::GetDeclaration()
67 {
68     return m_declaration;
69 }
70 
71 const Declaration&
72 FunctionInfo::GetDeclaration() const
73 {
74     return m_declaration;
75 }
76 
77 const ConstString&
78 FunctionInfo::GetName() const
79 {
80     return m_name;
81 }
82 
83 size_t
84 FunctionInfo::MemorySize() const
85 {
86     return m_name.MemorySize() + m_declaration.MemorySize();
87 }
88 
89 
90 InlineFunctionInfo::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 
103 InlineFunctionInfo::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 
116 InlineFunctionInfo::~InlineFunctionInfo()
117 {
118 }
119 
120 int
121 InlineFunctionInfo::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 
131 void
132 InlineFunctionInfo::Dump(Stream *s) const
133 {
134     FunctionInfo::Dump(s);
135     if (m_mangled)
136         m_mangled.Dump(s);
137 }
138 
139 void
140 InlineFunctionInfo::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 
150 Declaration &
151 InlineFunctionInfo::GetCallSite ()
152 {
153     return m_call_decl;
154 }
155 
156 const Declaration &
157 InlineFunctionInfo::GetCallSite () const
158 {
159     return m_call_decl;
160 }
161 
162 
163 Mangled&
164 InlineFunctionInfo::GetMangled()
165 {
166     return m_mangled;
167 }
168 
169 const Mangled&
170 InlineFunctionInfo::GetMangled() const
171 {
172     return m_mangled;
173 }
174 
175 size_t
176 InlineFunctionInfo::MemorySize() const
177 {
178     return FunctionInfo::MemorySize() + m_mangled.MemorySize();
179 }
180 
181 //----------------------------------------------------------------------
182 //
183 //----------------------------------------------------------------------
184 Function::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 
206 Function::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 
229 Function::~Function()
230 {
231 }
232 
233 const AddressRange &
234 Function::GetAddressRange()
235 {
236     return GetBlocks(true).GetAddressRange();
237 }
238 
239 BlockList &
240 Function::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 
252 CompileUnit*
253 Function::GetCompileUnit()
254 {
255     return m_comp_unit;
256 }
257 
258 const CompileUnit*
259 Function::GetCompileUnit() const
260 {
261     return m_comp_unit;
262 }
263 
264 void
265 Function::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 
291 void
292 Function::CalculateSymbolContext(SymbolContext* sc)
293 {
294     sc->function = this;
295     m_comp_unit->CalculateSymbolContext(sc);
296 }
297 
298 void
299 Function::DumpSymbolContext(Stream *s)
300 {
301     m_comp_unit->DumpSymbolContext(s);
302     s->Printf(", Function{0x%8.8x}", GetID());
303 }
304 
305 size_t
306 Function::MemorySize () const
307 {
308     size_t mem_size = sizeof(Function) + m_blocks.MemorySize();
309     return mem_size;
310 }
311 
312 Type*
313 Function::GetType()
314 {
315     return m_type;
316 }
317 
318 const Type*
319 Function::GetType() const
320 {
321     return m_type;
322 }
323 
324 Type
325 Function::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 
343 int
344 Function::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 
358 const Type
359 Function::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 
387 const char *
388 Function::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 
397 bool
398 Function::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 
414 uint32_t
415 Function::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 
433