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