14dbb271fSSean Callanan //===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===// 24dbb271fSSean Callanan // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 64dbb271fSSean Callanan // 74dbb271fSSean Callanan //===----------------------------------------------------------------------===// 84dbb271fSSean Callanan 94dbb271fSSean Callanan #include "ASTStructExtractor.h" 104dbb271fSSean Callanan 116f9e6901SZachary Turner #include "lldb/Utility/Log.h" 124dbb271fSSean Callanan #include "stdlib.h" 134dbb271fSSean Callanan #include "clang/AST/ASTContext.h" 144dbb271fSSean Callanan #include "clang/AST/Decl.h" 154dbb271fSSean Callanan #include "clang/AST/DeclCXX.h" 164dbb271fSSean Callanan #include "clang/AST/DeclGroup.h" 174dbb271fSSean Callanan #include "clang/AST/Expr.h" 184dbb271fSSean Callanan #include "clang/AST/RecordLayout.h" 194dbb271fSSean Callanan #include "clang/AST/Stmt.h" 204dbb271fSSean Callanan #include "clang/Parse/Parser.h" 214dbb271fSSean Callanan #include "clang/Sema/Sema.h" 224dbb271fSSean Callanan #include "llvm/Support/Casting.h" 234dbb271fSSean Callanan #include "llvm/Support/raw_ostream.h" 244dbb271fSSean Callanan 254dbb271fSSean Callanan using namespace llvm; 264dbb271fSSean Callanan using namespace clang; 274dbb271fSSean Callanan using namespace lldb_private; 284dbb271fSSean Callanan 294dbb271fSSean Callanan ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, 304dbb271fSSean Callanan const char *struct_name, 31b9c1b51eSKate Stone ClangFunctionCaller &function) 32248a1305SKonrad Kleine : m_ast_context(nullptr), m_passthrough(passthrough), 33*2e033244SRaphael Isemann m_passthrough_sema(nullptr), m_sema(nullptr), m_function(function), 34*2e033244SRaphael Isemann m_struct_name(struct_name) { 354dbb271fSSean Callanan if (!m_passthrough) 364dbb271fSSean Callanan return; 374dbb271fSSean Callanan 384dbb271fSSean Callanan m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); 394dbb271fSSean Callanan } 404dbb271fSSean Callanan 41b9c1b51eSKate Stone ASTStructExtractor::~ASTStructExtractor() {} 424dbb271fSSean Callanan 43b9c1b51eSKate Stone void ASTStructExtractor::Initialize(ASTContext &Context) { 444dbb271fSSean Callanan m_ast_context = &Context; 454dbb271fSSean Callanan 464dbb271fSSean Callanan if (m_passthrough) 474dbb271fSSean Callanan m_passthrough->Initialize(Context); 484dbb271fSSean Callanan } 494dbb271fSSean Callanan 50b9c1b51eSKate Stone void ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) { 514dbb271fSSean Callanan if (!F->hasBody()) 524dbb271fSSean Callanan return; 534dbb271fSSean Callanan 544dbb271fSSean Callanan Stmt *body_stmt = F->getBody(); 554dbb271fSSean Callanan CompoundStmt *body_compound_stmt = dyn_cast<CompoundStmt>(body_stmt); 564dbb271fSSean Callanan 574dbb271fSSean Callanan if (!body_compound_stmt) 584dbb271fSSean Callanan return; // do we have to handle this? 594dbb271fSSean Callanan 60248a1305SKonrad Kleine RecordDecl *struct_decl = nullptr; 614dbb271fSSean Callanan 62771ef6d4SMalcolm Parsons StringRef desired_name(m_struct_name); 634dbb271fSSean Callanan 64b9c1b51eSKate Stone for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(), 65b9c1b51eSKate Stone be = body_compound_stmt->body_end(); 66b9c1b51eSKate Stone bi != be; ++bi) { 674dbb271fSSean Callanan Stmt *curr_stmt = *bi; 684dbb271fSSean Callanan DeclStmt *curr_decl_stmt = dyn_cast<DeclStmt>(curr_stmt); 694dbb271fSSean Callanan if (!curr_decl_stmt) 704dbb271fSSean Callanan continue; 714dbb271fSSean Callanan DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup(); 72b9c1b51eSKate Stone for (Decl *candidate_decl : decl_group) { 734dbb271fSSean Callanan RecordDecl *candidate_record_decl = dyn_cast<RecordDecl>(candidate_decl); 744dbb271fSSean Callanan if (!candidate_record_decl) 754dbb271fSSean Callanan continue; 76b9c1b51eSKate Stone if (candidate_record_decl->getName() == desired_name) { 774dbb271fSSean Callanan struct_decl = candidate_record_decl; 784dbb271fSSean Callanan break; 794dbb271fSSean Callanan } 804dbb271fSSean Callanan } 814dbb271fSSean Callanan if (struct_decl) 824dbb271fSSean Callanan break; 834dbb271fSSean Callanan } 844dbb271fSSean Callanan 854dbb271fSSean Callanan if (!struct_decl) 864dbb271fSSean Callanan return; 874dbb271fSSean Callanan 88b9c1b51eSKate Stone const ASTRecordLayout *struct_layout( 89b9c1b51eSKate Stone &m_ast_context->getASTRecordLayout(struct_decl)); 904dbb271fSSean Callanan 914dbb271fSSean Callanan if (!struct_layout) 924dbb271fSSean Callanan return; 934dbb271fSSean Callanan 94b9c1b51eSKate Stone m_function.m_struct_size = 95b9c1b51eSKate Stone struct_layout->getSize() 96b9c1b51eSKate Stone .getQuantity(); // TODO Store m_struct_size as CharUnits 97b9c1b51eSKate Stone m_function.m_return_offset = 98b9c1b51eSKate Stone struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8; 99b9c1b51eSKate Stone m_function.m_return_size = 100b9c1b51eSKate Stone struct_layout->getDataSize().getQuantity() - m_function.m_return_offset; 1014dbb271fSSean Callanan 1024dbb271fSSean Callanan for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount(); 103b9c1b51eSKate Stone field_index < num_fields; ++field_index) { 104b9c1b51eSKate Stone m_function.m_member_offsets.push_back( 105b9c1b51eSKate Stone struct_layout->getFieldOffset(field_index) / 8); 1064dbb271fSSean Callanan } 1074dbb271fSSean Callanan 1084dbb271fSSean Callanan m_function.m_struct_valid = true; 1094dbb271fSSean Callanan } 1104dbb271fSSean Callanan 111b9c1b51eSKate Stone void ASTStructExtractor::ExtractFromTopLevelDecl(Decl *D) { 1124dbb271fSSean Callanan LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D); 1134dbb271fSSean Callanan 114b9c1b51eSKate Stone if (linkage_spec_decl) { 1154dbb271fSSean Callanan RecordDecl::decl_iterator decl_iterator; 1164dbb271fSSean Callanan 1174dbb271fSSean Callanan for (decl_iterator = linkage_spec_decl->decls_begin(); 118b9c1b51eSKate Stone decl_iterator != linkage_spec_decl->decls_end(); ++decl_iterator) { 1194dbb271fSSean Callanan ExtractFromTopLevelDecl(*decl_iterator); 1204dbb271fSSean Callanan } 1214dbb271fSSean Callanan } 1224dbb271fSSean Callanan 1234dbb271fSSean Callanan FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D); 1244dbb271fSSean Callanan 125b9c1b51eSKate Stone if (m_ast_context && function_decl && 126b9c1b51eSKate Stone !m_function.m_wrapper_function_name.compare( 127771ef6d4SMalcolm Parsons function_decl->getNameAsString())) { 1284dbb271fSSean Callanan ExtractFromFunctionDecl(function_decl); 1294dbb271fSSean Callanan } 1304dbb271fSSean Callanan } 1314dbb271fSSean Callanan 132b9c1b51eSKate Stone bool ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D) { 1334dbb271fSSean Callanan DeclGroupRef::iterator decl_iterator; 1344dbb271fSSean Callanan 135b9c1b51eSKate Stone for (decl_iterator = D.begin(); decl_iterator != D.end(); ++decl_iterator) { 1364dbb271fSSean Callanan Decl *decl = *decl_iterator; 1374dbb271fSSean Callanan 1384dbb271fSSean Callanan ExtractFromTopLevelDecl(decl); 1394dbb271fSSean Callanan } 1404dbb271fSSean Callanan 1414dbb271fSSean Callanan if (m_passthrough) 1424dbb271fSSean Callanan return m_passthrough->HandleTopLevelDecl(D); 1434dbb271fSSean Callanan return true; 1444dbb271fSSean Callanan } 1454dbb271fSSean Callanan 146b9c1b51eSKate Stone void ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) { 1474dbb271fSSean Callanan if (m_passthrough) 1484dbb271fSSean Callanan m_passthrough->HandleTranslationUnit(Ctx); 1494dbb271fSSean Callanan } 1504dbb271fSSean Callanan 151b9c1b51eSKate Stone void ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) { 1524dbb271fSSean Callanan if (m_passthrough) 1534dbb271fSSean Callanan m_passthrough->HandleTagDeclDefinition(D); 1544dbb271fSSean Callanan } 1554dbb271fSSean Callanan 156b9c1b51eSKate Stone void ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) { 1574dbb271fSSean Callanan if (m_passthrough) 1584dbb271fSSean Callanan m_passthrough->CompleteTentativeDefinition(D); 1594dbb271fSSean Callanan } 1604dbb271fSSean Callanan 161b9c1b51eSKate Stone void ASTStructExtractor::HandleVTable(CXXRecordDecl *RD) { 1624dbb271fSSean Callanan if (m_passthrough) 1634dbb271fSSean Callanan m_passthrough->HandleVTable(RD); 1644dbb271fSSean Callanan } 1654dbb271fSSean Callanan 166b9c1b51eSKate Stone void ASTStructExtractor::PrintStats() { 1674dbb271fSSean Callanan if (m_passthrough) 1684dbb271fSSean Callanan m_passthrough->PrintStats(); 1694dbb271fSSean Callanan } 1704dbb271fSSean Callanan 171b9c1b51eSKate Stone void ASTStructExtractor::InitializeSema(Sema &S) { 1724dbb271fSSean Callanan m_sema = &S; 1734dbb271fSSean Callanan 1744dbb271fSSean Callanan if (m_passthrough_sema) 1754dbb271fSSean Callanan m_passthrough_sema->InitializeSema(S); 1764dbb271fSSean Callanan } 1774dbb271fSSean Callanan 178b9c1b51eSKate Stone void ASTStructExtractor::ForgetSema() { 179248a1305SKonrad Kleine m_sema = nullptr; 1804dbb271fSSean Callanan 1814dbb271fSSean Callanan if (m_passthrough_sema) 1824dbb271fSSean Callanan m_passthrough_sema->ForgetSema(); 1834dbb271fSSean Callanan } 184