diff options
Diffstat (limited to 'source/Expression/ExpressionSourceCode.cpp')
| -rw-r--r-- | source/Expression/ExpressionSourceCode.cpp | 145 | 
1 files changed, 141 insertions, 4 deletions
diff --git a/source/Expression/ExpressionSourceCode.cpp b/source/Expression/ExpressionSourceCode.cpp index 9a42510d0a24a..c4ab7a95d7a9a 100644 --- a/source/Expression/ExpressionSourceCode.cpp +++ b/source/Expression/ExpressionSourceCode.cpp @@ -10,9 +10,12 @@  #include "lldb/Expression/ExpressionSourceCode.h"  #include "lldb/Core/StreamString.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" -#include "lldb/Expression/ClangPersistentVariables.h" +#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/DebugMacros.h"  #include "lldb/Symbol/Block.h" +#include "lldb/Symbol/TypeSystem.h"  #include "lldb/Target/ExecutionContext.h"  #include "lldb/Target/Platform.h"  #include "lldb/Target/StackFrame.h" @@ -56,6 +59,121 @@ extern "C"  }  )"; +namespace { + +class AddMacroState +{ +    enum State +    { +        CURRENT_FILE_NOT_YET_PUSHED, +        CURRENT_FILE_PUSHED, +        CURRENT_FILE_POPPED +    }; + +public: +    AddMacroState(const FileSpec ¤t_file, const uint32_t current_file_line) +        : m_state(CURRENT_FILE_NOT_YET_PUSHED), +          m_current_file(current_file), +          m_current_file_line(current_file_line) +    { } + +    void +    StartFile(const FileSpec &file) +    { +        m_file_stack.push_back(file); +        if (file == m_current_file) +            m_state = CURRENT_FILE_PUSHED; +    } + +    void +    EndFile() +    { +        if (m_file_stack.size() == 0) +            return; + +        FileSpec old_top = m_file_stack.back(); +        m_file_stack.pop_back(); +        if (old_top == m_current_file) +            m_state = CURRENT_FILE_POPPED; +    } + +    // An entry is valid if it occurs before the current line in +    // the current file. +    bool +    IsValidEntry(uint32_t line) +    { +        switch (m_state) +        { +            case CURRENT_FILE_NOT_YET_PUSHED: +                return true; +            case CURRENT_FILE_POPPED: +                return false; +            case CURRENT_FILE_PUSHED: +                // If we are in file included in the current file, +                // the entry should be added. +                if (m_file_stack.back() != m_current_file) +                    return true; + +                if (line >= m_current_file_line) +                    return false; +                else +                    return true; +        } +    } + +private: +    std::vector<FileSpec> m_file_stack; +    State m_state; +    FileSpec m_current_file; +    uint32_t m_current_file_line; +}; + +} // anonymous namespace + +static void +AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, AddMacroState &state, StreamString &stream) +{ +    if (dm == nullptr) +        return; + +    for (size_t i = 0; i < dm->GetNumMacroEntries(); i++) +    { +        const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i); +        uint32_t line; + +        switch (entry.GetType()) +        { +            case DebugMacroEntry::DEFINE: +                if (state.IsValidEntry(entry.GetLineNumber())) +                    stream.Printf("#define %s\n", entry.GetMacroString().AsCString()); +                else +                    return; +                break; +            case DebugMacroEntry::UNDEF: +                if (state.IsValidEntry(entry.GetLineNumber())) +                    stream.Printf("#undef %s\n", entry.GetMacroString().AsCString()); +                else +                    return; +                break; +            case DebugMacroEntry::START_FILE: +                line = entry.GetLineNumber(); +                if (state.IsValidEntry(line)) +                    state.StartFile(entry.GetFileSpec(comp_unit)); +                else +                    return; +                break; +            case DebugMacroEntry::END_FILE: +                state.EndFile(); +                break; +            case DebugMacroEntry::INDIRECT: +                AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream); +                break; +            default: +                // This is an unknown/invalid entry. Ignore. +                break; +        } +    } +}  bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method, ExecutionContext &exe_ctx) const  { @@ -82,7 +200,8 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi          if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor())          { -            const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = target->GetPersistentVariables().GetHandLoadedClangModules(); +            ClangPersistentVariables *persistent_vars = llvm::cast<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); +            const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = persistent_vars->GetHandLoadedClangModules();              ClangModulesDeclVendor::ModuleVector modules_for_macros;              for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) @@ -118,6 +237,23 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi          }      } + +    StreamString debug_macros_stream; +    if (StackFrame *frame = exe_ctx.GetFramePtr()) +    { +        const SymbolContext &sc = frame->GetSymbolContext( +           lldb:: eSymbolContextCompUnit | lldb::eSymbolContextLineEntry); + +        if (sc.comp_unit && sc.line_entry.IsValid()) +        { +            DebugMacros *dm = sc.comp_unit->GetDebugMacros(); +            if (dm) +            { +                AddMacroState state(sc.line_entry.file, sc.line_entry.line); +                AddMacros(dm, sc.comp_unit, state, debug_macros_stream); +            } +        } +    }      if (m_wrap)      { @@ -133,8 +269,9 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi          StreamString wrap_stream; -        wrap_stream.Printf("%s\n%s\n%s\n%s\n", +        wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n",                             module_macros.c_str(), +                           debug_macros_stream.GetData(),                             g_expression_prefix,                             target_specific_defines,                             m_prefix.c_str());  | 
