[Lldb-commits] [lldb] r139772 - in /lldb/trunk: include/lldb/ include/lldb/Expression/ include/lldb/Target/ lldb.xcodeproj/ source/API/ source/Breakpoint/ source/Commands/ source/Expression/ source/Symbol/ source/Target/
Sean Callanan
scallanan at apple.com
Wed Sep 14 19:13:08 PDT 2011
Author: spyffe
Date: Wed Sep 14 21:13:07 2011
New Revision: 139772
URL: http://llvm.org/viewvc/llvm-project?rev=139772&view=rev
Log:
This patch modifies the expression parser to allow it
to execute expressions even in the absence of a process.
This allows expressions to run in situations where the
target cannot run -- e.g., to perform calculations based
on type information, or to inspect a binary's static
data.
This modification touches the following files:
lldb-private-enumerations.h
Introduce a new enum specifying the policy for
processing an expression. Some expressions should
always be JITted, for example if they are functions
that will be used over and over again. Some
expressions should always be interpreted, for
example if the target is unsafe to run. For most,
it is acceptable to JIT them, but interpretation
is preferable when possible.
Target.[h,cpp]
Have EvaluateExpression now accept the new enum.
ClangExpressionDeclMap.[cpp,h]
Add support for the IR interpreter and also make
the ClangExpressionDeclMap more robust in the
absence of a process.
ClangFunction.[cpp,h]
Add support for the new enum.
IRInterpreter.[cpp,h]
New implementation.
ClangUserExpression.[cpp,h]
Add support for the new enum, and for running
expressions in the absence of a process.
ClangExpression.h
Remove references to the old DWARF-based method
of evaluating expressions, because it has been
superseded for now.
ClangUtilityFunction.[cpp,h]
Add support for the new enum.
ClangExpressionParser.[cpp,h]
Add support for the new enum, remove references
to DWARF, and add support for checking whether
the expression could be evaluated statically.
IRForTarget.[h,cpp]
Add support for the new enum, and add utility
functions to support the interpreter.
IRToDWARF.cpp
Removed
CommandObjectExpression.cpp
Remove references to the obsolete -i option.
Process.cpp
Modify calls to ClangUserExpression::Evaluate
to pass the correct enum (for dlopen/dlclose)
SBValue.cpp
Add support for the new enum.
SBFrame.cpp
Add support for he new enum.
BreakpointOptions.cpp
Add support for the new enum.
Added:
lldb/trunk/include/lldb/Expression/IRInterpreter.h
lldb/trunk/source/Expression/IRInterpreter.cpp
Removed:
lldb/trunk/source/Expression/IRToDWARF.cpp
Modified:
lldb/trunk/include/lldb/Expression/ClangExpression.h
lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
lldb/trunk/include/lldb/Expression/ClangExpressionParser.h
lldb/trunk/include/lldb/Expression/ClangFunction.h
lldb/trunk/include/lldb/Expression/ClangUserExpression.h
lldb/trunk/include/lldb/Expression/ClangUtilityFunction.h
lldb/trunk/include/lldb/Expression/IRForTarget.h
lldb/trunk/include/lldb/Target/Target.h
lldb/trunk/include/lldb/lldb-private-enumerations.h
lldb/trunk/lldb.xcodeproj/project.pbxproj
lldb/trunk/source/API/SBFrame.cpp
lldb/trunk/source/API/SBValue.cpp
lldb/trunk/source/Breakpoint/BreakpointOptions.cpp
lldb/trunk/source/Commands/CommandObjectExpression.cpp
lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
lldb/trunk/source/Expression/ClangExpressionParser.cpp
lldb/trunk/source/Expression/ClangFunction.cpp
lldb/trunk/source/Expression/ClangUserExpression.cpp
lldb/trunk/source/Expression/ClangUtilityFunction.cpp
lldb/trunk/source/Expression/IRForTarget.cpp
lldb/trunk/source/Symbol/ClangASTImporter.cpp
lldb/trunk/source/Target/Process.cpp
lldb/trunk/source/Target/StopInfo.cpp
lldb/trunk/source/Target/Target.cpp
Modified: lldb/trunk/include/lldb/Expression/ClangExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpression.h?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpression.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangExpression.h Wed Sep 14 21:13:07 2011
@@ -98,13 +98,6 @@
ASTTransformer (clang::ASTConsumer *passthrough) = 0;
//------------------------------------------------------------------
- /// Return the stream that the parser should use to write DWARF
- /// opcodes.
- //------------------------------------------------------------------
- virtual StreamString &
- DwarfOpcodeStream () = 0;
-
- //------------------------------------------------------------------
/// Flags
//------------------------------------------------------------------
Modified: lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h Wed Sep 14 21:13:07 2011
@@ -349,6 +349,130 @@
GetSymbolAddress (const ConstString &name);
//------------------------------------------------------------------
+ /// [Used by IRInterpreter] Get basic target information.
+ ///
+ /// @param[out] byte_order
+ /// The byte order of the target.
+ ///
+ /// @param[out] address_byte_size
+ /// The size of a pointer in bytes.
+ ///
+ /// @return
+ /// True if the information could be determined; false
+ /// otherwise.
+ //------------------------------------------------------------------
+ struct TargetInfo
+ {
+ lldb::ByteOrder byte_order;
+ size_t address_byte_size;
+
+ TargetInfo() :
+ byte_order(lldb::eByteOrderInvalid),
+ address_byte_size(0)
+ {
+ }
+
+ bool IsValid()
+ {
+ return (byte_order != lldb::eByteOrderInvalid &&
+ address_byte_size != 0);
+ }
+ };
+ TargetInfo GetTargetInfo();
+
+ //------------------------------------------------------------------
+ /// [Used by IRInterpreter] Write to the target.
+ ///
+ /// @param[in] addr
+ /// The address to write to.
+ ///
+ /// @param[in] data
+ /// The address of the data buffer to read from.
+ ///
+ /// @param[in] length
+ /// The amount of data to write, in bytes.
+ ///
+ /// @return
+ /// True if the write could be performed; false otherwise.
+ //------------------------------------------------------------------
+ bool
+ WriteTarget (lldb_private::Value &value,
+ const uint8_t *data,
+ size_t length);
+
+ //------------------------------------------------------------------
+ /// [Used by IRInterpreter] Read from the target.
+ ///
+ /// @param[in] data
+ /// The address of the data buffer to write to.
+ ///
+ /// @param[in] addr
+ /// The address to read from.
+ ///
+ /// @param[in] length
+ /// The amount of data to read, in bytes.
+ ///
+ /// @return
+ /// True if the read could be performed; false otherwise.
+ //------------------------------------------------------------------
+ bool
+ ReadTarget (uint8_t *data,
+ lldb_private::Value &value,
+ size_t length);
+
+ //------------------------------------------------------------------
+ /// [Used by IRInterpreter] Get the Value for a NamedDecl.
+ ///
+ /// @param[in] decl
+ /// The Decl whose value is to be found.
+ ///
+ /// @return
+ /// The value, or NULL.
+ //------------------------------------------------------------------
+ lldb_private::Value
+ LookupDecl (clang::NamedDecl *decl);
+
+ //------------------------------------------------------------------
+ /// [Used by IRInterpreter] Returns true if the result is a
+ /// reference to data in the target, meaning it must be
+ /// dereferenced once more to get its data.
+ ///
+ /// @param[in] name
+ /// The name of the result.
+ ///
+ /// @return
+ /// True if the result is a reference; false otherwise (or on
+ /// error).
+ //------------------------------------------------------------------
+ bool
+ ResultIsReference (const ConstString &name);
+
+ //------------------------------------------------------------------
+ /// [Used by IRInterpreter] Find the result persistent variable,
+ /// propagate the given value to it, and return it.
+ ///
+ /// @param[out] valobj
+ /// Set to the complete object.
+ ///
+ /// @param[in] value
+ /// A value indicating the location of the value's contents.
+ ///
+ /// @param[in] name
+ /// The name of the result.
+ ///
+ /// @param[in] type
+ /// The type of the data.
+ ///
+ /// @return
+ /// True on success; false otherwise.
+ //------------------------------------------------------------------
+ bool
+ CompleteResultVariable (lldb::ClangExpressionVariableSP &valobj,
+ lldb_private::Value &value,
+ const ConstString &name,
+ lldb_private::TypeFromParser type);
+
+ //------------------------------------------------------------------
/// [Used by CommandObjectExpression] Materialize the entire struct
/// at a given address, which should be aligned as specified by
/// GetStructInfo().
@@ -596,6 +720,7 @@
bool m_enable_lookups; ///< Set to true during parsing if we have found the first "$__lldb" name.
bool m_ignore_lookups; ///< True during an import when we should be ignoring type lookups.
std::auto_ptr<ClangASTImporter> m_ast_importer; ///< The importer used to import types on the parser's behalf.
+ TargetInfo m_target_info; ///< Basic information about the target.
private:
DISALLOW_COPY_AND_ASSIGN (ParserVars);
};
@@ -742,6 +867,29 @@
const ConstString &name);
//------------------------------------------------------------------
+ /// Given a target, find a variable that matches the given name and
+ /// type.
+ ///
+ /// @param[in] target
+ /// The target to use as a basis for finding the variable.
+ ///
+ /// @param[in] name
+ /// The name as a plain C string.
+ ///
+ /// @param[in] type
+ /// The required type for the variable. This function may be called
+ /// during parsing, in which case we don't know its type; hence the
+ /// default.
+ ///
+ /// @return
+ /// The LLDB Variable found, or NULL if none was found.
+ //------------------------------------------------------------------
+ lldb::VariableSP
+ FindGlobalVariable (Target &target,
+ const char *name,
+ TypeFromUser *type = NULL);
+
+ //------------------------------------------------------------------
/// Get the value of a variable in a given execution context and return
/// the associated Types if needed.
///
Modified: lldb/trunk/include/lldb/Expression/ClangExpressionParser.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpressionParser.h?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpressionParser.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangExpressionParser.h Wed Sep 14 21:13:07 2011
@@ -73,20 +73,8 @@
Parse (Stream &stream);
//------------------------------------------------------------------
- /// Convert the IR for an already-parsed expression to DWARF if possible.
- ///
- /// @param[in] dwarf_opcode_strm
- /// The stream to place the resulting DWARF code into.
- ///
- /// @return
- /// An error code indicating the success or failure of the operation.
- /// Test with Success().
- //------------------------------------------------------------------
- Error
- MakeDWARF ();
-
- //------------------------------------------------------------------
- /// JIT-compile the IR for an already-parsed expression.
+ /// Ready an already-parsed expression for execution, possibly
+ /// evaluating it statically.
///
/// @param[out] func_allocation_addr
/// The address which can be used to deallocate the code for this
@@ -104,30 +92,36 @@
/// The execution context to write the function into.
///
/// @param[in] data_allocator
- /// If non-NULL, he static data allocator to use for literal strings.
+ /// If non-NULL, the static data allocator to use for literal strings.
+ ///
+ /// @param[out] evaluated_statically
+ /// Set to true if the expression could be interpreted statically;
+ /// untouched otherwise.
///
/// @param[out] const_result
/// If the result of the expression is constant, and the
/// expression has no side effects, this is set to the result of the
/// expression.
///
- /// @param[in] jit_only_if_needed
- /// True if the expression must be compiled, regardless of whether a
- /// constant result could be extracted from the IR or no.
+ /// @param[in] execution_policy
+ /// Determines whether the expression must be JIT-compiled, must be
+ /// evaluated statically, or whether this decision may be made
+ /// opportunistically.
///
/// @return
/// An error code indicating the success or failure of the operation.
/// Test with Success().
//------------------------------------------------------------------
Error
- MakeJIT (lldb::addr_t &func_allocation_addr,
- lldb::addr_t &func_addr,
- lldb::addr_t &func_end,
- ExecutionContext &exe_ctx,
- IRForTarget::StaticDataAllocator *data_allocator,
- lldb::ClangExpressionVariableSP &const_result,
- bool jit_only_if_needed = false);
-
+ PrepareForExecution (lldb::addr_t &func_allocation_addr,
+ lldb::addr_t &func_addr,
+ lldb::addr_t &func_end,
+ ExecutionContext &exe_ctx,
+ IRForTarget::StaticDataAllocator *data_allocator,
+ bool &evaluated_statically,
+ lldb::ClangExpressionVariableSP &const_result,
+ lldb_private::ExecutionPolicy execution_policy);
+
//------------------------------------------------------------------
/// Disassemble the machine code for a JITted function from the target
/// process's memory and print the result to a stream.
Modified: lldb/trunk/include/lldb/Expression/ClangFunction.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangFunction.h?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangFunction.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangFunction.h Wed Sep 14 21:13:07 2011
@@ -574,16 +574,6 @@
ASTTransformer (clang::ASTConsumer *passthrough);
//------------------------------------------------------------------
- /// Return the stream that the parser should use to write DWARF
- /// opcodes.
- //------------------------------------------------------------------
- StreamString &
- DwarfOpcodeStream ()
- {
- return *((StreamString*)0);
- }
-
- //------------------------------------------------------------------
/// Return true if validation code should be inserted into the
/// expression.
//------------------------------------------------------------------
Modified: lldb/trunk/include/lldb/Expression/ClangUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangUserExpression.h?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangUserExpression.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangUserExpression.h Wed Sep 14 21:13:07 2011
@@ -83,6 +83,9 @@
/// The type that the expression should be coerced to. If NULL,
/// inferred from the expression itself.
///
+ /// @param[in] execution_policy
+ /// Determines whether interpretation is possible or mandatory.
+ ///
/// @param[in] keep_result_in_memory
/// True if the resulting persistent variable should reside in
/// target memory, if applicable.
@@ -94,6 +97,7 @@
Parse (Stream &error_stream,
ExecutionContext &exe_ctx,
TypeFromUser desired_type,
+ lldb_private::ExecutionPolicy execution_policy,
bool keep_result_in_memory);
//------------------------------------------------------------------
@@ -227,13 +231,6 @@
ASTTransformer (clang::ASTConsumer *passthrough);
//------------------------------------------------------------------
- /// Return the stream that the parser should use to write DWARF
- /// opcodes.
- //------------------------------------------------------------------
- StreamString &
- DwarfOpcodeStream ();
-
- //------------------------------------------------------------------
/// Return true if validation code should be inserted into the
/// expression.
//------------------------------------------------------------------
@@ -259,6 +256,10 @@
/// @param[in] exe_ctx
/// The execution context to use when evaluating the expression.
///
+ /// @param[in] execution_policy
+ /// Determines whether or not to try using the IR interpreter to
+ /// avoid running the expression on the parser.
+ ///
/// @param[in] discard_on_error
/// True if the thread's state should be restored in the case
/// of an error.
@@ -277,14 +278,16 @@
/// A Process::ExecutionResults value. eExecutionCompleted for success.
//------------------------------------------------------------------
static ExecutionResults
- Evaluate (ExecutionContext &exe_ctx,
+ Evaluate (ExecutionContext &exe_ctx,
+ lldb_private::ExecutionPolicy execution_policy,
bool discard_on_error,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp);
static ExecutionResults
- EvaluateWithError (ExecutionContext &exe_ctx,
+ EvaluateWithError (ExecutionContext &exe_ctx,
+ lldb_private::ExecutionPolicy execution_policy,
bool discard_on_error,
const char *expr_cstr,
const char *expr_prefix,
@@ -307,6 +310,12 @@
lldb::addr_t &object_ptr,
lldb::addr_t &cmd_ptr);
+ bool
+ EvaluatedStatically ()
+ {
+ return m_evaluated_statically;
+ }
+
std::string m_expr_text; ///< The text of the expression, as typed by the user
std::string m_expr_prefix; ///< The text of the translation-level definitions, as provided by the user
std::string m_transformed_text; ///< The text of the expression, as send to the parser
@@ -314,7 +323,6 @@
std::auto_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing and materializing the expression.
std::auto_ptr<ClangExpressionVariableList> m_local_variables; ///< The local expression variables, if the expression is DWARF.
- std::auto_ptr<StreamString> m_dwarf_opcodes; ///< The DWARF opcodes for the expression. May be NULL.
std::auto_ptr<ProcessDataAllocator> m_data_allocator; ///< The allocator that the parser uses to place strings for use by JIT-compiled code.
bool m_cplusplus; ///< True if the expression is compiled as a C++ member function (true if it was parsed when exe_ctx was in a C++ method).
@@ -323,6 +331,7 @@
bool m_const_object; ///< True if "this" is const.
Target *m_target; ///< The target for storing persistent data like types and variables.
+ bool m_evaluated_statically; ///< True if the expression could be evaluated statically; false otherwise.
lldb::ClangExpressionVariableSP m_const_result; ///< The statically-computed result of the expression. NULL if it could not be computed statically or the expression has side effects.
};
Modified: lldb/trunk/include/lldb/Expression/ClangUtilityFunction.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangUtilityFunction.h?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangUtilityFunction.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangUtilityFunction.h Wed Sep 14 21:13:07 2011
@@ -149,16 +149,6 @@
}
//------------------------------------------------------------------
- /// Return the stream that the parser should use to write DWARF
- /// opcodes.
- //------------------------------------------------------------------
- StreamString &
- DwarfOpcodeStream ()
- {
- return *((StreamString*)NULL);
- }
-
- //------------------------------------------------------------------
/// Return true if validation code should be inserted into the
/// expression.
//------------------------------------------------------------------
Modified: lldb/trunk/include/lldb/Expression/IRForTarget.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/IRForTarget.h?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/IRForTarget.h (original)
+++ lldb/trunk/include/lldb/Expression/IRForTarget.h Wed Sep 14 21:13:07 2011
@@ -73,6 +73,10 @@
/// variables) should be resolved. If not, only external functions
/// are resolved.
///
+ /// @param[in] execution_policy
+ /// Determines whether an IR interpreter can be used to statically
+ /// evaluate the expression.
+ ///
/// @param[in] const_result
/// This variable is populated with the statically-computed result
/// of the function, if it has no side-effects and the result can
@@ -89,6 +93,7 @@
//------------------------------------------------------------------
IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map,
bool resolve_vars,
+ lldb_private::ExecutionPolicy execution_policy,
lldb::ClangExpressionVariableSP &const_result,
StaticDataAllocator *data_allocator,
lldb_private::Stream *error_stream,
@@ -133,6 +138,18 @@
//------------------------------------------------------------------
virtual llvm::PassManagerType
getPotentialPassManagerType() const;
+
+ //------------------------------------------------------------------
+ /// Checks whether the IR interpreter successfully interpreted the
+ /// expression.
+ ///
+ /// Returns true if it did; false otherwise.
+ //------------------------------------------------------------------
+ bool
+ interpretSuccess ()
+ {
+ return m_interpret_success;
+ }
private:
//------------------------------------------------------------------
@@ -236,16 +253,22 @@
//------------------------------------------------------------------
//------------------------------------------------------------------
- /// Set the constant result variable m_const_result to the provided
- /// constant, assuming it can be evaluated. The result variable
- /// will be reset to NULL later if the expression has side effects.
+ /// Find the NamedDecl corresponding to a Value. This interface is
+ /// exposed for the IR interpreter.
+ ///
+ /// @param[in] module
+ /// The module containing metadata to search
///
/// @param[in] global
/// The global entity to search for
///
/// @return
/// The corresponding variable declaration
- //------------------------------------------------------------------
+ //------------------------------------------------------------------
+public:
+ static clang::NamedDecl *
+ DeclForGlobal (const llvm::GlobalValue *global_val, llvm::Module *module);
+private:
clang::NamedDecl *
DeclForGlobal (llvm::GlobalValue *global);
@@ -549,8 +572,11 @@
/// Flags
bool m_resolve_vars; ///< True if external variable references and persistent variable references should be resolved
+ lldb_private::ExecutionPolicy m_execution_policy; ///< True if the interpreter should be used to attempt to get a static result
+ bool m_interpret_success; ///< True if the interpreter successfully handled the whole expression
std::string m_func_name; ///< The name of the function to translate
lldb_private::ConstString m_result_name; ///< The name of the result variable ($0, $1, ...)
+ lldb_private::TypeFromParser m_result_type; ///< The type of the result variable.
llvm::Module *m_module; ///< The module being processed, or NULL if that has not been determined yet.
lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls
StaticDataAllocator *m_data_allocator; ///< If non-NULL, the allocator to use for constant strings
Added: lldb/trunk/include/lldb/Expression/IRInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/IRInterpreter.h?rev=139772&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Expression/IRInterpreter.h (added)
+++ lldb/trunk/include/lldb/Expression/IRInterpreter.h Wed Sep 14 21:13:07 2011
@@ -0,0 +1,107 @@
+//===-- IRInterpreter.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_IRInterpreter_h_
+#define liblldb_IRInterpreter_h_
+
+#include "lldb/lldb-public.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/TaggedASTType.h"
+#include "llvm/Pass.h"
+
+namespace llvm {
+ class Function;
+ class Module;
+}
+
+namespace lldb_private {
+
+class ClangExpressionDeclMap;
+
+}
+
+//----------------------------------------------------------------------
+/// @class IRInterpreter IRInterpreter.h "lldb/Expression/IRInterpreter.h"
+/// @brief Attempt to interpret the function's code if it does not require
+/// running the target.
+///
+/// In some cases, the IR for an expression can be evaluated entirely
+/// in the debugger, manipulating variables but not executing any code
+/// in the target. The IRInterpreter attempts to do this.
+//----------------------------------------------------------------------
+class IRInterpreter
+{
+public:
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// @param[in] decl_map
+ /// The list of externally-referenced variables for the expression,
+ /// for use in looking up globals and allocating the argument
+ /// struct. See the documentation for ClangExpressionDeclMap.
+ ///
+ /// @param[in] error_stream
+ /// If non-NULL, a stream on which errors can be printed.
+ //------------------------------------------------------------------
+ IRInterpreter(lldb_private::ClangExpressionDeclMap &decl_map,
+ lldb_private::Stream *error_stream);
+
+ //------------------------------------------------------------------
+ /// Destructor
+ //------------------------------------------------------------------
+ ~IRInterpreter();
+
+ //------------------------------------------------------------------
+ /// Run the IR interpreter on a single function
+ ///
+ /// @param[in] result
+ /// This variable is populated with the return value of the
+ /// function, if it could be interpreted completely.
+ ///
+ /// @param[in] result_name
+ /// The name of the result in the IR. If this name got a
+ /// value written to it as part of execution, then that value
+ /// will be used to create the result variable.
+ ///
+ /// @param[in] result_type
+ /// The type of the result.
+ ///
+ /// @param[in] llvm_function
+ /// The function to interpret.
+ ///
+ /// @param[in] llvm_module
+ /// The module containing the function.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ maybeRunOnFunction (lldb::ClangExpressionVariableSP &result,
+ const lldb_private::ConstString &result_name,
+ lldb_private::TypeFromParser result_type,
+ llvm::Function &llvm_function,
+ llvm::Module &llvm_module);
+private:
+ /// Flags
+ lldb_private::ClangExpressionDeclMap &m_decl_map; ///< The DeclMap containing the Decls
+ lldb_private::Stream *m_error_stream;
+
+ bool
+ supportsFunction (llvm::Function &llvm_function);
+
+ bool
+ runOnFunction (lldb::ClangExpressionVariableSP &result,
+ const lldb_private::ConstString &result_name,
+ lldb_private::TypeFromParser result_type,
+ llvm::Function &llvm_function,
+ llvm::Module &llvm_module);
+};
+
+#endif
Modified: lldb/trunk/include/lldb/Target/Target.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Target.h (original)
+++ lldb/trunk/include/lldb/Target/Target.h Wed Sep 14 21:13:07 2011
@@ -600,6 +600,7 @@
ExecutionResults
EvaluateExpression (const char *expression,
StackFrame *frame,
+ lldb_private::ExecutionPolicy execution_policy,
bool unwind_on_error,
bool keep_in_memory,
lldb::DynamicValueType use_dynamic,
Modified: lldb/trunk/include/lldb/lldb-private-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-enumerations.h?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-private-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-private-enumerations.h Wed Sep 14 21:13:07 2011
@@ -214,6 +214,15 @@
eFormatCategoryItemRegexSynth = 0x0020
} FormatCategoryItem;
+//------------------------------------------------------------------
+/// Expression execution policies
+//------------------------------------------------------------------
+typedef enum {
+ eExecutionPolicyOnlyWhenNeeded,
+ eExecutionPolicyNever,
+ eExecutionPolicyAlways
+} ExecutionPolicy;
+
} // namespace lldb
Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Wed Sep 14 21:13:07 2011
@@ -179,7 +179,6 @@
2689006913353E0E00698AC0 /* ASTStructExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491193501226386000578B7F /* ASTStructExtractor.cpp */; };
2689006A13353E0E00698AC0 /* IRDynamicChecks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */; };
2689006B13353E0E00698AC0 /* IRForTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49307AAD11DEA4D90081F992 /* IRForTarget.cpp */; };
- 2689006C13353E0E00698AC0 /* IRToDWARF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DA742F11DE6A5A006AEF7E /* IRToDWARF.cpp */; };
2689006D13353E0E00698AC0 /* RecordingMemoryManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C98D3DB118FB96F00E575D0 /* RecordingMemoryManager.cpp */; };
2689006E13353E1A00698AC0 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C6EA213011581005E16B0 /* File.cpp */; };
2689006F13353E1A00698AC0 /* FileSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26FA43171301048600E71120 /* FileSpec.cpp */; };
@@ -330,7 +329,6 @@
2689FFFB13353DB600698AC0 /* BreakpointLocationList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1010F1B83100F91463 /* BreakpointLocationList.cpp */; };
2689FFFD13353DB600698AC0 /* BreakpointOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1110F1B83100F91463 /* BreakpointOptions.cpp */; };
2689FFFF13353DB600698AC0 /* BreakpointResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1210F1B83100F91463 /* BreakpointResolver.cpp */; };
- 268ED0A5140FF54200DE830F /* DataEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268ED0A4140FF54200DE830F /* DataEncoder.cpp */; };
268F9D53123AA15200B91E9B /* SBSymbolContextList.h in Headers */ = {isa = PBXBuildFile; fileRef = 268F9D52123AA15200B91E9B /* SBSymbolContextList.h */; settings = {ATTRIBUTES = (Public, ); }; };
268F9D55123AA16600B91E9B /* SBSymbolContextList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268F9D54123AA16600B91E9B /* SBSymbolContextList.cpp */; };
2690B3711381D5C300ECFBAE /* Memory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2690B3701381D5C300ECFBAE /* Memory.cpp */; };
@@ -396,6 +394,9 @@
26F5C37510F3F61B009D5894 /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C37410F3F61B009D5894 /* libobjc.dylib */; };
26F5C39110F3FA26009D5894 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C39010F3FA26009D5894 /* CoreFoundation.framework */; };
26F73062139D8FDB00FD51C7 /* History.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F73061139D8FDB00FD51C7 /* History.cpp */; };
+ 496B015B1406DEB100F830D5 /* IRInterpreter.h in Headers */ = {isa = PBXBuildFile; fileRef = 496B015A1406DEB100F830D5 /* IRInterpreter.h */; };
+ 49A71FE7141FFA5C00D59478 /* IRInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 496B01581406DE8900F830D5 /* IRInterpreter.cpp */; };
+ 49A71FE8141FFACF00D59478 /* DataEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268ED0A4140FF54200DE830F /* DataEncoder.cpp */; };
49C8507C1384A786007DB519 /* ProcessDataAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49C850781384A0CA007DB519 /* ProcessDataAllocator.cpp */; };
49D8FB3913B5598F00411094 /* ClangASTImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D8FB3513B558DE00411094 /* ClangASTImporter.cpp */; };
4C74CB6312288704006A8171 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C74CB6212288704006A8171 /* Carbon.framework */; };
@@ -1104,6 +1105,8 @@
49445E341225AB6A00C11A81 /* ClangUserExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangUserExpression.h; path = include/lldb/Expression/ClangUserExpression.h; sourceTree = "<group>"; };
495BBACB119A0DBE00418BEA /* PathMappingList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PathMappingList.cpp; path = source/Target/PathMappingList.cpp; sourceTree = "<group>"; };
495BBACF119A0DE700418BEA /* PathMappingList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PathMappingList.h; path = include/lldb/Target/PathMappingList.h; sourceTree = "<group>"; };
+ 496B01581406DE8900F830D5 /* IRInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRInterpreter.cpp; path = source/Expression/IRInterpreter.cpp; sourceTree = "<group>"; };
+ 496B015A1406DEB100F830D5 /* IRInterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRInterpreter.h; path = include/lldb/Expression/IRInterpreter.h; sourceTree = "<group>"; };
497C86BD122823D800B54702 /* ClangUtilityFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangUtilityFunction.cpp; path = source/Expression/ClangUtilityFunction.cpp; sourceTree = "<group>"; };
497C86C1122823F300B54702 /* ClangUtilityFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangUtilityFunction.h; path = include/lldb/Expression/ClangUtilityFunction.h; sourceTree = "<group>"; };
497E7B331188ED300065CCA1 /* ABI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ABI.h; path = include/lldb/Target/ABI.h; sourceTree = "<group>"; };
@@ -1123,8 +1126,6 @@
49D7072811B5AD11001AD875 /* ClangASTSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTSource.cpp; path = source/Expression/ClangASTSource.cpp; sourceTree = "<group>"; };
49D8FB3513B558DE00411094 /* ClangASTImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTImporter.cpp; path = source/Symbol/ClangASTImporter.cpp; sourceTree = "<group>"; };
49D8FB3713B5594900411094 /* ClangASTImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangASTImporter.h; path = include/lldb/Symbol/ClangASTImporter.h; sourceTree = "<group>"; };
- 49DA742F11DE6A5A006AEF7E /* IRToDWARF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRToDWARF.cpp; path = source/Expression/IRToDWARF.cpp; sourceTree = "<group>"; };
- 49DA743411DE6BB2006AEF7E /* IRToDWARF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRToDWARF.h; path = include/lldb/Expression/IRToDWARF.h; sourceTree = "<group>"; };
49E45FA911F660DC008F7B28 /* ClangASTType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangASTType.h; path = include/lldb/Symbol/ClangASTType.h; sourceTree = "<group>"; };
49E45FAD11F660FE008F7B28 /* ClangASTType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTType.cpp; path = source/Symbol/ClangASTType.cpp; sourceTree = "<group>"; };
49EC3E98118F90AC00B1265E /* ThreadPlanCallFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanCallFunction.cpp; path = source/Target/ThreadPlanCallFunction.cpp; sourceTree = "<group>"; };
@@ -2280,8 +2281,8 @@
49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */,
49307AB111DEA4F20081F992 /* IRForTarget.h */,
49307AAD11DEA4D90081F992 /* IRForTarget.cpp */,
- 49DA743411DE6BB2006AEF7E /* IRToDWARF.h */,
- 49DA742F11DE6A5A006AEF7E /* IRToDWARF.cpp */,
+ 496B015A1406DEB100F830D5 /* IRInterpreter.h */,
+ 496B01581406DE8900F830D5 /* IRInterpreter.cpp */,
4C98D3E1118FB98F00E575D0 /* RecordingMemoryManager.h */,
4C98D3DB118FB96F00E575D0 /* RecordingMemoryManager.cpp */,
49C850761384A02F007DB519 /* ProcessDataAllocator.h */,
@@ -2760,6 +2761,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ 496B015B1406DEB100F830D5 /* IRInterpreter.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3151,7 +3153,6 @@
2689006913353E0E00698AC0 /* ASTStructExtractor.cpp in Sources */,
2689006A13353E0E00698AC0 /* IRDynamicChecks.cpp in Sources */,
2689006B13353E0E00698AC0 /* IRForTarget.cpp in Sources */,
- 2689006C13353E0E00698AC0 /* IRToDWARF.cpp in Sources */,
2689006D13353E0E00698AC0 /* RecordingMemoryManager.cpp in Sources */,
2689006E13353E1A00698AC0 /* File.cpp in Sources */,
2689006F13353E1A00698AC0 /* FileSpec.cpp in Sources */,
@@ -3361,11 +3362,12 @@
26274FA714030F79006BA130 /* DynamicLoaderDarwinKernel.cpp in Sources */,
94FA3DE01405D50400833217 /* ValueObjectConstResultChild.cpp in Sources */,
949ADF031406F648004833E1 /* ValueObjectConstResultImpl.cpp in Sources */,
- 268ED0A5140FF54200DE830F /* DataEncoder.cpp in Sources */,
26A0DA4E140F7226006DA411 /* HashedNameToDIE.cpp in Sources */,
B27318421416AC12006039C8 /* WatchpointLocationList.cpp in Sources */,
26E152261419CAD4007967D0 /* ObjectFilePECOFF.cpp in Sources */,
B2462247141AD37D00F3D409 /* OptionGroupWatchpoint.cpp in Sources */,
+ 49A71FE7141FFA5C00D59478 /* IRInterpreter.cpp in Sources */,
+ 49A71FE8141FFACF00D59478 /* DataEncoder.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Modified: lldb/trunk/source/API/SBFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBFrame.cpp?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/source/API/SBFrame.cpp (original)
+++ lldb/trunk/source/API/SBFrame.cpp Wed Sep 14 21:13:07 2011
@@ -759,7 +759,8 @@
const bool keep_in_memory = false;
exe_results = m_opaque_sp->GetThread().GetProcess().GetTarget().EvaluateExpression(expr,
- m_opaque_sp.get(),
+ m_opaque_sp.get(),
+ eExecutionPolicyOnlyWhenNeeded,
unwind_on_error,
keep_in_memory,
fetch_dynamic_value,
Modified: lldb/trunk/source/API/SBValue.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBValue.cpp?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/source/API/SBValue.cpp (original)
+++ lldb/trunk/source/API/SBValue.cpp Wed Sep 14 21:13:07 2011
@@ -379,7 +379,10 @@
ValueObjectSP result_valobj_sp;
m_opaque_sp->GetUpdatePoint().GetTargetSP()->EvaluateExpression (expression,
m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()->CalculateStackFrame(),
- true, true, eNoDynamicValues,
+ eExecutionPolicyAlways,
+ true, // unwind on error
+ true, // keep in memory
+ eNoDynamicValues,
result_valobj_sp);
result_valobj_sp->SetName(ConstString(name));
result = SBValue(result_valobj_sp);
Modified: lldb/trunk/source/Breakpoint/BreakpointOptions.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointOptions.cpp?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointOptions.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointOptions.cpp Wed Sep 14 21:13:07 2011
@@ -199,7 +199,9 @@
ClangASTContext *ast_context = exe_ctx.target->GetScratchClangASTContext();
TypeFromUser bool_type(ast_context->GetBuiltInType_bool(), ast_context->getASTContext());
- if (!m_condition_ap->Parse (error_stream, exe_ctx, bool_type, false /* keep_in_memory */))
+ const bool keep_in_memory = false;
+
+ if (!m_condition_ap->Parse (error_stream, exe_ctx, bool_type, eExecutionPolicyAlways, keep_in_memory))
{
// Errors mean we should stop.
return NULL;
Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Wed Sep 14 21:13:07 2011
@@ -95,12 +95,13 @@
break;
case 'u':
- bool success;
- unwind_on_error = Args::StringToBoolean(option_arg, true, &success);
- if (!success)
- error.SetErrorStringWithFormat("Could not convert \"%s\" to a boolean value.", option_arg);
- break;
-
+ {
+ bool success;
+ unwind_on_error = Args::StringToBoolean(option_arg, true, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("Could not convert \"%s\" to a boolean value.", option_arg);
+ break;
+ }
default:
error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
break;
@@ -292,7 +293,13 @@
break;
}
- exe_results = m_exe_ctx.target->EvaluateExpression(expr, m_exe_ctx.frame, m_options.unwind_on_error, keep_in_memory, use_dynamic, result_valobj_sp);
+ exe_results = m_exe_ctx.target->EvaluateExpression(expr,
+ m_exe_ctx.frame,
+ eExecutionPolicyOnlyWhenNeeded,
+ m_options.unwind_on_error,
+ keep_in_memory,
+ use_dynamic,
+ result_valobj_sp);
if (exe_results == eExecutionInterrupted && !m_options.unwind_on_error)
{
@@ -488,7 +495,6 @@
{ LLDB_OPT_SET_2, false, "dynamic-value", 'd', required_argument, NULL, 0, eArgTypeBoolean, "Upcast the value resulting from the expression to its dynamic type if available."},
{ LLDB_OPT_SET_ALL, false, "unwind-on-error", 'u', required_argument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, breakpoint hit or signal."},
{ LLDB_OPT_SET_ALL, false, "debug", 'g', no_argument, NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."},
-{ LLDB_OPT_SET_ALL, false, "use-ir", 'i', no_argument, NULL, 0, eArgTypeNone, "[Temporary] Instructs the expression evaluator to use IR instead of ASTs."},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Wed Sep 14 21:13:07 2011
@@ -82,6 +82,8 @@
if (exe_ctx.target && !exe_ctx.target->GetScratchClangASTContext())
return false;
+ m_parser_vars->m_target_info = GetTargetInfo();
+
return true;
}
@@ -118,6 +120,29 @@
// Interface for IRForTarget
+ClangExpressionDeclMap::TargetInfo
+ClangExpressionDeclMap::GetTargetInfo()
+{
+ assert (m_parser_vars.get());
+
+ TargetInfo ret;
+
+ ExecutionContext *exe_ctx = m_parser_vars->m_exe_ctx;
+
+ if (exe_ctx->process)
+ {
+ ret.byte_order = exe_ctx->process->GetByteOrder();
+ ret.address_byte_size = exe_ctx->process->GetAddressByteSize();
+ }
+ else if (exe_ctx->target)
+ {
+ ret.byte_order = exe_ctx->target->GetArchitecture().GetByteOrder();
+ ret.address_byte_size = exe_ctx->target->GetArchitecture().GetAddressByteSize();
+ }
+
+ return ret;
+}
+
const ConstString &
ClangExpressionDeclMap::GetPersistentResultName ()
{
@@ -146,12 +171,12 @@
type.GetASTContext(),
type.GetOpaqueQualType()),
context);
-
+
if (!m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx->GetBestExecutionContextScope (),
name,
user_type,
- exe_ctx->process->GetByteOrder(),
- exe_ctx->process->GetAddressByteSize()))
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size))
return lldb::ClangExpressionVariableSP();
ClangExpressionVariableSP pvar_sp (m_parser_vars->m_persistent_vars->GetVariable(name));
@@ -164,9 +189,7 @@
return lldb::ClangExpressionVariableSP();
uint64_t value64 = value.getLimitedValue();
-
- ByteOrder byte_order = exe_ctx->process->GetByteOrder();
-
+
size_t num_val_bytes = sizeof(value64);
size_t num_data_bytes = pvar_sp->GetByteSize();
@@ -182,7 +205,7 @@
uint64_t mask = 0xffll << shift;
uint8_t cur_byte = (uint8_t)((value64 & mask) >> shift);
- switch (byte_order)
+ switch (m_parser_vars->m_target_info.byte_order)
{
case eByteOrderBig:
// High Low
@@ -276,6 +299,59 @@
return pvar_sp;
}
+bool
+ClangExpressionDeclMap::ResultIsReference (const ConstString &name)
+{
+ ClangExpressionVariableSP pvar_sp = m_parser_vars->m_persistent_vars->GetVariable(name);
+
+ return (pvar_sp->m_flags & ClangExpressionVariable::EVIsProgramReference);
+}
+
+bool
+ClangExpressionDeclMap::CompleteResultVariable (lldb::ClangExpressionVariableSP &valobj,
+ lldb_private::Value &value,
+ const ConstString &name,
+ lldb_private::TypeFromParser type)
+{
+ assert (m_parser_vars.get());
+
+ ClangExpressionVariableSP pvar_sp = m_parser_vars->m_persistent_vars->GetVariable(name);
+
+ if (!pvar_sp)
+ return false;
+
+ if (pvar_sp->m_flags & ClangExpressionVariable::EVIsProgramReference &&
+ !pvar_sp->m_live_sp)
+ {
+ // The reference comes from the program. We need to set up a live SP for it.
+
+ pvar_sp->m_live_sp = ValueObjectConstResult::Create(m_parser_vars->m_exe_ctx->GetBestExecutionContextScope(),
+ pvar_sp->GetTypeFromUser().GetASTContext(),
+ pvar_sp->GetTypeFromUser().GetOpaqueQualType(),
+ pvar_sp->GetName(),
+ value.GetScalar().ULongLong(),
+ value.GetValueAddressType(),
+ pvar_sp->GetByteSize());
+ }
+
+ if (pvar_sp->m_flags & ClangExpressionVariable::EVNeedsFreezeDry)
+ {
+ pvar_sp->ValueUpdated();
+
+ const size_t pvar_byte_size = pvar_sp->GetByteSize();
+ uint8_t *pvar_data = pvar_sp->GetValueBytes();
+
+ if (!ReadTarget(pvar_data, value, pvar_byte_size))
+ return false;
+
+ pvar_sp->m_flags &= ~(ClangExpressionVariable::EVNeedsFreezeDry);
+ }
+
+ valobj = pvar_sp;
+
+ return true;
+}
+
bool
ClangExpressionDeclMap::AddPersistentVariable
(
@@ -297,12 +373,15 @@
parser_type.GetASTContext(),
parser_type.GetOpaqueQualType()),
context);
+
+ if (!m_parser_vars->m_target_info.IsValid())
+ return false;
if (!m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx->GetBestExecutionContextScope (),
name,
user_type,
- exe_ctx->process->GetByteOrder(),
- exe_ctx->process->GetAddressByteSize()))
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size))
return false;
ClangExpressionVariableSP var_sp (m_parser_vars->m_persistent_vars->GetVariable(name));
@@ -653,6 +732,204 @@
return GetSymbolAddress(*m_parser_vars->m_exe_ctx->target, name);
}
+// Interface for IRInterpreter
+
+bool
+ClangExpressionDeclMap::WriteTarget (lldb_private::Value &value,
+ const uint8_t *data,
+ size_t length)
+{
+ assert (m_parser_vars.get());
+
+ ExecutionContext *exe_ctx = m_parser_vars->m_exe_ctx;
+
+ if (value.GetContextType() == Value::eContextTypeRegisterInfo)
+ {
+ if (!exe_ctx->process)
+ return false;
+
+ RegisterContext *reg_ctx = exe_ctx->GetRegisterContext();
+ RegisterInfo *reg_info = value.GetRegisterInfo();
+
+ if (!reg_ctx)
+ return false;
+
+ lldb_private::RegisterValue reg_value;
+ Error err;
+
+ if (!reg_value.SetFromMemoryData (reg_info, data, length, exe_ctx->process->GetByteOrder(), err))
+ return false;
+
+ return reg_ctx->WriteRegister(reg_info, reg_value);
+ }
+ else
+ {
+ switch (value.GetValueType())
+ {
+ default:
+ return false;
+ case Value::eValueTypeFileAddress:
+ {
+ if (!exe_ctx->process)
+ return false;
+
+ Address file_addr;
+
+ if (!exe_ctx->target->GetImages().ResolveFileAddress((lldb::addr_t)value.GetScalar().ULongLong(), file_addr))
+ return false;
+
+ lldb::addr_t load_addr = file_addr.GetLoadAddress(exe_ctx->target);
+
+ Error err;
+ exe_ctx->process->WriteMemory(load_addr, data, length, err);
+
+ return err.Success();
+ }
+ case Value::eValueTypeLoadAddress:
+ {
+ if (!exe_ctx->process)
+ return false;
+
+ Error err;
+ exe_ctx->process->WriteMemory((lldb::addr_t)value.GetScalar().ULongLong(), data, length, err);
+
+ return err.Success();
+ }
+ case Value::eValueTypeHostAddress:
+ memcpy ((void *)value.GetScalar().ULongLong(), data, length);
+ return true;
+ case Value::eValueTypeScalar:
+ return false;
+ }
+ }
+}
+
+bool
+ClangExpressionDeclMap::ReadTarget (uint8_t *data,
+ lldb_private::Value &value,
+ size_t length)
+{
+ assert (m_parser_vars.get());
+
+ ExecutionContext *exe_ctx = m_parser_vars->m_exe_ctx;
+
+ if (value.GetContextType() == Value::eContextTypeRegisterInfo)
+ {
+ if (!exe_ctx->process)
+ return false;
+
+ RegisterContext *reg_ctx = exe_ctx->GetRegisterContext();
+ RegisterInfo *reg_info = value.GetRegisterInfo();
+
+ if (!reg_ctx)
+ return false;
+
+ lldb_private::RegisterValue reg_value;
+ Error err;
+
+ if (!reg_ctx->ReadRegister(reg_info, reg_value))
+ return false;
+
+ return reg_value.GetAsMemoryData(reg_info, data, length, exe_ctx->process->GetByteOrder(), err);
+ }
+ else
+ {
+ switch (value.GetValueType())
+ {
+ default:
+ return false;
+ case Value::eValueTypeFileAddress:
+ {
+ if (!exe_ctx->target)
+ return false;
+
+ Address file_addr;
+
+ if (!exe_ctx->target->GetImages().ResolveFileAddress((lldb::addr_t)value.GetScalar().ULongLong(), file_addr))
+ return false;
+
+ Error err;
+ exe_ctx->target->ReadMemory(file_addr, true, data, length, err);
+
+ return err.Success();
+ }
+ case Value::eValueTypeLoadAddress:
+ {
+ if (!exe_ctx->process)
+ return false;
+
+ Error err;
+ exe_ctx->process->ReadMemory((lldb::addr_t)value.GetScalar().ULongLong(), data, length, err);
+
+ return err.Success();
+ }
+ case Value::eValueTypeHostAddress:
+ memcpy (data, (const void *)value.GetScalar().ULongLong(), length);
+ return true;
+ case Value::eValueTypeScalar:
+ return false;
+ }
+ }
+}
+
+lldb_private::Value
+ClangExpressionDeclMap::LookupDecl (clang::NamedDecl *decl)
+{
+ assert (m_parser_vars.get());
+
+ ExecutionContext exe_ctx = *m_parser_vars->m_exe_ctx;
+
+ ClangExpressionVariableSP expr_var_sp (m_found_entities.GetVariable(decl));
+ ClangExpressionVariableSP persistent_var_sp (m_parser_vars->m_persistent_vars->GetVariable(decl));
+
+ if (expr_var_sp)
+ {
+ const ConstString &name(expr_var_sp->GetName());
+ TypeFromUser type(expr_var_sp->GetTypeFromUser());
+
+ if (m_parser_vars->m_exe_ctx->frame)
+ {
+ VariableSP var(FindVariableInScope (*exe_ctx.frame, name, &type));
+
+ if (var)
+ return *GetVariableValue(exe_ctx, var, NULL);
+ }
+
+ if (m_parser_vars->m_exe_ctx->target)
+ {
+ VariableSP global(FindGlobalVariable (*exe_ctx.target, name.GetCString(), &type));
+
+ if (global)
+ return *GetVariableValue(exe_ctx, global, NULL);
+
+ lldb::addr_t location_load_addr = GetSymbolAddress(*exe_ctx.target, name);
+
+ if (location_load_addr != LLDB_INVALID_ADDRESS)
+ {
+ lldb_private::Value ret;
+ ret.SetValueType(Value::eValueTypeLoadAddress);
+ ret.SetContext(Value::eContextTypeInvalid, NULL);
+ ret.GetScalar() = location_load_addr;
+ return ret;
+ }
+ }
+
+ return Value();
+ }
+ else if (persistent_var_sp)
+ {
+ lldb_private::Value ret;
+ ret.SetValueType(Value::eValueTypeHostAddress);
+ ret.SetContext(Value::eContextTypeInvalid, NULL);
+ ret.GetScalar() = (lldb::addr_t)persistent_var_sp->GetValueBytes();
+ return ret;
+ }
+ else
+ {
+ return Value();
+ }
+}
+
// Interface for CommandObjectExpression
bool
@@ -1630,8 +1907,8 @@
SymbolContextList sc_list;
target.GetImages().FindSymbolsWithNameAndType(name,
- eSymbolTypeData,
- sc_list);
+ eSymbolTypeData,
+ sc_list);
if (sc_list.GetSize())
{
@@ -1644,7 +1921,67 @@
return NULL;
}
+// This is a callback used with Variable::GetValuesForVariableExpressionPath
+
+static uint32_t GetVariableCallback (void *baton,
+ const char *name,
+ VariableList &variable_list)
+{
+ Target *target = static_cast<Target *>(baton);
+ if (target)
+ {
+ return target->GetImages().FindGlobalVariables (ConstString(name),
+ true,
+ UINT32_MAX,
+ variable_list);
+ }
+ return 0;
+}
+
+lldb::VariableSP
+ClangExpressionDeclMap::FindGlobalVariable
+(
+ Target &target,
+ const char *name,
+ TypeFromUser *type
+)
+{
+ VariableList vars;
+ ValueObjectList valobjs;
+
+ Error error (Variable::GetValuesForVariableExpressionPath (name,
+ &target,
+ GetVariableCallback,
+ &target,
+ vars,
+ valobjs));
+
+ if (vars.GetSize())
+ {
+ if (type)
+ {
+ for (size_t i = 0; i < vars.GetSize(); ++i)
+ {
+ VariableSP var_sp = vars.GetVariableAtIndex(i);
+
+ if (type->GetASTContext() == var_sp->GetType()->GetClangAST())
+ {
+ if (ClangASTContext::AreTypesSame(type->GetASTContext(), type->GetOpaqueQualType(), var_sp->GetType()->GetClangFullType()))
+ return var_sp;
+ }
+ }
+ }
+ else
+ {
+ return vars.GetVariableAtIndex(0);
+ }
+ }
+
+ return VariableSP();
+}
+
// Interface for ClangASTSource
+
void
ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString &name)
{
@@ -1656,10 +1993,6 @@
if (log)
log->Printf("Hunting for a definition for '%s'", name.GetCString());
- // Back out in all cases where we're not fully initialized
- if (m_parser_vars->m_exe_ctx->frame == NULL)
- return;
-
if (m_parser_vars->m_ignore_lookups)
{
if (log)
@@ -1740,19 +2073,37 @@
ValueObjectSP valobj;
VariableSP var;
Error err;
+ bool found = false;
- valobj = m_parser_vars->m_exe_ctx->frame->GetValueForVariableExpressionPath(name_unique_cstr,
- eNoDynamicValues,
- StackFrame::eExpressionPathOptionCheckPtrVsMember,
- var,
- err);
-
- // If we found a variable in scope, no need to pull up function names
- if (err.Success() && var != NULL)
+ if (m_parser_vars->m_exe_ctx->frame)
{
- AddOneVariable(context, var);
+ valobj = m_parser_vars->m_exe_ctx->frame->GetValueForVariableExpressionPath(name_unique_cstr,
+ eNoDynamicValues,
+ StackFrame::eExpressionPathOptionCheckPtrVsMember,
+ var,
+ err);
+
+ // If we found a variable in scope, no need to pull up function names
+ if (err.Success() && var != NULL)
+ {
+ AddOneVariable(context, var);
+ found = true;
+ }
}
- else
+ else if (m_parser_vars->m_exe_ctx->target)
+ {
+ var = FindGlobalVariable(*m_parser_vars->m_exe_ctx->target,
+ name_unique_cstr,
+ NULL);
+
+ if (var)
+ {
+ AddOneVariable(context, var);
+ found = true;
+ }
+ }
+
+ if (!found)
{
const bool include_symbols = true;
const bool append = false;
@@ -1781,6 +2132,7 @@
if (!found_specific)
AddOneFunction(context, sym_ctx.function, NULL);
found_specific = true;
+ found = true;
}
else if (sym_ctx.symbol)
{
@@ -1794,12 +2146,19 @@
if (!found_specific)
{
if (generic_symbol)
+ {
AddOneFunction (context, NULL, generic_symbol);
+ found = true;
+ }
else if (non_extern_symbol)
+ {
AddOneFunction (context, NULL, non_extern_symbol);
+ found = true;
+ }
}
}
- else
+
+ if (!found)
{
// We couldn't find a variable or function for this. Now we'll hunt for a generic
// data symbol, and -- if it is found -- treat it as a variable.
@@ -1807,7 +2166,10 @@
Symbol *data_symbol = FindGlobalDataSymbol(*m_parser_vars->m_exe_ctx->target, name);
if (data_symbol)
+ {
AddOneGenericVariable(context, *data_symbol);
+ found = true;
+ }
}
}
@@ -1829,15 +2191,19 @@
NamespaceDecl *clang_namespace_decl = AddNamespace(context, namespace_decl);
if (clang_namespace_decl)
clang_namespace_decl->setHasExternalLexicalStorage();
- }
+ }
}
else
{
static ConstString g_lldb_class_name ("$__lldb_class");
+
if (name == g_lldb_class_name)
{
// Clang is looking for the type of "this"
+ if (!m_parser_vars->m_exe_ctx->frame)
+ return;
+
VariableList *vars = m_parser_vars->m_exe_ctx->frame->GetVariableList(false);
if (!vars)
@@ -1900,6 +2266,9 @@
{
// Clang is looking for the type of "*self"
+ if (!m_parser_vars->m_exe_ctx->frame)
+ return;
+
VariableList *vars = m_parser_vars->m_exe_ctx->frame->GetVariableList(false);
if (!vars)
@@ -2213,8 +2582,11 @@
lldb::addr_t load_addr = so_addr.GetLoadAddress(exe_ctx.target);
- var_location->GetScalar() = load_addr;
- var_location->SetValueType(Value::eValueTypeLoadAddress);
+ if (load_addr != LLDB_INVALID_ADDRESS)
+ {
+ var_location->GetScalar() = load_addr;
+ var_location->SetValueType(Value::eValueTypeLoadAddress);
+ }
}
if (user_type)
@@ -2229,7 +2601,7 @@
assert (m_parser_vars.get());
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
+
TypeFromUser ut;
TypeFromParser pt;
@@ -2248,8 +2620,8 @@
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->GetBestExecutionContextScope (),
entity_name,
ut,
- m_parser_vars->m_exe_ctx->process->GetByteOrder(),
- m_parser_vars->m_exe_ctx->process->GetAddressByteSize()));
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size));
assert (entity.get());
entity->EnableParserVars();
entity->m_parser_vars->m_parser_type = pt;
@@ -2331,8 +2703,8 @@
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->GetBestExecutionContextScope (),
entity_name,
user_type,
- m_parser_vars->m_exe_ctx->process->GetByteOrder(),
- m_parser_vars->m_exe_ctx->process->GetAddressByteSize()));
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size));
assert (entity.get());
std::auto_ptr<Value> symbol_location(new Value);
@@ -2449,8 +2821,8 @@
NamedDecl *var_decl = context.AddVarDecl(parser_type.GetOpaqueQualType());
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->GetBestExecutionContextScope(),
- m_parser_vars->m_exe_ctx->process->GetByteOrder(),
- m_parser_vars->m_exe_ctx->process->GetAddressByteSize()));
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size));
assert (entity.get());
std::string decl_name(context.m_decl_name.getAsString());
entity->SetName (ConstString (decl_name.c_str()));
@@ -2547,8 +2919,8 @@
fun_location->GetScalar() = load_addr;
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->GetBestExecutionContextScope (),
- m_parser_vars->m_exe_ctx->process->GetByteOrder(),
- m_parser_vars->m_exe_ctx->process->GetAddressByteSize()));
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size));
assert (entity.get());
std::string decl_name(context.m_decl_name.getAsString());
entity->SetName(ConstString(decl_name.c_str()));
Modified: lldb/trunk/source/Expression/ClangExpressionParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionParser.cpp?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionParser.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionParser.cpp Wed Sep 14 21:13:07 2011
@@ -19,7 +19,6 @@
#include "lldb/Expression/ClangExpression.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/IRDynamicChecks.h"
-#include "lldb/Expression/IRToDWARF.h"
#include "lldb/Expression/RecordingMemoryManager.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
@@ -418,66 +417,14 @@
}
Error
-ClangExpressionParser::MakeDWARF ()
-{
- Error err;
-
- llvm::Module *module = m_code_generator->GetModule();
-
- if (!module)
- {
- err.SetErrorToGenericError();
- err.SetErrorString("IR doesn't contain a module");
- return err;
- }
-
- ClangExpressionVariableList *local_variables = m_expr.LocalVariables();
- ClangExpressionDeclMap *decl_map = m_expr.DeclMap();
-
- if (!local_variables)
- {
- err.SetErrorToGenericError();
- err.SetErrorString("Can't convert an expression without a VariableList to DWARF");
- return err;
- }
-
- if (!decl_map)
- {
- err.SetErrorToGenericError();
- err.SetErrorString("Can't convert an expression without a DeclMap to DWARF");
- return err;
- }
-
- std::string function_name;
-
- if (!FindFunctionInModule(function_name, module, m_expr.FunctionName()))
- {
- err.SetErrorToGenericError();
- err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName());
- return err;
- }
-
- IRToDWARF ir_to_dwarf(*local_variables, decl_map, m_expr.DwarfOpcodeStream(), function_name.c_str());
-
- if (!ir_to_dwarf.runOnModule(*module))
- {
- err.SetErrorToGenericError();
- err.SetErrorString("Couldn't convert the expression to DWARF");
- return err;
- }
-
- err.Clear();
- return err;
-}
-
-Error
-ClangExpressionParser::MakeJIT (lldb::addr_t &func_allocation_addr,
- lldb::addr_t &func_addr,
- lldb::addr_t &func_end,
- ExecutionContext &exe_ctx,
- IRForTarget::StaticDataAllocator *data_allocator,
- lldb::ClangExpressionVariableSP &const_result,
- bool jit_only_if_needed)
+ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr,
+ lldb::addr_t &func_addr,
+ lldb::addr_t &func_end,
+ ExecutionContext &exe_ctx,
+ IRForTarget::StaticDataAllocator *data_allocator,
+ bool &evaluated_statically,
+ lldb::ClangExpressionVariableSP &const_result,
+ ExecutionPolicy execution_policy)
{
func_allocation_addr = LLDB_INVALID_ADDRESS;
func_addr = LLDB_INVALID_ADDRESS;
@@ -520,8 +467,9 @@
if (exe_ctx.target)
error_stream = &exe_ctx.target->GetDebugger().GetErrorStream();
- IRForTarget ir_for_target(decl_map,
+ IRForTarget ir_for_target(decl_map,
m_expr.NeedsVariableResolution(),
+ execution_policy,
const_result,
data_allocator,
error_stream,
@@ -530,17 +478,25 @@
if (!ir_for_target.runOnModule(*module))
{
err.SetErrorToGenericError();
- err.SetErrorString("Couldn't convert the expression to DWARF");
+ err.SetErrorString("Couldn't prepare the expression for execution in the target");
return err;
}
- if (jit_only_if_needed && const_result.get())
+ if (execution_policy != eExecutionPolicyAlways && ir_for_target.interpretSuccess())
{
+ evaluated_statically = true;
err.Clear();
return err;
}
- if (m_expr.NeedsValidation() && exe_ctx.process->GetDynamicCheckers())
+ if (!exe_ctx.process || execution_policy == eExecutionPolicyNever)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("Execution needed to run in the target, but the target can't be run");
+ return err;
+ }
+
+ if (m_expr.NeedsValidation() && exe_ctx.process && exe_ctx.process->GetDynamicCheckers())
{
IRDynamicChecks ir_dynamic_checks(*exe_ctx.process->GetDynamicCheckers(), function_name.c_str());
Modified: lldb/trunk/source/Expression/ClangFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangFunction.cpp?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangFunction.cpp (original)
+++ lldb/trunk/source/Expression/ClangFunction.cpp Wed Sep 14 21:13:07 2011
@@ -253,7 +253,16 @@
lldb::ClangExpressionVariableSP const_result;
- Error jit_error (m_parser->MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, NULL, const_result));
+ bool evaluated_statically = false; // should stay that way
+
+ Error jit_error (m_parser->PrepareForExecution (m_jit_alloc,
+ m_jit_start_addr,
+ m_jit_end_addr,
+ exe_ctx,
+ NULL,
+ evaluated_statically,
+ const_result,
+ eExecutionPolicyAlways));
if (!jit_error.Success())
return false;
Modified: lldb/trunk/source/Expression/ClangUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUserExpression.cpp?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangUserExpression.cpp (original)
+++ lldb/trunk/source/Expression/ClangUserExpression.cpp Wed Sep 14 21:13:07 2011
@@ -53,6 +53,7 @@
m_objectivec (false),
m_needs_object_ptr (false),
m_const_object (false),
+ m_evaluated_statically (false),
m_const_result (),
m_target (NULL)
{
@@ -167,6 +168,7 @@
ClangUserExpression::Parse (Stream &error_stream,
ExecutionContext &exe_ctx,
TypeFromUser desired_type,
+ lldb_private::ExecutionPolicy execution_policy,
bool keep_result_in_memory)
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -279,39 +281,23 @@
return false;
}
- ///////////////////////////////////////////////
- // Convert the output of the parser to DWARF
+ //////////////////////////////////////////////////////////////////////////////////////////
+ // Prepare the output of the parser for execution, evaluating it statically if possible
//
-
- m_dwarf_opcodes.reset(new StreamString);
- m_dwarf_opcodes->SetByteOrder (lldb::endian::InlHostByteOrder());
- m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);
-
- m_local_variables.reset(new ClangExpressionVariableList());
-
- Error dwarf_error = parser.MakeDWARF ();
-
- if (dwarf_error.Success())
- {
- if (log)
- log->Printf("Code can be interpreted.");
- m_expr_decl_map->DidParse();
-
- return true;
- }
-
- //////////////////////////////////
- // JIT the output of the parser
- //
-
- m_dwarf_opcodes.reset();
-
- m_data_allocator.reset(new ProcessDataAllocator(*exe_ctx.process));
+ if (execution_policy != eExecutionPolicyNever && exe_ctx.process)
+ m_data_allocator.reset(new ProcessDataAllocator(*exe_ctx.process));
- Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, m_data_allocator.get(), m_const_result, true);
+ Error jit_error = parser.PrepareForExecution (m_jit_alloc,
+ m_jit_start_addr,
+ m_jit_end_addr,
+ exe_ctx,
+ m_data_allocator.get(),
+ m_evaluated_statically,
+ m_const_result,
+ execution_policy);
- if (log)
+ if (log && m_data_allocator.get())
{
StreamString dump_string;
m_data_allocator->Dump(dump_string);
@@ -505,15 +491,7 @@
// expression, it's quite convenient to have these logs come out with the STEP log as well.
lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
- if (m_dwarf_opcodes.get())
- {
- // TODO execute the JITted opcodes
-
- error_stream.Printf("We don't currently support executing DWARF expressions");
-
- return eExecutionSetupError;
- }
- else if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
+ if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
{
lldb::addr_t struct_address;
@@ -594,38 +572,31 @@
}
else
{
- error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function is present");
+ error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
return eExecutionSetupError;
}
}
-StreamString &
-ClangUserExpression::DwarfOpcodeStream ()
-{
- if (!m_dwarf_opcodes.get())
- m_dwarf_opcodes.reset(new StreamString());
-
- return *m_dwarf_opcodes.get();
-}
-
ExecutionResults
-ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
+ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
+ lldb_private::ExecutionPolicy execution_policy,
bool discard_on_error,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp)
{
Error error;
- return EvaluateWithError (exe_ctx, discard_on_error, expr_cstr, expr_prefix, result_valobj_sp, error);
+ return EvaluateWithError (exe_ctx, execution_policy, discard_on_error, expr_cstr, expr_prefix, result_valobj_sp, error);
}
ExecutionResults
-ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
- bool discard_on_error,
- const char *expr_cstr,
- const char *expr_prefix,
- lldb::ValueObjectSP &result_valobj_sp,
- Error &error)
+ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
+ lldb_private::ExecutionPolicy execution_policy,
+ bool discard_on_error,
+ const char *expr_cstr,
+ const char *expr_prefix,
+ lldb::ValueObjectSP &result_valobj_sp,
+ Error &error)
{
lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
@@ -633,13 +604,18 @@
if (exe_ctx.process == NULL || exe_ctx.process->GetState() != lldb::eStateStopped)
{
- error.SetErrorString ("must have a stopped process to evaluate expressions.");
+ if (execution_policy == eExecutionPolicyAlways)
+ {
+ if (log)
+ log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
- result_valobj_sp = ValueObjectConstResult::Create (NULL, error);
- return eExecutionSetupError;
+ error.SetErrorString ("expression needed to run but couldn't");
+
+ return execution_results;
+ }
}
-
- if (!exe_ctx.process->GetDynamicCheckers())
+
+ if (execution_policy != eExecutionPolicyNever && !exe_ctx.process->GetDynamicCheckers())
{
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Installing dynamic checkers ==");
@@ -672,7 +648,9 @@
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
- if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), true))
+ const bool keep_expression_in_memory = true;
+
+ if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), execution_policy, keep_expression_in_memory))
{
if (error_stream.GetString().empty())
error.SetErrorString ("expression failed to parse, unknown error");
@@ -683,14 +661,26 @@
{
lldb::ClangExpressionVariableSP expr_result;
- if (user_expression_sp->m_const_result.get())
+ if (user_expression_sp->EvaluatedStatically())
{
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
- result_valobj_sp = user_expression_sp->m_const_result->GetValueObject();
+ if (user_expression_sp->m_const_result)
+ result_valobj_sp = user_expression_sp->m_const_result->GetValueObject();
+ else
+ error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
+
execution_results = eExecutionCompleted;
}
+ else if (execution_policy == eExecutionPolicyNever)
+ {
+ if (log)
+ log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
+
+ if (error_stream.GetString().empty())
+ error.SetErrorString ("expression needed to run but couldn't");
+ }
else
{
error_stream.GetString().clear();
Modified: lldb/trunk/source/Expression/ClangUtilityFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUtilityFunction.cpp?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangUtilityFunction.cpp (original)
+++ lldb/trunk/source/Expression/ClangUtilityFunction.cpp Wed Sep 14 21:13:07 2011
@@ -128,8 +128,16 @@
lldb::ClangExpressionVariableSP const_result;
-
- Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, m_data_allocator.get(), const_result);
+ bool evaluated_statically = false; // should stay that way
+
+ Error jit_error = parser.PrepareForExecution (m_jit_alloc,
+ m_jit_start_addr,
+ m_jit_end_addr,
+ exe_ctx,
+ m_data_allocator.get(),
+ evaluated_statically,
+ const_result,
+ eExecutionPolicyAlways);
if (log)
{
Modified: lldb/trunk/source/Expression/IRForTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRForTarget.cpp?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRForTarget.cpp (original)
+++ lldb/trunk/source/Expression/IRForTarget.cpp Wed Sep 14 21:13:07 2011
@@ -1,4 +1,4 @@
-//===-- IRForTarget.cpp -------------------------------------------*- C++ -*-===//
+//===-- IRForTarget.cpp -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -26,6 +26,7 @@
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
@@ -45,12 +46,15 @@
IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
bool resolve_vars,
+ lldb_private::ExecutionPolicy execution_policy,
lldb::ClangExpressionVariableSP &const_result,
StaticDataAllocator *data_allocator,
lldb_private::Stream *error_stream,
const char *func_name) :
ModulePass(ID),
m_resolve_vars(resolve_vars),
+ m_execution_policy(execution_policy),
+ m_interpret_success(false),
m_func_name(func_name),
m_module(NULL),
m_decl_map(decl_map),
@@ -309,12 +313,13 @@
return true;
}
+
clang::NamedDecl *
-IRForTarget::DeclForGlobal (GlobalValue *global_val)
+IRForTarget::DeclForGlobal (const GlobalValue *global_val, Module *module)
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- NamedMDNode *named_metadata = m_module->getNamedMetadata("clang.global.decl.ptrs");
+ NamedMDNode *named_metadata = module->getNamedMetadata("clang.global.decl.ptrs");
if (!named_metadata)
return NULL;
@@ -350,6 +355,12 @@
return NULL;
}
+clang::NamedDecl *
+IRForTarget::DeclForGlobal (GlobalValue *global_val)
+{
+ return DeclForGlobal(global_val, m_module);
+}
+
void
IRForTarget::MaybeSetConstantResult (llvm::Constant *initializer,
const lldb_private::ConstString &name,
@@ -553,9 +564,7 @@
// Get the next available result name from m_decl_map and create the persistent
// variable for it
-
- lldb_private::TypeFromParser result_decl_type;
-
+
// If the result is an Lvalue, it is emitted as a pointer; see
// ASTResultSynthesizer::SynthesizeBodyResult.
if (m_result_is_pointer)
@@ -577,19 +586,19 @@
clang::QualType element_qual_type = pointer_pointertype->getPointeeType();
- result_decl_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(),
+ m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(),
&result_decl->getASTContext());
}
else
{
- result_decl_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(),
+ m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(),
&result_decl->getASTContext());
}
if (log)
{
lldb_private::StreamString type_desc_stream;
- result_decl_type.DumpTypeDescription(&type_desc_stream);
+ m_result_type.DumpTypeDescription(&type_desc_stream);
log->Printf("Result decl type: \"%s\"", type_desc_stream.GetString().c_str());
}
@@ -665,7 +674,7 @@
{
MaybeSetConstantResult (initializer,
m_result_name,
- result_decl_type);
+ m_result_type);
}
StoreInst *synthesized_store = new StoreInst(initializer,
@@ -677,9 +686,9 @@
}
else
{
- if (!m_has_side_effects && lldb_private::ClangASTContext::IsPointerType (result_decl_type.GetOpaqueQualType()))
+ if (!m_has_side_effects && lldb_private::ClangASTContext::IsPointerType (m_result_type.GetOpaqueQualType()))
{
- MaybeSetCastResult (result_decl_type);
+ MaybeSetCastResult (m_result_type);
}
result_global->replaceAllUsesWith(new_result_global);
@@ -688,7 +697,7 @@
if (!m_const_result)
m_decl_map->AddPersistentVariable(result_decl,
m_result_name,
- result_decl_type,
+ m_result_type,
true,
m_result_is_pointer);
@@ -2247,6 +2256,9 @@
bool
IRForTarget::CompleteDataAllocation ()
{
+ if (!m_data_allocator)
+ return true;
+
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (!m_data_allocator->GetStream().GetSize())
@@ -2335,9 +2347,49 @@
return false;
}
-
- if (m_const_result)
+
+ if (m_const_result && m_execution_policy != lldb_private::eExecutionPolicyAlways)
+ {
+ m_interpret_success = true;
return true;
+ }
+
+ for (bbi = function->begin();
+ bbi != function->end();
+ ++bbi)
+ {
+ if (!RemoveGuards(*bbi))
+ {
+ if (log)
+ log->Printf("RemoveGuards() failed");
+
+ // RemoveGuards() reports its own errors, so we don't do so here
+
+ return false;
+ }
+
+ if (!RewritePersistentAllocs(*bbi))
+ {
+ if (log)
+ log->Printf("RewritePersistentAllocs() failed");
+
+ // RewritePersistentAllocs() reports its own errors, so we don't do so here
+
+ return false;
+ }
+ }
+
+ if (m_decl_map && m_execution_policy != lldb_private::eExecutionPolicyAlways)
+ {
+ IRInterpreter interpreter (*m_decl_map,
+ m_error_stream);
+
+ if (interpreter.maybeRunOnFunction(m_const_result, m_result_name, m_result_type, *function, llvm_module))
+ {
+ m_interpret_success = true;
+ return true;
+ }
+ }
if (log)
{
@@ -2379,34 +2431,10 @@
return false;
}
- //////////////////////////////////
- // Run basic-block level passes
- //
-
for (bbi = function->begin();
bbi != function->end();
++bbi)
{
- if (!RemoveGuards(*bbi))
- {
- if (log)
- log->Printf("RemoveGuards() failed");
-
- // RemoveGuards() reports its own errors, so we don't do so here
-
- return false;
- }
-
- if (!RewritePersistentAllocs(*bbi))
- {
- if (log)
- log->Printf("RewritePersistentAllocs() failed");
-
- // RewritePersistentAllocs() reports its own errors, so we don't do so here
-
- return false;
- }
-
if (!RewriteObjCSelectors(*bbi))
{
if (log)
Added: lldb/trunk/source/Expression/IRInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRInterpreter.cpp?rev=139772&view=auto
==============================================================================
--- lldb/trunk/source/Expression/IRInterpreter.cpp (added)
+++ lldb/trunk/source/Expression/IRInterpreter.cpp Wed Sep 14 21:13:07 2011
@@ -0,0 +1,1391 @@
+//===-- IRInterpreter.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/DataEncoder.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "lldb/Expression/IRForTarget.h"
+#include "lldb/Expression/IRInterpreter.h"
+
+#include "llvm/Constants.h"
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/Module.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetData.h"
+
+#include <map>
+
+using namespace llvm;
+
+IRInterpreter::IRInterpreter(lldb_private::ClangExpressionDeclMap &decl_map,
+ lldb_private::Stream *error_stream) :
+ m_decl_map(decl_map),
+ m_error_stream(error_stream)
+{
+
+}
+
+IRInterpreter::~IRInterpreter()
+{
+
+}
+
+static std::string
+PrintValue(const Value *value, bool truncate = false)
+{
+ std::string s;
+ raw_string_ostream rso(s);
+ value->print(rso);
+ rso.flush();
+ if (truncate)
+ s.resize(s.length() - 1);
+
+ size_t offset;
+ while ((offset = s.find('\n')) != s.npos)
+ s.erase(offset, 1);
+ while (s[0] == ' ' || s[0] == '\t')
+ s.erase(0, 1);
+
+ return s;
+}
+
+static std::string
+PrintType(const Type *type, bool truncate = false)
+{
+ std::string s;
+ raw_string_ostream rso(s);
+ type->print(rso);
+ rso.flush();
+ if (truncate)
+ s.resize(s.length() - 1);
+ return s;
+}
+
+typedef lldb::SharedPtr <lldb_private::DataEncoder>::Type DataEncoderSP;
+typedef lldb::SharedPtr <lldb_private::DataExtractor>::Type DataExtractorSP;
+
+class Memory
+{
+public:
+ typedef uint32_t index_t;
+
+ struct Allocation
+ {
+ // m_virtual_address is always the address of the variable in the virtual memory
+ // space provided by Memory.
+ //
+ // m_origin is always non-NULL and describes the source of the data (possibly
+ // m_data if this allocation is the authoritative source).
+ //
+ // Possible value configurations:
+ //
+ // Allocation type getValueType() getContextType() m_origin->GetScalar() m_data
+ // =========================================================================================================================
+ // FileAddress eValueTypeFileAddress eContextTypeInvalid A location in a binary NULL
+ // image
+ //
+ // LoadAddress eValueTypeLoadAddress eContextTypeInvalid A location in the target's NULL
+ // virtual memory
+ //
+ // Alloca eValueTypeHostAddress eContextTypeInvalid == m_data->GetBytes() Deleted at end of
+ // execution
+ //
+ // PersistentVar eValueTypeHostAddress eContextTypeClangType A persistent variable's NULL
+ // location in LLDB's memory
+ //
+ // Register [ignored] eContextTypeRegister [ignored] Flushed to the register
+ // at the end of execution
+
+ lldb::addr_t m_virtual_address;
+ size_t m_extent;
+ lldb_private::Value m_origin;
+ lldb::DataBufferSP m_data;
+
+ Allocation (lldb::addr_t virtual_address,
+ size_t extent,
+ lldb::DataBufferSP data) :
+ m_virtual_address(virtual_address),
+ m_extent(extent),
+ m_data(data)
+ {
+ }
+
+ Allocation (const Allocation &allocation) :
+ m_virtual_address(allocation.m_virtual_address),
+ m_extent(allocation.m_extent),
+ m_origin(allocation.m_origin),
+ m_data(allocation.m_data)
+ {
+ }
+ };
+
+ typedef lldb::SharedPtr <Allocation>::Type AllocationSP;
+
+ struct Region
+ {
+ AllocationSP m_allocation;
+ uint64_t m_base;
+ uint64_t m_extent;
+
+ Region () :
+ m_allocation(),
+ m_base(0),
+ m_extent(0)
+ {
+ }
+
+ Region (AllocationSP allocation, uint64_t base, uint64_t extent) :
+ m_allocation(allocation),
+ m_base(base),
+ m_extent(extent)
+ {
+ }
+
+ Region (const Region ®ion) :
+ m_allocation(region.m_allocation),
+ m_base(region.m_base),
+ m_extent(region.m_extent)
+ {
+ }
+
+ bool IsValid ()
+ {
+ return m_allocation != NULL;
+ }
+
+ bool IsInvalid ()
+ {
+ return m_allocation == NULL;
+ }
+ };
+
+ typedef std::vector <AllocationSP> MemoryMap;
+
+private:
+ lldb::addr_t m_addr_base;
+ lldb::addr_t m_addr_max;
+ MemoryMap m_memory;
+ lldb::ByteOrder m_byte_order;
+ lldb::addr_t m_addr_byte_size;
+ TargetData &m_target_data;
+
+ lldb_private::ClangExpressionDeclMap &m_decl_map;
+
+ MemoryMap::iterator LookupInternal (lldb::addr_t addr)
+ {
+ for (MemoryMap::iterator i = m_memory.begin(), e = m_memory.end();
+ i != e;
+ ++i)
+ {
+ if ((*i)->m_virtual_address <= addr &&
+ (*i)->m_virtual_address + (*i)->m_extent > addr)
+ return i;
+ }
+
+ return m_memory.end();
+ }
+
+public:
+ Memory (TargetData &target_data,
+ lldb_private::ClangExpressionDeclMap &decl_map,
+ lldb::addr_t alloc_start,
+ lldb::addr_t alloc_max) :
+ m_addr_base(alloc_start),
+ m_addr_max(alloc_max),
+ m_target_data(target_data),
+ m_decl_map(decl_map)
+ {
+ m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle : lldb::eByteOrderBig);
+ m_addr_byte_size = (target_data.getPointerSize());
+ }
+
+ Region Malloc (size_t size, size_t align)
+ {
+ lldb::DataBufferSP data(new lldb_private::DataBufferHeap(size, 0));
+
+ if (data)
+ {
+ index_t index = m_memory.size();
+
+ const size_t mask = (align - 1);
+
+ m_addr_base += mask;
+ m_addr_base &= ~mask;
+
+ if (m_addr_base + size < m_addr_base ||
+ m_addr_base + size > m_addr_max)
+ return Region();
+
+ uint64_t base = m_addr_base;
+
+ m_memory.push_back(AllocationSP(new Allocation(base, size, data)));
+
+ m_addr_base += size;
+
+ AllocationSP alloc = m_memory[index];
+
+ alloc->m_origin.GetScalar() = (unsigned long long)data->GetBytes();
+ alloc->m_origin.SetContext(lldb_private::Value::eContextTypeInvalid, NULL);
+ alloc->m_origin.SetValueType(lldb_private::Value::eValueTypeHostAddress);
+
+ return Region(alloc, base, size);
+ }
+
+ return Region();
+ }
+
+ Region Malloc (Type *type)
+ {
+ return Malloc (m_target_data.getTypeAllocSize(type),
+ m_target_data.getPrefTypeAlignment(type));
+ }
+
+ Region Place (Type *type, lldb::addr_t base, lldb_private::Value &value)
+ {
+ index_t index = m_memory.size();
+ size_t size = m_target_data.getTypeAllocSize(type);
+
+ m_memory.push_back(AllocationSP(new Allocation(base, size, lldb::DataBufferSP())));
+
+ AllocationSP alloc = m_memory[index];
+
+ alloc->m_origin = value;
+
+ return Region(alloc, base, size);
+ }
+
+ void Free (lldb::addr_t addr)
+ {
+ MemoryMap::iterator i = LookupInternal (addr);
+
+ if (i != m_memory.end())
+ m_memory.erase(i);
+ }
+
+ Region Lookup (lldb::addr_t addr, Type *type)
+ {
+ MemoryMap::iterator i = LookupInternal(addr);
+
+ if (i == m_memory.end())
+ return Region();
+
+ size_t size = m_target_data.getTypeStoreSize(type);
+
+ return Region(*i, addr, size);
+ }
+
+ DataEncoderSP GetEncoder (Region region)
+ {
+ if (region.m_allocation->m_origin.GetValueType() != lldb_private::Value::eValueTypeHostAddress)
+ return DataEncoderSP();
+
+ lldb::DataBufferSP buffer = region.m_allocation->m_data;
+
+ if (!buffer)
+ return DataEncoderSP();
+
+ size_t base_offset = (size_t)(region.m_base - region.m_allocation->m_virtual_address);
+
+ return DataEncoderSP(new lldb_private::DataEncoder(buffer->GetBytes() + base_offset, region.m_extent, m_byte_order, m_addr_byte_size));
+ }
+
+ DataExtractorSP GetExtractor (Region region)
+ {
+ if (region.m_allocation->m_origin.GetValueType() != lldb_private::Value::eValueTypeHostAddress)
+ return DataExtractorSP();
+
+ lldb::DataBufferSP buffer = region.m_allocation->m_data;
+ size_t base_offset = (size_t)(region.m_base - region.m_allocation->m_virtual_address);
+
+ if (buffer)
+ return DataExtractorSP(new lldb_private::DataExtractor(buffer->GetBytes() + base_offset, region.m_extent, m_byte_order, m_addr_byte_size));
+ else
+ return DataExtractorSP(new lldb_private::DataExtractor((uint8_t*)region.m_allocation->m_origin.GetScalar().ULongLong() + base_offset, region.m_extent, m_byte_order, m_addr_byte_size));
+ }
+
+ lldb_private::Value GetAccessTarget(lldb::addr_t addr)
+ {
+ MemoryMap::iterator i = LookupInternal(addr);
+
+ if (i == m_memory.end())
+ return lldb_private::Value();
+
+ lldb_private::Value target = (*i)->m_origin;
+
+ if (target.GetContextType() == lldb_private::Value::eContextTypeRegisterInfo)
+ {
+ target.SetContext(lldb_private::Value::eContextTypeInvalid, NULL);
+ target.SetValueType(lldb_private::Value::eValueTypeHostAddress);
+ target.GetScalar() = (unsigned long long)(*i)->m_data->GetBytes();
+ }
+
+ target.GetScalar() += (addr - (*i)->m_virtual_address);
+
+ return target;
+ }
+
+ bool Write (lldb::addr_t addr, const uint8_t *data, size_t length)
+ {
+ lldb_private::Value target = GetAccessTarget(addr);
+
+ return m_decl_map.WriteTarget(target, data, length);
+ }
+
+ bool Read (uint8_t *data, lldb::addr_t addr, size_t length)
+ {
+ lldb_private::Value target = GetAccessTarget(addr);
+
+ return m_decl_map.ReadTarget(data, target, length);
+ }
+
+ std::string PrintData (lldb::addr_t addr, size_t length)
+ {
+ lldb_private::Value target = GetAccessTarget(addr);
+
+ lldb_private::DataBufferHeap buf(length, 0);
+
+ if (!m_decl_map.ReadTarget(buf.GetBytes(), target, length))
+ return std::string("<couldn't read data>");
+
+ lldb_private::StreamString ss;
+
+ for (size_t i = 0; i < length; i++)
+ {
+ if ((!(i & 0xf)) && i)
+ ss.Printf("%02hhx - ", buf.GetBytes()[i]);
+ else
+ ss.Printf("%02hhx ", buf.GetBytes()[i]);
+ }
+
+ return ss.GetString();
+ }
+
+ std::string SummarizeRegion (Region ®ion)
+ {
+ lldb_private::StreamString ss;
+
+ lldb_private::Value base = GetAccessTarget(region.m_base);
+
+ ss.Printf("%llx [%s - %s %llx]",
+ region.m_base,
+ lldb_private::Value::GetValueTypeAsCString(base.GetValueType()),
+ lldb_private::Value::GetContextTypeAsCString(base.GetContextType()),
+ base.GetScalar().ULongLong());
+
+ ss.Printf(" %s", PrintData(region.m_base, region.m_extent).c_str());
+
+ return ss.GetString();
+ }
+};
+
+class InterpreterStackFrame
+{
+public:
+ typedef std::map <const Value*, Memory::Region> ValueMap;
+
+ ValueMap m_values;
+ Memory &m_memory;
+ TargetData &m_target_data;
+ lldb_private::ClangExpressionDeclMap &m_decl_map;
+ const BasicBlock *m_bb;
+ BasicBlock::const_iterator m_ii;
+ BasicBlock::const_iterator m_ie;
+
+ lldb::ByteOrder m_byte_order;
+ size_t m_addr_byte_size;
+
+ InterpreterStackFrame (TargetData &target_data,
+ Memory &memory,
+ lldb_private::ClangExpressionDeclMap &decl_map) :
+ m_target_data (target_data),
+ m_memory (memory),
+ m_decl_map (decl_map)
+ {
+ m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle : lldb::eByteOrderBig);
+ m_addr_byte_size = (target_data.getPointerSize());
+ }
+
+ void Jump (const BasicBlock *bb)
+ {
+ m_bb = bb;
+ m_ii = m_bb->begin();
+ m_ie = m_bb->end();
+ }
+
+ bool Cache (Memory::AllocationSP allocation, Type *type)
+ {
+ if (allocation->m_origin.GetContextType() != lldb_private::Value::eContextTypeRegisterInfo)
+ return false;
+
+ return m_decl_map.ReadTarget(allocation->m_data->GetBytes(), allocation->m_origin, allocation->m_data->GetByteSize());
+ }
+
+ std::string SummarizeValue (const Value *value)
+ {
+ lldb_private::StreamString ss;
+
+ ss.Printf("%s", PrintValue(value).c_str());
+
+ ValueMap::iterator i = m_values.find(value);
+
+ if (i != m_values.end())
+ {
+ Memory::Region region = i->second;
+
+ ss.Printf(" %s", m_memory.SummarizeRegion(region).c_str());
+ }
+
+ return ss.GetString();
+ }
+
+ bool AssignToMatchType (lldb_private::Scalar &scalar, uint64_t u64value, Type *type)
+ {
+ size_t type_size = m_target_data.getTypeStoreSize(type);
+
+ switch (type_size)
+ {
+ case 1:
+ scalar = (uint8_t)u64value;
+ break;
+ case 2:
+ scalar = (uint16_t)u64value;
+ break;
+ case 4:
+ scalar = (uint32_t)u64value;
+ break;
+ case 8:
+ scalar = (uint64_t)u64value;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+ }
+
+ bool EvaluateValue (lldb_private::Scalar &scalar, const Value *value, Module &module)
+ {
+ const Constant *constant = dyn_cast<Constant>(value);
+
+ if (constant)
+ {
+ if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant))
+ {
+ return AssignToMatchType(scalar, constant_int->getLimitedValue(), value->getType());
+ }
+ }
+ else
+ {
+ Memory::Region region = ResolveValue(value, module);
+ DataExtractorSP value_extractor = m_memory.GetExtractor(region);
+
+ if (!value_extractor)
+ return false;
+
+ size_t value_size = m_target_data.getTypeStoreSize(value->getType());
+
+ uint32_t offset = 0;
+ uint64_t u64value = value_extractor->GetMaxU64(&offset, value_size);
+
+ return AssignToMatchType(scalar, u64value, value->getType());
+ }
+
+ return false;
+ }
+
+ bool AssignValue (const Value *value, lldb_private::Scalar &scalar, Module &module)
+ {
+ Memory::Region region = ResolveValue (value, module);
+
+ lldb_private::Scalar cast_scalar;
+
+ if (!AssignToMatchType(cast_scalar, scalar.GetRawBits64(0), value->getType()))
+ return false;
+
+ lldb_private::DataBufferHeap buf(cast_scalar.GetByteSize(), 0);
+
+ lldb_private::Error err;
+
+ if (!cast_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(), m_byte_order, err))
+ return false;
+
+ DataEncoderSP region_encoder = m_memory.GetEncoder(region);
+
+ memcpy(region_encoder->GetDataStart(), buf.GetBytes(), buf.GetByteSize());
+
+ return true;
+ }
+
+ bool ResolveConstant (Memory::Region ®ion, const Constant *constant)
+ {
+ size_t constant_size = m_target_data.getTypeStoreSize(constant->getType());
+
+ if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant))
+ {
+ const uint64_t *raw_data = constant_int->getValue().getRawData();
+ return m_memory.Write(region.m_base, (const uint8_t*)raw_data, constant_size);
+ }
+ if (const ConstantFP *constant_fp = dyn_cast<ConstantFP>(constant))
+ {
+ const uint64_t *raw_data = constant_fp->getValueAPF().bitcastToAPInt().getRawData();
+ return m_memory.Write(region.m_base, (const uint8_t*)raw_data, constant_size);
+ }
+
+ return false;
+ }
+
+ Memory::Region ResolveValue (const Value *value, Module &module)
+ {
+ ValueMap::iterator i = m_values.find(value);
+
+ if (i != m_values.end())
+ return i->second;
+
+ const GlobalValue *global_value = dyn_cast<GlobalValue>(value);
+
+ // Attempt to resolve the value using the program's data.
+ // If it is, the values to be created are:
+ //
+ // data_region - a region of memory in which the variable's data resides.
+ // ref_region - a region of memory in which its address (i.e., &var) resides.
+ // In the JIT case, this region would be a member of the struct passed in.
+ // pointer_region - a region of memory in which the address of the pointer
+ // resides. This is an IR-level variable.
+ do
+ {
+ if (!global_value)
+ break;
+
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ clang::NamedDecl *decl = IRForTarget::DeclForGlobal(global_value, &module);
+
+ if (!decl)
+ break;
+
+ lldb_private::Value resolved_value = m_decl_map.LookupDecl(decl);
+
+ if (resolved_value.GetScalar().GetType() != lldb_private::Scalar::e_void)
+ {
+ if (resolved_value.GetContextType() == lldb_private::Value::eContextTypeRegisterInfo)
+ {
+ Memory::Region data_region = m_memory.Malloc(value->getType());
+ data_region.m_allocation->m_origin = resolved_value;
+ Memory::Region ref_region = m_memory.Malloc(value->getType());
+ Memory::Region pointer_region = m_memory.Malloc(value->getType());
+
+ if (!Cache(data_region.m_allocation, value->getType()))
+ return Memory::Region();
+
+ if (ref_region.IsInvalid())
+ return Memory::Region();
+
+ if (pointer_region.IsInvalid())
+ return Memory::Region();
+
+ DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region);
+
+ if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX)
+ return Memory::Region();
+
+ DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region);
+
+ if (pointer_encoder->PutAddress(0, ref_region.m_base) == UINT32_MAX)
+ return Memory::Region();
+
+ m_values[value] = pointer_region;
+ return pointer_region;
+ }
+ else if (isa<clang::FunctionDecl>(decl))
+ {
+ if (log)
+ log->Printf("The interpreter does not handle function pointers at the moment");
+
+ return Memory::Region();
+ }
+ else
+ {
+ Memory::Region data_region = m_memory.Place(value->getType(), resolved_value.GetScalar().ULongLong(), resolved_value);
+ Memory::Region ref_region = m_memory.Malloc(value->getType());
+ Memory::Region pointer_region = m_memory.Malloc(value->getType());
+
+ if (ref_region.IsInvalid())
+ return Memory::Region();
+
+ if (pointer_region.IsInvalid())
+ return Memory::Region();
+
+ DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region);
+
+ if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX)
+ return Memory::Region();
+
+ DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region);
+
+ if (pointer_encoder->PutAddress(0, ref_region.m_base) == UINT32_MAX)
+ return Memory::Region();
+
+ m_values[value] = pointer_region;
+
+ if (log)
+ {
+ log->Printf("Made an allocation for %s", PrintValue(global_value).c_str());
+ log->Printf(" Data contents : %s", m_memory.PrintData(data_region.m_base, data_region.m_extent).c_str());
+ log->Printf(" Data region : %llx", (unsigned long long)data_region.m_base);
+ log->Printf(" Ref region : %llx", (unsigned long long)ref_region.m_base);
+ log->Printf(" Pointer region : %llx", (unsigned long long)pointer_region.m_base);
+ }
+
+ return pointer_region;
+ }
+ }
+ }
+ while(0);
+
+ // Fall back and allocate space [allocation type Alloca]
+
+ Type *type = value->getType();
+
+ lldb::ValueSP backing_value(new lldb_private::Value);
+
+ Memory::Region data_region = m_memory.Malloc(type);
+ data_region.m_allocation->m_origin.GetScalar() = (unsigned long long)data_region.m_allocation->m_data->GetBytes();
+ data_region.m_allocation->m_origin.SetContext(lldb_private::Value::eContextTypeInvalid, NULL);
+ data_region.m_allocation->m_origin.SetValueType(lldb_private::Value::eValueTypeHostAddress);
+
+ const Constant *constant = dyn_cast<Constant>(value);
+
+ do
+ {
+ if (!constant)
+ break;
+
+ if (!ResolveConstant (data_region, constant))
+ return Memory::Region();
+ }
+ while(0);
+
+ m_values[value] = data_region;
+ return data_region;
+ }
+
+ bool ConstructResult (lldb::ClangExpressionVariableSP &result,
+ const GlobalValue *result_value,
+ const lldb_private::ConstString &result_name,
+ lldb_private::TypeFromParser result_type,
+ Module &module)
+ {
+ // The result_value resolves to P, a pointer to a region R containing the result data.
+ // If the result variable is a reference, the region R contains a pointer to the result R_final in the original process.
+
+ if (!result_value)
+ return true; // There was no slot for a result â the expression doesn't return one.
+
+ ValueMap::iterator i = m_values.find(result_value);
+
+ if (i == m_values.end())
+ return false; // There was a slot for the result, but we didn't write into it.
+
+ Memory::Region P = i->second;
+ DataExtractorSP P_extractor = m_memory.GetExtractor(P);
+
+ if (!P_extractor)
+ return false;
+
+ Type *pointer_ty = result_value->getType();
+ PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty);
+ if (!pointer_ptr_ty)
+ return false;
+ Type *R_ty = pointer_ptr_ty->getElementType();
+
+ uint32_t offset = 0;
+ lldb::addr_t pointer = P_extractor->GetAddress(&offset);
+
+ Memory::Region R = m_memory.Lookup(pointer, R_ty);
+
+ if (R.m_allocation->m_origin.GetValueType() != lldb_private::Value::eValueTypeHostAddress ||
+ !R.m_allocation->m_data)
+ return false;
+
+ lldb_private::Value base;
+
+ if (m_decl_map.ResultIsReference(result_name))
+ {
+ PointerType *R_ptr_ty = dyn_cast<PointerType>(R_ty);
+ if (!R_ptr_ty)
+ return false;
+ Type *R_final_ty = R_ptr_ty->getElementType();
+
+ DataExtractorSP R_extractor = m_memory.GetExtractor(R);
+
+ if (!R_extractor)
+ return false;
+
+ offset = 0;
+ lldb::addr_t R_pointer = R_extractor->GetAddress(&offset);
+
+ Memory::Region R_final = m_memory.Lookup(R_pointer, R_final_ty);
+
+ if (!R_final.m_allocation)
+ return false;
+
+ base = R_final.m_allocation->m_origin;
+ base.GetScalar() += (R_final.m_base - R_final.m_allocation->m_virtual_address);
+ }
+ else
+ {
+ base.SetContext(lldb_private::Value::eContextTypeInvalid, NULL);
+ base.SetValueType(lldb_private::Value::eValueTypeHostAddress);
+ base.GetScalar() = (unsigned long long)R.m_allocation->m_data->GetBytes() + (R.m_base - R.m_allocation->m_virtual_address);
+ }
+
+ return m_decl_map.CompleteResultVariable (result, base, result_name, result_type);
+ }
+};
+
+bool
+IRInterpreter::maybeRunOnFunction (lldb::ClangExpressionVariableSP &result,
+ const lldb_private::ConstString &result_name,
+ lldb_private::TypeFromParser result_type,
+ Function &llvm_function,
+ Module &llvm_module)
+{
+ if (supportsFunction (llvm_function))
+ return runOnFunction(result,
+ result_name,
+ result_type,
+ llvm_function,
+ llvm_module);
+ else
+ return false;
+}
+
+bool
+IRInterpreter::supportsFunction (Function &llvm_function)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ for (Function::iterator bbi = llvm_function.begin(), bbe = llvm_function.end();
+ bbi != bbe;
+ ++bbi)
+ {
+ for (BasicBlock::iterator ii = bbi->begin(), ie = bbi->end();
+ ii != ie;
+ ++ii)
+ {
+ switch (ii->getOpcode())
+ {
+ default:
+ {
+ if (log)
+ log->Printf("Unsupported instruction: %s", PrintValue(ii).c_str());
+ return false;
+ }
+ case Instruction::Add:
+ case Instruction::Alloca:
+ case Instruction::BitCast:
+ case Instruction::Br:
+ case Instruction::GetElementPtr:
+ break;
+ case Instruction::ICmp:
+ {
+ ICmpInst *icmp_inst = dyn_cast<ICmpInst>(ii);
+
+ if (!icmp_inst)
+ return false;
+
+ switch (icmp_inst->getPredicate())
+ {
+ default:
+ {
+ if (log)
+ log->Printf("Unsupported ICmp predicate: %s", PrintValue(ii).c_str());
+ return false;
+ }
+ case CmpInst::ICMP_EQ:
+ case CmpInst::ICMP_NE:
+ case CmpInst::ICMP_UGT:
+ case CmpInst::ICMP_UGE:
+ case CmpInst::ICMP_ULT:
+ case CmpInst::ICMP_ULE:
+ case CmpInst::ICMP_SGT:
+ case CmpInst::ICMP_SGE:
+ case CmpInst::ICMP_SLT:
+ case CmpInst::ICMP_SLE:
+ break;
+ }
+ }
+ break;
+ case Instruction::Load:
+ case Instruction::Mul:
+ case Instruction::Ret:
+ case Instruction::SDiv:
+ case Instruction::Store:
+ case Instruction::Sub:
+ case Instruction::UDiv:
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool
+IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result,
+ const lldb_private::ConstString &result_name,
+ lldb_private::TypeFromParser result_type,
+ Function &llvm_function,
+ Module &llvm_module)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ lldb_private::ClangExpressionDeclMap::TargetInfo target_info = m_decl_map.GetTargetInfo();
+
+ if (!target_info.IsValid())
+ return false;
+
+ lldb::addr_t alloc_min;
+ lldb::addr_t alloc_max;
+
+ switch (target_info.address_byte_size)
+ {
+ default:
+ return false;
+ case 4:
+ alloc_min = 0x00001000llu;
+ alloc_max = 0x0000ffffllu;
+ break;
+ case 8:
+ alloc_min = 0x0000000000001000llu;
+ alloc_max = 0x000000000000ffffllu;
+ break;
+ }
+
+ TargetData target_data(&llvm_module);
+ if (target_data.getPointerSize() != target_info.address_byte_size)
+ return false;
+ if (target_data.isLittleEndian() != (target_info.byte_order == lldb::eByteOrderLittle))
+ return false;
+
+ Memory memory(target_data, m_decl_map, alloc_min, alloc_max);
+ InterpreterStackFrame frame(target_data, memory, m_decl_map);
+
+ uint32_t num_insts = 0;
+
+ frame.Jump(llvm_function.begin());
+
+ while (frame.m_ii != frame.m_ie && (++num_insts < 4096))
+ {
+ const Instruction *inst = frame.m_ii;
+
+ if (log)
+ log->Printf("Interpreting %s", PrintValue(inst).c_str());
+
+ switch (inst->getOpcode())
+ {
+ default:
+ break;
+ case Instruction::Add:
+ case Instruction::Sub:
+ case Instruction::Mul:
+ case Instruction::SDiv:
+ case Instruction::UDiv:
+ {
+ const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(inst);
+
+ if (!bin_op)
+ {
+ if (log)
+ log->Printf("getOpcode() returns %s, but instruction is not a BinaryOperator", inst->getOpcodeName());
+
+ return false;
+ }
+
+ Value *lhs = inst->getOperand(0);
+ Value *rhs = inst->getOperand(1);
+
+ lldb_private::Scalar L;
+ lldb_private::Scalar R;
+
+ if (!frame.EvaluateValue(L, lhs, llvm_module))
+ {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str());
+
+ return false;
+ }
+
+ if (!frame.EvaluateValue(R, rhs, llvm_module))
+ {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str());
+
+ return false;
+ }
+
+ lldb_private::Scalar result;
+
+ switch (inst->getOpcode())
+ {
+ default:
+ break;
+ case Instruction::Add:
+ result = L + R;
+ break;
+ case Instruction::Mul:
+ result = L * R;
+ break;
+ case Instruction::Sub:
+ result = L - R;
+ break;
+ case Instruction::SDiv:
+ result = L / R;
+ break;
+ case Instruction::UDiv:
+ result = L.GetRawBits64(0) / R.GetRawBits64(1);
+ break;
+ }
+
+ frame.AssignValue(inst, result, llvm_module);
+
+ if (log)
+ {
+ log->Printf("Interpreted a %s", inst->getOpcodeName());
+ log->Printf(" L : %s", frame.SummarizeValue(lhs).c_str());
+ log->Printf(" R : %s", frame.SummarizeValue(rhs).c_str());
+ log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
+ }
+ }
+ break;
+ case Instruction::Alloca:
+ {
+ const AllocaInst *alloca_inst = dyn_cast<AllocaInst>(inst);
+
+ if (!alloca_inst)
+ {
+ if (log)
+ log->Printf("getOpcode() returns Alloca, but instruction is not an AllocaInst");
+
+ return false;
+ }
+
+ if (alloca_inst->isArrayAllocation())
+ {
+ if (log)
+ log->Printf("AllocaInsts are not handled if isArrayAllocation() is true");
+
+ return false;
+ }
+
+ // The semantics of Alloca are:
+ // Create a region R of virtual memory of type T, backed by a data buffer
+ // Create a region P of virtual memory of type T*, backed by a data buffer
+ // Write the virtual address of R into P
+
+ Type *T = alloca_inst->getAllocatedType();
+ Type *Tptr = alloca_inst->getType();
+
+ Memory::Region R = memory.Malloc(T);
+
+ if (R.IsInvalid())
+ {
+ if (log)
+ log->Printf("Couldn't allocate memory for an AllocaInst");
+
+ return false;
+ }
+
+ Memory::Region P = memory.Malloc(Tptr);
+
+ if (P.IsInvalid())
+ {
+ if (log)
+ log->Printf("Couldn't allocate the result pointer for an AllocaInst");
+
+ return false;
+ }
+
+ DataEncoderSP P_encoder = memory.GetEncoder(P);
+
+ if (P_encoder->PutAddress(0, R.m_base) == UINT32_MAX)
+ {
+ if (log)
+ log->Printf("Couldn't write the reseult pointer for an AllocaInst");
+
+ return false;
+ }
+
+ frame.m_values[alloca_inst] = P;
+
+ if (log)
+ {
+ log->Printf("Interpreted an AllocaInst");
+ log->Printf(" R : %s", memory.SummarizeRegion(R).c_str());
+ log->Printf(" P : %s", frame.SummarizeValue(alloca_inst).c_str());
+ }
+ }
+ break;
+ case Instruction::BitCast:
+ {
+ const BitCastInst *bit_cast_inst = dyn_cast<BitCastInst>(inst);
+
+ if (!bit_cast_inst)
+ {
+ if (log)
+ log->Printf("getOpcode() returns BitCast, but instruction is not a BitCastInst");
+
+ return false;
+ }
+
+ Value *source = bit_cast_inst->getOperand(0);
+
+ lldb_private::Scalar S;
+
+ if (!frame.EvaluateValue(S, source, llvm_module))
+ {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(source).c_str());
+
+ return false;
+ }
+
+ frame.AssignValue(inst, S, llvm_module);
+ }
+ break;
+ case Instruction::Br:
+ {
+ const BranchInst *br_inst = dyn_cast<BranchInst>(inst);
+
+ if (!br_inst)
+ {
+ if (log)
+ log->Printf("getOpcode() returns Br, but instruction is not a BranchInst");
+
+ return false;
+ }
+
+ if (br_inst->isConditional())
+ {
+ Value *condition = br_inst->getCondition();
+
+ lldb_private::Scalar C;
+
+ if (!frame.EvaluateValue(C, condition, llvm_module))
+ {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(condition).c_str());
+
+ return false;
+ }
+
+ if (C.GetRawBits64(0))
+ frame.Jump(br_inst->getSuccessor(0));
+ else
+ frame.Jump(br_inst->getSuccessor(1));
+
+ if (log)
+ {
+ log->Printf("Interpreted a BrInst with a condition");
+ log->Printf(" cond : %s", frame.SummarizeValue(condition).c_str());
+ }
+ }
+ else
+ {
+ frame.Jump(br_inst->getSuccessor(0));
+
+ if (log)
+ {
+ log->Printf("Interpreted a BrInst with no condition");
+ }
+ }
+ }
+ continue;
+ case Instruction::GetElementPtr:
+ {
+ const GetElementPtrInst *gep_inst = dyn_cast<GetElementPtrInst>(inst);
+
+ if (!gep_inst)
+ {
+ if (log)
+ log->Printf("getOpcode() returns GetElementPtr, but instruction is not a GetElementPtrInst");
+
+ return false;
+ }
+
+ const Value *pointer_operand = gep_inst->getPointerOperand();
+ Type *pointer_type = pointer_operand->getType();
+
+ lldb_private::Scalar P;
+
+ if (!frame.EvaluateValue(P, pointer_operand, llvm_module))
+ return false;
+
+ SmallVector <Value *, 8> indices (gep_inst->idx_begin(),
+ gep_inst->idx_end());
+
+ uint64_t offset = target_data.getIndexedOffset(pointer_type, indices);
+
+ lldb_private::Scalar Poffset = P + offset;
+
+ frame.AssignValue(inst, Poffset, llvm_module);
+
+ if (log)
+ {
+ log->Printf("Interpreted a GetElementPtrInst");
+ log->Printf(" P : %s", frame.SummarizeValue(pointer_operand).c_str());
+ log->Printf(" Poffset : %s", frame.SummarizeValue(inst).c_str());
+ }
+ }
+ break;
+ case Instruction::ICmp:
+ {
+ const ICmpInst *icmp_inst = dyn_cast<ICmpInst>(inst);
+
+ if (!icmp_inst)
+ {
+ if (log)
+ log->Printf("getOpcode() returns ICmp, but instruction is not an ICmpInst");
+
+ return false;
+ }
+
+ CmpInst::Predicate predicate = icmp_inst->getPredicate();
+
+ Value *lhs = inst->getOperand(0);
+ Value *rhs = inst->getOperand(1);
+
+ lldb_private::Scalar L;
+ lldb_private::Scalar R;
+
+ if (!frame.EvaluateValue(L, lhs, llvm_module))
+ {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str());
+
+ return false;
+ }
+
+ if (!frame.EvaluateValue(R, rhs, llvm_module))
+ {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str());
+
+ return false;
+ }
+
+ lldb_private::Scalar result;
+
+ switch (predicate)
+ {
+ default:
+ return false;
+ case CmpInst::ICMP_EQ:
+ result = (L == R);
+ break;
+ case CmpInst::ICMP_NE:
+ result = (L != R);
+ break;
+ case CmpInst::ICMP_UGT:
+ result = (L.GetRawBits64(0) > R.GetRawBits64(0));
+ break;
+ case CmpInst::ICMP_UGE:
+ result = (L.GetRawBits64(0) >= R.GetRawBits64(0));
+ break;
+ case CmpInst::ICMP_ULT:
+ result = (L.GetRawBits64(0) < R.GetRawBits64(0));
+ break;
+ case CmpInst::ICMP_ULE:
+ result = (L.GetRawBits64(0) <= R.GetRawBits64(0));
+ break;
+ case CmpInst::ICMP_SGT:
+ result = (L > R);
+ break;
+ case CmpInst::ICMP_SGE:
+ result = (L >= R);
+ break;
+ case CmpInst::ICMP_SLT:
+ result = (L < R);
+ break;
+ case CmpInst::ICMP_SLE:
+ result = (L <= R);
+ break;
+ }
+
+ frame.AssignValue(inst, result, llvm_module);
+
+ if (log)
+ {
+ log->Printf("Interpreted an ICmpInst");
+ log->Printf(" L : %s", frame.SummarizeValue(lhs).c_str());
+ log->Printf(" R : %s", frame.SummarizeValue(rhs).c_str());
+ log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
+ }
+ }
+ break;
+ case Instruction::Load:
+ {
+ const LoadInst *load_inst = dyn_cast<LoadInst>(inst);
+
+ if (!load_inst)
+ {
+ if (log)
+ log->Printf("getOpcode() returns Load, but instruction is not a LoadInst");
+
+ return false;
+ }
+
+ // The semantics of Load are:
+ // Create a region D that will contain the loaded data
+ // Resolve the region P containing a pointer
+ // Dereference P to get the region R that the data should be loaded from
+ // Transfer a unit of type type(D) from R to D
+
+ const Value *pointer_operand = load_inst->getPointerOperand();
+
+ Type *pointer_ty = pointer_operand->getType();
+ PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty);
+ if (!pointer_ptr_ty)
+ return false;
+ Type *target_ty = pointer_ptr_ty->getElementType();
+
+ Memory::Region D = frame.ResolveValue(load_inst, llvm_module);
+ Memory::Region P = frame.ResolveValue(pointer_operand, llvm_module);
+
+ if (D.IsInvalid())
+ {
+ if (log)
+ log->Printf("LoadInst's value doesn't resolve to anything");
+
+ return false;
+ }
+
+ if (P.IsInvalid())
+ {
+ if (log)
+ log->Printf("LoadInst's pointer doesn't resolve to anything");
+
+ return false;
+ }
+
+ DataExtractorSP P_extractor(memory.GetExtractor(P));
+ DataEncoderSP D_encoder(memory.GetEncoder(D));
+
+ uint32_t offset = 0;
+ lldb::addr_t pointer = P_extractor->GetAddress(&offset);
+
+ Memory::Region R = memory.Lookup(pointer, target_ty);
+
+ memory.Read(D_encoder->GetDataStart(), R.m_base, target_data.getTypeStoreSize(target_ty));
+
+ if (log)
+ {
+ log->Printf("Interpreted a LoadInst");
+ log->Printf(" P : %s", frame.SummarizeValue(pointer_operand).c_str());
+ log->Printf(" R : %s", memory.SummarizeRegion(R).c_str());
+ log->Printf(" D : %s", frame.SummarizeValue(load_inst).c_str());
+ }
+ }
+ break;
+ case Instruction::Ret:
+ {
+ if (result_name.IsEmpty())
+ return true;
+
+ GlobalValue *result_value = llvm_module.getNamedValue(result_name.GetCString());
+ return frame.ConstructResult(result, result_value, result_name, result_type, llvm_module);
+ }
+ case Instruction::Store:
+ {
+ const StoreInst *store_inst = dyn_cast<StoreInst>(inst);
+
+ if (!store_inst)
+ {
+ if (log)
+ log->Printf("getOpcode() returns Store, but instruction is not a StoreInst");
+
+ return false;
+ }
+
+ // The semantics of Store are:
+ // Resolve the region D containing the data to be stored
+ // Resolve the region P containing a pointer
+ // Dereference P to get the region R that the data should be stored in
+ // Transfer a unit of type type(D) from D to R
+
+ const Value *value_operand = store_inst->getValueOperand();
+ const Value *pointer_operand = store_inst->getPointerOperand();
+
+ Type *pointer_ty = pointer_operand->getType();
+ PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty);
+ if (!pointer_ptr_ty)
+ return false;
+ Type *target_ty = pointer_ptr_ty->getElementType();
+
+ Memory::Region D = frame.ResolveValue(value_operand, llvm_module);
+ Memory::Region P = frame.ResolveValue(pointer_operand, llvm_module);
+
+ if (D.IsInvalid())
+ {
+ if (log)
+ log->Printf("StoreInst's value doesn't resolve to anything");
+
+ return false;
+ }
+
+ if (P.IsInvalid())
+ {
+ if (log)
+ log->Printf("StoreInst's pointer doesn't resolve to anything");
+
+ return false;
+ }
+
+ DataExtractorSP P_extractor(memory.GetExtractor(P));
+ DataExtractorSP D_extractor(memory.GetExtractor(D));
+
+ if (!P_extractor || !D_extractor)
+ return false;
+
+ uint32_t offset = 0;
+ lldb::addr_t pointer = P_extractor->GetAddress(&offset);
+
+ Memory::Region R = memory.Lookup(pointer, target_ty);
+
+ if (R.IsInvalid())
+ {
+ if (log)
+ log->Printf("StoreInst's pointer doesn't point to a valid target");
+
+ return false;
+ }
+
+ memory.Write(R.m_base, D_extractor->GetDataStart(), target_data.getTypeStoreSize(target_ty));
+
+ if (log)
+ {
+ log->Printf("Interpreted a StoreInst");
+ log->Printf(" D : %s", frame.SummarizeValue(value_operand).c_str());
+ log->Printf(" P : %s", frame.SummarizeValue(pointer_operand).c_str());
+ log->Printf(" R : %s", memory.SummarizeRegion(R).c_str());
+ }
+ }
+ break;
+ }
+
+ ++frame.m_ii;
+ }
+
+ if (num_insts >= 4096)
+ return false;
+
+ return false;
+}
\ No newline at end of file
Removed: lldb/trunk/source/Expression/IRToDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRToDWARF.cpp?rev=139771&view=auto
==============================================================================
--- lldb/trunk/source/Expression/IRToDWARF.cpp (original)
+++ lldb/trunk/source/Expression/IRToDWARF.cpp (removed)
@@ -1,219 +0,0 @@
-//===-- IRToDWARF.cpp -------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Expression/IRToDWARF.h"
-
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/InstrTypes.h"
-#include "llvm/Module.h"
-
-#include "lldb/Core/dwarf.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Core/Scalar.h"
-#include "lldb/Core/StreamString.h"
-#include "lldb/Expression/ClangExpressionDeclMap.h"
-#include "lldb/Expression/ClangExpressionVariable.h"
-
-#include <map>
-
-using namespace llvm;
-
-static char ID;
-
-IRToDWARF::IRToDWARF(lldb_private::ClangExpressionVariableList &local_vars,
- lldb_private::ClangExpressionDeclMap *decl_map,
- lldb_private::StreamString &strm,
- const char *func_name) :
- ModulePass(ID),
- m_func_name(func_name),
- m_local_vars(local_vars),
- m_decl_map(decl_map),
- m_strm(strm)
-{
-}
-
-IRToDWARF::~IRToDWARF()
-{
-}
-
-class Relocator
-{
-public:
- Relocator()
- {
- }
-
- ~Relocator()
- {
- }
-
- void MarkBasicBlock(BasicBlock *bb, uint16_t offset)
- {
- m_basic_blocks[bb] = offset;
- }
-
- bool BasicBlockIsMarked(BasicBlock *bb)
- {
- return m_basic_blocks.find(bb) != m_basic_blocks.end();
- }
-
- void MarkRelocation(BasicBlock *bb, uint16_t offset)
- {
- m_relocations[offset] = bb;
- }
-
- bool ResolveRelocations(lldb_private::StreamString &strm)
- {
- std::map<uint16_t, BasicBlock*>::const_iterator iter;
-
- lldb_private::StreamString swapper(0, 32, strm.GetByteOrder());
-
- // This array must be delete [] d at every exit
- size_t temporary_bufsize = strm.GetSize();
- uint8_t *temporary_buffer(new uint8_t[temporary_bufsize]);
-
- memcpy(temporary_buffer, strm.GetData(), temporary_bufsize);
-
- for (iter = m_relocations.begin();
- iter != m_relocations.end();
- ++iter)
- {
- const std::pair<uint16_t, BasicBlock*> &pair = *iter;
-
- uint16_t off = pair.first;
- BasicBlock *bb = pair.second;
-
- if (m_basic_blocks.find(bb) == m_basic_blocks.end())
- {
- delete [] temporary_buffer;
- return false;
- }
-
- uint16_t target_off = m_basic_blocks[bb];
-
- int16_t relative = (int16_t)target_off - (int16_t)off;
-
- swapper.Clear();
- swapper << relative;
-
- // off is intended to be the offset of the branch opcode (which is
- // what the relative location is added to) so
- // (temporary_buffer + off + 1) skips the opcode and writes to the
- // relative location
- memcpy(temporary_buffer + off + 1, swapper.GetData(), sizeof(uint16_t));
- }
-
- strm.Clear();
- strm.Write(temporary_buffer, temporary_bufsize);
-
- delete [] temporary_buffer;
- return true;
- }
-private:
- std::map<BasicBlock*, uint16_t> m_basic_blocks;
- std::map<uint16_t, BasicBlock*> m_relocations;
-};
-
-bool
-IRToDWARF::runOnBasicBlock(BasicBlock &BB, Relocator &R)
-{
- ///////////////////////////////////////
- // Mark the current block as visited
- //
-
- size_t stream_size = m_strm.GetSize();
-
- if (stream_size > 0xffff)
- return false;
-
- uint16_t offset = stream_size & 0xffff;
-
- R.MarkBasicBlock(&BB, offset);
-
- ////////////////////////////////////////////////
- // Translate the current basic block to DWARF
- //
-
- /////////////////////////////////////////////////
- // Visit all successors we haven't visited yet
- //
-
- TerminatorInst *arnold = BB.getTerminator();
-
- if (!arnold)
- return false;
-
- unsigned successor_index;
- unsigned num_successors = arnold->getNumSuccessors();
-
- for (successor_index = 0;
- successor_index < num_successors;
- ++successor_index)
- {
- BasicBlock *successor = arnold->getSuccessor(successor_index);
-
- if (!R.BasicBlockIsMarked(successor))
- {
- if (!runOnBasicBlock(*successor, R))
- return false;
- }
- }
-
- return true;
-}
-
-bool
-IRToDWARF::runOnModule(Module &M)
-{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- llvm::Function* function = M.getFunction(StringRef(m_func_name.c_str()));
-
- if (!function)
- {
- if (log)
- log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
-
- return false;
- }
-
- Relocator relocator;
-
- if (!runOnBasicBlock(function->getEntryBlock(), relocator))
- return false;
-
- if (log && log->GetVerbose())
- {
- std::string s;
- raw_string_ostream oss(s);
-
- M.print(oss, NULL);
-
- oss.flush();
-
- log->Printf ("Module being translated to DWARF: \n%s", s.c_str());
- }
-
- // TEMPORARY: Fail in order to force execution in the target.
- return false;
-
- return relocator.ResolveRelocations(m_strm);
-}
-
-void
-IRToDWARF::assignPassManager(PMStack &PMS,
- PassManagerType T)
-{
-}
-
-PassManagerType
-IRToDWARF::getPotentialPassManagerType() const
-{
- return PMT_ModulePassManager;
-}
Modified: lldb/trunk/source/Symbol/ClangASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTImporter.cpp?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTImporter.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTImporter.cpp Wed Sep 14 21:13:07 2011
@@ -117,7 +117,8 @@
{
ObjCInterfaceDecl *to_interface_decl = dyn_cast<ObjCInterfaceDecl>(to);
- to_interface_decl->setExternallyCompleted();
+ if (!to_interface_decl->isForwardDecl())
+ to_interface_decl->setExternallyCompleted();
}
return clang::ASTImporter::Imported(from, to);
Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Wed Sep 14 21:13:07 2011
@@ -1154,7 +1154,7 @@
expr.Printf("dlopen (\"%s\", 2)", path);
const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n";
lldb::ValueObjectSP result_valobj_sp;
- ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
+ ClangUserExpression::Evaluate (exe_ctx, eExecutionPolicyAlways, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
error = result_valobj_sp->GetError();
if (error.Success())
{
@@ -1218,7 +1218,7 @@
expr.Printf("dlclose ((void *)0x%llx)", image_addr);
const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
lldb::ValueObjectSP result_valobj_sp;
- ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
+ ClangUserExpression::Evaluate (exe_ctx, eExecutionPolicyAlways, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
if (result_valobj_sp->GetError().Success())
{
Scalar scalar;
Modified: lldb/trunk/source/Target/StopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StopInfo.cpp?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/source/Target/StopInfo.cpp (original)
+++ lldb/trunk/source/Target/StopInfo.cpp Wed Sep 14 21:13:07 2011
@@ -194,11 +194,12 @@
const bool discard_on_error = true;
Error error;
result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx,
- discard_on_error,
- bp_loc_sp->GetConditionText(),
- NULL,
- result_value_sp,
- error);
+ eExecutionPolicyAlways,
+ discard_on_error,
+ bp_loc_sp->GetConditionText(),
+ NULL,
+ result_value_sp,
+ error);
if (result_code == eExecutionCompleted)
{
if (result_value_sp)
Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=139772&r1=139771&r2=139772&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Wed Sep 14 21:13:07 2011
@@ -1133,6 +1133,7 @@
(
const char *expr_cstr,
StackFrame *frame,
+ lldb_private::ExecutionPolicy execution_policy,
bool unwind_on_error,
bool keep_in_memory,
lldb::DynamicValueType use_dynamic,
@@ -1242,8 +1243,9 @@
else
{
const char *prefix = GetExpressionPrefixContentsAsCString();
-
+
execution_results = ClangUserExpression::Evaluate (exe_ctx,
+ execution_policy,
unwind_on_error,
expr_cstr,
prefix,
More information about the lldb-commits
mailing list