15ffd83dbSDimitry Andric //===-- ClangExpressionSourceCode.cpp -------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "ClangExpressionSourceCode.h" 100b57cec5SDimitry Andric 11fcaf7f86SDimitry Andric #include "ClangExpressionUtil.h" 12fcaf7f86SDimitry Andric 130b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h" 145ffd83dbSDimitry Andric #include "clang/Basic/FileManager.h" 150b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h" 160b57cec5SDimitry Andric #include "clang/Lex/Lexer.h" 1706c3fb27SDimitry Andric #include "llvm/ADT/ScopeExit.h" 180b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" 210b57cec5SDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" 220b57cec5SDimitry Andric #include "lldb/Symbol/Block.h" 230b57cec5SDimitry Andric #include "lldb/Symbol/CompileUnit.h" 240b57cec5SDimitry Andric #include "lldb/Symbol/DebugMacros.h" 250b57cec5SDimitry Andric #include "lldb/Symbol/TypeSystem.h" 260b57cec5SDimitry Andric #include "lldb/Symbol/VariableList.h" 270b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h" 280b57cec5SDimitry Andric #include "lldb/Target/Language.h" 290b57cec5SDimitry Andric #include "lldb/Target/Platform.h" 300b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h" 310b57cec5SDimitry Andric #include "lldb/Target/Target.h" 320b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h" 33fcaf7f86SDimitry Andric #include "lldb/lldb-forward.h" 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric using namespace lldb_private; 360b57cec5SDimitry Andric 379dba64beSDimitry Andric #define PREFIX_NAME "<lldb wrapper prefix>" 38fe6060f1SDimitry Andric #define SUFFIX_NAME "<lldb wrapper suffix>" 399dba64beSDimitry Andric 409dba64beSDimitry Andric const llvm::StringRef ClangExpressionSourceCode::g_prefix_file_name = PREFIX_NAME; 419dba64beSDimitry Andric 429dba64beSDimitry Andric const char *ClangExpressionSourceCode::g_expression_prefix = 439dba64beSDimitry Andric "#line 1 \"" PREFIX_NAME R"(" 449dba64beSDimitry Andric #ifndef offsetof 459dba64beSDimitry Andric #define offsetof(t, d) __builtin_offsetof(t, d) 469dba64beSDimitry Andric #endif 470b57cec5SDimitry Andric #ifndef NULL 480b57cec5SDimitry Andric #define NULL (__null) 490b57cec5SDimitry Andric #endif 500b57cec5SDimitry Andric #ifndef Nil 510b57cec5SDimitry Andric #define Nil (__null) 520b57cec5SDimitry Andric #endif 530b57cec5SDimitry Andric #ifndef nil 540b57cec5SDimitry Andric #define nil (__null) 550b57cec5SDimitry Andric #endif 560b57cec5SDimitry Andric #ifndef YES 570b57cec5SDimitry Andric #define YES ((BOOL)1) 580b57cec5SDimitry Andric #endif 590b57cec5SDimitry Andric #ifndef NO 600b57cec5SDimitry Andric #define NO ((BOOL)0) 610b57cec5SDimitry Andric #endif 620b57cec5SDimitry Andric typedef __INT8_TYPE__ int8_t; 630b57cec5SDimitry Andric typedef __UINT8_TYPE__ uint8_t; 640b57cec5SDimitry Andric typedef __INT16_TYPE__ int16_t; 650b57cec5SDimitry Andric typedef __UINT16_TYPE__ uint16_t; 660b57cec5SDimitry Andric typedef __INT32_TYPE__ int32_t; 670b57cec5SDimitry Andric typedef __UINT32_TYPE__ uint32_t; 680b57cec5SDimitry Andric typedef __INT64_TYPE__ int64_t; 690b57cec5SDimitry Andric typedef __UINT64_TYPE__ uint64_t; 700b57cec5SDimitry Andric typedef __INTPTR_TYPE__ intptr_t; 710b57cec5SDimitry Andric typedef __UINTPTR_TYPE__ uintptr_t; 720b57cec5SDimitry Andric typedef __SIZE_TYPE__ size_t; 730b57cec5SDimitry Andric typedef __PTRDIFF_TYPE__ ptrdiff_t; 740b57cec5SDimitry Andric typedef unsigned short unichar; 750b57cec5SDimitry Andric extern "C" 760b57cec5SDimitry Andric { 770b57cec5SDimitry Andric int printf(const char * __restrict, ...); 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric )"; 800b57cec5SDimitry Andric 81fe6060f1SDimitry Andric const char *ClangExpressionSourceCode::g_expression_suffix = 82fe6060f1SDimitry Andric "\n;\n#line 1 \"" SUFFIX_NAME "\"\n"; 83fe6060f1SDimitry Andric 840b57cec5SDimitry Andric namespace { 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric class AddMacroState { 870b57cec5SDimitry Andric enum State { 880b57cec5SDimitry Andric CURRENT_FILE_NOT_YET_PUSHED, 890b57cec5SDimitry Andric CURRENT_FILE_PUSHED, 900b57cec5SDimitry Andric CURRENT_FILE_POPPED 910b57cec5SDimitry Andric }; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric public: 940b57cec5SDimitry Andric AddMacroState(const FileSpec ¤t_file, const uint32_t current_file_line) 9581ad6265SDimitry Andric : m_current_file(current_file), m_current_file_line(current_file_line) {} 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric void StartFile(const FileSpec &file) { 980b57cec5SDimitry Andric m_file_stack.push_back(file); 990b57cec5SDimitry Andric if (file == m_current_file) 1000b57cec5SDimitry Andric m_state = CURRENT_FILE_PUSHED; 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric void EndFile() { 1040b57cec5SDimitry Andric if (m_file_stack.size() == 0) 1050b57cec5SDimitry Andric return; 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric FileSpec old_top = m_file_stack.back(); 1080b57cec5SDimitry Andric m_file_stack.pop_back(); 1090b57cec5SDimitry Andric if (old_top == m_current_file) 1100b57cec5SDimitry Andric m_state = CURRENT_FILE_POPPED; 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric // An entry is valid if it occurs before the current line in the current 1140b57cec5SDimitry Andric // file. 1150b57cec5SDimitry Andric bool IsValidEntry(uint32_t line) { 1160b57cec5SDimitry Andric switch (m_state) { 1170b57cec5SDimitry Andric case CURRENT_FILE_NOT_YET_PUSHED: 1180b57cec5SDimitry Andric return true; 1190b57cec5SDimitry Andric case CURRENT_FILE_PUSHED: 1200b57cec5SDimitry Andric // If we are in file included in the current file, the entry should be 1210b57cec5SDimitry Andric // added. 1220b57cec5SDimitry Andric if (m_file_stack.back() != m_current_file) 1230b57cec5SDimitry Andric return true; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric return line < m_current_file_line; 1260b57cec5SDimitry Andric default: 1270b57cec5SDimitry Andric return false; 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric private: 1320b57cec5SDimitry Andric std::vector<FileSpec> m_file_stack; 13381ad6265SDimitry Andric State m_state = CURRENT_FILE_NOT_YET_PUSHED; 1340b57cec5SDimitry Andric FileSpec m_current_file; 1350b57cec5SDimitry Andric uint32_t m_current_file_line; 1360b57cec5SDimitry Andric }; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric } // anonymous namespace 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric static void AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, 1410b57cec5SDimitry Andric AddMacroState &state, StreamString &stream) { 1420b57cec5SDimitry Andric if (dm == nullptr) 1430b57cec5SDimitry Andric return; 1440b57cec5SDimitry Andric 14506c3fb27SDimitry Andric // The macros directives below can potentially redefine builtin macros of the 14606c3fb27SDimitry Andric // Clang instance which parses the user expression. The Clang diagnostics 14706c3fb27SDimitry Andric // caused by this are not useful for the user as the source code here is 14806c3fb27SDimitry Andric // generated by LLDB. 14906c3fb27SDimitry Andric stream << "#pragma clang diagnostic push\n"; 15006c3fb27SDimitry Andric stream << "#pragma clang diagnostic ignored \"-Wmacro-redefined\"\n"; 15106c3fb27SDimitry Andric stream << "#pragma clang diagnostic ignored \"-Wbuiltin-macro-redefined\"\n"; 15206c3fb27SDimitry Andric auto pop_warning = llvm::make_scope_exit([&stream](){ 15306c3fb27SDimitry Andric stream << "#pragma clang diagnostic pop\n"; 15406c3fb27SDimitry Andric }); 15506c3fb27SDimitry Andric 1560b57cec5SDimitry Andric for (size_t i = 0; i < dm->GetNumMacroEntries(); i++) { 1570b57cec5SDimitry Andric const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i); 1580b57cec5SDimitry Andric uint32_t line; 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric switch (entry.GetType()) { 1610b57cec5SDimitry Andric case DebugMacroEntry::DEFINE: 1620b57cec5SDimitry Andric if (state.IsValidEntry(entry.GetLineNumber())) 1630b57cec5SDimitry Andric stream.Printf("#define %s\n", entry.GetMacroString().AsCString()); 1640b57cec5SDimitry Andric else 1650b57cec5SDimitry Andric return; 1660b57cec5SDimitry Andric break; 1670b57cec5SDimitry Andric case DebugMacroEntry::UNDEF: 1680b57cec5SDimitry Andric if (state.IsValidEntry(entry.GetLineNumber())) 1690b57cec5SDimitry Andric stream.Printf("#undef %s\n", entry.GetMacroString().AsCString()); 1700b57cec5SDimitry Andric else 1710b57cec5SDimitry Andric return; 1720b57cec5SDimitry Andric break; 1730b57cec5SDimitry Andric case DebugMacroEntry::START_FILE: 1740b57cec5SDimitry Andric line = entry.GetLineNumber(); 1750b57cec5SDimitry Andric if (state.IsValidEntry(line)) 1760b57cec5SDimitry Andric state.StartFile(entry.GetFileSpec(comp_unit)); 1770b57cec5SDimitry Andric else 1780b57cec5SDimitry Andric return; 1790b57cec5SDimitry Andric break; 1800b57cec5SDimitry Andric case DebugMacroEntry::END_FILE: 1810b57cec5SDimitry Andric state.EndFile(); 1820b57cec5SDimitry Andric break; 1830b57cec5SDimitry Andric case DebugMacroEntry::INDIRECT: 1840b57cec5SDimitry Andric AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream); 1850b57cec5SDimitry Andric break; 1860b57cec5SDimitry Andric default: 1870b57cec5SDimitry Andric // This is an unknown/invalid entry. Ignore. 1880b57cec5SDimitry Andric break; 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric 1939dba64beSDimitry Andric lldb_private::ClangExpressionSourceCode::ClangExpressionSourceCode( 1949dba64beSDimitry Andric llvm::StringRef filename, llvm::StringRef name, llvm::StringRef prefix, 1955ffd83dbSDimitry Andric llvm::StringRef body, Wrapping wrap, WrapKind wrap_kind) 1965ffd83dbSDimitry Andric : ExpressionSourceCode(name, prefix, body, wrap), m_wrap_kind(wrap_kind) { 1979dba64beSDimitry Andric // Use #line markers to pretend that we have a single-line source file 1989dba64beSDimitry Andric // containing only the user expression. This will hide our wrapper code 1999dba64beSDimitry Andric // from the user when we render diagnostics with Clang. 2009dba64beSDimitry Andric m_start_marker = "#line 1 \"" + filename.str() + "\"\n"; 201fe6060f1SDimitry Andric m_end_marker = g_expression_suffix; 2029dba64beSDimitry Andric } 2039dba64beSDimitry Andric 2040b57cec5SDimitry Andric namespace { 2050b57cec5SDimitry Andric /// Allows checking if a token is contained in a given expression. 2060b57cec5SDimitry Andric class TokenVerifier { 2070b57cec5SDimitry Andric /// The tokens we found in the expression. 2080b57cec5SDimitry Andric llvm::StringSet<> m_tokens; 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric public: 2110b57cec5SDimitry Andric TokenVerifier(std::string body); 2120b57cec5SDimitry Andric /// Returns true iff the given expression body contained a token with the 2130b57cec5SDimitry Andric /// given content. 2140b57cec5SDimitry Andric bool hasToken(llvm::StringRef token) const { 21506c3fb27SDimitry Andric return m_tokens.contains(token); 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric }; 218fcaf7f86SDimitry Andric 219fcaf7f86SDimitry Andric // If we're evaluating from inside a lambda that captures a 'this' pointer, 220fcaf7f86SDimitry Andric // add a "using" declaration to 'stream' for each capture used in the 221fcaf7f86SDimitry Andric // expression (tokenized by 'verifier'). 222fcaf7f86SDimitry Andric // 223fcaf7f86SDimitry Andric // If no 'this' capture exists, generate no using declarations. Instead 224fcaf7f86SDimitry Andric // capture lookups will get resolved by the same mechanism as class member 225fcaf7f86SDimitry Andric // variable lookup. That's because Clang generates an unnamed structure 226fcaf7f86SDimitry Andric // representing the lambda closure whose members are the captured variables. 227fcaf7f86SDimitry Andric void AddLambdaCaptureDecls(StreamString &stream, StackFrame *frame, 228fcaf7f86SDimitry Andric TokenVerifier const &verifier) { 229fcaf7f86SDimitry Andric assert(frame); 230fcaf7f86SDimitry Andric 231fcaf7f86SDimitry Andric if (auto thisValSP = ClangExpressionUtil::GetLambdaValueObject(frame)) { 232*0fca6ea1SDimitry Andric uint32_t numChildren = thisValSP->GetNumChildrenIgnoringErrors(); 233fcaf7f86SDimitry Andric for (uint32_t i = 0; i < numChildren; ++i) { 23406c3fb27SDimitry Andric auto childVal = thisValSP->GetChildAtIndex(i); 235fcaf7f86SDimitry Andric ConstString childName(childVal ? childVal->GetName() : ConstString("")); 236fcaf7f86SDimitry Andric 237fcaf7f86SDimitry Andric if (!childName.IsEmpty() && verifier.hasToken(childName.GetStringRef()) && 238fcaf7f86SDimitry Andric childName != "this") { 239fcaf7f86SDimitry Andric stream.Printf("using $__lldb_local_vars::%s;\n", 240fcaf7f86SDimitry Andric childName.GetCString()); 241fcaf7f86SDimitry Andric } 242fcaf7f86SDimitry Andric } 243fcaf7f86SDimitry Andric } 244fcaf7f86SDimitry Andric } 245fcaf7f86SDimitry Andric 2460b57cec5SDimitry Andric } // namespace 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric TokenVerifier::TokenVerifier(std::string body) { 2490b57cec5SDimitry Andric using namespace clang; 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric // We only care about tokens and not their original source locations. If we 2520b57cec5SDimitry Andric // move the whole expression to only be in one line we can simplify the 2530b57cec5SDimitry Andric // following code that extracts the token contents. 2540b57cec5SDimitry Andric std::replace(body.begin(), body.end(), '\n', ' '); 2550b57cec5SDimitry Andric std::replace(body.begin(), body.end(), '\r', ' '); 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric FileSystemOptions file_opts; 2580b57cec5SDimitry Andric FileManager file_mgr(file_opts, 2590b57cec5SDimitry Andric FileSystem::Instance().GetVirtualFileSystem()); 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric // Let's build the actual source code Clang needs and setup some utility 2620b57cec5SDimitry Andric // objects. 2630b57cec5SDimitry Andric llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_ids(new DiagnosticIDs()); 2640b57cec5SDimitry Andric llvm::IntrusiveRefCntPtr<DiagnosticOptions> diags_opts( 2650b57cec5SDimitry Andric new DiagnosticOptions()); 2660b57cec5SDimitry Andric DiagnosticsEngine diags(diag_ids, diags_opts); 2670b57cec5SDimitry Andric clang::SourceManager SM(diags, file_mgr); 2680b57cec5SDimitry Andric auto buf = llvm::MemoryBuffer::getMemBuffer(body); 2690b57cec5SDimitry Andric 270e8d8bef9SDimitry Andric FileID FID = SM.createFileID(buf->getMemBufferRef()); 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric // Let's just enable the latest ObjC and C++ which should get most tokens 2730b57cec5SDimitry Andric // right. 2740b57cec5SDimitry Andric LangOptions Opts; 2750b57cec5SDimitry Andric Opts.ObjC = true; 2760b57cec5SDimitry Andric Opts.DollarIdents = true; 27706c3fb27SDimitry Andric Opts.CPlusPlus20 = true; 2780b57cec5SDimitry Andric Opts.LineComment = true; 2790b57cec5SDimitry Andric 280e8d8bef9SDimitry Andric Lexer lex(FID, buf->getMemBufferRef(), SM, Opts); 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric Token token; 2830b57cec5SDimitry Andric bool exit = false; 2840b57cec5SDimitry Andric while (!exit) { 2850b57cec5SDimitry Andric // Returns true if this is the last token we get from the lexer. 2860b57cec5SDimitry Andric exit = lex.LexFromRawLexer(token); 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric // Extract the column number which we need to extract the token content. 2890b57cec5SDimitry Andric // Our expression is just one line, so we don't need to handle any line 2900b57cec5SDimitry Andric // numbers here. 2910b57cec5SDimitry Andric bool invalid = false; 2920b57cec5SDimitry Andric unsigned start = SM.getSpellingColumnNumber(token.getLocation(), &invalid); 2930b57cec5SDimitry Andric if (invalid) 2940b57cec5SDimitry Andric continue; 2950b57cec5SDimitry Andric // Column numbers start at 1, but indexes in our string start at 0. 2960b57cec5SDimitry Andric --start; 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric // Annotations don't have a length, so let's skip them. 2990b57cec5SDimitry Andric if (token.isAnnotation()) 3000b57cec5SDimitry Andric continue; 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric // Extract the token string from our source code and store it. 3030b57cec5SDimitry Andric std::string token_str = body.substr(start, token.getLength()); 3040b57cec5SDimitry Andric if (token_str.empty()) 3050b57cec5SDimitry Andric continue; 3060b57cec5SDimitry Andric m_tokens.insert(token_str); 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric } 3090b57cec5SDimitry Andric 310fcaf7f86SDimitry Andric void ClangExpressionSourceCode::AddLocalVariableDecls(StreamString &stream, 311fcaf7f86SDimitry Andric const std::string &expr, 312fcaf7f86SDimitry Andric StackFrame *frame) const { 313fcaf7f86SDimitry Andric assert(frame); 3140b57cec5SDimitry Andric TokenVerifier tokens(expr); 3150b57cec5SDimitry Andric 316fcaf7f86SDimitry Andric lldb::VariableListSP var_list_sp = frame->GetInScopeVariableList(false, true); 317fcaf7f86SDimitry Andric 3180b57cec5SDimitry Andric for (size_t i = 0; i < var_list_sp->GetSize(); i++) { 3190b57cec5SDimitry Andric lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i); 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric ConstString var_name = var_sp->GetName(); 3220b57cec5SDimitry Andric 323fcaf7f86SDimitry Andric if (var_name == "this" && m_wrap_kind == WrapKind::CppMemberFunction) { 324fcaf7f86SDimitry Andric AddLambdaCaptureDecls(stream, frame, tokens); 325fcaf7f86SDimitry Andric 326fcaf7f86SDimitry Andric continue; 327fcaf7f86SDimitry Andric } 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric // We can check for .block_descriptor w/o checking for langauge since this 3300b57cec5SDimitry Andric // is not a valid identifier in either C or C++. 3310b57cec5SDimitry Andric if (!var_name || var_name == ".block_descriptor") 3320b57cec5SDimitry Andric continue; 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric if (!expr.empty() && !tokens.hasToken(var_name.GetStringRef())) 3350b57cec5SDimitry Andric continue; 3360b57cec5SDimitry Andric 3375ffd83dbSDimitry Andric const bool is_objc = m_wrap_kind == WrapKind::ObjCInstanceMethod || 3385ffd83dbSDimitry Andric m_wrap_kind == WrapKind::ObjCStaticMethod; 3395ffd83dbSDimitry Andric if ((var_name == "self" || var_name == "_cmd") && is_objc) 3400b57cec5SDimitry Andric continue; 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString()); 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric } 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric bool ClangExpressionSourceCode::GetText( 3475ffd83dbSDimitry Andric std::string &text, ExecutionContext &exe_ctx, bool add_locals, 3485ffd83dbSDimitry Andric bool force_add_all_locals, llvm::ArrayRef<std::string> modules) const { 3490b57cec5SDimitry Andric const char *target_specific_defines = "typedef signed char BOOL;\n"; 3500b57cec5SDimitry Andric std::string module_macros; 351e8d8bef9SDimitry Andric llvm::raw_string_ostream module_macros_stream(module_macros); 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric Target *target = exe_ctx.GetTargetPtr(); 3540b57cec5SDimitry Andric if (target) { 3559dba64beSDimitry Andric if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64 || 3569dba64beSDimitry Andric target->GetArchitecture().GetMachine() == llvm::Triple::aarch64_32) { 3570b57cec5SDimitry Andric target_specific_defines = "typedef bool BOOL;\n"; 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) { 3600b57cec5SDimitry Andric if (lldb::PlatformSP platform_sp = target->GetPlatform()) { 361349cc55cSDimitry Andric if (platform_sp->GetPluginName() == "ios-simulator") { 3620b57cec5SDimitry Andric target_specific_defines = "typedef bool BOOL;\n"; 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric 367480093f4SDimitry Andric auto *persistent_vars = llvm::cast<ClangPersistentVariables>( 368480093f4SDimitry Andric target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); 369fe6060f1SDimitry Andric std::shared_ptr<ClangModulesDeclVendor> decl_vendor = 370fe6060f1SDimitry Andric persistent_vars->GetClangModulesDeclVendor(); 371fe6060f1SDimitry Andric if (decl_vendor) { 3720b57cec5SDimitry Andric const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = 3730b57cec5SDimitry Andric persistent_vars->GetHandLoadedClangModules(); 3740b57cec5SDimitry Andric ClangModulesDeclVendor::ModuleVector modules_for_macros; 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) { 3770b57cec5SDimitry Andric modules_for_macros.push_back(module); 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric if (target->GetEnableAutoImportClangModules()) { 3810b57cec5SDimitry Andric if (StackFrame *frame = exe_ctx.GetFramePtr()) { 3820b57cec5SDimitry Andric if (Block *block = frame->GetFrameBlock()) { 3830b57cec5SDimitry Andric SymbolContext sc; 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric block->CalculateSymbolContext(&sc); 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric if (sc.comp_unit) { 3880b57cec5SDimitry Andric StreamString error_stream; 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric decl_vendor->AddModulesForCompileUnit( 3910b57cec5SDimitry Andric *sc.comp_unit, modules_for_macros, error_stream); 3920b57cec5SDimitry Andric } 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric } 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric decl_vendor->ForEachMacro( 3980b57cec5SDimitry Andric modules_for_macros, 399e8d8bef9SDimitry Andric [&module_macros_stream](llvm::StringRef token, 400e8d8bef9SDimitry Andric llvm::StringRef expansion) -> bool { 401e8d8bef9SDimitry Andric // Check if the macro hasn't already been defined in the 402e8d8bef9SDimitry Andric // g_expression_prefix (which defines a few builtin macros). 403e8d8bef9SDimitry Andric module_macros_stream << "#ifndef " << token << "\n"; 404e8d8bef9SDimitry Andric module_macros_stream << expansion << "\n"; 405e8d8bef9SDimitry Andric module_macros_stream << "#endif\n"; 4060b57cec5SDimitry Andric return false; 4070b57cec5SDimitry Andric }); 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric } 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric StreamString debug_macros_stream; 4120b57cec5SDimitry Andric StreamString lldb_local_var_decls; 4130b57cec5SDimitry Andric if (StackFrame *frame = exe_ctx.GetFramePtr()) { 4140b57cec5SDimitry Andric const SymbolContext &sc = frame->GetSymbolContext( 4150b57cec5SDimitry Andric lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry); 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric if (sc.comp_unit && sc.line_entry.IsValid()) { 4180b57cec5SDimitry Andric DebugMacros *dm = sc.comp_unit->GetDebugMacros(); 4190b57cec5SDimitry Andric if (dm) { 420*0fca6ea1SDimitry Andric AddMacroState state(sc.line_entry.GetFile(), sc.line_entry.line); 4210b57cec5SDimitry Andric AddMacros(dm, sc.comp_unit, state, debug_macros_stream); 4220b57cec5SDimitry Andric } 4230b57cec5SDimitry Andric } 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric if (add_locals) 4260b57cec5SDimitry Andric if (target->GetInjectLocalVariables(&exe_ctx)) { 427fcaf7f86SDimitry Andric AddLocalVariableDecls(lldb_local_var_decls, 428fcaf7f86SDimitry Andric force_add_all_locals ? "" : m_body, frame); 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric if (m_wrap) { 4330b57cec5SDimitry Andric // Generate a list of @import statements that will import the specified 4340b57cec5SDimitry Andric // module into our expression. 4350b57cec5SDimitry Andric std::string module_imports; 4360b57cec5SDimitry Andric for (const std::string &module : modules) { 4370b57cec5SDimitry Andric module_imports.append("@import "); 4380b57cec5SDimitry Andric module_imports.append(module); 4390b57cec5SDimitry Andric module_imports.append(";\n"); 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric StreamString wrap_stream; 4430b57cec5SDimitry Andric 444e8d8bef9SDimitry Andric wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n", g_expression_prefix, 445e8d8bef9SDimitry Andric module_macros.c_str(), debug_macros_stream.GetData(), 4460b57cec5SDimitry Andric target_specific_defines, m_prefix.c_str()); 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric // First construct a tagged form of the user expression so we can find it 4490b57cec5SDimitry Andric // later: 4500b57cec5SDimitry Andric std::string tagged_body; 4519dba64beSDimitry Andric tagged_body.append(m_start_marker); 4520b57cec5SDimitry Andric tagged_body.append(m_body); 4539dba64beSDimitry Andric tagged_body.append(m_end_marker); 4545ffd83dbSDimitry Andric 4555ffd83dbSDimitry Andric switch (m_wrap_kind) { 4565ffd83dbSDimitry Andric case WrapKind::Function: 4570b57cec5SDimitry Andric wrap_stream.Printf("%s" 4580b57cec5SDimitry Andric "void \n" 4590b57cec5SDimitry Andric "%s(void *$__lldb_arg) \n" 4600b57cec5SDimitry Andric "{ \n" 4610b57cec5SDimitry Andric " %s; \n" 4620b57cec5SDimitry Andric "%s" 4630b57cec5SDimitry Andric "} \n", 4640b57cec5SDimitry Andric module_imports.c_str(), m_name.c_str(), 4650b57cec5SDimitry Andric lldb_local_var_decls.GetData(), tagged_body.c_str()); 4660b57cec5SDimitry Andric break; 4675ffd83dbSDimitry Andric case WrapKind::CppMemberFunction: 4680b57cec5SDimitry Andric wrap_stream.Printf("%s" 4690b57cec5SDimitry Andric "void \n" 4700b57cec5SDimitry Andric "$__lldb_class::%s(void *$__lldb_arg) \n" 4710b57cec5SDimitry Andric "{ \n" 4720b57cec5SDimitry Andric " %s; \n" 4730b57cec5SDimitry Andric "%s" 4740b57cec5SDimitry Andric "} \n", 4750b57cec5SDimitry Andric module_imports.c_str(), m_name.c_str(), 4760b57cec5SDimitry Andric lldb_local_var_decls.GetData(), tagged_body.c_str()); 4770b57cec5SDimitry Andric break; 4785ffd83dbSDimitry Andric case WrapKind::ObjCInstanceMethod: 4790b57cec5SDimitry Andric wrap_stream.Printf( 4800b57cec5SDimitry Andric "%s" 4810b57cec5SDimitry Andric "@interface $__lldb_objc_class ($__lldb_category) \n" 4820b57cec5SDimitry Andric "-(void)%s:(void *)$__lldb_arg; \n" 4830b57cec5SDimitry Andric "@end \n" 4840b57cec5SDimitry Andric "@implementation $__lldb_objc_class ($__lldb_category) \n" 4850b57cec5SDimitry Andric "-(void)%s:(void *)$__lldb_arg \n" 4860b57cec5SDimitry Andric "{ \n" 4870b57cec5SDimitry Andric " %s; \n" 4880b57cec5SDimitry Andric "%s" 4890b57cec5SDimitry Andric "} \n" 4900b57cec5SDimitry Andric "@end \n", 4910b57cec5SDimitry Andric module_imports.c_str(), m_name.c_str(), m_name.c_str(), 4920b57cec5SDimitry Andric lldb_local_var_decls.GetData(), tagged_body.c_str()); 4935ffd83dbSDimitry Andric break; 4945ffd83dbSDimitry Andric 4955ffd83dbSDimitry Andric case WrapKind::ObjCStaticMethod: 4965ffd83dbSDimitry Andric wrap_stream.Printf( 4975ffd83dbSDimitry Andric "%s" 4985ffd83dbSDimitry Andric "@interface $__lldb_objc_class ($__lldb_category) \n" 4995ffd83dbSDimitry Andric "+(void)%s:(void *)$__lldb_arg; \n" 5005ffd83dbSDimitry Andric "@end \n" 5015ffd83dbSDimitry Andric "@implementation $__lldb_objc_class ($__lldb_category) \n" 5025ffd83dbSDimitry Andric "+(void)%s:(void *)$__lldb_arg \n" 5035ffd83dbSDimitry Andric "{ \n" 5045ffd83dbSDimitry Andric " %s; \n" 5055ffd83dbSDimitry Andric "%s" 5065ffd83dbSDimitry Andric "} \n" 5075ffd83dbSDimitry Andric "@end \n", 5085ffd83dbSDimitry Andric module_imports.c_str(), m_name.c_str(), m_name.c_str(), 5095ffd83dbSDimitry Andric lldb_local_var_decls.GetData(), tagged_body.c_str()); 5100b57cec5SDimitry Andric break; 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric 5135ffd83dbSDimitry Andric text = std::string(wrap_stream.GetString()); 5140b57cec5SDimitry Andric } else { 5150b57cec5SDimitry Andric text.append(m_body); 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric return true; 5190b57cec5SDimitry Andric } 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric bool ClangExpressionSourceCode::GetOriginalBodyBounds( 5225ffd83dbSDimitry Andric std::string transformed_text, size_t &start_loc, size_t &end_loc) { 5239dba64beSDimitry Andric start_loc = transformed_text.find(m_start_marker); 5240b57cec5SDimitry Andric if (start_loc == std::string::npos) 5250b57cec5SDimitry Andric return false; 5269dba64beSDimitry Andric start_loc += m_start_marker.size(); 5279dba64beSDimitry Andric end_loc = transformed_text.find(m_end_marker); 5280b57cec5SDimitry Andric return end_loc != std::string::npos; 5290b57cec5SDimitry Andric } 530