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 
265 void
266 Function::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 
274 void
275 Function::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 
301 void
302 Function::CalculateSymbolContext(SymbolContext* sc)
303 {
304     sc->function = this;
305     m_comp_unit->CalculateSymbolContext(sc);
306 }
307 
308 void
309 Function::DumpSymbolContext(Stream *s)
310 {
311     m_comp_unit->DumpSymbolContext(s);
312     s->Printf(", Function{0x%8.8x}", GetID());
313 }
314 
315 size_t
316 Function::MemorySize () const
317 {
318     size_t mem_size = sizeof(Function) + m_blocks.MemorySize();
319     return mem_size;
320 }
321 
322 Type*
323 Function::GetType()
324 {
325     return m_type;
326 }
327 
328 const Type*
329 Function::GetType() const
330 {
331     return m_type;
332 }
333 
334 Type
335 Function::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 
353 int
354 Function::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 
368 const Type
369 Function::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 
397 const char *
398 Function::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 
407 bool
408 Function::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 
424 uint32_t
425 Function::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