1ac7ddfbfSEd Maste //===-- ExpressionSourceCode.cpp --------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste #include "lldb/Expression/ExpressionSourceCode.h"
11ac7ddfbfSEd Maste 
12ac7ddfbfSEd Maste #include "lldb/Core/StreamString.h"
139f2f44ceSEd Maste #include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
149f2f44ceSEd Maste #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
159f2f44ceSEd Maste #include "lldb/Symbol/CompileUnit.h"
169f2f44ceSEd Maste #include "lldb/Symbol/DebugMacros.h"
171c3bbb01SEd Maste #include "lldb/Symbol/Block.h"
189f2f44ceSEd Maste #include "lldb/Symbol/TypeSystem.h"
190127ef0fSEd Maste #include "lldb/Target/ExecutionContext.h"
200127ef0fSEd Maste #include "lldb/Target/Platform.h"
211c3bbb01SEd Maste #include "lldb/Target/StackFrame.h"
220127ef0fSEd Maste #include "lldb/Target/Target.h"
23ac7ddfbfSEd Maste 
24ac7ddfbfSEd Maste using namespace lldb_private;
25ac7ddfbfSEd Maste 
26ac7ddfbfSEd Maste const char *
27ac7ddfbfSEd Maste ExpressionSourceCode::g_expression_prefix = R"(
281c3bbb01SEd Maste #ifndef NULL
29ac7ddfbfSEd Maste #define NULL (__null)
301c3bbb01SEd Maste #endif
311c3bbb01SEd Maste #ifndef Nil
32ac7ddfbfSEd Maste #define Nil (__null)
331c3bbb01SEd Maste #endif
341c3bbb01SEd Maste #ifndef nil
35ac7ddfbfSEd Maste #define nil (__null)
361c3bbb01SEd Maste #endif
371c3bbb01SEd Maste #ifndef YES
38ac7ddfbfSEd Maste #define YES ((BOOL)1)
391c3bbb01SEd Maste #endif
401c3bbb01SEd Maste #ifndef NO
41ac7ddfbfSEd Maste #define NO ((BOOL)0)
421c3bbb01SEd Maste #endif
430127ef0fSEd Maste typedef __INT8_TYPE__ int8_t;
440127ef0fSEd Maste typedef __UINT8_TYPE__ uint8_t;
450127ef0fSEd Maste typedef __INT16_TYPE__ int16_t;
460127ef0fSEd Maste typedef __UINT16_TYPE__ uint16_t;
470127ef0fSEd Maste typedef __INT32_TYPE__ int32_t;
480127ef0fSEd Maste typedef __UINT32_TYPE__ uint32_t;
490127ef0fSEd Maste typedef __INT64_TYPE__ int64_t;
500127ef0fSEd Maste typedef __UINT64_TYPE__ uint64_t;
510127ef0fSEd Maste typedef __INTPTR_TYPE__ intptr_t;
520127ef0fSEd Maste typedef __UINTPTR_TYPE__ uintptr_t;
53ac7ddfbfSEd Maste typedef __SIZE_TYPE__ size_t;
54ac7ddfbfSEd Maste typedef __PTRDIFF_TYPE__ ptrdiff_t;
55ac7ddfbfSEd Maste typedef unsigned short unichar;
561c3bbb01SEd Maste extern "C"
571c3bbb01SEd Maste {
581c3bbb01SEd Maste     int printf(const char * __restrict, ...);
591c3bbb01SEd Maste }
60ac7ddfbfSEd Maste )";
61ac7ddfbfSEd Maste 
629f2f44ceSEd Maste namespace {
639f2f44ceSEd Maste 
649f2f44ceSEd Maste class AddMacroState
659f2f44ceSEd Maste {
669f2f44ceSEd Maste     enum State
679f2f44ceSEd Maste     {
689f2f44ceSEd Maste         CURRENT_FILE_NOT_YET_PUSHED,
699f2f44ceSEd Maste         CURRENT_FILE_PUSHED,
709f2f44ceSEd Maste         CURRENT_FILE_POPPED
719f2f44ceSEd Maste     };
729f2f44ceSEd Maste 
739f2f44ceSEd Maste public:
749f2f44ceSEd Maste     AddMacroState(const FileSpec &current_file, const uint32_t current_file_line)
759f2f44ceSEd Maste         : m_state(CURRENT_FILE_NOT_YET_PUSHED),
769f2f44ceSEd Maste           m_current_file(current_file),
779f2f44ceSEd Maste           m_current_file_line(current_file_line)
789f2f44ceSEd Maste     { }
799f2f44ceSEd Maste 
809f2f44ceSEd Maste     void
819f2f44ceSEd Maste     StartFile(const FileSpec &file)
829f2f44ceSEd Maste     {
839f2f44ceSEd Maste         m_file_stack.push_back(file);
849f2f44ceSEd Maste         if (file == m_current_file)
859f2f44ceSEd Maste             m_state = CURRENT_FILE_PUSHED;
869f2f44ceSEd Maste     }
879f2f44ceSEd Maste 
889f2f44ceSEd Maste     void
899f2f44ceSEd Maste     EndFile()
909f2f44ceSEd Maste     {
919f2f44ceSEd Maste         if (m_file_stack.size() == 0)
929f2f44ceSEd Maste             return;
939f2f44ceSEd Maste 
949f2f44ceSEd Maste         FileSpec old_top = m_file_stack.back();
959f2f44ceSEd Maste         m_file_stack.pop_back();
969f2f44ceSEd Maste         if (old_top == m_current_file)
979f2f44ceSEd Maste             m_state = CURRENT_FILE_POPPED;
989f2f44ceSEd Maste     }
999f2f44ceSEd Maste 
1009f2f44ceSEd Maste     // An entry is valid if it occurs before the current line in
1019f2f44ceSEd Maste     // the current file.
1029f2f44ceSEd Maste     bool
1039f2f44ceSEd Maste     IsValidEntry(uint32_t line)
1049f2f44ceSEd Maste     {
1059f2f44ceSEd Maste         switch (m_state)
1069f2f44ceSEd Maste         {
1079f2f44ceSEd Maste             case CURRENT_FILE_NOT_YET_PUSHED:
1089f2f44ceSEd Maste                 return true;
1099f2f44ceSEd Maste             case CURRENT_FILE_POPPED:
1109f2f44ceSEd Maste                 return false;
1119f2f44ceSEd Maste             case CURRENT_FILE_PUSHED:
1129f2f44ceSEd Maste                 // If we are in file included in the current file,
1139f2f44ceSEd Maste                 // the entry should be added.
1149f2f44ceSEd Maste                 if (m_file_stack.back() != m_current_file)
1159f2f44ceSEd Maste                     return true;
1169f2f44ceSEd Maste 
1179f2f44ceSEd Maste                 if (line >= m_current_file_line)
1189f2f44ceSEd Maste                     return false;
1199f2f44ceSEd Maste                 else
1209f2f44ceSEd Maste                     return true;
1219f2f44ceSEd Maste         }
1229f2f44ceSEd Maste     }
1239f2f44ceSEd Maste 
1249f2f44ceSEd Maste private:
1259f2f44ceSEd Maste     std::vector<FileSpec> m_file_stack;
1269f2f44ceSEd Maste     State m_state;
1279f2f44ceSEd Maste     FileSpec m_current_file;
1289f2f44ceSEd Maste     uint32_t m_current_file_line;
1299f2f44ceSEd Maste };
1309f2f44ceSEd Maste 
1319f2f44ceSEd Maste } // anonymous namespace
1329f2f44ceSEd Maste 
1339f2f44ceSEd Maste static void
1349f2f44ceSEd Maste AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, AddMacroState &state, StreamString &stream)
1359f2f44ceSEd Maste {
1369f2f44ceSEd Maste     if (dm == nullptr)
1379f2f44ceSEd Maste         return;
1389f2f44ceSEd Maste 
1399f2f44ceSEd Maste     for (size_t i = 0; i < dm->GetNumMacroEntries(); i++)
1409f2f44ceSEd Maste     {
1419f2f44ceSEd Maste         const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i);
1429f2f44ceSEd Maste         uint32_t line;
1439f2f44ceSEd Maste 
1449f2f44ceSEd Maste         switch (entry.GetType())
1459f2f44ceSEd Maste         {
1469f2f44ceSEd Maste             case DebugMacroEntry::DEFINE:
1479f2f44ceSEd Maste                 if (state.IsValidEntry(entry.GetLineNumber()))
1489f2f44ceSEd Maste                     stream.Printf("#define %s\n", entry.GetMacroString().AsCString());
1499f2f44ceSEd Maste                 else
1509f2f44ceSEd Maste                     return;
1519f2f44ceSEd Maste                 break;
1529f2f44ceSEd Maste             case DebugMacroEntry::UNDEF:
1539f2f44ceSEd Maste                 if (state.IsValidEntry(entry.GetLineNumber()))
1549f2f44ceSEd Maste                     stream.Printf("#undef %s\n", entry.GetMacroString().AsCString());
1559f2f44ceSEd Maste                 else
1569f2f44ceSEd Maste                     return;
1579f2f44ceSEd Maste                 break;
1589f2f44ceSEd Maste             case DebugMacroEntry::START_FILE:
1599f2f44ceSEd Maste                 line = entry.GetLineNumber();
1609f2f44ceSEd Maste                 if (state.IsValidEntry(line))
1619f2f44ceSEd Maste                     state.StartFile(entry.GetFileSpec(comp_unit));
1629f2f44ceSEd Maste                 else
1639f2f44ceSEd Maste                     return;
1649f2f44ceSEd Maste                 break;
1659f2f44ceSEd Maste             case DebugMacroEntry::END_FILE:
1669f2f44ceSEd Maste                 state.EndFile();
1679f2f44ceSEd Maste                 break;
1689f2f44ceSEd Maste             case DebugMacroEntry::INDIRECT:
1699f2f44ceSEd Maste                 AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream);
1709f2f44ceSEd Maste                 break;
1719f2f44ceSEd Maste             default:
1729f2f44ceSEd Maste                 // This is an unknown/invalid entry. Ignore.
1739f2f44ceSEd Maste                 break;
1749f2f44ceSEd Maste         }
1759f2f44ceSEd Maste     }
1769f2f44ceSEd Maste }
177ac7ddfbfSEd Maste 
1780127ef0fSEd Maste bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method, ExecutionContext &exe_ctx) const
179ac7ddfbfSEd Maste {
1800127ef0fSEd Maste     const char *target_specific_defines = "typedef signed char BOOL;\n";
1811c3bbb01SEd Maste     std::string module_macros;
1820127ef0fSEd Maste 
1830127ef0fSEd Maste     if (Target *target = exe_ctx.GetTargetPtr())
1840127ef0fSEd Maste     {
1850127ef0fSEd Maste         if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64)
1860127ef0fSEd Maste         {
1870127ef0fSEd Maste             target_specific_defines = "typedef bool BOOL;\n";
1880127ef0fSEd Maste         }
1890127ef0fSEd Maste         if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64)
1900127ef0fSEd Maste         {
1910127ef0fSEd Maste             if (lldb::PlatformSP platform_sp = target->GetPlatform())
1920127ef0fSEd Maste             {
1931c3bbb01SEd Maste                 static ConstString g_platform_ios_simulator ("ios-simulator");
1940127ef0fSEd Maste                 if (platform_sp->GetPluginName() == g_platform_ios_simulator)
1950127ef0fSEd Maste                 {
1960127ef0fSEd Maste                     target_specific_defines = "typedef bool BOOL;\n";
1970127ef0fSEd Maste                 }
1980127ef0fSEd Maste             }
1990127ef0fSEd Maste         }
2001c3bbb01SEd Maste 
2011c3bbb01SEd Maste         if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor())
2021c3bbb01SEd Maste         {
2039f2f44ceSEd Maste             ClangPersistentVariables *persistent_vars = llvm::cast<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
2049f2f44ceSEd Maste             const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = persistent_vars->GetHandLoadedClangModules();
2051c3bbb01SEd Maste             ClangModulesDeclVendor::ModuleVector modules_for_macros;
2061c3bbb01SEd Maste 
2071c3bbb01SEd Maste             for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules)
2081c3bbb01SEd Maste             {
2091c3bbb01SEd Maste                 modules_for_macros.push_back(module);
2101c3bbb01SEd Maste             }
2111c3bbb01SEd Maste 
2121c3bbb01SEd Maste             if (target->GetEnableAutoImportClangModules())
2131c3bbb01SEd Maste             {
2141c3bbb01SEd Maste                 if (StackFrame *frame = exe_ctx.GetFramePtr())
2151c3bbb01SEd Maste                 {
2161c3bbb01SEd Maste                     if (Block *block = frame->GetFrameBlock())
2171c3bbb01SEd Maste                     {
2181c3bbb01SEd Maste                         SymbolContext sc;
2191c3bbb01SEd Maste 
2201c3bbb01SEd Maste                         block->CalculateSymbolContext(&sc);
2211c3bbb01SEd Maste 
2221c3bbb01SEd Maste                         if (sc.comp_unit)
2231c3bbb01SEd Maste                         {
2241c3bbb01SEd Maste                             StreamString error_stream;
2251c3bbb01SEd Maste 
2261c3bbb01SEd Maste                             decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream);
2271c3bbb01SEd Maste                         }
2281c3bbb01SEd Maste                     }
2291c3bbb01SEd Maste                 }
2301c3bbb01SEd Maste             }
2311c3bbb01SEd Maste 
2321c3bbb01SEd Maste             decl_vendor->ForEachMacro(modules_for_macros, [&module_macros] (const std::string &expansion) -> bool {
2331c3bbb01SEd Maste                 module_macros.append(expansion);
2341c3bbb01SEd Maste                 module_macros.append("\n");
2351c3bbb01SEd Maste                 return false;
2361c3bbb01SEd Maste             });
2371c3bbb01SEd Maste         }
2381c3bbb01SEd Maste 
2390127ef0fSEd Maste     }
2400127ef0fSEd Maste 
2419f2f44ceSEd Maste     StreamString debug_macros_stream;
2429f2f44ceSEd Maste     if (StackFrame *frame = exe_ctx.GetFramePtr())
2439f2f44ceSEd Maste     {
2449f2f44ceSEd Maste         const SymbolContext &sc = frame->GetSymbolContext(
2459f2f44ceSEd Maste            lldb:: eSymbolContextCompUnit | lldb::eSymbolContextLineEntry);
2469f2f44ceSEd Maste 
2479f2f44ceSEd Maste         if (sc.comp_unit && sc.line_entry.IsValid())
2489f2f44ceSEd Maste         {
2499f2f44ceSEd Maste             DebugMacros *dm = sc.comp_unit->GetDebugMacros();
2509f2f44ceSEd Maste             if (dm)
2519f2f44ceSEd Maste             {
2529f2f44ceSEd Maste                 AddMacroState state(sc.line_entry.file, sc.line_entry.line);
2539f2f44ceSEd Maste                 AddMacros(dm, sc.comp_unit, state, debug_macros_stream);
2549f2f44ceSEd Maste             }
2559f2f44ceSEd Maste         }
2569f2f44ceSEd Maste     }
2579f2f44ceSEd Maste 
258ac7ddfbfSEd Maste     if (m_wrap)
259ac7ddfbfSEd Maste     {
260ac7ddfbfSEd Maste         switch (wrapping_language)
261ac7ddfbfSEd Maste         {
262ac7ddfbfSEd Maste         default:
263ac7ddfbfSEd Maste             return false;
264ac7ddfbfSEd Maste         case lldb::eLanguageTypeC:
265ac7ddfbfSEd Maste         case lldb::eLanguageTypeC_plus_plus:
266ac7ddfbfSEd Maste         case lldb::eLanguageTypeObjC:
267ac7ddfbfSEd Maste             break;
268ac7ddfbfSEd Maste         }
269ac7ddfbfSEd Maste 
270ac7ddfbfSEd Maste         StreamString wrap_stream;
271ac7ddfbfSEd Maste 
2729f2f44ceSEd Maste         wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n",
2731c3bbb01SEd Maste                            module_macros.c_str(),
2749f2f44ceSEd Maste                            debug_macros_stream.GetData(),
2751c3bbb01SEd Maste                            g_expression_prefix,
2761c3bbb01SEd Maste                            target_specific_defines,
2771c3bbb01SEd Maste                            m_prefix.c_str());
2781c3bbb01SEd Maste 
279ac7ddfbfSEd Maste         switch (wrapping_language)
280ac7ddfbfSEd Maste         {
281ac7ddfbfSEd Maste         default:
282ac7ddfbfSEd Maste             break;
283ac7ddfbfSEd Maste         case lldb::eLanguageTypeC:
2841c3bbb01SEd Maste             wrap_stream.Printf("void                           \n"
285ac7ddfbfSEd Maste                                "%s(void *$__lldb_arg)          \n"
286ac7ddfbfSEd Maste                                "{                              \n"
287ac7ddfbfSEd Maste                                "    %s;                        \n"
288ac7ddfbfSEd Maste                                "}                              \n",
289ac7ddfbfSEd Maste                                m_name.c_str(),
290ac7ddfbfSEd Maste                                m_body.c_str());
291ac7ddfbfSEd Maste             break;
292ac7ddfbfSEd Maste         case lldb::eLanguageTypeC_plus_plus:
2931c3bbb01SEd Maste             wrap_stream.Printf("void                                   \n"
294ac7ddfbfSEd Maste                                "$__lldb_class::%s(void *$__lldb_arg) %s\n"
295ac7ddfbfSEd Maste                                "{                                      \n"
296ac7ddfbfSEd Maste                                "    %s;                                \n"
297ac7ddfbfSEd Maste                                "}                                      \n",
298ac7ddfbfSEd Maste                                m_name.c_str(),
299ac7ddfbfSEd Maste                                (const_object ? "const" : ""),
300ac7ddfbfSEd Maste                                m_body.c_str());
301ac7ddfbfSEd Maste             break;
302ac7ddfbfSEd Maste         case lldb::eLanguageTypeObjC:
303ac7ddfbfSEd Maste             if (static_method)
304ac7ddfbfSEd Maste             {
3051c3bbb01SEd Maste                 wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category)        \n"
306ac7ddfbfSEd Maste                                    "+(void)%s:(void *)$__lldb_arg;                          \n"
307ac7ddfbfSEd Maste                                    "@end                                                    \n"
308ac7ddfbfSEd Maste                                    "@implementation $__lldb_objc_class ($__lldb_category)   \n"
309ac7ddfbfSEd Maste                                    "+(void)%s:(void *)$__lldb_arg                           \n"
310ac7ddfbfSEd Maste                                    "{                                                       \n"
311ac7ddfbfSEd Maste                                    "    %s;                                                 \n"
312ac7ddfbfSEd Maste                                    "}                                                       \n"
313ac7ddfbfSEd Maste                                    "@end                                                    \n",
314ac7ddfbfSEd Maste                                    m_name.c_str(),
315ac7ddfbfSEd Maste                                    m_name.c_str(),
316ac7ddfbfSEd Maste                                    m_body.c_str());
317ac7ddfbfSEd Maste             }
318ac7ddfbfSEd Maste             else
319ac7ddfbfSEd Maste             {
3201c3bbb01SEd Maste                 wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category)       \n"
321ac7ddfbfSEd Maste                                    "-(void)%s:(void *)$__lldb_arg;                         \n"
322ac7ddfbfSEd Maste                                    "@end                                                   \n"
323ac7ddfbfSEd Maste                                    "@implementation $__lldb_objc_class ($__lldb_category)  \n"
324ac7ddfbfSEd Maste                                    "-(void)%s:(void *)$__lldb_arg                          \n"
325ac7ddfbfSEd Maste                                    "{                                                      \n"
326ac7ddfbfSEd Maste                                    "    %s;                                                \n"
327ac7ddfbfSEd Maste                                    "}                                                      \n"
328ac7ddfbfSEd Maste                                    "@end                                                   \n",
329ac7ddfbfSEd Maste                                    m_name.c_str(),
330ac7ddfbfSEd Maste                                    m_name.c_str(),
331ac7ddfbfSEd Maste                                    m_body.c_str());
332ac7ddfbfSEd Maste             }
333ac7ddfbfSEd Maste             break;
334ac7ddfbfSEd Maste         }
335ac7ddfbfSEd Maste 
336ac7ddfbfSEd Maste         text = wrap_stream.GetString();
337ac7ddfbfSEd Maste     }
338ac7ddfbfSEd Maste     else
339ac7ddfbfSEd Maste     {
340ac7ddfbfSEd Maste         text.append(m_body);
341ac7ddfbfSEd Maste     }
342ac7ddfbfSEd Maste 
343ac7ddfbfSEd Maste     return true;
344ac7ddfbfSEd Maste }
345