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