1*4dbb271fSSean Callanan //===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===// 2*4dbb271fSSean Callanan // 3*4dbb271fSSean Callanan // The LLVM Compiler Infrastructure 4*4dbb271fSSean Callanan // 5*4dbb271fSSean Callanan // This file is distributed under the University of Illinois Open Source 6*4dbb271fSSean Callanan // License. See LICENSE.TXT for details. 7*4dbb271fSSean Callanan // 8*4dbb271fSSean Callanan //===----------------------------------------------------------------------===// 9*4dbb271fSSean Callanan 10*4dbb271fSSean Callanan #include "ASTStructExtractor.h" 11*4dbb271fSSean Callanan 12*4dbb271fSSean Callanan #include "stdlib.h" 13*4dbb271fSSean Callanan #include "clang/AST/ASTContext.h" 14*4dbb271fSSean Callanan #include "clang/AST/Decl.h" 15*4dbb271fSSean Callanan #include "clang/AST/DeclCXX.h" 16*4dbb271fSSean Callanan #include "clang/AST/DeclGroup.h" 17*4dbb271fSSean Callanan #include "clang/AST/Expr.h" 18*4dbb271fSSean Callanan #include "clang/AST/RecordLayout.h" 19*4dbb271fSSean Callanan #include "clang/AST/Stmt.h" 20*4dbb271fSSean Callanan #include "clang/Parse/Parser.h" 21*4dbb271fSSean Callanan #include "clang/Sema/Sema.h" 22*4dbb271fSSean Callanan #include "llvm/Support/Casting.h" 23*4dbb271fSSean Callanan #include "llvm/Support/raw_ostream.h" 24*4dbb271fSSean Callanan #include "lldb/Core/Log.h" 25*4dbb271fSSean Callanan 26*4dbb271fSSean Callanan using namespace llvm; 27*4dbb271fSSean Callanan using namespace clang; 28*4dbb271fSSean Callanan using namespace lldb_private; 29*4dbb271fSSean Callanan 30*4dbb271fSSean Callanan ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, 31*4dbb271fSSean Callanan const char *struct_name, 32*4dbb271fSSean Callanan ClangFunctionCaller &function) : 33*4dbb271fSSean Callanan m_ast_context (NULL), 34*4dbb271fSSean Callanan m_passthrough (passthrough), 35*4dbb271fSSean Callanan m_passthrough_sema (NULL), 36*4dbb271fSSean Callanan m_sema (NULL), 37*4dbb271fSSean Callanan m_action (NULL), 38*4dbb271fSSean Callanan m_function (function), 39*4dbb271fSSean Callanan m_struct_name (struct_name) 40*4dbb271fSSean Callanan { 41*4dbb271fSSean Callanan if (!m_passthrough) 42*4dbb271fSSean Callanan return; 43*4dbb271fSSean Callanan 44*4dbb271fSSean Callanan m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); 45*4dbb271fSSean Callanan } 46*4dbb271fSSean Callanan 47*4dbb271fSSean Callanan ASTStructExtractor::~ASTStructExtractor() 48*4dbb271fSSean Callanan { 49*4dbb271fSSean Callanan } 50*4dbb271fSSean Callanan 51*4dbb271fSSean Callanan void 52*4dbb271fSSean Callanan ASTStructExtractor::Initialize(ASTContext &Context) 53*4dbb271fSSean Callanan { 54*4dbb271fSSean Callanan m_ast_context = &Context; 55*4dbb271fSSean Callanan 56*4dbb271fSSean Callanan if (m_passthrough) 57*4dbb271fSSean Callanan m_passthrough->Initialize(Context); 58*4dbb271fSSean Callanan } 59*4dbb271fSSean Callanan 60*4dbb271fSSean Callanan void 61*4dbb271fSSean Callanan ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) 62*4dbb271fSSean Callanan { 63*4dbb271fSSean Callanan if (!F->hasBody()) 64*4dbb271fSSean Callanan return; 65*4dbb271fSSean Callanan 66*4dbb271fSSean Callanan Stmt *body_stmt = F->getBody(); 67*4dbb271fSSean Callanan CompoundStmt *body_compound_stmt = dyn_cast<CompoundStmt>(body_stmt); 68*4dbb271fSSean Callanan 69*4dbb271fSSean Callanan if (!body_compound_stmt) 70*4dbb271fSSean Callanan return; // do we have to handle this? 71*4dbb271fSSean Callanan 72*4dbb271fSSean Callanan RecordDecl *struct_decl = NULL; 73*4dbb271fSSean Callanan 74*4dbb271fSSean Callanan StringRef desired_name(m_struct_name.c_str()); 75*4dbb271fSSean Callanan 76*4dbb271fSSean Callanan for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(), be = body_compound_stmt->body_end(); 77*4dbb271fSSean Callanan bi != be; 78*4dbb271fSSean Callanan ++bi) 79*4dbb271fSSean Callanan { 80*4dbb271fSSean Callanan Stmt *curr_stmt = *bi; 81*4dbb271fSSean Callanan DeclStmt *curr_decl_stmt = dyn_cast<DeclStmt>(curr_stmt); 82*4dbb271fSSean Callanan if (!curr_decl_stmt) 83*4dbb271fSSean Callanan continue; 84*4dbb271fSSean Callanan DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup(); 85*4dbb271fSSean Callanan for (Decl *candidate_decl : decl_group) 86*4dbb271fSSean Callanan { 87*4dbb271fSSean Callanan RecordDecl *candidate_record_decl = dyn_cast<RecordDecl>(candidate_decl); 88*4dbb271fSSean Callanan if (!candidate_record_decl) 89*4dbb271fSSean Callanan continue; 90*4dbb271fSSean Callanan if (candidate_record_decl->getName() == desired_name) 91*4dbb271fSSean Callanan { 92*4dbb271fSSean Callanan struct_decl = candidate_record_decl; 93*4dbb271fSSean Callanan break; 94*4dbb271fSSean Callanan } 95*4dbb271fSSean Callanan } 96*4dbb271fSSean Callanan if (struct_decl) 97*4dbb271fSSean Callanan break; 98*4dbb271fSSean Callanan } 99*4dbb271fSSean Callanan 100*4dbb271fSSean Callanan if (!struct_decl) 101*4dbb271fSSean Callanan return; 102*4dbb271fSSean Callanan 103*4dbb271fSSean Callanan const ASTRecordLayout* struct_layout(&m_ast_context->getASTRecordLayout (struct_decl)); 104*4dbb271fSSean Callanan 105*4dbb271fSSean Callanan if (!struct_layout) 106*4dbb271fSSean Callanan return; 107*4dbb271fSSean Callanan 108*4dbb271fSSean Callanan m_function.m_struct_size = struct_layout->getSize().getQuantity(); // TODO Store m_struct_size as CharUnits 109*4dbb271fSSean Callanan m_function.m_return_offset = struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8; 110*4dbb271fSSean Callanan m_function.m_return_size = struct_layout->getDataSize().getQuantity() - m_function.m_return_offset; 111*4dbb271fSSean Callanan 112*4dbb271fSSean Callanan for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount(); 113*4dbb271fSSean Callanan field_index < num_fields; 114*4dbb271fSSean Callanan ++field_index) 115*4dbb271fSSean Callanan { 116*4dbb271fSSean Callanan m_function.m_member_offsets.push_back(struct_layout->getFieldOffset(field_index) / 8); 117*4dbb271fSSean Callanan } 118*4dbb271fSSean Callanan 119*4dbb271fSSean Callanan m_function.m_struct_valid = true; 120*4dbb271fSSean Callanan } 121*4dbb271fSSean Callanan 122*4dbb271fSSean Callanan void 123*4dbb271fSSean Callanan ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D) 124*4dbb271fSSean Callanan { 125*4dbb271fSSean Callanan LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D); 126*4dbb271fSSean Callanan 127*4dbb271fSSean Callanan if (linkage_spec_decl) 128*4dbb271fSSean Callanan { 129*4dbb271fSSean Callanan RecordDecl::decl_iterator decl_iterator; 130*4dbb271fSSean Callanan 131*4dbb271fSSean Callanan for (decl_iterator = linkage_spec_decl->decls_begin(); 132*4dbb271fSSean Callanan decl_iterator != linkage_spec_decl->decls_end(); 133*4dbb271fSSean Callanan ++decl_iterator) 134*4dbb271fSSean Callanan { 135*4dbb271fSSean Callanan ExtractFromTopLevelDecl(*decl_iterator); 136*4dbb271fSSean Callanan } 137*4dbb271fSSean Callanan } 138*4dbb271fSSean Callanan 139*4dbb271fSSean Callanan FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D); 140*4dbb271fSSean Callanan 141*4dbb271fSSean Callanan if (m_ast_context && 142*4dbb271fSSean Callanan function_decl && 143*4dbb271fSSean Callanan !m_function.m_wrapper_function_name.compare(function_decl->getNameAsString().c_str())) 144*4dbb271fSSean Callanan { 145*4dbb271fSSean Callanan ExtractFromFunctionDecl(function_decl); 146*4dbb271fSSean Callanan } 147*4dbb271fSSean Callanan } 148*4dbb271fSSean Callanan 149*4dbb271fSSean Callanan bool 150*4dbb271fSSean Callanan ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D) 151*4dbb271fSSean Callanan { 152*4dbb271fSSean Callanan DeclGroupRef::iterator decl_iterator; 153*4dbb271fSSean Callanan 154*4dbb271fSSean Callanan for (decl_iterator = D.begin(); 155*4dbb271fSSean Callanan decl_iterator != D.end(); 156*4dbb271fSSean Callanan ++decl_iterator) 157*4dbb271fSSean Callanan { 158*4dbb271fSSean Callanan Decl *decl = *decl_iterator; 159*4dbb271fSSean Callanan 160*4dbb271fSSean Callanan ExtractFromTopLevelDecl(decl); 161*4dbb271fSSean Callanan } 162*4dbb271fSSean Callanan 163*4dbb271fSSean Callanan if (m_passthrough) 164*4dbb271fSSean Callanan return m_passthrough->HandleTopLevelDecl(D); 165*4dbb271fSSean Callanan return true; 166*4dbb271fSSean Callanan } 167*4dbb271fSSean Callanan 168*4dbb271fSSean Callanan void 169*4dbb271fSSean Callanan ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) 170*4dbb271fSSean Callanan { 171*4dbb271fSSean Callanan if (m_passthrough) 172*4dbb271fSSean Callanan m_passthrough->HandleTranslationUnit(Ctx); 173*4dbb271fSSean Callanan } 174*4dbb271fSSean Callanan 175*4dbb271fSSean Callanan void 176*4dbb271fSSean Callanan ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) 177*4dbb271fSSean Callanan { 178*4dbb271fSSean Callanan if (m_passthrough) 179*4dbb271fSSean Callanan m_passthrough->HandleTagDeclDefinition(D); 180*4dbb271fSSean Callanan } 181*4dbb271fSSean Callanan 182*4dbb271fSSean Callanan void 183*4dbb271fSSean Callanan ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) 184*4dbb271fSSean Callanan { 185*4dbb271fSSean Callanan if (m_passthrough) 186*4dbb271fSSean Callanan m_passthrough->CompleteTentativeDefinition(D); 187*4dbb271fSSean Callanan } 188*4dbb271fSSean Callanan 189*4dbb271fSSean Callanan void 190*4dbb271fSSean Callanan ASTStructExtractor::HandleVTable(CXXRecordDecl *RD) 191*4dbb271fSSean Callanan { 192*4dbb271fSSean Callanan if (m_passthrough) 193*4dbb271fSSean Callanan m_passthrough->HandleVTable(RD); 194*4dbb271fSSean Callanan } 195*4dbb271fSSean Callanan 196*4dbb271fSSean Callanan void 197*4dbb271fSSean Callanan ASTStructExtractor::PrintStats() 198*4dbb271fSSean Callanan { 199*4dbb271fSSean Callanan if (m_passthrough) 200*4dbb271fSSean Callanan m_passthrough->PrintStats(); 201*4dbb271fSSean Callanan } 202*4dbb271fSSean Callanan 203*4dbb271fSSean Callanan void 204*4dbb271fSSean Callanan ASTStructExtractor::InitializeSema(Sema &S) 205*4dbb271fSSean Callanan { 206*4dbb271fSSean Callanan m_sema = &S; 207*4dbb271fSSean Callanan m_action = reinterpret_cast<Action*>(m_sema); 208*4dbb271fSSean Callanan 209*4dbb271fSSean Callanan if (m_passthrough_sema) 210*4dbb271fSSean Callanan m_passthrough_sema->InitializeSema(S); 211*4dbb271fSSean Callanan } 212*4dbb271fSSean Callanan 213*4dbb271fSSean Callanan void 214*4dbb271fSSean Callanan ASTStructExtractor::ForgetSema() 215*4dbb271fSSean Callanan { 216*4dbb271fSSean Callanan m_sema = NULL; 217*4dbb271fSSean Callanan m_action = NULL; 218*4dbb271fSSean Callanan 219*4dbb271fSSean Callanan if (m_passthrough_sema) 220*4dbb271fSSean Callanan m_passthrough_sema->ForgetSema(); 221*4dbb271fSSean Callanan } 222