1 //===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "ClangExpressionDeclMap.h"
11 #include "ClangExpressionParser.h"
12 #include "ClangUtilityFunction.h"
13 
14 // C Includes
15 #include <stdio.h>
16 #if HAVE_SYS_TYPES_H
17 #  include <sys/types.h>
18 #endif
19 
20 // C++ Includes
21 
22 #include "lldb/Core/ConstString.h"
23 #include "lldb/Core/Log.h"
24 #include "lldb/Core/Module.h"
25 #include "lldb/Core/Stream.h"
26 #include "lldb/Core/StreamFile.h"
27 #include "lldb/Expression/ExpressionSourceCode.h"
28 #include "lldb/Expression/IRExecutionUnit.h"
29 #include "lldb/Host/Host.h"
30 #include "lldb/Target/ExecutionContext.h"
31 #include "lldb/Target/Target.h"
32 
33 using namespace lldb_private;
34 
35 //------------------------------------------------------------------
36 /// Constructor
37 ///
38 /// @param[in] text
39 ///     The text of the function.  Must be a full translation unit.
40 ///
41 /// @param[in] name
42 ///     The name of the function, as used in the text.
43 //------------------------------------------------------------------
44 ClangUtilityFunction::ClangUtilityFunction (ExecutionContextScope &exe_scope,
45                                             const char *text,
46                                             const char *name) :
47     UtilityFunction (exe_scope, text, name)
48 {
49 }
50 
51 ClangUtilityFunction::~ClangUtilityFunction ()
52 {
53 }
54 
55 //------------------------------------------------------------------
56 /// Install the utility function into a process
57 ///
58 /// @param[in] diagnostic_manager
59 ///     A diagnostic manager to report errors and warnings to.
60 ///
61 /// @param[in] exe_ctx
62 ///     The execution context to install the utility function to.
63 ///
64 /// @return
65 ///     True on success (no errors); false otherwise.
66 //------------------------------------------------------------------
67 bool
68 ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx)
69 {
70     if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
71     {
72         diagnostic_manager.PutCString(eDiagnosticSeverityWarning, "already installed");
73         return false;
74     }
75 
76     ////////////////////////////////////
77     // Set up the target and compiler
78     //
79 
80     Target *target = exe_ctx.GetTargetPtr();
81 
82     if (!target)
83     {
84         diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target");
85         return false;
86     }
87 
88     Process *process = exe_ctx.GetProcessPtr();
89 
90     if (!process)
91     {
92         diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid process");
93         return false;
94     }
95 
96     //////////////////////////
97     // Parse the expression
98     //
99 
100     bool keep_result_in_memory = false;
101 
102     ResetDeclMap(exe_ctx, keep_result_in_memory);
103 
104     if (!DeclMap()->WillParse(exe_ctx, NULL))
105     {
106         diagnostic_manager.PutCString(eDiagnosticSeverityError,
107                                       "current process state is unsuitable for expression parsing");
108         return false;
109     }
110 
111     const bool generate_debug_info = true;
112     ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info);
113 
114     unsigned num_errors = parser.Parse(diagnostic_manager);
115 
116     if (num_errors)
117     {
118         diagnostic_manager.Printf(eDiagnosticSeverityError, "%d error%s parsing expression", num_errors,
119                                   num_errors == 1 ? "" : "s");
120 
121         ResetDeclMap();
122 
123         return false;
124     }
125 
126     //////////////////////////////////
127     // JIT the output of the parser
128     //
129 
130     bool can_interpret = false; // should stay that way
131 
132     Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
133                                                   m_jit_end_addr,
134                                                   m_execution_unit_sp,
135                                                   exe_ctx,
136                                                   can_interpret,
137                                                   eExecutionPolicyAlways);
138 
139     if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
140     {
141         m_jit_process_wp = process->shared_from_this();
142         if (parser.GetGenerateDebugInfo())
143         {
144             lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
145 
146             if (jit_module_sp)
147             {
148                 ConstString const_func_name(FunctionName());
149                 FileSpec jit_file;
150                 jit_file.GetFilename() = const_func_name;
151                 jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
152                 m_jit_module_wp = jit_module_sp;
153                 target->GetImages().Append(jit_module_sp);
154             }
155         }
156     }
157 
158 #if 0
159 	// jingham: look here
160     StreamFile logfile ("/tmp/exprs.txt", "a");
161     logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n",
162                     m_jit_start_addr,
163                     m_function_name.c_str(),
164                     m_function_text.c_str());
165 #endif
166 
167     DeclMap()->DidParse();
168 
169     ResetDeclMap();
170 
171     if (jit_error.Success())
172     {
173         return true;
174     }
175     else
176     {
177         const char *error_cstr = jit_error.AsCString();
178         if (error_cstr && error_cstr[0])
179         {
180             diagnostic_manager.Printf(eDiagnosticSeverityError, "%s", error_cstr);
181         }
182         else
183         {
184             diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run");
185         }
186         return false;
187     }
188 }
189 
190 void
191 ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory)
192 {
193     m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, nullptr, exe_ctx));
194 }
195