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