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
33using 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//------------------------------------------------------------------
44ClangUtilityFunction::ClangUtilityFunction (ExecutionContextScope &exe_scope,
45                                            const char *text,
46                                            const char *name) :
47    UtilityFunction (exe_scope, text, name)
48{
49}
50
51ClangUtilityFunction::~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//------------------------------------------------------------------
67bool
68ClangUtilityFunction::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
185void
186ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory)
187{
188    m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, nullptr, exe_ctx));
189}
190