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