blob: 6b376560218ea08a5fb991a58e549198c8d06f52 [file] [log] [blame]
Sean Callanan65dafa82010-08-27 01:01:44 +00001//===-- 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// C Includes
11#include <stdio.h>
12#if HAVE_SYS_TYPES_H
13# include <sys/types.h>
14#endif
15
16// C++ Includes
17#include <cstdlib>
18#include <string>
19#include <map>
20
21#include "lldb/Core/ConstString.h"
22#include "lldb/Core/Log.h"
23#include "lldb/Core/StreamString.h"
24#include "lldb/Expression/ClangExpressionDeclMap.h"
25#include "lldb/Expression/ClangExpressionParser.h"
26#include "lldb/Expression/ClangFunction.h"
27#include "lldb/Expression/ASTResultSynthesizer.h"
28#include "lldb/Expression/ClangUserExpression.h"
29#include "lldb/Host/Host.h"
30#include "lldb/Target/ExecutionContext.h"
31#include "lldb/Target/Target.h"
32
33using namespace lldb_private;
34
35ClangUserExpression::ClangUserExpression (const char *expr) :
36 m_expr_text(expr),
37 m_jit_addr(LLDB_INVALID_ADDRESS)
38{
39 StreamString m_transformed_stream;
40
Sean Callanancc074622010-09-14 21:59:34 +000041 m_transformed_stream.Printf("#define this ___clang_this \n"
42 "#define self ___clang_self \n"
43 "extern \"C\" void \n"
44 "%s(void *___clang_arg) \n"
45 "{ \n"
46 "%s; \n"
47 "} \n",
Sean Callanan65dafa82010-08-27 01:01:44 +000048 FunctionName(),
49 m_expr_text.c_str());
50
51 m_transformed_text = m_transformed_stream.GetData();
52}
53
Sean Callanan830a9032010-08-27 23:31:21 +000054ClangUserExpression::~ClangUserExpression ()
55{
56}
57
Sean Callanan65dafa82010-08-27 01:01:44 +000058clang::ASTConsumer *
59ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
60{
61 return new ASTResultSynthesizer(passthrough);
62}
63
64bool
65ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx)
66{
67 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
68
69 ////////////////////////////////////
70 // Set up the target and compiler
71 //
72
73 Target *target = exe_ctx.target;
74
75 if (!target)
76 {
77 error_stream.PutCString ("error: invalid target\n");
78 return false;
79 }
80
81 ConstString target_triple;
82
83 target->GetTargetTriple (target_triple);
84
85 if (!target_triple)
86 target_triple = Host::GetTargetTriple ();
87
88 if (!target_triple)
89 {
90 error_stream.PutCString ("error: invalid target triple\n");
91 return false;
92 }
93
94 //////////////////////////
95 // Parse the expression
96 //
97
98 m_expr_decl_map.reset(new ClangExpressionDeclMap(&exe_ctx));
99
100 ClangExpressionParser parser(target_triple.GetCString(), *this);
101
102 unsigned num_errors = parser.Parse (error_stream);
103
104 if (num_errors)
105 {
106 error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
107 return false;
108 }
109
110 ///////////////////////////////////////////////
111 // Convert the output of the parser to DWARF
112 //
113
114 m_dwarf_opcodes.reset(new StreamString);
115 m_dwarf_opcodes->SetByteOrder (lldb::eByteOrderHost);
116 m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);
117
118 m_local_variables.reset(new ClangExpressionVariableStore());
119
120 Error dwarf_error = parser.MakeDWARF ();
121
122 if (dwarf_error.Success())
123 {
124 if (log)
125 log->Printf("Code can be interpreted.");
126
127 return true;
128 }
129
130 //////////////////////////////////
131 // JIT the output of the parser
132 //
133
134 m_dwarf_opcodes.reset();
135
Sean Callanan830a9032010-08-27 23:31:21 +0000136 lldb::addr_t jit_end;
137
138 Error jit_error = parser.MakeJIT (m_jit_addr, jit_end, exe_ctx);
Sean Callanan65dafa82010-08-27 01:01:44 +0000139
140 if (jit_error.Success())
141 {
142 if (log)
143 {
144 log->Printf("Code can be run in the target.");
145
146 StreamString disassembly_stream;
147
148 Error err = parser.DisassembleFunction(disassembly_stream, exe_ctx);
149
150 if (!err.Success())
151 {
152 log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
153 }
154 else
155 {
156 log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
157 }
158 }
159
160 return true;
161 }
162 else
163 {
164 error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors);
165 return false;
166 }
167}
168
169bool
170ClangUserExpression::Execute (Stream &error_stream,
171 ExecutionContext &exe_ctx,
172 ClangExpressionVariable *&result)
173{
174 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
175
176 if (m_dwarf_opcodes.get())
177 {
178 // TODO execute the JITted opcodes
179
180 error_stream.Printf("We don't currently support executing DWARF expressions");
181
182 return false;
183 }
184 else if (m_jit_addr != LLDB_INVALID_ADDRESS)
185 {
186 lldb::addr_t struct_address;
187
188 Error materialize_error;
189
190 if (!m_expr_decl_map->Materialize(&exe_ctx, struct_address, materialize_error))
191 {
192 error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString("unknown error"));
193 return false;
194 }
195
196 if (log)
197 {
198 log->Printf("Function address : 0x%llx", (uint64_t)m_jit_addr);
199 log->Printf("Structure address : 0x%llx", (uint64_t)struct_address);
200
201 StreamString args;
202
203 Error dump_error;
204
Sean Callanane8a59a82010-09-13 21:34:21 +0000205 if (struct_address)
Sean Callanan65dafa82010-08-27 01:01:44 +0000206 {
Sean Callanane8a59a82010-09-13 21:34:21 +0000207 if (!m_expr_decl_map->DumpMaterializedStruct(&exe_ctx, args, dump_error))
208 {
209 log->Printf("Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
210 }
211 else
212 {
213 log->Printf("Structure contents:\n%s", args.GetData());
214 }
Sean Callanan65dafa82010-08-27 01:01:44 +0000215 }
216 }
217
218 ClangFunction::ExecutionResults execution_result =
219 ClangFunction::ExecuteFunction (exe_ctx, m_jit_addr, struct_address, true, true, 10000, error_stream);
220
221 if (execution_result != ClangFunction::eExecutionCompleted)
222 {
223 const char *result_name;
224
225 switch (execution_result)
226 {
227 case ClangFunction::eExecutionCompleted:
228 result_name = "eExecutionCompleted";
229 break;
230 case ClangFunction::eExecutionDiscarded:
231 result_name = "eExecutionDiscarded";
232 break;
233 case ClangFunction::eExecutionInterrupted:
234 result_name = "eExecutionInterrupted";
235 break;
236 case ClangFunction::eExecutionSetupError:
237 result_name = "eExecutionSetupError";
238 break;
239 case ClangFunction::eExecutionTimedOut:
240 result_name = "eExecutionTimedOut";
241 break;
242 }
243
244 error_stream.Printf ("Couldn't execute function; result was %s\n", result_name);
245 return false;
246 }
247
248 Error expr_error;
249
250 if (!m_expr_decl_map->Dematerialize(&exe_ctx, result, expr_error))
251 {
252 error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
253 return false;
254 }
255
256 return true;
257 }
258 else
259 {
260 error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function are present");
261 return false;
262 }
263}
264
265StreamString &
266ClangUserExpression::DwarfOpcodeStream ()
267{
268 if (!m_dwarf_opcodes.get())
269 m_dwarf_opcodes.reset(new StreamString());
270
271 return *m_dwarf_opcodes.get();
272}