19f2f44ceSEd Maste //===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===//
29f2f44ceSEd Maste //
39f2f44ceSEd Maste //                     The LLVM Compiler Infrastructure
49f2f44ceSEd Maste //
59f2f44ceSEd Maste // This file is distributed under the University of Illinois Open Source
69f2f44ceSEd Maste // License. See LICENSE.TXT for details.
79f2f44ceSEd Maste //
89f2f44ceSEd Maste //===----------------------------------------------------------------------===//
99f2f44ceSEd Maste 
109f2f44ceSEd Maste #include "ASTStructExtractor.h"
119f2f44ceSEd Maste 
12*f678e45dSDimitry Andric #include "lldb/Utility/Log.h"
139f2f44ceSEd Maste #include "stdlib.h"
149f2f44ceSEd Maste #include "clang/AST/ASTContext.h"
159f2f44ceSEd Maste #include "clang/AST/Decl.h"
169f2f44ceSEd Maste #include "clang/AST/DeclCXX.h"
179f2f44ceSEd Maste #include "clang/AST/DeclGroup.h"
189f2f44ceSEd Maste #include "clang/AST/Expr.h"
199f2f44ceSEd Maste #include "clang/AST/RecordLayout.h"
209f2f44ceSEd Maste #include "clang/AST/Stmt.h"
219f2f44ceSEd Maste #include "clang/Parse/Parser.h"
229f2f44ceSEd Maste #include "clang/Sema/Sema.h"
239f2f44ceSEd Maste #include "llvm/Support/Casting.h"
249f2f44ceSEd Maste #include "llvm/Support/raw_ostream.h"
259f2f44ceSEd Maste 
269f2f44ceSEd Maste using namespace llvm;
279f2f44ceSEd Maste using namespace clang;
289f2f44ceSEd Maste using namespace lldb_private;
299f2f44ceSEd Maste 
ASTStructExtractor(ASTConsumer * passthrough,const char * struct_name,ClangFunctionCaller & function)309f2f44ceSEd Maste ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough,
319f2f44ceSEd Maste                                        const char *struct_name,
32435933ddSDimitry Andric                                        ClangFunctionCaller &function)
33435933ddSDimitry Andric     : m_ast_context(NULL), m_passthrough(passthrough), m_passthrough_sema(NULL),
34435933ddSDimitry Andric       m_sema(NULL), m_action(NULL), m_function(function),
35435933ddSDimitry Andric       m_struct_name(struct_name) {
369f2f44ceSEd Maste   if (!m_passthrough)
379f2f44ceSEd Maste     return;
389f2f44ceSEd Maste 
399f2f44ceSEd Maste   m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
409f2f44ceSEd Maste }
419f2f44ceSEd Maste 
~ASTStructExtractor()42435933ddSDimitry Andric ASTStructExtractor::~ASTStructExtractor() {}
439f2f44ceSEd Maste 
Initialize(ASTContext & Context)44435933ddSDimitry Andric void ASTStructExtractor::Initialize(ASTContext &Context) {
459f2f44ceSEd Maste   m_ast_context = &Context;
469f2f44ceSEd Maste 
479f2f44ceSEd Maste   if (m_passthrough)
489f2f44ceSEd Maste     m_passthrough->Initialize(Context);
499f2f44ceSEd Maste }
509f2f44ceSEd Maste 
ExtractFromFunctionDecl(FunctionDecl * F)51435933ddSDimitry Andric void ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) {
529f2f44ceSEd Maste   if (!F->hasBody())
539f2f44ceSEd Maste     return;
549f2f44ceSEd Maste 
559f2f44ceSEd Maste   Stmt *body_stmt = F->getBody();
569f2f44ceSEd Maste   CompoundStmt *body_compound_stmt = dyn_cast<CompoundStmt>(body_stmt);
579f2f44ceSEd Maste 
589f2f44ceSEd Maste   if (!body_compound_stmt)
599f2f44ceSEd Maste     return; // do we have to handle this?
609f2f44ceSEd Maste 
619f2f44ceSEd Maste   RecordDecl *struct_decl = NULL;
629f2f44ceSEd Maste 
63435933ddSDimitry Andric   StringRef desired_name(m_struct_name);
649f2f44ceSEd Maste 
65435933ddSDimitry Andric   for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(),
66435933ddSDimitry Andric                                          be = body_compound_stmt->body_end();
67435933ddSDimitry Andric        bi != be; ++bi) {
689f2f44ceSEd Maste     Stmt *curr_stmt = *bi;
699f2f44ceSEd Maste     DeclStmt *curr_decl_stmt = dyn_cast<DeclStmt>(curr_stmt);
709f2f44ceSEd Maste     if (!curr_decl_stmt)
719f2f44ceSEd Maste       continue;
729f2f44ceSEd Maste     DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup();
73435933ddSDimitry Andric     for (Decl *candidate_decl : decl_group) {
749f2f44ceSEd Maste       RecordDecl *candidate_record_decl = dyn_cast<RecordDecl>(candidate_decl);
759f2f44ceSEd Maste       if (!candidate_record_decl)
769f2f44ceSEd Maste         continue;
77435933ddSDimitry Andric       if (candidate_record_decl->getName() == desired_name) {
789f2f44ceSEd Maste         struct_decl = candidate_record_decl;
799f2f44ceSEd Maste         break;
809f2f44ceSEd Maste       }
819f2f44ceSEd Maste     }
829f2f44ceSEd Maste     if (struct_decl)
839f2f44ceSEd Maste       break;
849f2f44ceSEd Maste   }
859f2f44ceSEd Maste 
869f2f44ceSEd Maste   if (!struct_decl)
879f2f44ceSEd Maste     return;
889f2f44ceSEd Maste 
89435933ddSDimitry Andric   const ASTRecordLayout *struct_layout(
90435933ddSDimitry Andric       &m_ast_context->getASTRecordLayout(struct_decl));
919f2f44ceSEd Maste 
929f2f44ceSEd Maste   if (!struct_layout)
939f2f44ceSEd Maste     return;
949f2f44ceSEd Maste 
95435933ddSDimitry Andric   m_function.m_struct_size =
96435933ddSDimitry Andric       struct_layout->getSize()
97435933ddSDimitry Andric           .getQuantity(); // TODO Store m_struct_size as CharUnits
98435933ddSDimitry Andric   m_function.m_return_offset =
99435933ddSDimitry Andric       struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8;
100435933ddSDimitry Andric   m_function.m_return_size =
101435933ddSDimitry Andric       struct_layout->getDataSize().getQuantity() - m_function.m_return_offset;
1029f2f44ceSEd Maste 
1039f2f44ceSEd Maste   for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount();
104435933ddSDimitry Andric        field_index < num_fields; ++field_index) {
105435933ddSDimitry Andric     m_function.m_member_offsets.push_back(
106435933ddSDimitry Andric         struct_layout->getFieldOffset(field_index) / 8);
1079f2f44ceSEd Maste   }
1089f2f44ceSEd Maste 
1099f2f44ceSEd Maste   m_function.m_struct_valid = true;
1109f2f44ceSEd Maste }
1119f2f44ceSEd Maste 
ExtractFromTopLevelDecl(Decl * D)112435933ddSDimitry Andric void ASTStructExtractor::ExtractFromTopLevelDecl(Decl *D) {
1139f2f44ceSEd Maste   LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D);
1149f2f44ceSEd Maste 
115435933ddSDimitry Andric   if (linkage_spec_decl) {
1169f2f44ceSEd Maste     RecordDecl::decl_iterator decl_iterator;
1179f2f44ceSEd Maste 
1189f2f44ceSEd Maste     for (decl_iterator = linkage_spec_decl->decls_begin();
119435933ddSDimitry Andric          decl_iterator != linkage_spec_decl->decls_end(); ++decl_iterator) {
1209f2f44ceSEd Maste       ExtractFromTopLevelDecl(*decl_iterator);
1219f2f44ceSEd Maste     }
1229f2f44ceSEd Maste   }
1239f2f44ceSEd Maste 
1249f2f44ceSEd Maste   FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D);
1259f2f44ceSEd Maste 
126435933ddSDimitry Andric   if (m_ast_context && function_decl &&
127435933ddSDimitry Andric       !m_function.m_wrapper_function_name.compare(
128435933ddSDimitry Andric           function_decl->getNameAsString())) {
1299f2f44ceSEd Maste     ExtractFromFunctionDecl(function_decl);
1309f2f44ceSEd Maste   }
1319f2f44ceSEd Maste }
1329f2f44ceSEd Maste 
HandleTopLevelDecl(DeclGroupRef D)133435933ddSDimitry Andric bool ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D) {
1349f2f44ceSEd Maste   DeclGroupRef::iterator decl_iterator;
1359f2f44ceSEd Maste 
136435933ddSDimitry Andric   for (decl_iterator = D.begin(); decl_iterator != D.end(); ++decl_iterator) {
1379f2f44ceSEd Maste     Decl *decl = *decl_iterator;
1389f2f44ceSEd Maste 
1399f2f44ceSEd Maste     ExtractFromTopLevelDecl(decl);
1409f2f44ceSEd Maste   }
1419f2f44ceSEd Maste 
1429f2f44ceSEd Maste   if (m_passthrough)
1439f2f44ceSEd Maste     return m_passthrough->HandleTopLevelDecl(D);
1449f2f44ceSEd Maste   return true;
1459f2f44ceSEd Maste }
1469f2f44ceSEd Maste 
HandleTranslationUnit(ASTContext & Ctx)147435933ddSDimitry Andric void ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) {
1489f2f44ceSEd Maste   if (m_passthrough)
1499f2f44ceSEd Maste     m_passthrough->HandleTranslationUnit(Ctx);
1509f2f44ceSEd Maste }
1519f2f44ceSEd Maste 
HandleTagDeclDefinition(TagDecl * D)152435933ddSDimitry Andric void ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) {
1539f2f44ceSEd Maste   if (m_passthrough)
1549f2f44ceSEd Maste     m_passthrough->HandleTagDeclDefinition(D);
1559f2f44ceSEd Maste }
1569f2f44ceSEd Maste 
CompleteTentativeDefinition(VarDecl * D)157435933ddSDimitry Andric void ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) {
1589f2f44ceSEd Maste   if (m_passthrough)
1599f2f44ceSEd Maste     m_passthrough->CompleteTentativeDefinition(D);
1609f2f44ceSEd Maste }
1619f2f44ceSEd Maste 
HandleVTable(CXXRecordDecl * RD)162435933ddSDimitry Andric void ASTStructExtractor::HandleVTable(CXXRecordDecl *RD) {
1639f2f44ceSEd Maste   if (m_passthrough)
1649f2f44ceSEd Maste     m_passthrough->HandleVTable(RD);
1659f2f44ceSEd Maste }
1669f2f44ceSEd Maste 
PrintStats()167435933ddSDimitry Andric void ASTStructExtractor::PrintStats() {
1689f2f44ceSEd Maste   if (m_passthrough)
1699f2f44ceSEd Maste     m_passthrough->PrintStats();
1709f2f44ceSEd Maste }
1719f2f44ceSEd Maste 
InitializeSema(Sema & S)172435933ddSDimitry Andric void ASTStructExtractor::InitializeSema(Sema &S) {
1739f2f44ceSEd Maste   m_sema = &S;
1749f2f44ceSEd Maste   m_action = reinterpret_cast<Action *>(m_sema);
1759f2f44ceSEd Maste 
1769f2f44ceSEd Maste   if (m_passthrough_sema)
1779f2f44ceSEd Maste     m_passthrough_sema->InitializeSema(S);
1789f2f44ceSEd Maste }
1799f2f44ceSEd Maste 
ForgetSema()180435933ddSDimitry Andric void ASTStructExtractor::ForgetSema() {
1819f2f44ceSEd Maste   m_sema = NULL;
1829f2f44ceSEd Maste   m_action = NULL;
1839f2f44ceSEd Maste 
1849f2f44ceSEd Maste   if (m_passthrough_sema)
1859f2f44ceSEd Maste     m_passthrough_sema->ForgetSema();
1869f2f44ceSEd Maste }
187