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 26 using namespace llvm; 27 using namespace clang; 28 using namespace lldb_private; 29 30 ASTStructExtractor::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 47 ASTStructExtractor::~ASTStructExtractor() 48 { 49 } 50 51 void 52 ASTStructExtractor::Initialize(ASTContext &Context) 53 { 54 m_ast_context = &Context; 55 56 if (m_passthrough) 57 m_passthrough->Initialize(Context); 58 } 59 60 void 61 ASTStructExtractor::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 122 void 123 ASTStructExtractor::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 149 bool 150 ASTStructExtractor::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 168 void 169 ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) 170 { 171 if (m_passthrough) 172 m_passthrough->HandleTranslationUnit(Ctx); 173 } 174 175 void 176 ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) 177 { 178 if (m_passthrough) 179 m_passthrough->HandleTagDeclDefinition(D); 180 } 181 182 void 183 ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) 184 { 185 if (m_passthrough) 186 m_passthrough->CompleteTentativeDefinition(D); 187 } 188 189 void 190 ASTStructExtractor::HandleVTable(CXXRecordDecl *RD) 191 { 192 if (m_passthrough) 193 m_passthrough->HandleVTable(RD); 194 } 195 196 void 197 ASTStructExtractor::PrintStats() 198 { 199 if (m_passthrough) 200 m_passthrough->PrintStats(); 201 } 202 203 void 204 ASTStructExtractor::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 213 void 214 ASTStructExtractor::ForgetSema() 215 { 216 m_sema = NULL; 217 m_action = NULL; 218 219 if (m_passthrough_sema) 220 m_passthrough_sema->ForgetSema(); 221 } 222