diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Expression/ASTStructExtractor.cpp')
| -rw-r--r-- | contrib/llvm/tools/lldb/source/Expression/ASTStructExtractor.cpp | 220 | 
1 files changed, 220 insertions, 0 deletions
diff --git a/contrib/llvm/tools/lldb/source/Expression/ASTStructExtractor.cpp b/contrib/llvm/tools/lldb/source/Expression/ASTStructExtractor.cpp new file mode 100644 index 000000000000..d1f21923deb4 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Expression/ASTStructExtractor.cpp @@ -0,0 +1,220 @@ +//===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "stdlib.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclGroup.h" +#include "clang/AST/Expr.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/Stmt.h" +#include "clang/Parse/Parser.h" +#include "clang/Sema/Sema.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" +#include "lldb/Core/Log.h" +#include "lldb/Expression/ASTStructExtractor.h" + +using namespace llvm; +using namespace clang; +using namespace lldb_private; + +ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, +                                       const char *struct_name, +                                       ClangFunction &function) : +    m_ast_context (NULL), +    m_passthrough (passthrough), +    m_passthrough_sema (NULL), +    m_sema (NULL), +    m_action (NULL), +    m_function (function), +    m_struct_name (struct_name) +{ +    if (!m_passthrough) +        return; +     +    m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); +} + +ASTStructExtractor::~ASTStructExtractor() +{ +} + +void +ASTStructExtractor::Initialize(ASTContext &Context)  +{ +    m_ast_context = &Context; +     +    if (m_passthrough) +        m_passthrough->Initialize(Context); +} + +void +ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) +{ +    if (!F->hasBody()) +        return; +     +    Stmt *body_stmt = F->getBody(); +    CompoundStmt *body_compound_stmt = dyn_cast<CompoundStmt>(body_stmt); +     +    if (!body_compound_stmt) +        return; // do we have to handle this? +     +    RecordDecl *struct_decl = NULL; +     +    StringRef desired_name(m_struct_name.c_str()); +     +    for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(), be = body_compound_stmt->body_end(); +         bi != be; +         ++bi) +    { +        Stmt *curr_stmt = *bi; +        DeclStmt *curr_decl_stmt = dyn_cast<DeclStmt>(curr_stmt); +        if (!curr_decl_stmt) +            continue; +        DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup(); +        for (Decl *candidate_decl : decl_group) +        { +            RecordDecl *candidate_record_decl = dyn_cast<RecordDecl>(candidate_decl); +            if (!candidate_record_decl) +                continue; +            if (candidate_record_decl->getName() == desired_name) +            { +                struct_decl = candidate_record_decl; +                break; +            } +        } +        if (struct_decl) +            break; +    } +     +    if (!struct_decl) +        return; +     +    const ASTRecordLayout* struct_layout(&m_ast_context->getASTRecordLayout (struct_decl)); +     +    if (!struct_layout) +        return; +     +    m_function.m_struct_size = struct_layout->getSize().getQuantity(); // TODO Store m_struct_size as CharUnits    +    m_function.m_return_offset = struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8; +    m_function.m_return_size = struct_layout->getDataSize().getQuantity() - m_function.m_return_offset; +     +    for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount(); +         field_index < num_fields; +         ++field_index) +    { +        m_function.m_member_offsets.push_back(struct_layout->getFieldOffset(field_index) / 8); +    } +     +    m_function.m_struct_valid = true; +} + +void +ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D) +{ +    LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D); +     +    if (linkage_spec_decl) +    { +        RecordDecl::decl_iterator decl_iterator; +         +        for (decl_iterator = linkage_spec_decl->decls_begin(); +             decl_iterator != linkage_spec_decl->decls_end(); +             ++decl_iterator) +        { +            ExtractFromTopLevelDecl(*decl_iterator); +        } +    } +     +    FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D); +     +    if (m_ast_context && +        function_decl && +        !m_function.m_wrapper_function_name.compare(function_decl->getNameAsString().c_str())) +    { +        ExtractFromFunctionDecl(function_decl); +    } +} + +bool  +ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D) +{ +    DeclGroupRef::iterator decl_iterator; +     +    for (decl_iterator = D.begin(); +         decl_iterator != D.end(); +         ++decl_iterator) +    { +        Decl *decl = *decl_iterator; +         +        ExtractFromTopLevelDecl(decl); +    } +     +    if (m_passthrough) +        return m_passthrough->HandleTopLevelDecl(D); +    return true; +} + +void +ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) +{     +    if (m_passthrough) +        m_passthrough->HandleTranslationUnit(Ctx); +} + +void  +ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) +{ +    if (m_passthrough) +        m_passthrough->HandleTagDeclDefinition(D); +} + +void +ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) +{ +    if (m_passthrough) +        m_passthrough->CompleteTentativeDefinition(D); +} + +void  +ASTStructExtractor::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)  +{ +    if (m_passthrough) +        m_passthrough->HandleVTable(RD, DefinitionRequired); +} + +void +ASTStructExtractor::PrintStats()  +{ +    if (m_passthrough) +        m_passthrough->PrintStats(); +} + +void +ASTStructExtractor::InitializeSema(Sema &S) +{ +    m_sema = &S; +    m_action = reinterpret_cast<Action*>(m_sema); +     +    if (m_passthrough_sema) +        m_passthrough_sema->InitializeSema(S); +} + +void  +ASTStructExtractor::ForgetSema()  +{ +    m_sema = NULL; +    m_action = NULL; +     +    if (m_passthrough_sema) +        m_passthrough_sema->ForgetSema(); +}  | 
