mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-11 09:56:06 +00:00

from IRExecutionUnit into a superclass called IRMemoryMap. IRMemoryMap handles all reading and writing, ensuring that areas are kept track of and memory is properly cached (and deleted). Also fixed several cases where we would simply leak binary data in the target process over time. Now the expression objects explicitly own their IRExecutionUnit and delete it when they go away. This is why I had to modify ClangUserExpression, ClangUtilityFunction, and ClangFunction. As a side effect of this, I am removing the JIT mutex for an IRMemoryMap. If it turns out that we need this mutex, I'll add it in then, but right now it's just adding complexity. This is part of a more general project to make expressions fully reusable. The next step is to make materialization and dematerialization use the IRMemoryMap API rather than writing and reading directly from the process's memory. This will allow the IR interpreter to use the same data, but in the host's memory, without having to use a different set of pointers. llvm-svn: 178832
172 lines
4.9 KiB
C++
172 lines
4.9 KiB
C++
//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// C Includes
|
|
#include <stdio.h>
|
|
#if HAVE_SYS_TYPES_H
|
|
# include <sys/types.h>
|
|
#endif
|
|
|
|
// C++ Includes
|
|
|
|
#include "lldb/Core/ConstString.h"
|
|
#include "lldb/Core/Log.h"
|
|
#include "lldb/Core/Stream.h"
|
|
#include "lldb/Core/StreamFile.h"
|
|
#include "lldb/Expression/ClangExpressionDeclMap.h"
|
|
#include "lldb/Expression/ClangExpressionParser.h"
|
|
#include "lldb/Expression/ClangUtilityFunction.h"
|
|
#include "lldb/Expression/ExpressionSourceCode.h"
|
|
#include "lldb/Host/Host.h"
|
|
#include "lldb/Target/ExecutionContext.h"
|
|
#include "lldb/Target/Target.h"
|
|
|
|
using namespace lldb_private;
|
|
|
|
//------------------------------------------------------------------
|
|
/// Constructor
|
|
///
|
|
/// @param[in] text
|
|
/// The text of the function. Must be a full translation unit.
|
|
///
|
|
/// @param[in] name
|
|
/// The name of the function, as used in the text.
|
|
//------------------------------------------------------------------
|
|
ClangUtilityFunction::ClangUtilityFunction (const char *text,
|
|
const char *name) :
|
|
ClangExpression (),
|
|
m_function_text (ExpressionSourceCode::g_expression_prefix),
|
|
m_function_name (name)
|
|
{
|
|
if (text && text[0])
|
|
m_function_text.append (text);
|
|
}
|
|
|
|
ClangUtilityFunction::~ClangUtilityFunction ()
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
/// Install the utility function into a process
|
|
///
|
|
/// @param[in] error_stream
|
|
/// A stream to print parse errors and warnings to.
|
|
///
|
|
/// @param[in] exe_ctx
|
|
/// The execution context to install the utility function to.
|
|
///
|
|
/// @return
|
|
/// True on success (no errors); false otherwise.
|
|
//------------------------------------------------------------------
|
|
bool
|
|
ClangUtilityFunction::Install (Stream &error_stream,
|
|
ExecutionContext &exe_ctx)
|
|
{
|
|
if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
|
|
{
|
|
error_stream.PutCString("error: already installed\n");
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////
|
|
// Set up the target and compiler
|
|
//
|
|
|
|
Target *target = exe_ctx.GetTargetPtr();
|
|
|
|
if (!target)
|
|
{
|
|
error_stream.PutCString ("error: invalid target\n");
|
|
return false;
|
|
}
|
|
|
|
Process *process = exe_ctx.GetProcessPtr();
|
|
|
|
if (!process)
|
|
{
|
|
error_stream.PutCString ("error: invalid process\n");
|
|
return false;
|
|
}
|
|
|
|
//////////////////////////
|
|
// Parse the expression
|
|
//
|
|
|
|
bool keep_result_in_memory = false;
|
|
|
|
m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
|
|
|
|
if (!m_expr_decl_map->WillParse(exe_ctx))
|
|
{
|
|
error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
|
|
return false;
|
|
}
|
|
|
|
ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this);
|
|
|
|
unsigned num_errors = parser.Parse (error_stream);
|
|
|
|
if (num_errors)
|
|
{
|
|
error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
|
|
|
|
m_expr_decl_map.reset();
|
|
|
|
return false;
|
|
}
|
|
|
|
//////////////////////////////////
|
|
// JIT the output of the parser
|
|
//
|
|
|
|
lldb::ClangExpressionVariableSP const_result;
|
|
|
|
bool evaluated_statically = false; // should stay that way
|
|
|
|
Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
|
|
m_jit_end_addr,
|
|
m_execution_unit_ap,
|
|
exe_ctx,
|
|
evaluated_statically,
|
|
const_result,
|
|
eExecutionPolicyAlways);
|
|
|
|
if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
|
|
m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
|
|
|
|
#if 0
|
|
// jingham: look here
|
|
StreamFile logfile ("/tmp/exprs.txt", "a");
|
|
logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n",
|
|
m_jit_start_addr,
|
|
m_function_name.c_str(),
|
|
m_function_text.c_str());
|
|
#endif
|
|
|
|
m_expr_decl_map->DidParse();
|
|
|
|
m_expr_decl_map.reset();
|
|
|
|
if (jit_error.Success())
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
const char *error_cstr = jit_error.AsCString();
|
|
if (error_cstr && error_cstr[0])
|
|
error_stream.Printf ("error: %s\n", error_cstr);
|
|
else
|
|
error_stream.Printf ("error: expression can't be interpreted or run\n");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|