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] error_stream
59 ///     A stream to print parse 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 (Stream &error_stream,
69                                ExecutionContext &exe_ctx)
70 {
71     if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
72     {
73         error_stream.PutCString("error: already installed\n");
74         return false;
75     }
76 
77     ////////////////////////////////////
78     // Set up the target and compiler
79     //
80 
81     Target *target = exe_ctx.GetTargetPtr();
82 
83     if (!target)
84     {
85         error_stream.PutCString ("error: invalid target\n");
86         return false;
87     }
88 
89     Process *process = exe_ctx.GetProcessPtr();
90 
91     if (!process)
92     {
93         error_stream.PutCString ("error: invalid process\n");
94         return false;
95     }
96 
97     //////////////////////////
98     // Parse the expression
99     //
100 
101     bool keep_result_in_memory = false;
102 
103     ResetDeclMap(exe_ctx, keep_result_in_memory);
104 
105     if (!DeclMap()->WillParse(exe_ctx, NULL))
106     {
107         error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
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 (error_stream);
115 
116     if (num_errors)
117     {
118         error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
119 
120         ResetDeclMap();
121 
122         return false;
123     }
124 
125     //////////////////////////////////
126     // JIT the output of the parser
127     //
128 
129     bool can_interpret = false; // should stay that way
130 
131     Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
132                                                   m_jit_end_addr,
133                                                   m_execution_unit_sp,
134                                                   exe_ctx,
135                                                   can_interpret,
136                                                   eExecutionPolicyAlways);
137 
138     if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
139     {
140         m_jit_process_wp = process->shared_from_this();
141         if (parser.GetGenerateDebugInfo())
142         {
143             lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
144 
145             if (jit_module_sp)
146             {
147                 ConstString const_func_name(FunctionName());
148                 FileSpec jit_file;
149                 jit_file.GetFilename() = const_func_name;
150                 jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
151                 m_jit_module_wp = jit_module_sp;
152                 target->GetImages().Append(jit_module_sp);
153             }
154         }
155     }
156 
157 #if 0
158 	// jingham: look here
159     StreamFile logfile ("/tmp/exprs.txt", "a");
160     logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n",
161                     m_jit_start_addr,
162                     m_function_name.c_str(),
163                     m_function_text.c_str());
164 #endif
165 
166     DeclMap()->DidParse();
167 
168     ResetDeclMap();
169 
170     if (jit_error.Success())
171     {
172         return true;
173     }
174     else
175     {
176         const char *error_cstr = jit_error.AsCString();
177         if (error_cstr && error_cstr[0])
178             error_stream.Printf ("error: %s\n", error_cstr);
179         else
180             error_stream.Printf ("error: expression can't be interpreted or run\n");
181         return false;
182     }
183 }
184 
185 void
186 ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory)
187 {
188     m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
189 }
190