180814287SRaphael Isemann //===-- ASTStructExtractor.cpp --------------------------------------------===//
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 "clang/AST/ASTContext.h"
134dbb271fSSean Callanan #include "clang/AST/Decl.h"
144dbb271fSSean Callanan #include "clang/AST/DeclCXX.h"
154dbb271fSSean Callanan #include "clang/AST/DeclGroup.h"
164dbb271fSSean Callanan #include "clang/AST/Expr.h"
174dbb271fSSean Callanan #include "clang/AST/RecordLayout.h"
184dbb271fSSean Callanan #include "clang/AST/Stmt.h"
194dbb271fSSean Callanan #include "clang/Parse/Parser.h"
204dbb271fSSean Callanan #include "clang/Sema/Sema.h"
214dbb271fSSean Callanan #include "llvm/Support/Casting.h"
224dbb271fSSean Callanan #include "llvm/Support/raw_ostream.h"
2376e47d48SRaphael Isemann #include <cstdlib>
244dbb271fSSean Callanan
254dbb271fSSean Callanan using namespace llvm;
264dbb271fSSean Callanan using namespace clang;
274dbb271fSSean Callanan using namespace lldb_private;
284dbb271fSSean Callanan
ASTStructExtractor(ASTConsumer * passthrough,const char * struct_name,ClangFunctionCaller & function)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),
332e033244SRaphael Isemann m_passthrough_sema(nullptr), m_sema(nullptr), m_function(function),
342e033244SRaphael 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
41*fd2433e1SJonas Devlieghere ASTStructExtractor::~ASTStructExtractor() = default;
424dbb271fSSean Callanan
Initialize(ASTContext & Context)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
ExtractFromFunctionDecl(FunctionDecl * F)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
ExtractFromTopLevelDecl(Decl * D)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
HandleTopLevelDecl(DeclGroupRef D)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
HandleTranslationUnit(ASTContext & Ctx)146b9c1b51eSKate Stone void ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) {
1474dbb271fSSean Callanan if (m_passthrough)
1484dbb271fSSean Callanan m_passthrough->HandleTranslationUnit(Ctx);
1494dbb271fSSean Callanan }
1504dbb271fSSean Callanan
HandleTagDeclDefinition(TagDecl * D)151b9c1b51eSKate Stone void ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) {
1524dbb271fSSean Callanan if (m_passthrough)
1534dbb271fSSean Callanan m_passthrough->HandleTagDeclDefinition(D);
1544dbb271fSSean Callanan }
1554dbb271fSSean Callanan
CompleteTentativeDefinition(VarDecl * D)156b9c1b51eSKate Stone void ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) {
1574dbb271fSSean Callanan if (m_passthrough)
1584dbb271fSSean Callanan m_passthrough->CompleteTentativeDefinition(D);
1594dbb271fSSean Callanan }
1604dbb271fSSean Callanan
HandleVTable(CXXRecordDecl * RD)161b9c1b51eSKate Stone void ASTStructExtractor::HandleVTable(CXXRecordDecl *RD) {
1624dbb271fSSean Callanan if (m_passthrough)
1634dbb271fSSean Callanan m_passthrough->HandleVTable(RD);
1644dbb271fSSean Callanan }
1654dbb271fSSean Callanan
PrintStats()166b9c1b51eSKate Stone void ASTStructExtractor::PrintStats() {
1674dbb271fSSean Callanan if (m_passthrough)
1684dbb271fSSean Callanan m_passthrough->PrintStats();
1694dbb271fSSean Callanan }
1704dbb271fSSean Callanan
InitializeSema(Sema & S)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
ForgetSema()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