blob: c25916243a57f6fc3f86bd6bb2e453f7b6e03681 [file] [log] [blame]
Sean Callanane71d5532010-08-27 23:31:21 +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
18#include "lldb/Core/ConstString.h"
Sean Callanan79763a42011-05-23 21:40:23 +000019#include "lldb/Core/Log.h"
Sean Callanane71d5532010-08-27 23:31:21 +000020#include "lldb/Core/Stream.h"
Greg Claytonc4e411f2011-01-18 19:36:39 +000021#include "lldb/Core/StreamFile.h"
Sean Callanan9e6ed532010-09-13 21:34:21 +000022#include "lldb/Expression/ClangExpressionDeclMap.h"
Sean Callanane71d5532010-08-27 23:31:21 +000023#include "lldb/Expression/ClangExpressionParser.h"
24#include "lldb/Expression/ClangUtilityFunction.h"
25#include "lldb/Host/Host.h"
26#include "lldb/Target/ExecutionContext.h"
27#include "lldb/Target/Target.h"
28
29using namespace lldb_private;
30
Greg Claytona66c4d92013-02-13 22:56:14 +000031static const char *g_global_defines =
32"#undef NULL \n"
33"#undef Nil \n"
34"#undef nil \n"
35"#undef YES \n"
36"#undef NO \n"
37"#define NULL ((int)0) \n"
38"#define Nil ((Class)0) \n"
39"#define nil ((id)0) \n"
40"#define YES ((BOOL)1) \n"
41"#define NO ((BOOL)0) \n"
42"typedef signed char BOOL; \n"
43"typedef signed __INT8_TYPE__ int8_t;\n"
44"typedef unsigned __INT8_TYPE__ uint8_t;\n"
45"typedef signed __INT16_TYPE__ int16_t;\n"
46"typedef unsigned __INT16_TYPE__ uint16_t;\n"
47"typedef signed __INT32_TYPE__ int32_t;\n"
48"typedef unsigned __INT32_TYPE__ uint32_t;\n"
49"typedef signed __INT64_TYPE__ int64_t;\n"
50"typedef unsigned __INT64_TYPE__ uint64_t;\n"
51"typedef signed __INTPTR_TYPE__ intptr_t;\n"
52"typedef unsigned __INTPTR_TYPE__ uintptr_t;\n"
53"typedef __SIZE_TYPE__ size_t; \n"
54"typedef __PTRDIFF_TYPE__ ptrdiff_t;\n"
55"typedef unsigned short unichar;\n";
56
57
Sean Callanane71d5532010-08-27 23:31:21 +000058//------------------------------------------------------------------
59/// Constructor
60///
61/// @param[in] text
62/// The text of the function. Must be a full translation unit.
63///
64/// @param[in] name
65/// The name of the function, as used in the text.
66//------------------------------------------------------------------
67ClangUtilityFunction::ClangUtilityFunction (const char *text,
68 const char *name) :
Greg Clayton22a939a2011-01-19 23:00:49 +000069 ClangExpression (),
Greg Claytona66c4d92013-02-13 22:56:14 +000070 m_function_text (g_global_defines),
Greg Clayton22a939a2011-01-19 23:00:49 +000071 m_function_name (name)
Sean Callanane71d5532010-08-27 23:31:21 +000072{
Greg Claytona66c4d92013-02-13 22:56:14 +000073 if (text && text[0])
74 m_function_text.append (text);
Sean Callanane71d5532010-08-27 23:31:21 +000075}
76
Greg Clayton5573fde2010-09-24 23:07:41 +000077ClangUtilityFunction::~ClangUtilityFunction ()
78{
79}
80
Sean Callanane71d5532010-08-27 23:31:21 +000081//------------------------------------------------------------------
82/// Install the utility function into a process
83///
84/// @param[in] error_stream
85/// A stream to print parse errors and warnings to.
86///
87/// @param[in] exe_ctx
88/// The execution context to install the utility function to.
89///
90/// @return
91/// True on success (no errors); false otherwise.
92//------------------------------------------------------------------
93bool
94ClangUtilityFunction::Install (Stream &error_stream,
95 ExecutionContext &exe_ctx)
Sean Callanan6961e872010-09-01 00:58:00 +000096{
Sean Callanan79763a42011-05-23 21:40:23 +000097 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
98
Greg Clayton22a939a2011-01-19 23:00:49 +000099 if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
Sean Callanan6961e872010-09-01 00:58:00 +0000100 {
101 error_stream.PutCString("error: already installed\n");
102 return false;
103 }
104
Sean Callanane71d5532010-08-27 23:31:21 +0000105 ////////////////////////////////////
106 // Set up the target and compiler
107 //
108
Greg Claytonc14ee322011-09-22 04:58:26 +0000109 Target *target = exe_ctx.GetTargetPtr();
Sean Callanane71d5532010-08-27 23:31:21 +0000110
111 if (!target)
112 {
113 error_stream.PutCString ("error: invalid target\n");
114 return false;
115 }
Sean Callanan79763a42011-05-23 21:40:23 +0000116
Greg Claytonc14ee322011-09-22 04:58:26 +0000117 Process *process = exe_ctx.GetProcessPtr();
Sean Callanan79763a42011-05-23 21:40:23 +0000118
119 if (!process)
120 {
121 error_stream.PutCString ("error: invalid process\n");
122 return false;
123 }
Greg Clayton514487e2011-02-15 21:59:32 +0000124
Sean Callanane71d5532010-08-27 23:31:21 +0000125 //////////////////////////
126 // Parse the expression
127 //
Sean Callanan9e6ed532010-09-13 21:34:21 +0000128
Sean Callanan92adcac2011-01-13 08:53:35 +0000129 bool keep_result_in_memory = false;
130
Sean Callanan1ee44b72011-10-29 01:58:46 +0000131 m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
Sean Callanan979f74d2010-12-03 01:38:59 +0000132
Greg Claytonc14ee322011-09-22 04:58:26 +0000133 m_data_allocator.reset(new ProcessDataAllocator(*process));
Sean Callanan79763a42011-05-23 21:40:23 +0000134
Sean Callananb9951192011-08-01 18:18:33 +0000135 if (!m_expr_decl_map->WillParse(exe_ctx))
136 {
137 error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
138 return false;
139 }
Sean Callanane71d5532010-08-27 23:31:21 +0000140
Greg Clayton514487e2011-02-15 21:59:32 +0000141 ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this);
Sean Callanane71d5532010-08-27 23:31:21 +0000142
143 unsigned num_errors = parser.Parse (error_stream);
144
145 if (num_errors)
146 {
147 error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
Sean Callanan9e6ed532010-09-13 21:34:21 +0000148
149 m_expr_decl_map.reset();
150
Sean Callanane71d5532010-08-27 23:31:21 +0000151 return false;
152 }
153
154 //////////////////////////////////
155 // JIT the output of the parser
156 //
Sean Callanan63697e52011-05-07 01:06:41 +0000157
158 lldb::ClangExpressionVariableSP const_result;
Sean Callanan79763a42011-05-23 21:40:23 +0000159
Sean Callanan3bfdaa22011-09-15 02:13:07 +0000160 bool evaluated_statically = false; // should stay that way
161
162 Error jit_error = parser.PrepareForExecution (m_jit_alloc,
163 m_jit_start_addr,
164 m_jit_end_addr,
165 exe_ctx,
166 m_data_allocator.get(),
167 evaluated_statically,
168 const_result,
169 eExecutionPolicyAlways);
Sean Callanan79763a42011-05-23 21:40:23 +0000170
171 if (log)
172 {
173 StreamString dump_string;
174 m_data_allocator->Dump(dump_string);
175
176 log->Printf("Data buffer contents:\n%s", dump_string.GetString().c_str());
177 }
Greg Clayton22a939a2011-01-19 23:00:49 +0000178
Greg Claytonc14ee322011-09-22 04:58:26 +0000179 if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
Enrico Granatadfc88a02012-09-18 00:08:47 +0000180 m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
Sean Callanane71d5532010-08-27 23:31:21 +0000181
Greg Claytonc4e411f2011-01-18 19:36:39 +0000182#if 0
183 // jingham: look here
184 StreamFile logfile ("/tmp/exprs.txt", "a");
Daniel Malead01b2952012-11-29 21:49:15 +0000185 logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n",
Greg Clayton22a939a2011-01-19 23:00:49 +0000186 m_jit_start_addr,
Greg Claytonc4e411f2011-01-18 19:36:39 +0000187 m_function_name.c_str(),
188 m_function_text.c_str());
189#endif
190
Sean Callanan979f74d2010-12-03 01:38:59 +0000191 m_expr_decl_map->DidParse();
192
Sean Callanan9e6ed532010-09-13 21:34:21 +0000193 m_expr_decl_map.reset();
194
Sean Callanane71d5532010-08-27 23:31:21 +0000195 if (jit_error.Success())
196 {
197 return true;
198 }
199 else
200 {
Greg Claytone6a9e432011-05-17 03:51:29 +0000201 const char *error_cstr = jit_error.AsCString();
202 if (error_cstr && error_cstr[0])
203 error_stream.Printf ("error: %s\n", error_cstr);
204 else
Jason Molendafd54b362011-09-20 21:44:10 +0000205 error_stream.Printf ("error: expression can't be interpreted or run\n");
Sean Callanane71d5532010-08-27 23:31:21 +0000206 return false;
207 }
208}
209
210