diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp b/contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp new file mode 100644 index 0000000..c4ab7a9 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp @@ -0,0 +1,344 @@ +//===-- ExpressionSourceCode.cpp --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Expression/ExpressionSourceCode.h" + +#include "lldb/Core/StreamString.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" +#include "lldb/Target/Target.h" + +using namespace lldb_private; + +const char * +ExpressionSourceCode::g_expression_prefix = R"( +#ifndef NULL +#define NULL (__null) +#endif +#ifndef Nil +#define Nil (__null) +#endif +#ifndef nil +#define nil (__null) +#endif +#ifndef YES +#define YES ((BOOL)1) +#endif +#ifndef NO +#define NO ((BOOL)0) +#endif +typedef __INT8_TYPE__ int8_t; +typedef __UINT8_TYPE__ uint8_t; +typedef __INT16_TYPE__ int16_t; +typedef __UINT16_TYPE__ uint16_t; +typedef __INT32_TYPE__ int32_t; +typedef __UINT32_TYPE__ uint32_t; +typedef __INT64_TYPE__ int64_t; +typedef __UINT64_TYPE__ uint64_t; +typedef __INTPTR_TYPE__ intptr_t; +typedef __UINTPTR_TYPE__ uintptr_t; +typedef __SIZE_TYPE__ size_t; +typedef __PTRDIFF_TYPE__ ptrdiff_t; +typedef unsigned short unichar; +extern "C" +{ + int printf(const char * __restrict, ...); +} +)"; + +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 +{ + const char *target_specific_defines = "typedef signed char BOOL;\n"; + std::string module_macros; + + if (Target *target = exe_ctx.GetTargetPtr()) + { + if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) + { + target_specific_defines = "typedef bool BOOL;\n"; + } + if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) + { + if (lldb::PlatformSP platform_sp = target->GetPlatform()) + { + static ConstString g_platform_ios_simulator ("ios-simulator"); + if (platform_sp->GetPluginName() == g_platform_ios_simulator) + { + target_specific_defines = "typedef bool BOOL;\n"; + } + } + } + + if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor()) + { + 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) + { + modules_for_macros.push_back(module); + } + + if (target->GetEnableAutoImportClangModules()) + { + if (StackFrame *frame = exe_ctx.GetFramePtr()) + { + if (Block *block = frame->GetFrameBlock()) + { + SymbolContext sc; + + block->CalculateSymbolContext(&sc); + + if (sc.comp_unit) + { + StreamString error_stream; + + decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream); + } + } + } + } + + decl_vendor->ForEachMacro(modules_for_macros, [&module_macros] (const std::string &expansion) -> bool { + module_macros.append(expansion); + module_macros.append("\n"); + return false; + }); + } + + } + + 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) + { + switch (wrapping_language) + { + default: + return false; + case lldb::eLanguageTypeC: + case lldb::eLanguageTypeC_plus_plus: + case lldb::eLanguageTypeObjC: + break; + } + + StreamString wrap_stream; + + 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()); + + switch (wrapping_language) + { + default: + break; + case lldb::eLanguageTypeC: + wrap_stream.Printf("void \n" + "%s(void *$__lldb_arg) \n" + "{ \n" + " %s; \n" + "} \n", + m_name.c_str(), + m_body.c_str()); + break; + case lldb::eLanguageTypeC_plus_plus: + wrap_stream.Printf("void \n" + "$__lldb_class::%s(void *$__lldb_arg) %s\n" + "{ \n" + " %s; \n" + "} \n", + m_name.c_str(), + (const_object ? "const" : ""), + m_body.c_str()); + break; + case lldb::eLanguageTypeObjC: + if (static_method) + { + wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category) \n" + "+(void)%s:(void *)$__lldb_arg; \n" + "@end \n" + "@implementation $__lldb_objc_class ($__lldb_category) \n" + "+(void)%s:(void *)$__lldb_arg \n" + "{ \n" + " %s; \n" + "} \n" + "@end \n", + m_name.c_str(), + m_name.c_str(), + m_body.c_str()); + } + else + { + wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category) \n" + "-(void)%s:(void *)$__lldb_arg; \n" + "@end \n" + "@implementation $__lldb_objc_class ($__lldb_category) \n" + "-(void)%s:(void *)$__lldb_arg \n" + "{ \n" + " %s; \n" + "} \n" + "@end \n", + m_name.c_str(), + m_name.c_str(), + m_body.c_str()); + } + break; + } + + text = wrap_stream.GetString(); + } + else + { + text.append(m_body); + } + + return true; +} |