1254721Semaste//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste// C Includes
11254721Semaste#include <stdio.h>
12254721Semaste#if HAVE_SYS_TYPES_H
13254721Semaste#  include <sys/types.h>
14254721Semaste#endif
15254721Semaste
16254721Semaste// C++ Includes
17254721Semaste
18254721Semaste#include "lldb/Core/ConstString.h"
19254721Semaste#include "lldb/Core/Log.h"
20254721Semaste#include "lldb/Core/Stream.h"
21254721Semaste#include "lldb/Core/StreamFile.h"
22254721Semaste#include "lldb/Expression/ClangExpressionDeclMap.h"
23254721Semaste#include "lldb/Expression/ClangExpressionParser.h"
24254721Semaste#include "lldb/Expression/ClangUtilityFunction.h"
25254721Semaste#include "lldb/Expression/ExpressionSourceCode.h"
26254721Semaste#include "lldb/Expression/IRExecutionUnit.h"
27254721Semaste#include "lldb/Host/Host.h"
28254721Semaste#include "lldb/Target/ExecutionContext.h"
29254721Semaste#include "lldb/Target/Target.h"
30254721Semaste
31254721Semasteusing namespace lldb_private;
32254721Semaste
33254721Semaste//------------------------------------------------------------------
34254721Semaste/// Constructor
35254721Semaste///
36254721Semaste/// @param[in] text
37254721Semaste///     The text of the function.  Must be a full translation unit.
38254721Semaste///
39254721Semaste/// @param[in] name
40254721Semaste///     The name of the function, as used in the text.
41254721Semaste//------------------------------------------------------------------
42254721SemasteClangUtilityFunction::ClangUtilityFunction (const char *text,
43254721Semaste                                            const char *name) :
44254721Semaste    ClangExpression (),
45254721Semaste    m_function_text (ExpressionSourceCode::g_expression_prefix),
46254721Semaste    m_function_name (name)
47254721Semaste{
48254721Semaste    if (text && text[0])
49254721Semaste        m_function_text.append (text);
50254721Semaste}
51254721Semaste
52254721SemasteClangUtilityFunction::~ClangUtilityFunction ()
53254721Semaste{
54254721Semaste}
55254721Semaste
56254721Semaste//------------------------------------------------------------------
57254721Semaste/// Install the utility function into a process
58254721Semaste///
59254721Semaste/// @param[in] error_stream
60254721Semaste///     A stream to print parse errors and warnings to.
61254721Semaste///
62254721Semaste/// @param[in] exe_ctx
63254721Semaste///     The execution context to install the utility function to.
64254721Semaste///
65254721Semaste/// @return
66254721Semaste///     True on success (no errors); false otherwise.
67254721Semaste//------------------------------------------------------------------
68254721Semastebool
69254721SemasteClangUtilityFunction::Install (Stream &error_stream,
70254721Semaste                               ExecutionContext &exe_ctx)
71254721Semaste{
72254721Semaste    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
73254721Semaste    {
74254721Semaste        error_stream.PutCString("error: already installed\n");
75254721Semaste        return false;
76254721Semaste    }
77254721Semaste
78254721Semaste    ////////////////////////////////////
79254721Semaste    // Set up the target and compiler
80254721Semaste    //
81254721Semaste
82254721Semaste    Target *target = exe_ctx.GetTargetPtr();
83254721Semaste
84254721Semaste    if (!target)
85254721Semaste    {
86254721Semaste        error_stream.PutCString ("error: invalid target\n");
87254721Semaste        return false;
88254721Semaste    }
89254721Semaste
90254721Semaste    Process *process = exe_ctx.GetProcessPtr();
91254721Semaste
92254721Semaste    if (!process)
93254721Semaste    {
94254721Semaste        error_stream.PutCString ("error: invalid process\n");
95254721Semaste        return false;
96254721Semaste    }
97254721Semaste
98254721Semaste    //////////////////////////
99254721Semaste    // Parse the expression
100254721Semaste    //
101254721Semaste
102254721Semaste    bool keep_result_in_memory = false;
103254721Semaste
104254721Semaste    m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
105254721Semaste
106254721Semaste    if (!m_expr_decl_map->WillParse(exe_ctx, NULL))
107254721Semaste    {
108254721Semaste        error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
109254721Semaste        return false;
110254721Semaste    }
111254721Semaste
112254721Semaste    ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this);
113254721Semaste
114254721Semaste    unsigned num_errors = parser.Parse (error_stream);
115254721Semaste
116254721Semaste    if (num_errors)
117254721Semaste    {
118254721Semaste        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
119254721Semaste
120254721Semaste        m_expr_decl_map.reset();
121254721Semaste
122254721Semaste        return false;
123254721Semaste    }
124254721Semaste
125254721Semaste    //////////////////////////////////
126254721Semaste    // JIT the output of the parser
127254721Semaste    //
128254721Semaste
129254721Semaste    bool can_interpret = false; // should stay that way
130254721Semaste
131254721Semaste    Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
132254721Semaste                                                  m_jit_end_addr,
133254721Semaste                                                  m_execution_unit_ap,
134254721Semaste                                                  exe_ctx,
135254721Semaste                                                  can_interpret,
136254721Semaste                                                  eExecutionPolicyAlways);
137254721Semaste
138254721Semaste    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
139254721Semaste        m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
140254721Semaste
141254721Semaste#if 0
142254721Semaste	// jingham: look here
143254721Semaste    StreamFile logfile ("/tmp/exprs.txt", "a");
144254721Semaste    logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n",
145254721Semaste                    m_jit_start_addr,
146254721Semaste                    m_function_name.c_str(),
147254721Semaste                    m_function_text.c_str());
148254721Semaste#endif
149254721Semaste
150254721Semaste    m_expr_decl_map->DidParse();
151254721Semaste
152254721Semaste    m_expr_decl_map.reset();
153254721Semaste
154254721Semaste    if (jit_error.Success())
155254721Semaste    {
156254721Semaste        return true;
157254721Semaste    }
158254721Semaste    else
159254721Semaste    {
160254721Semaste        const char *error_cstr = jit_error.AsCString();
161254721Semaste        if (error_cstr && error_cstr[0])
162254721Semaste            error_stream.Printf ("error: %s\n", error_cstr);
163254721Semaste        else
164254721Semaste            error_stream.Printf ("error: expression can't be interpreted or run\n");
165254721Semaste        return false;
166254721Semaste    }
167254721Semaste}
168254721Semaste
169254721Semaste
170