14dbb271fSSean Callanan //===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===// 24dbb271fSSean Callanan // 34dbb271fSSean Callanan // The LLVM Compiler Infrastructure 44dbb271fSSean Callanan // 54dbb271fSSean Callanan // This file is distributed under the University of Illinois Open Source 64dbb271fSSean Callanan // License. See LICENSE.TXT for details. 74dbb271fSSean Callanan // 84dbb271fSSean Callanan //===----------------------------------------------------------------------===// 94dbb271fSSean Callanan 104dbb271fSSean Callanan #include "ASTStructExtractor.h" 114dbb271fSSean Callanan 12b9c1b51eSKate Stone #include "lldb/Core/Log.h" 134dbb271fSSean Callanan #include "stdlib.h" 144dbb271fSSean Callanan #include "clang/AST/ASTContext.h" 154dbb271fSSean Callanan #include "clang/AST/Decl.h" 164dbb271fSSean Callanan #include "clang/AST/DeclCXX.h" 174dbb271fSSean Callanan #include "clang/AST/DeclGroup.h" 184dbb271fSSean Callanan #include "clang/AST/Expr.h" 194dbb271fSSean Callanan #include "clang/AST/RecordLayout.h" 204dbb271fSSean Callanan #include "clang/AST/Stmt.h" 214dbb271fSSean Callanan #include "clang/Parse/Parser.h" 224dbb271fSSean Callanan #include "clang/Sema/Sema.h" 234dbb271fSSean Callanan #include "llvm/Support/Casting.h" 244dbb271fSSean Callanan #include "llvm/Support/raw_ostream.h" 254dbb271fSSean Callanan 264dbb271fSSean Callanan using namespace llvm; 274dbb271fSSean Callanan using namespace clang; 284dbb271fSSean Callanan using namespace lldb_private; 294dbb271fSSean Callanan 304dbb271fSSean Callanan ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, 314dbb271fSSean Callanan const char *struct_name, 32b9c1b51eSKate Stone ClangFunctionCaller &function) 33b9c1b51eSKate Stone : m_ast_context(NULL), m_passthrough(passthrough), m_passthrough_sema(NULL), 34b9c1b51eSKate Stone m_sema(NULL), m_action(NULL), m_function(function), 35b9c1b51eSKate Stone m_struct_name(struct_name) { 364dbb271fSSean Callanan if (!m_passthrough) 374dbb271fSSean Callanan return; 384dbb271fSSean Callanan 394dbb271fSSean Callanan m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); 404dbb271fSSean Callanan } 414dbb271fSSean Callanan 42b9c1b51eSKate Stone ASTStructExtractor::~ASTStructExtractor() {} 434dbb271fSSean Callanan 44b9c1b51eSKate Stone void ASTStructExtractor::Initialize(ASTContext &Context) { 454dbb271fSSean Callanan m_ast_context = &Context; 464dbb271fSSean Callanan 474dbb271fSSean Callanan if (m_passthrough) 484dbb271fSSean Callanan m_passthrough->Initialize(Context); 494dbb271fSSean Callanan } 504dbb271fSSean Callanan 51b9c1b51eSKate Stone void ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) { 524dbb271fSSean Callanan if (!F->hasBody()) 534dbb271fSSean Callanan return; 544dbb271fSSean Callanan 554dbb271fSSean Callanan Stmt *body_stmt = F->getBody(); 564dbb271fSSean Callanan CompoundStmt *body_compound_stmt = dyn_cast<CompoundStmt>(body_stmt); 574dbb271fSSean Callanan 584dbb271fSSean Callanan if (!body_compound_stmt) 594dbb271fSSean Callanan return; // do we have to handle this? 604dbb271fSSean Callanan 614dbb271fSSean Callanan RecordDecl *struct_decl = NULL; 624dbb271fSSean Callanan 63*771ef6d4SMalcolm Parsons StringRef desired_name(m_struct_name); 644dbb271fSSean Callanan 65b9c1b51eSKate Stone for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(), 66b9c1b51eSKate Stone be = body_compound_stmt->body_end(); 67b9c1b51eSKate Stone bi != be; ++bi) { 684dbb271fSSean Callanan Stmt *curr_stmt = *bi; 694dbb271fSSean Callanan DeclStmt *curr_decl_stmt = dyn_cast<DeclStmt>(curr_stmt); 704dbb271fSSean Callanan if (!curr_decl_stmt) 714dbb271fSSean Callanan continue; 724dbb271fSSean Callanan DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup(); 73b9c1b51eSKate Stone for (Decl *candidate_decl : decl_group) { 744dbb271fSSean Callanan RecordDecl *candidate_record_decl = dyn_cast<RecordDecl>(candidate_decl); 754dbb271fSSean Callanan if (!candidate_record_decl) 764dbb271fSSean Callanan continue; 77b9c1b51eSKate Stone if (candidate_record_decl->getName() == desired_name) { 784dbb271fSSean Callanan struct_decl = candidate_record_decl; 794dbb271fSSean Callanan break; 804dbb271fSSean Callanan } 814dbb271fSSean Callanan } 824dbb271fSSean Callanan if (struct_decl) 834dbb271fSSean Callanan break; 844dbb271fSSean Callanan } 854dbb271fSSean Callanan 864dbb271fSSean Callanan if (!struct_decl) 874dbb271fSSean Callanan return; 884dbb271fSSean Callanan 89b9c1b51eSKate Stone const ASTRecordLayout *struct_layout( 90b9c1b51eSKate Stone &m_ast_context->getASTRecordLayout(struct_decl)); 914dbb271fSSean Callanan 924dbb271fSSean Callanan if (!struct_layout) 934dbb271fSSean Callanan return; 944dbb271fSSean Callanan 95b9c1b51eSKate Stone m_function.m_struct_size = 96b9c1b51eSKate Stone struct_layout->getSize() 97b9c1b51eSKate Stone .getQuantity(); // TODO Store m_struct_size as CharUnits 98b9c1b51eSKate Stone m_function.m_return_offset = 99b9c1b51eSKate Stone struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8; 100b9c1b51eSKate Stone m_function.m_return_size = 101b9c1b51eSKate Stone struct_layout->getDataSize().getQuantity() - m_function.m_return_offset; 1024dbb271fSSean Callanan 1034dbb271fSSean Callanan for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount(); 104b9c1b51eSKate Stone field_index < num_fields; ++field_index) { 105b9c1b51eSKate Stone m_function.m_member_offsets.push_back( 106b9c1b51eSKate Stone struct_layout->getFieldOffset(field_index) / 8); 1074dbb271fSSean Callanan } 1084dbb271fSSean Callanan 1094dbb271fSSean Callanan m_function.m_struct_valid = true; 1104dbb271fSSean Callanan } 1114dbb271fSSean Callanan 112b9c1b51eSKate Stone void ASTStructExtractor::ExtractFromTopLevelDecl(Decl *D) { 1134dbb271fSSean Callanan LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D); 1144dbb271fSSean Callanan 115b9c1b51eSKate Stone if (linkage_spec_decl) { 1164dbb271fSSean Callanan RecordDecl::decl_iterator decl_iterator; 1174dbb271fSSean Callanan 1184dbb271fSSean Callanan for (decl_iterator = linkage_spec_decl->decls_begin(); 119b9c1b51eSKate Stone decl_iterator != linkage_spec_decl->decls_end(); ++decl_iterator) { 1204dbb271fSSean Callanan ExtractFromTopLevelDecl(*decl_iterator); 1214dbb271fSSean Callanan } 1224dbb271fSSean Callanan } 1234dbb271fSSean Callanan 1244dbb271fSSean Callanan FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D); 1254dbb271fSSean Callanan 126b9c1b51eSKate Stone if (m_ast_context && function_decl && 127b9c1b51eSKate Stone !m_function.m_wrapper_function_name.compare( 128*771ef6d4SMalcolm Parsons function_decl->getNameAsString())) { 1294dbb271fSSean Callanan ExtractFromFunctionDecl(function_decl); 1304dbb271fSSean Callanan } 1314dbb271fSSean Callanan } 1324dbb271fSSean Callanan 133b9c1b51eSKate Stone bool ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D) { 1344dbb271fSSean Callanan DeclGroupRef::iterator decl_iterator; 1354dbb271fSSean Callanan 136b9c1b51eSKate Stone for (decl_iterator = D.begin(); decl_iterator != D.end(); ++decl_iterator) { 1374dbb271fSSean Callanan Decl *decl = *decl_iterator; 1384dbb271fSSean Callanan 1394dbb271fSSean Callanan ExtractFromTopLevelDecl(decl); 1404dbb271fSSean Callanan } 1414dbb271fSSean Callanan 1424dbb271fSSean Callanan if (m_passthrough) 1434dbb271fSSean Callanan return m_passthrough->HandleTopLevelDecl(D); 1444dbb271fSSean Callanan return true; 1454dbb271fSSean Callanan } 1464dbb271fSSean Callanan 147b9c1b51eSKate Stone void ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) { 1484dbb271fSSean Callanan if (m_passthrough) 1494dbb271fSSean Callanan m_passthrough->HandleTranslationUnit(Ctx); 1504dbb271fSSean Callanan } 1514dbb271fSSean Callanan 152b9c1b51eSKate Stone void ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) { 1534dbb271fSSean Callanan if (m_passthrough) 1544dbb271fSSean Callanan m_passthrough->HandleTagDeclDefinition(D); 1554dbb271fSSean Callanan } 1564dbb271fSSean Callanan 157b9c1b51eSKate Stone void ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) { 1584dbb271fSSean Callanan if (m_passthrough) 1594dbb271fSSean Callanan m_passthrough->CompleteTentativeDefinition(D); 1604dbb271fSSean Callanan } 1614dbb271fSSean Callanan 162b9c1b51eSKate Stone void ASTStructExtractor::HandleVTable(CXXRecordDecl *RD) { 1634dbb271fSSean Callanan if (m_passthrough) 1644dbb271fSSean Callanan m_passthrough->HandleVTable(RD); 1654dbb271fSSean Callanan } 1664dbb271fSSean Callanan 167b9c1b51eSKate Stone void ASTStructExtractor::PrintStats() { 1684dbb271fSSean Callanan if (m_passthrough) 1694dbb271fSSean Callanan m_passthrough->PrintStats(); 1704dbb271fSSean Callanan } 1714dbb271fSSean Callanan 172b9c1b51eSKate Stone void ASTStructExtractor::InitializeSema(Sema &S) { 1734dbb271fSSean Callanan m_sema = &S; 1744dbb271fSSean Callanan m_action = reinterpret_cast<Action *>(m_sema); 1754dbb271fSSean Callanan 1764dbb271fSSean Callanan if (m_passthrough_sema) 1774dbb271fSSean Callanan m_passthrough_sema->InitializeSema(S); 1784dbb271fSSean Callanan } 1794dbb271fSSean Callanan 180b9c1b51eSKate Stone void ASTStructExtractor::ForgetSema() { 1814dbb271fSSean Callanan m_sema = NULL; 1824dbb271fSSean Callanan m_action = NULL; 1834dbb271fSSean Callanan 1844dbb271fSSean Callanan if (m_passthrough_sema) 1854dbb271fSSean Callanan m_passthrough_sema->ForgetSema(); 1864dbb271fSSean Callanan } 187