[Lldb-commits] [lldb] r112249 - in /lldb/trunk: include/lldb/ include/lldb/Core/ include/lldb/Expression/ lldb.xcodeproj/ source/Commands/ source/Expression/ source/Interpreter/

Sean Callanan scallanan at apple.com
Thu Aug 26 18:01:45 PDT 2010


Author: spyffe
Date: Thu Aug 26 20:01:44 2010
New Revision: 112249

URL: http://llvm.org/viewvc/llvm-project?rev=112249&view=rev
Log:
This is a major refactoring of the expression parser.
The goal is to separate the parser's data from the data
belonging to the parser's clients.  This allows clients
to use the parser to obtain (for example) a JIT compiled
function or some DWARF code, and then discard the parser
state.

Previously, parser state was held in ClangExpression and
used liberally by ClangFunction, which inherited from
ClangExpression.  The main effects of this refactoring 
are:

- reducing ClangExpression to an abstract class that
  declares methods that any client must expose to the
  expression parser,

- moving the code specific to implementing the "expr"
  command from ClangExpression and
  CommandObjectExpression into ClangUserExpression,
  a new class,

- moving the common parser interaction code from
  ClangExpression into ClangExpressionParser, a new
  class, and

- making ClangFunction rely only on
  ClangExpressionParser and not depend on the
  internal implementation of ClangExpression.

Side effects include:

- the compiler interaction code has been factored
  out of ClangFunction and is now in an AST pass
  (ASTStructExtractor),

- the header file for ClangFunction is now fully
  documented,

- several bugs that only popped up when Clang was
  deallocated (which never happened, since the
  lifetime of the compiler was essentially infinite)
  are now fixed, and

- the developer-only "call" command has been
  disabled.

I have tested the expr command and the Objective-C
step-into code, which use ClangUserExpression and
ClangFunction, respectively, and verified that they
work.  Please let me know if you encounter bugs or
poor documentation.

Added:
    lldb/trunk/include/lldb/Expression/ASTResultSynthesizer.h
      - copied, changed from r112086, lldb/trunk/include/lldb/Expression/ClangResultSynthesizer.h
    lldb/trunk/include/lldb/Expression/ASTStructExtractor.h
    lldb/trunk/include/lldb/Expression/ClangExpressionParser.h
    lldb/trunk/include/lldb/Expression/ClangUserExpression.h
    lldb/trunk/source/Expression/ASTResultSynthesizer.cpp
      - copied, changed from r112086, lldb/trunk/source/Expression/ClangResultSynthesizer.cpp
    lldb/trunk/source/Expression/ASTStructExtractor.cpp
    lldb/trunk/source/Expression/ClangExpressionParser.cpp
    lldb/trunk/source/Expression/ClangUserExpression.cpp
      - copied, changed from r111952, lldb/trunk/source/Expression/ClangExpression.cpp
Removed:
    lldb/trunk/include/lldb/Expression/ClangResultSynthesizer.h
    lldb/trunk/source/Expression/ClangExpression.cpp
    lldb/trunk/source/Expression/ClangResultSynthesizer.cpp
Modified:
    lldb/trunk/include/lldb/Core/ClangForward.h
    lldb/trunk/include/lldb/Expression/ClangExpression.h
    lldb/trunk/include/lldb/Expression/ClangFunction.h
    lldb/trunk/include/lldb/Expression/IRForTarget.h
    lldb/trunk/include/lldb/Expression/IRToDWARF.h
    lldb/trunk/include/lldb/Expression/RecordingMemoryManager.h
    lldb/trunk/include/lldb/lldb-forward.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/Commands/CommandObjectCall.cpp
    lldb/trunk/source/Commands/CommandObjectExpression.cpp
    lldb/trunk/source/Expression/ClangFunction.cpp
    lldb/trunk/source/Expression/IRForTarget.cpp
    lldb/trunk/source/Expression/IRToDWARF.cpp
    lldb/trunk/source/Interpreter/CommandInterpreter.cpp

Modified: lldb/trunk/include/lldb/Core/ClangForward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ClangForward.h?rev=112249&r1=112248&r2=112249&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ClangForward.h (original)
+++ lldb/trunk/include/lldb/Core/ClangForward.h Thu Aug 26 20:01:44 2010
@@ -25,6 +25,7 @@
     }
 
     class Action;
+    class ASTConsumer;
     class ASTContext;
     class ASTRecordLayout;
     class AddrLabelExpr;
@@ -52,6 +53,7 @@
     class DiagnosticOptions;
     class EnumDecl;
     class Expr;
+    class ExternalASTSource;
     class ExtVectorElementExpr;
     class FieldDecl;
     class FloatingLiteral;

Copied: lldb/trunk/include/lldb/Expression/ASTResultSynthesizer.h (from r112086, lldb/trunk/include/lldb/Expression/ClangResultSynthesizer.h)
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ASTResultSynthesizer.h?p2=lldb/trunk/include/lldb/Expression/ASTResultSynthesizer.h&p1=lldb/trunk/include/lldb/Expression/ClangResultSynthesizer.h&r1=112086&r2=112249&rev=112249&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangResultSynthesizer.h (original)
+++ lldb/trunk/include/lldb/Expression/ASTResultSynthesizer.h Thu Aug 26 20:01:44 2010
@@ -1,4 +1,4 @@
-//===-- ClangResultSynthesizer.h --------------------------------*- C++ -*-===//
+//===-- ASTResultSynthesizer.h ----------------------------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef liblldb_ClangResultSynthesizer_h_
-#define liblldb_ClangResultSynthesizer_h_
+#ifndef liblldb_ASTResultSynthesizer_h_
+#define liblldb_ASTResultSynthesizer_h_
 
 #include "clang/Sema/SemaConsumer.h"
 #include "lldb/Core/ClangForward.h"
@@ -16,7 +16,7 @@
 namespace lldb_private {
 
 //----------------------------------------------------------------------
-/// @class ClangResultSynthesizer ClangResultSynthesizer.h "lldb/Expression/ClangResultSynthesizer.h"
+/// @class ASTResultSynthesizer ASTResultSynthesizer.h "lldb/Expression/ASTResultSynthesizer.h"
 /// @brief Adds a result variable declaration to the ASTs for an expression.
 ///
 /// Users expect the expression "i + 3" to return a result, even if a result
@@ -24,11 +24,11 @@
 /// a result variable to the expression, transforming it to 
 /// "int ___clang_expr_result = i + 3."  The IR transformers ensure that the
 /// resulting variable is mapped to the right piece of memory.
-/// ClangResultSynthesizer's job is to add the variable and its initialization to
+/// ASTResultSynthesizer's job is to add the variable and its initialization to
 /// the ASTs for the expression, and it does so by acting as a SemaConsumer for
 /// Clang.
 //----------------------------------------------------------------------
-class ClangResultSynthesizer : public clang::SemaConsumer
+class ASTResultSynthesizer : public clang::SemaConsumer
 {
 public:
     //----------------------------------------------------------------------
@@ -40,12 +40,12 @@
     ///     pass to the next step in the chain after processing.  Passthrough is
     ///     the next ASTConsumer, or NULL if none is required.
     //----------------------------------------------------------------------
-    ClangResultSynthesizer(clang::ASTConsumer *passthrough);
+    ASTResultSynthesizer(clang::ASTConsumer *passthrough);
     
     //----------------------------------------------------------------------
     /// Destructor
     //----------------------------------------------------------------------
-    ~ClangResultSynthesizer();
+    ~ASTResultSynthesizer();
     
     //----------------------------------------------------------------------
     /// Link this consumer with a particular AST context

Added: lldb/trunk/include/lldb/Expression/ASTStructExtractor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ASTStructExtractor.h?rev=112249&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Expression/ASTStructExtractor.h (added)
+++ lldb/trunk/include/lldb/Expression/ASTStructExtractor.h Thu Aug 26 20:01:44 2010
@@ -0,0 +1,156 @@
+//===-- ASTStructExtractor.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_ASTStructExtractor_h_
+#define liblldb_ASTStructExtractor_h_
+
+#include "clang/Sema/SemaConsumer.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Expression/ClangExpressionVariable.h"
+#include "lldb/Expression/ClangFunction.h"
+
+namespace lldb_private {
+    
+//----------------------------------------------------------------------
+/// @class ASTStructExtractor ASTStructExtractor.h "lldb/Expression/ASTStructExtractor.h"
+/// @brief Extracts and describes the argument structure for a wrapped function.
+///
+/// This pass integrates with ClangFunction, which calls functions with custom
+/// sets of arguments.  To avoid having to implement the full calling convention
+/// for the target's architecture, ClangFunction writes a simple wrapper
+/// function that takes a pointer to an argument structure that contains room
+/// for the address of the function to be called, the values of all its
+/// arguments, and room for the function's return value.
+///
+/// The definition of this struct is itself in the body of the wrapper function,
+/// so Clang does the structure layout itself.  ASTStructExtractor reads through
+/// the AST for the wrapper funtion and finds the struct.
+//----------------------------------------------------------------------
+class ASTStructExtractor : public clang::SemaConsumer
+{
+public:
+    //----------------------------------------------------------------------
+    /// Constructor
+    ///
+    /// @param[in] passthrough
+    ///     Since the ASTs must typically go through to the Clang code generator
+    ///     in order to produce LLVM IR, this SemaConsumer must allow them to
+    ///     pass to the next step in the chain after processing.  Passthrough is
+    ///     the next ASTConsumer, or NULL if none is required.
+    ///
+    /// @param[in] struct_name
+    ///     The name of the structure to extract from the wrapper function.
+    ///
+    /// @param[in] function
+    ///     The caller object whose members should be populated with information
+    ///     about the argument struct.  ClangFunction friends ASTStructExtractor
+    ///     for this purpose.
+    //----------------------------------------------------------------------
+    ASTStructExtractor(clang::ASTConsumer *passthrough,
+                       const char *struct_name,
+                       ClangFunction &function);
+    
+    //----------------------------------------------------------------------
+    /// Destructor
+    //----------------------------------------------------------------------
+    ~ASTStructExtractor();
+    
+    //----------------------------------------------------------------------
+    /// Link this consumer with a particular AST context
+    ///
+    /// @param[in] Context
+    ///     This AST context will be used for types and identifiers, and also
+    ///     forwarded to the passthrough consumer, if one exists.
+    //----------------------------------------------------------------------
+    void Initialize(clang::ASTContext &Context);
+    
+    //----------------------------------------------------------------------
+    /// Examine a list of Decls to find the function ___clang_expr and 
+    /// transform its code
+    ///
+    /// @param[in] D
+    ///     The list of Decls to search.  These may contain LinkageSpecDecls,
+    ///     which need to be searched recursively.  That job falls to
+    ///     TransformTopLevelDecl.
+    //----------------------------------------------------------------------
+    void HandleTopLevelDecl(clang::DeclGroupRef D);
+    
+    //----------------------------------------------------------------------
+    /// Passthrough stub
+    //----------------------------------------------------------------------
+    void HandleTranslationUnit(clang::ASTContext &Ctx);
+    
+    //----------------------------------------------------------------------
+    /// Passthrough stub
+    //----------------------------------------------------------------------
+    void HandleTagDeclDefinition(clang::TagDecl *D);
+    
+    //----------------------------------------------------------------------
+    /// Passthrough stub
+    //----------------------------------------------------------------------
+    void CompleteTentativeDefinition(clang::VarDecl *D);
+    
+    //----------------------------------------------------------------------
+    /// Passthrough stub
+    //----------------------------------------------------------------------
+    void HandleVTable(clang::CXXRecordDecl *RD, bool DefinitionRequired);
+    
+    //----------------------------------------------------------------------
+    /// Passthrough stub
+    //----------------------------------------------------------------------
+    void PrintStats();
+    
+    //----------------------------------------------------------------------
+    /// Set the Sema object to use when performing transforms, and pass it on
+    ///
+    /// @param[in] S
+    ///     The Sema to use.  Because Sema isn't externally visible, this class
+    ///     casts it to an Action for actual use.
+    //----------------------------------------------------------------------
+    void InitializeSema(clang::Sema &S);
+    
+    //----------------------------------------------------------------------
+    /// Reset the Sema to NULL now that transformations are done
+    //----------------------------------------------------------------------
+    void ForgetSema();
+private:
+    //----------------------------------------------------------------------
+    /// Hunt the given FunctionDecl for the argument struct and place
+    /// information about it into m_function
+    ///
+    /// @param[in] F
+    ///     The FunctionDecl to hunt.
+    //----------------------------------------------------------------------
+    void
+    ExtractFromFunctionDecl(clang::FunctionDecl* F);
+    
+    //----------------------------------------------------------------------
+    /// Hunt the given Decl for FunctionDecls named the same as the wrapper
+    /// function name, recursing as necessary through LinkageSpecDecls, and 
+    /// calling ExtractFromFunctionDecl on anything that was found
+    ///
+    /// @param[in] D
+    ///     The Decl to hunt.
+    //----------------------------------------------------------------------
+    void
+    ExtractFromTopLevelDecl(clang::Decl* D);
+    
+    clang::ASTContext              *m_ast_context;          ///< The AST context to use for identifiers and types.
+    clang::ASTConsumer             *m_passthrough;          ///< The ASTConsumer down the chain, for passthrough.  NULL if it's a SemaConsumer.
+    clang::SemaConsumer            *m_passthrough_sema;     ///< The SemaConsumer down the chain, for passthrough.  NULL if it's an ASTConsumer.
+    clang::Sema                    *m_sema;                 ///< The Sema to use.
+    clang::Action                  *m_action;               ///< The Sema to use, cast to an Action so it's usable.
+    
+    ClangFunction                  &m_function;             ///< The function to populate with information about the argument structure.
+    std::string                     m_struct_name;          ///< The name of the structure to extract.
+};
+    
+}
+
+#endif
\ No newline at end of file

Modified: lldb/trunk/include/lldb/Expression/ClangExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpression.h?rev=112249&r1=112248&r2=112249&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpression.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangExpression.h Thu Aug 26 20:01:44 2010
@@ -25,12 +25,6 @@
 #include "lldb/Core/ClangForward.h"
 #include "llvm/ExecutionEngine/JITMemoryManager.h"
 
-namespace llvm
-{
-    class ExecutionEngine;
-    class StringRef;
-}
-
 namespace lldb_private {
 
 class RecordingMemoryManager;
@@ -48,245 +42,51 @@
 {
 public:
     //------------------------------------------------------------------
-    /// Constructor
-    ///
-    /// Initializes class variabes.
-    ///
-    /// @param[in] target_triple
-    ///     The LLVM-friendly target triple for use in initializing the
-    ///     compiler.
-    ///
-    /// @param[in] expr_decl_map
-    ///     The object that looks up externally-defined names in LLDB's
-    ///     debug information.
-    //------------------------------------------------------------------
-    ClangExpression(const char *target_triple,
-                    ClangExpressionDeclMap *expr_decl_map);
-
-    //------------------------------------------------------------------
-    /// Destructor
+    /// Return the string that the parser should parse.  Must be a full
+    /// translation unit.
     //------------------------------------------------------------------
-    ~ClangExpression();
+    virtual const char *
+    Text () = 0;
     
     //------------------------------------------------------------------
-    /// Parse a single expression and convert it to IR using Clang.  Wrap
-    /// the expression in a function with signature void ___clang_expr(void*).
-    ///
-    /// @param[in] expr_text
-    ///     The text of the expression to be parsed.
-    ///
-    /// @param[in] stream
-    ///     The stream to print errors to.
-    ///
-    /// @param[in] add_result_var
-    ///     True if a special result variable should be generated for
-    ///     the expression.
-    ///
-    /// @return
-    ///     The number of errors encountered during parsing.  0 means
-    ///     success.
-    //------------------------------------------------------------------
-    unsigned
-    ParseExpression (const char *expr_text, 
-                     Stream &stream, 
-                     bool add_result_var = false);
-
-    //------------------------------------------------------------------
-    /// Parse a single expression and convert it to IR using Clang.  Don't
-    /// wrap the expression in anything at all.
-    ///
-    /// @param[in] expr_text
-    ///     The text of the expression to be parsed.
-    ///
-    /// @param[in] stream
-    ///     The stream to print errors to.
-    ///
-    /// @param[in] add_result_var
-    ///     True if a special result variable should be generated for
-    ///     the expression.
-    ///
-    /// @return
-    ///     The number of errors encountered during parsing.  0 means
-    ///     success.
-    //------------------------------------------------------------------
-    unsigned
-    ParseBareExpression (llvm::StringRef expr_text, 
-                         Stream &stream, 
-                         bool add_result_var = false);
-    
+    /// Return the function name that should be used for executing the
+    /// expression.  Text() should contain the definition of this
+    /// function.
     //------------------------------------------------------------------
-    /// Convert the IR for an already-parsed expression to DWARF if possible.
-    ///
-    /// @param[in] expr_local_variable_list
-    ///     The list of local variables the expression uses, with types, for
-    ///     use by the DWARF parser.
-    ///
-    /// @param[in] dwarf_opcode_strm
-    ///     The stream to place the resulting DWARF code into.
-    ///
-    /// @return
-    ///     True on success; false on failure.  On failure, it may be appropriate
-    ///     to call PrepareIRForTarget().
-    //------------------------------------------------------------------
-    bool
-    ConvertIRToDWARF (ClangExpressionVariableList &excpr_local_variable_list,
-                      StreamString &dwarf_opcode_strm);
+    virtual const char *
+    FunctionName () = 0;
     
     //------------------------------------------------------------------
-    /// Prepare the IR for an already-parsed expression for execution in the
-    /// target process by (among other things) making all externally-defined
-    /// variables point to offsets from the void* argument.
-    ///
-    /// @return
-    ///     True on success; false on failure.  On failure, this expression
-    ///     cannot be executed by LLDB.
-    //------------------------------------------------------------------
-    bool
-    PrepareIRForTarget ();
-
-    //------------------------------------------------------------------
-    /// Use the JIT to compile an already-prepared expression from IR into
-    /// machine code, but keep the code in the current process for now.
-    ///
-    /// @param[in] func_name
-    ///     The name of the function to be JITted.  By default, the function
-    ///     wrapped by ParseExpression().
-    ///
-    /// @return
-    ///     True on success; false otherwise.
-    //------------------------------------------------------------------
-    bool
-    JITFunction (const char *func_name = "___clang_expr");
-
+    /// Return the object that the parser should use when resolving external
+    /// values.  May be NULL if everything should be self-contained.
     //------------------------------------------------------------------
-    /// Write the machine code generated by the JIT into the target's memory.
-    ///
-    /// @param[in] exc_context
-    ///     The execution context that the JITted code must be copied into.
-    ///
-    /// @return
-    ///     True on success; false otherwise.
-    //------------------------------------------------------------------
-    bool
-    WriteJITCode (const ExecutionContext &exc_context);
-
-    //------------------------------------------------------------------
-    /// Write the machine code generated by the JIT into the target process.
-    ///
-    /// @param[in] func_name
-    ///     The name of the function whose address is being requested.
-    ///     By default, the function wrapped by ParseExpression().
-    ///
-    /// @return
-    ///     True on success; false otherwise.
-    //------------------------------------------------------------------
-    lldb::addr_t
-    GetFunctionAddress (const char *func_name = "___clang_expr");
+    virtual ClangExpressionDeclMap *
+    DeclMap () = 0;
     
     //------------------------------------------------------------------
-    /// Disassemble the machine code for a JITted function from the target 
-    /// process's memory and print the result to a stream.
-    ///
-    /// @param[in] stream
-    ///     The stream to print disassembly to.
-    ///
-    /// @param[in] exc_context
-    ///     The execution context to get the machine code from.
-    ///
-    /// @param[in] func_name
-    ///     The name of the function to be disassembled.  By default, the
-    ///     function wrapped by ParseExpression().
-    ///
-    /// @return
-    ///     The error generated.  If .Success() is true, disassembly succeeded.
-    //------------------------------------------------------------------
-    Error
-    DisassembleFunction (Stream &stream, ExecutionContext &exc_context, const char *func_name = "___clang_expr");
-
-    //------------------------------------------------------------------
-    /// Return the Clang compiler instance being used by this expression.
+    /// Return the object that the parser should use when registering
+    /// local variables.  May be NULL if the Expression doesn't care.
     //------------------------------------------------------------------
-    clang::CompilerInstance *
-    GetCompilerInstance ()
-    {
-        return m_clang_ap.get();
-    }
-
-    //------------------------------------------------------------------
-    /// Return the AST context being used by this expression.
-    //------------------------------------------------------------------
-    clang::ASTContext *
-    GetASTContext ();
-
-    //------------------------------------------------------------------
-    /// Return the mutex being used to serialize access to Clang.
-    //------------------------------------------------------------------
-    static Mutex &
-    GetClangMutex ();
-protected:
-    //------------------------------------------------------------------
-    // Classes that inherit from ClangExpression can see and modify these
-    //------------------------------------------------------------------
-
-    //----------------------------------------------------------------------
-    /// @class JittedFunction ClangExpression.h "lldb/Expression/ClangExpression.h"
-    /// @brief Encapsulates a single function that has been generated by the JIT.
-    ///
-    /// Functions that have been generated by the JIT are first resident in the
-    /// local process, and then placed in the target process.  JittedFunction
-    /// represents a function possibly resident in both.
-    //----------------------------------------------------------------------
-    struct JittedFunction {
-        std::string m_name;             ///< The function's name
-        lldb::addr_t m_local_addr;      ///< The address of the function in LLDB's memory
-        lldb::addr_t m_remote_addr;     ///< The address of the function in the target's memory
-
-        //------------------------------------------------------------------
-        /// Constructor
-        ///
-        /// Initializes class variabes.
-        ///
-        /// @param[in] name
-        ///     The name of the function.
-        ///
-        /// @param[in] local_addr
-        ///     The address of the function in LLDB, or LLDB_INVALID_ADDRESS if
-        ///     it is not present in LLDB's memory.
-        ///
-        /// @param[in] remote_addr
-        ///     The address of the function in the target, or LLDB_INVALID_ADDRESS
-        ///     if it is not present in the target's memory.
-        //------------------------------------------------------------------
-        JittedFunction (const char *name,
-                        lldb::addr_t local_addr = LLDB_INVALID_ADDRESS,
-                        lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) :
-            m_name (name),
-            m_local_addr (local_addr),
-            m_remote_addr (remote_addr) {}
-    };
-
-    std::string m_target_triple;                                ///< The target triple used to initialize LLVM
-    ClangExpressionDeclMap *m_decl_map;                         ///< The class used to look up entities defined in the debug info
-    std::auto_ptr<clang::CompilerInstance> m_clang_ap;          ///< The Clang compiler used to parse expressions into IR
-    clang::CodeGenerator *m_code_generator_ptr;                 ///< [owned by the Execution Engine] The Clang object that generates IR
-    RecordingMemoryManager *m_jit_mm_ptr;                       ///< [owned by the Execution Engine] The memory manager that allocates code pages on the JIT's behalf
-    std::auto_ptr<llvm::ExecutionEngine> m_execution_engine;    ///< The LLVM JIT
-    std::vector<JittedFunction> m_jitted_functions;             ///< A vector of all functions that have been JITted into machine code (just one, if ParseExpression() was called)
-private:
+    virtual ClangExpressionVariableStore *
+    LocalVariables () = 0;
+    
     //------------------------------------------------------------------
-    /// Initialize m_clang_ap to a compiler instance with all the options
-    /// required by the expression parser.
+    /// Return the object that the parser should allow to access ASTs.
+    /// May be NULL if the ASTs do not need to be transformed.
     ///
-    /// @return
-    ///     True on success; false otherwise.
+    /// @param[in] passthrough
+    ///     The ASTConsumer that the returned transformer should send
+    ///     the ASTs to after transformation.
     //------------------------------------------------------------------
-    bool CreateCompilerInstance();
-        
+    virtual clang::ASTConsumer *
+    ASTTransformer (clang::ASTConsumer *passthrough) = 0;
+    
     //------------------------------------------------------------------
-    // For ClangExpression only
+    /// Return the stream that the parser should use to write DWARF
+    /// opcodes.
     //------------------------------------------------------------------
-    ClangExpression(const ClangExpression&);
-    const ClangExpression& operator=(const ClangExpression&);
+    virtual StreamString &
+    DwarfOpcodeStream () = 0;
 };
 
 } // namespace lldb_private

Added: lldb/trunk/include/lldb/Expression/ClangExpressionParser.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpressionParser.h?rev=112249&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpressionParser.h (added)
+++ lldb/trunk/include/lldb/Expression/ClangExpressionParser.h Thu Aug 26 20:01:44 2010
@@ -0,0 +1,182 @@
+//===-- ClangExpressionParser.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_ClangExpressionParser_h_
+#define liblldb_ClangExpressionParser_h_
+
+#include "lldb/lldb-include.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Core/Error.h"
+
+#include <string>
+#include <vector>
+
+namespace llvm
+{
+    class ExecutionEngine;
+}
+
+namespace lldb_private
+{
+
+class RecordingMemoryManager;
+    
+//----------------------------------------------------------------------
+/// @class ClangExpressionParser ClangExpressionParser.h "lldb/Expression/ClangExpressionParser.h"
+/// @brief Encapsulates an instance of Clang that can parse expressions.
+///
+/// ClangExpressionParser is responsible for preparing an instance of
+/// ClangExpression for execution.  ClangExpressionParser uses ClangExpression
+/// as a glorified parameter list, performing the required parsing and
+/// conversion to formats (DWARF bytecode, or JIT compiled machine code)
+/// that can be executed.
+//----------------------------------------------------------------------
+class ClangExpressionParser
+{
+public:
+    //------------------------------------------------------------------
+    /// Constructor
+    ///
+    /// Initializes class variabes.
+    ///
+    /// @param[in] target_triple
+    ///     The LLVM-friendly target triple for use in initializing the
+    ///     compiler.
+    ///
+    /// @param[in] expr
+    ///     The expression to be parsed.
+    //------------------------------------------------------------------
+    ClangExpressionParser (const char *target_triple,
+                           ClangExpression &expr);
+    
+    //------------------------------------------------------------------
+    /// Destructor
+    //------------------------------------------------------------------
+    ~ClangExpressionParser ();
+    
+    //------------------------------------------------------------------
+    /// Parse a single expression and convert it to IR using Clang.  Don't
+    /// wrap the expression in anything at all.
+    ///
+    /// @param[in] stream
+    ///     The stream to print errors to.
+    ///
+    /// @return
+    ///     The number of errors encountered during parsing.  0 means
+    ///     success.
+    //------------------------------------------------------------------
+    unsigned
+    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.
+    ///
+    /// @param[out] func_addr
+    ///     The address to which the function has been written.
+    ///
+    /// @para[in] exe_ctx
+    ///     The execution context to write the function into.
+    ///
+    /// @return
+    ///     An error code indicating the success or failure of the operation.
+    ///     Test with Success().
+    //------------------------------------------------------------------
+    Error
+    MakeJIT (lldb::addr_t &func_addr, 
+             ExecutionContext &exe_ctx);
+    
+    //------------------------------------------------------------------
+    /// Disassemble the machine code for a JITted function from the target 
+    /// process's memory and print the result to a stream.
+    ///
+    /// @param[in] stream
+    ///     The stream to print disassembly to.
+    ///
+    /// @param[in] exc_context
+    ///     The execution context to get the machine code from.
+    ///
+    /// @param[in] func_name
+    ///     The name of the function to be disassembled.  By default, the
+    ///     function wrapped by ParseExpression().
+    ///
+    /// @return
+    ///     The error generated.  If .Success() is true, disassembly succeeded.
+    //------------------------------------------------------------------
+    Error
+    DisassembleFunction (Stream &stream, ExecutionContext &exc_context);
+    
+private:
+    //----------------------------------------------------------------------
+    /// @class JittedFunction ClangExpressionParser.h "lldb/Expression/ClangExpressionParser.h"
+    /// @brief Encapsulates a single function that has been generated by the JIT.
+    ///
+    /// Functions that have been generated by the JIT are first resident in the
+    /// local process, and then placed in the target process.  JittedFunction
+    /// represents a function possibly resident in both.
+    //----------------------------------------------------------------------
+    struct JittedFunction {
+        std::string m_name;             ///< The function's name
+        lldb::addr_t m_local_addr;      ///< The address of the function in LLDB's memory
+        lldb::addr_t m_remote_addr;     ///< The address of the function in the target's memory
+        
+        //------------------------------------------------------------------
+        /// Constructor
+        ///
+        /// Initializes class variabes.
+        ///
+        /// @param[in] name
+        ///     The name of the function.
+        ///
+        /// @param[in] local_addr
+        ///     The address of the function in LLDB, or LLDB_INVALID_ADDRESS if
+        ///     it is not present in LLDB's memory.
+        ///
+        /// @param[in] remote_addr
+        ///     The address of the function in the target, or LLDB_INVALID_ADDRESS
+        ///     if it is not present in the target's memory.
+        //------------------------------------------------------------------
+        JittedFunction (const char *name,
+                        lldb::addr_t local_addr = LLDB_INVALID_ADDRESS,
+                        lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) :
+            m_name (name),
+            m_local_addr (local_addr),
+            m_remote_addr (remote_addr)
+        {
+        }
+    };
+    
+    ClangExpression                            &m_expr;                 ///< The expression to be parsed
+    
+    std::string                                 m_target_triple;        ///< The target triple used to initialize LLVM
+    std::auto_ptr<clang::TextDiagnosticBuffer>  m_diagnostic_buffer;    ///< The container for errors produced by the compiler
+    std::auto_ptr<clang::CompilerInstance>      m_compiler;             ///< The Clang compiler used to parse expressions into IR
+    std::auto_ptr<clang::Builtin::Context>      m_builtin_context;      ///< Context for Clang built-ins
+    std::auto_ptr<clang::ASTContext>            m_ast_context;          ///< The AST context used to hold types and names for the parser
+    std::auto_ptr<clang::CodeGenerator>         m_code_generator;       ///< [owned by the Execution Engine] The Clang object that generates IR
+    RecordingMemoryManager                     *m_jit_mm;               ///< The memory manager for the LLVM JIT
+    std::auto_ptr<llvm::ExecutionEngine>        m_execution_engine;     ///< The LLVM JIT
+    std::vector<JittedFunction>                 m_jitted_functions;     ///< A vector of all functions that have been JITted into machine code (just one, if ParseExpression() was called)
+};
+    
+}
+
+#endif  // liblldb_ClangExpressionParser_h_

Modified: lldb/trunk/include/lldb/Expression/ClangFunction.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangFunction.h?rev=112249&r1=112248&r2=112249&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangFunction.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangFunction.h Thu Aug 26 20:01:44 2010
@@ -20,7 +20,6 @@
 #include "lldb/Core/Address.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Core/ValueObjectList.h"
-
 #include "lldb/Expression/ClangExpression.h"
 
 // Right now, this is just a toy.  It calls a set function, with fixed
@@ -28,11 +27,47 @@
 
 namespace lldb_private
 {
+    
+class ASTStructExtractor;
+class ClangExpressionParser;
 
-class ClangFunction : private ClangExpression
+//----------------------------------------------------------------------
+/// @class ClangFunction ClangFunction.h "lldb/Expression/ClangFunction.h"
+/// @brief Encapsulates a function that can be called.
+///
+/// A given ClangFunction object can handle a single function signature.
+/// Once constructed, it can set up any number of concurrent calls to
+/// functions with that signature.
+///
+/// It performs the call by synthesizing a structure that contains the pointer
+/// to the function and the arguments that should be passed to that function,
+/// and producing a special-purpose JIT-compiled function that accepts a void*
+/// pointing to this struct as its only argument and calls the function in the 
+/// struct with the written arguments.  This method lets Clang handle the
+/// vagaries of function calling conventions.
+///
+/// The simplest use of the ClangFunction is to construct it with a
+/// function representative of the signature you want to use, then call
+/// ExecuteFunction(ExecutionContext &, Stream &, Value &).
+///
+/// If you need to reuse the arguments for several calls, you can call
+/// InsertFunction() followed by WriteFunctionArguments(), which will return
+/// the location of the args struct for the wrapper function in args_addr_ref.
+///
+/// If you need to call the function on the thread plan stack, you can also 
+/// call InsertFunction() followed by GetThreadPlanToCallFunction().
+///
+/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed
+/// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated
+/// and its address returned in that variable.
+/// 
+/// Any of the methods that take arg_addr_ptr can be passed NULL, and the
+/// argument space will be managed for you.
+//----------------------------------------------------------------------    
+class ClangFunction : public ClangExpression
 {
+    friend class ASTStructExtractor;
 public:
-
     enum ExecutionResults
     {
         eExecutionSetupError,
@@ -43,56 +78,200 @@
     };
         
 	//------------------------------------------------------------------
-	// Constructors and Destructors
+	/// Constructor
+    ///
+    /// @param[in] target_triple
+    ///     The LLVM-style target triple for the target in which the
+    ///     function is to be executed.
+    ///
+    /// @param[in] function_ptr
+    ///     The default function to be called.  Can be overridden using
+    ///     WriteFunctionArguments().
+    ///
+    /// @param[in] ast_context
+    ///     The AST context to evaluate argument types in.
+    ///
+    /// @param[in] arg_value_list
+    ///     The default values to use when calling this function.  Can
+    ///     be overridden using WriteFunctionArguments().
+	//------------------------------------------------------------------  
+	ClangFunction(const char *target_triple, 
+                  Function &function_ptr, 
+                  ClangASTContext *ast_context, 
+                  const ValueList &arg_value_list);
+    
+    //------------------------------------------------------------------
+	/// Constructor
+    ///
+    /// @param[in] target_triple
+    ///     The LLVM-style target triple for the target in which the
+    ///     function is to be executed.
+    ///
+    /// @param[in] ast_context
+    ///     The AST context to evaluate argument types in.
+    ///
+    /// @param[in] return_qualtype
+    ///     An opaque Clang QualType for the function result.  Should be
+    ///     defined in ast_context.
+    ///
+    /// @param[in] function_address
+    ///     The address of the function to call.
+    ///
+    /// @param[in] arg_value_list
+    ///     The default values to use when calling this function.  Can
+    ///     be overridden using WriteFunctionArguments().
 	//------------------------------------------------------------------
-    // Usage Note:
+	ClangFunction(const char *target_triple, 
+                  ClangASTContext *ast_context, 
+                  void *return_qualtype, 
+                  const Address& function_address, 
+                  const ValueList &arg_value_list);
     
-    // A given ClangFunction object can handle any function with a common signature.  It can also be used to
-    // set up any number of concurrent functions calls once it has been constructed.
-    // When you construct it you pass in a particular function, information sufficient to determine the function signature 
-    // and value list.
-    // The simplest use of the ClangFunction is to construct the function, then call ExecuteFunction (context, errors, results). The function
-    // will be called using the initial arguments, and the results determined for you, and all cleanup done.
-    //
-    // However, if you need to use the function caller in Thread Plans, you need to call the function on the plan stack.
-    // In that case, you call GetThreadPlanToCallFunction, args_addr will be the location of the args struct, and after you are
-    // done running this thread plan you can recover the results using FetchFunctionResults passing in the same value.
-    // You are required to call InsertFunction before calling GetThreadPlanToCallFunction.
-    //
-    // You can also reuse the struct if you want, by calling ExecuteFunction but passing in args_addr_ptr primed to this value.
-    //
-    // You can also reuse the ClangFunction for the same signature but different function or argument values by rewriting the
-    // Functions arguments with WriteFunctionArguments, and then calling ExecuteFunction passing in the same args_addr.
-    //
-    // Note, any of the functions below that take arg_addr_ptr, or arg_addr_ref, can be passed a pointer set to LLDB_INVALID_ADDRESS and 
-    // new structure will be allocated and its address returned in that variable.
-    // Any of the functions below that take arg_addr_ptr can be passed NULL, and the argument space will be managed for you.
-    
-	ClangFunction(const char *target_triple, Function &function_ptr, ClangASTContext *ast_context, const ValueList &arg_value_list);
-    // This constructor takes its return type as a Clang QualType opaque pointer, and the ast_context it comes from.
-    // FIXME: We really should be able to easily make a Type from the qualtype, and then just pass that in.
-	ClangFunction(const char *target_triple, ClangASTContext *ast_context, void *return_qualtype, const Address& functionAddress, const ValueList &arg_value_list);
+    //------------------------------------------------------------------
+	/// Destructor
+	//------------------------------------------------------------------
 	virtual ~ClangFunction();
 
+    //------------------------------------------------------------------
+	/// Compile the wrapper function
+    ///
+    /// @param[in] errors
+    ///     The stream to print parser errors to.
+    ///
+    /// @return
+    ///     The number of errors.
+	//------------------------------------------------------------------
     unsigned CompileFunction (Stream &errors);
     
-    // args_addr is a pointer to the address the addr will be filled with.  If the value on 
-    // input is LLDB_INVALID_ADDRESS then a new address will be allocated, and returned in args_addr.
-    // If args_addr is a value already returned from a previous call to InsertFunction, then 
-    // the args structure at that address is overwritten. 
-    // If any other value is returned, then we return false, and do nothing.
-    bool InsertFunction (ExecutionContext &context, lldb::addr_t &args_addr_ref, Stream &errors);
-
-    bool WriteFunctionWrapper (ExecutionContext &exec_ctx, Stream &errors);
+    //------------------------------------------------------------------
+	/// Insert the default function wrapper and its default argument struct  
+    ///
+    /// @param[in] exe_ctx
+    ///     The execution context to insert the function and its arguments
+    ///     into.
+    ///
+    /// @param[in,out] args_addr_ref
+    ///     The address of the structure to write the arguments into.  May
+    ///     be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated
+    ///     and args_addr_ref is pointed to it.
+    ///
+    /// @param[in] errors
+    ///     The stream to write errors to.
+    ///
+    /// @return
+    ///     True on success; false otherwise.
+	//------------------------------------------------------------------
+    bool InsertFunction (ExecutionContext &exe_ctx, 
+                         lldb::addr_t &args_addr_ref, 
+                         Stream &errors);
+
+    //------------------------------------------------------------------
+	/// Insert the default function wrapper (using the JIT)
+    ///
+    /// @param[in] exe_ctx
+    ///     The execution context to insert the function and its arguments
+    ///     into.
+    ///
+    /// @param[in] errors
+    ///     The stream to write errors to.
+    ///
+    /// @return
+    ///     True on success; false otherwise.
+	//------------------------------------------------------------------
+    bool WriteFunctionWrapper (ExecutionContext &exe_ctx, 
+                               Stream &errors);
     
-    // This variant writes down the original function address and values to args_addr.
-    bool WriteFunctionArguments (ExecutionContext &exec_ctx, lldb::addr_t &args_addr_ref, Stream &errors);
+    //------------------------------------------------------------------
+	/// Insert the default function argument struct  
+    ///
+    /// @param[in] exe_ctx
+    ///     The execution context to insert the function and its arguments
+    ///     into.
+    ///
+    /// @param[in,out] args_addr_ref
+    ///     The address of the structure to write the arguments into.  May
+    ///     be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated
+    ///     and args_addr_ref is pointed to it.
+    ///
+    /// @param[in] errors
+    ///     The stream to write errors to.
+    ///
+    /// @return
+    ///     True on success; false otherwise.
+	//------------------------------------------------------------------
+    bool WriteFunctionArguments (ExecutionContext &exe_ctx, 
+                                 lldb::addr_t &args_addr_ref, 
+                                 Stream &errors);
     
-    // This variant writes down function_address and arg_value.
-    bool WriteFunctionArguments (ExecutionContext &exc_context, lldb::addr_t &args_addr_ref, Address function_address, ValueList &arg_values, Stream &errors);
+    //------------------------------------------------------------------
+	/// Insert an argument struct with a non-default function address and
+    /// non-default argument values
+    ///
+    /// @param[in] exe_ctx
+    ///     The execution context to insert the function and its arguments
+    ///     into.
+    ///
+    /// @param[in,out] args_addr_ref
+    ///     The address of the structure to write the arguments into.  May
+    ///     be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated
+    ///     and args_addr_ref is pointed to it.
+    ///
+    /// @param[in] function_address
+    ///     The address of the function to call.
+    ///
+    /// @param[in] arg_values
+    ///     The values of the function's arguments.
+    ///
+    /// @param[in] errors
+    ///     The stream to write errors to.
+    ///
+    /// @return
+    ///     True on success; false otherwise.
+	//------------------------------------------------------------------
+    bool WriteFunctionArguments (ExecutionContext &exe_ctx, 
+                                 lldb::addr_t &args_addr_ref, 
+                                 Address function_address, 
+                                 ValueList &arg_values, 
+                                 Stream &errors);
 
-    // Run a function at a particular address, with a given address passed on the stack.
-    static ExecutionResults ExecuteFunction (ExecutionContext &exe_ctx, lldb::addr_t function_address, lldb::addr_t &void_arg, bool stop_others, bool try_all_threads, uint32_t single_thread_timeout_usec, Stream &errors);
+    //------------------------------------------------------------------
+	/// [Static] Execute a function, passing it a single void* parameter.
+    /// ClangFunction uses this to call the wrapper function.
+    ///
+    /// @param[in] exe_ctx
+    ///     The execution context to insert the function and its arguments
+    ///     into.
+    ///
+    /// @param[in] function_address
+    ///     The address of the function in the target process.
+    ///
+    /// @param[in] void_arg
+    ///     The value of the void* parameter.
+    ///
+    /// @param[in] stop_others
+    ///     True if other threads should pause during execution.
+    ///
+    /// @param[in] try_all_threads
+    ///     If the timeout expires, true if other threads should run.  If
+    ///     the function may try to take locks, this is useful.
+    /// 
+    /// @param[in] single_thread_timeout_usec
+    ///     If stop_others is true, the length of time to wait before
+    ///     concluding that the system is deadlocked.
+    ///
+    /// @param[in] errors
+    ///     The stream to write errors to.
+    ///
+    /// @return
+    ///     Returns one of the ExecutionResults enum indicating function call status.
+	//------------------------------------------------------------------
+    static ExecutionResults ExecuteFunction (ExecutionContext &exe_ctx, 
+                                             lldb::addr_t function_address, 
+                                             lldb::addr_t &void_arg, 
+                                             bool stop_others, 
+                                             bool try_all_threads, 
+                                             uint32_t single_thread_timeout_usec, 
+                                             Stream &errors);
     
     //------------------------------------------------------------------
     /// Run the function this ClangFunction was created with.
@@ -101,7 +280,7 @@
     /// for a fixed timeout period (1000 usec) and if it does not complete,
     /// we halt the process and try with all threads running.
     ///
-    /// @param[in] context
+    /// @param[in] exe_ctx
     ///     The thread & process in which this function will run.
     ///
     /// @param[in] errors
@@ -113,7 +292,9 @@
     /// @return
     ///     Returns one of the ExecutionResults enum indicating function call status.
     //------------------------------------------------------------------
-    ExecutionResults ExecuteFunction(ExecutionContext &context, Stream &errors, Value &results);
+    ExecutionResults ExecuteFunction(ExecutionContext &exe_ctx, 
+                                     Stream &errors, 
+                                     Value &results);
     
     //------------------------------------------------------------------
     /// Run the function this ClangFunction was created with.
@@ -121,7 +302,7 @@
     /// This simple version will run the function obeying the stop_others
     /// argument.  There is no timeout.
     ///
-    /// @param[in] context
+    /// @param[in] exe_ctx
     ///     The thread & process in which this function will run.
     ///
     /// @param[in] errors
@@ -136,7 +317,9 @@
     /// @return
     ///     Returns one of the ExecutionResults enum indicating function call status.
     //------------------------------------------------------------------
-    ExecutionResults ExecuteFunction(ExecutionContext &exc_context, Stream &errors, bool stop_others, Value &results);
+    ExecutionResults ExecuteFunction(ExecutionContext &exe_ctx, 
+                                     Stream &errors, bool stop_others, 
+                                     Value &results);
     
     //------------------------------------------------------------------
     /// Run the function this ClangFunction was created with.
@@ -145,7 +328,7 @@
     /// is not zero, we time out after that timeout.  If \a try_all_threads is true, then we will
     /// resume with all threads on, otherwise we halt the process, and eExecutionInterrupted will be returned.
     ///
-    /// @param[in] context
+    /// @param[in] exe_ctx
     ///     The thread & process in which this function will run.
     ///
     /// @param[in] errors
@@ -163,14 +346,18 @@
     /// @return
     ///     Returns one of the ExecutionResults enum indicating function call status.
     //------------------------------------------------------------------
-    ExecutionResults ExecuteFunction(ExecutionContext &context, Stream &errors, uint32_t single_thread_timeout_usec, bool try_all_threads, Value &results);
+    ExecutionResults ExecuteFunction(ExecutionContext &exe_ctx, 
+                                     Stream &errors, 
+                                     uint32_t single_thread_timeout_usec, 
+                                     bool try_all_threads, 
+                                     Value &results);
     
     //------------------------------------------------------------------
     /// Run the function this ClangFunction was created with.
     ///
     /// This is the full version.
     ///
-    /// @param[in] context
+    /// @param[in] exe_ctx
     ///     The thread & process in which this function will run.
     ///
     /// @param[in] args_addr_ptr
@@ -198,48 +385,220 @@
     /// @return
     ///     Returns one of the ExecutionResults enum indicating function call status.
     //------------------------------------------------------------------
-    ExecutionResults ExecuteFunction(ExecutionContext &context, lldb::addr_t *args_addr_ptr, Stream &errors, bool stop_others, uint32_t single_thread_timeout_usec, bool try_all_threads, Value &results);
-    ExecutionResults ExecuteFunctionWithABI(ExecutionContext &context, Stream &errors, Value &results);
-
+    ExecutionResults ExecuteFunction(ExecutionContext &exe_ctx, 
+                                     lldb::addr_t *args_addr_ptr, 
+                                     Stream &errors, 
+                                     bool stop_others, 
+                                     uint32_t single_thread_timeout_usec,
+                                     bool try_all_threads, 
+                                     Value &results);
+    
+    //------------------------------------------------------------------
+    /// [static] Get a thread plan to run a function.
+    ///
+    /// @param[in] exe_ctx
+    ///     The execution context to insert the function and its arguments
+    ///     into.
+    ///
+    /// @param[in] func_addr
+    ///     The address of the function in the target process.
+    ///
+    /// @param[in] args_addr_ref
+    ///     The value of the void* parameter.
+    ///
+    /// @param[in] errors
+    ///     The stream to write errors to.
+    ///
+    /// @param[in] stop_others
+    ///     True if other threads should pause during execution.
+    ///
+    /// @param[in] discard_on_error
+    ///     True if the thread plan may simply be discarded if an error occurs.
+    ///
+    /// @return
+    ///     A ThreadPlan for executing the function.
+	//------------------------------------------------------------------
     static ThreadPlan *
-    GetThreadPlanToCallFunction (ExecutionContext &exc_context, lldb::addr_t func_addr, lldb::addr_t &args_addr_ref, Stream &errors, bool stop_others, bool discard_on_error = true);
+    GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, 
+                                 lldb::addr_t func_addr, 
+                                 lldb::addr_t &args_addr_ref, 
+                                 Stream &errors, 
+                                 bool stop_others, 
+                                 bool discard_on_error = true);
     
+    //------------------------------------------------------------------
+    /// Get a thread plan to run the function this ClangFunction was created with.
+    ///
+    /// @param[in] exe_ctx
+    ///     The execution context to insert the function and its arguments
+    ///     into.
+    ///
+    /// @param[in] func_addr
+    ///     The address of the function in the target process.
+    ///
+    /// @param[in] args_addr_ref
+    ///     The value of the void* parameter.
+    ///
+    /// @param[in] errors
+    ///     The stream to write errors to.
+    ///
+    /// @param[in] stop_others
+    ///     True if other threads should pause during execution.
+    ///
+    /// @param[in] discard_on_error
+    ///     True if the thread plan may simply be discarded if an error occurs.
+    ///
+    /// @return
+    ///     A ThreadPlan for executing the function.
+	//------------------------------------------------------------------
     ThreadPlan *
-    GetThreadPlanToCallFunction (ExecutionContext &exc_context, lldb::addr_t &args_addr_ref, Stream &errors, bool stop_others, bool discard_on_error = true)
+    GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, 
+                                 lldb::addr_t &args_addr_ref, 
+                                 Stream &errors, 
+                                 bool stop_others, 
+                                 bool discard_on_error = true)
     {
-        return ClangFunction::GetThreadPlanToCallFunction (exc_context, m_wrapper_function_addr, args_addr_ref, errors, stop_others, discard_on_error);
+        return ClangFunction::GetThreadPlanToCallFunction (exe_ctx, 
+                                                           m_wrapper_function_addr, 
+                                                           args_addr_ref, 
+                                                           errors, 
+                                                           stop_others, 
+                                                           discard_on_error);
     }
-    bool FetchFunctionResults (ExecutionContext &exc_context, lldb::addr_t args_addr, Value &ret_value);
-    void DeallocateFunctionResults (ExecutionContext &exc_context, lldb::addr_t args_addr);
-        
-protected:
+    
+    //------------------------------------------------------------------
+    /// Get the result of the function from its struct
+    ///
+    /// @param[in] exe_ctx
+    ///     The execution context to retrieve the result from.
+    ///
+    /// @param[in] args_addr
+    ///     The address of the argument struct.
+    ///
+    /// @param[in] ret_value
+    ///     The value returned by the function.
+    ///
+    /// @return
+    ///     True on success; false otherwise.
+	//------------------------------------------------------------------
+    bool FetchFunctionResults (ExecutionContext &exe_ctx, 
+                               lldb::addr_t args_addr, 
+                               Value &ret_value);
+    
     //------------------------------------------------------------------
-    // Classes that inherit from ClangFunction can see and modify these
+    /// Deallocate the arguments structure
+    ///
+    /// @param[in] exe_ctx
+    ///     The execution context to insert the function and its arguments
+    ///     into.
+    ///
+    /// @param[in] args_addr
+    ///     The address of the argument struct.
+	//------------------------------------------------------------------
+    void DeallocateFunctionResults (ExecutionContext &exe_ctx, 
+                                    lldb::addr_t args_addr);
+    
     //------------------------------------------------------------------
-
+    /// Interface for ClangExpression
+    //------------------------------------------------------------------
+    
+    //------------------------------------------------------------------
+    /// Return the string that the parser should parse.  Must be a full
+    /// translation unit.
+    //------------------------------------------------------------------
+    const char *
+    Text ()
+    {
+        return m_wrapper_function_text.c_str();
+    }
+    
+    //------------------------------------------------------------------
+    /// Return the function name that should be used for executing the
+    /// expression.  Text() should contain the definition of this
+    /// function.
+    //------------------------------------------------------------------
+    const char *
+    FunctionName ()
+    {
+        return m_wrapper_function_name.c_str();
+    }
+    
+    //------------------------------------------------------------------
+    /// Return the object that the parser should use when resolving external
+    /// values.  May be NULL if everything should be self-contained.
+    //------------------------------------------------------------------
+    ClangExpressionDeclMap *
+    DeclMap ()
+    {
+        return NULL;
+    }
+    
+    //------------------------------------------------------------------
+    /// Return the object that the parser should use when registering
+    /// local variables.  May be NULL if the Expression doesn't care.
+    //------------------------------------------------------------------
+    ClangExpressionVariableStore *
+    LocalVariables ()
+    {
+        return NULL;
+    }
+    
+    //------------------------------------------------------------------
+    /// Return the object that the parser should allow to access ASTs.
+    /// May be NULL if the ASTs do not need to be transformed.
+    ///
+    /// @param[in] passthrough
+    ///     The ASTConsumer that the returned transformer should send
+    ///     the ASTs to after transformation.
+    //------------------------------------------------------------------
+    clang::ASTConsumer *
+    ASTTransformer (clang::ASTConsumer *passthrough);
+    
+    //------------------------------------------------------------------
+    /// Return the stream that the parser should use to write DWARF
+    /// opcodes.
+    //------------------------------------------------------------------
+    StreamString &
+    DwarfOpcodeStream ()
+    {
+        return *((StreamString*)0);
+    }
+    
 private:
 	//------------------------------------------------------------------
 	// For ClangFunction only
 	//------------------------------------------------------------------
+
+    std::auto_ptr<ClangExpressionParser>    m_parser;               ///< The parser responsible for compiling the function.
+    
+    Function                       *m_function_ptr;                 ///< The function we're going to call.  May be NULL if we don't have debug info for the function.
+    Address                         m_function_addr;                ///< If we don't have the FunctionSP, we at least need the address & return type.
+    void                           *m_function_return_qual_type;    ///< The opaque clang qual type for the function return type.
+    ClangASTContext                *m_clang_ast_context;            ///< This is the clang_ast_context that we're getting types from the and value, and the function return the function pointer is NULL.
+    std::string                     m_target_triple;                ///< The target triple to compile the wrapper function for.
+
+    std::string                     m_wrapper_function_name;        ///< The name of the wrapper function.
+    std::string                     m_wrapper_function_text;        ///< The contents of the wrapper function.
+    std::string                     m_wrapper_struct_name;          ///< The name of the struct that contains the target function address, arguments, and result.
+    lldb::addr_t                    m_wrapper_function_addr;        ///< The address of the wrapper function.
+    std::list<lldb::addr_t>         m_wrapper_args_addrs;           ///< The addresses of the arguments to the wrapper function.
     
-   Function *m_function_ptr; // The function we're going to call.  May be NULL if we don't have debug info for the function.
-   Address    m_function_addr; // If we don't have the FunctionSP, we at least need the address & return type.
-   void *m_function_return_qual_type;  // The opaque clang qual type for the function return type.
-   ClangASTContext *m_clang_ast_context;  // This is the clang_ast_context that we're getting types from the and value, and the function return the function pointer is NULL.
-
-   std::string m_wrapper_function_name;
-   std::string m_wrapper_struct_name;
-   lldb::addr_t m_wrapper_function_addr;
-   std::list<lldb::addr_t> m_wrapper_args_addrs;
-   const clang::ASTRecordLayout *m_struct_layout;
-   ValueList m_arg_values;
-   
-   size_t m_value_struct_size;
-   size_t m_return_offset;
-   uint64_t m_return_size;  // Not strictly necessary, could get it from the Function...
-   bool m_compiled;
-   bool m_JITted;
+    bool                            m_struct_valid;                 ///< True if the ASTStructExtractor has populated the variables below.
+    
+	//------------------------------------------------------------------
+	/// These values are populated by the ASTStructExtractor
+    size_t                          m_struct_size;                  ///< The size of the argument struct, in bytes.
+    std::vector<uint64_t>           m_member_offsets;               ///< The offset of each member in the struct, in bytes.
+    uint64_t                        m_return_size;                  ///< The size of the result variable, in bytes.
+    uint64_t                        m_return_offset;                ///< The offset of the result variable in the struct, in bytes.
+    //------------------------------------------------------------------
+
+    ValueList                       m_arg_values;                   ///< The default values of the arguments.
+    
+    bool                            m_compiled;                     ///< True if the wrapper function has already been parsed.
+    bool                            m_JITted;                       ///< True if the wrapper function has already been JIT-compiled.
 };
 
 } // Namespace lldb_private
+
 #endif  // lldb_ClangFunction_h_

Removed: lldb/trunk/include/lldb/Expression/ClangResultSynthesizer.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangResultSynthesizer.h?rev=112248&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangResultSynthesizer.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangResultSynthesizer.h (removed)
@@ -1,136 +0,0 @@
-//===-- ClangResultSynthesizer.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_ClangResultSynthesizer_h_
-#define liblldb_ClangResultSynthesizer_h_
-
-#include "clang/Sema/SemaConsumer.h"
-#include "lldb/Core/ClangForward.h"
-
-namespace lldb_private {
-
-//----------------------------------------------------------------------
-/// @class ClangResultSynthesizer ClangResultSynthesizer.h "lldb/Expression/ClangResultSynthesizer.h"
-/// @brief Adds a result variable declaration to the ASTs for an expression.
-///
-/// Users expect the expression "i + 3" to return a result, even if a result
-/// variable wasn't specifically declared.  To fulfil this requirement, LLDB adds
-/// a result variable to the expression, transforming it to 
-/// "int ___clang_expr_result = i + 3."  The IR transformers ensure that the
-/// resulting variable is mapped to the right piece of memory.
-/// ClangResultSynthesizer's job is to add the variable and its initialization to
-/// the ASTs for the expression, and it does so by acting as a SemaConsumer for
-/// Clang.
-//----------------------------------------------------------------------
-class ClangResultSynthesizer : public clang::SemaConsumer
-{
-public:
-    //----------------------------------------------------------------------
-    /// Constructor
-    ///
-    /// @param[in] passthrough
-    ///     Since the ASTs must typically go through to the Clang code generator
-    ///     in order to produce LLVM IR, this SemaConsumer must allow them to
-    ///     pass to the next step in the chain after processing.  Passthrough is
-    ///     the next ASTConsumer, or NULL if none is required.
-    //----------------------------------------------------------------------
-    ClangResultSynthesizer(clang::ASTConsumer *passthrough);
-    
-    //----------------------------------------------------------------------
-    /// Destructor
-    //----------------------------------------------------------------------
-    ~ClangResultSynthesizer();
-    
-    //----------------------------------------------------------------------
-    /// Link this consumer with a particular AST context
-    ///
-    /// @param[in] Context
-    ///     This AST context will be used for types and identifiers, and also
-    ///     forwarded to the passthrough consumer, if one exists.
-    //----------------------------------------------------------------------
-    void Initialize(clang::ASTContext &Context);
-    
-    //----------------------------------------------------------------------
-    /// Examine a list of Decls to find the function ___clang_expr and 
-    /// transform its code
-    ///
-    /// @param[in] D
-    ///     The list of Decls to search.  These may contain LinkageSpecDecls,
-    ///     which need to be searched recursively.  That job falls to
-    ///     TransformTopLevelDecl.
-    //----------------------------------------------------------------------
-    void HandleTopLevelDecl(clang::DeclGroupRef D);
-    
-    //----------------------------------------------------------------------
-    /// Passthrough stub
-    //----------------------------------------------------------------------
-    void HandleTranslationUnit(clang::ASTContext &Ctx);
-    
-    //----------------------------------------------------------------------
-    /// Passthrough stub
-    //----------------------------------------------------------------------
-    void HandleTagDeclDefinition(clang::TagDecl *D);
-    
-    //----------------------------------------------------------------------
-    /// Passthrough stub
-    //----------------------------------------------------------------------
-    void CompleteTentativeDefinition(clang::VarDecl *D);
-    
-    //----------------------------------------------------------------------
-    /// Passthrough stub
-    //----------------------------------------------------------------------
-    void HandleVTable(clang::CXXRecordDecl *RD, bool DefinitionRequired);
-    
-    //----------------------------------------------------------------------
-    /// Passthrough stub
-    //----------------------------------------------------------------------
-    void PrintStats();
-    
-    //----------------------------------------------------------------------
-    /// Set the Sema object to use when performing transforms, and pass it on
-    ///
-    /// @param[in] S
-    ///     The Sema to use.  Because Sema isn't externally visible, this class
-    ///     casts it to an Action for actual use.
-    //----------------------------------------------------------------------
-    void InitializeSema(clang::Sema &S);
-    
-    //----------------------------------------------------------------------
-    /// Reset the Sema to NULL now that transformations are done
-    //----------------------------------------------------------------------
-    void ForgetSema();
-private:
-    //----------------------------------------------------------------------
-    /// Hunt the given Decl for FunctionDecls named ___clang_expr, recursing
-    /// as necessary through LinkageSpecDecls, and calling SynthesizeResult on
-    /// anything that was found
-    ///
-    /// @param[in] D
-    ///     The Decl to hunt.
-    //----------------------------------------------------------------------
-    void TransformTopLevelDecl(clang::Decl *D);
-    
-    //----------------------------------------------------------------------
-    /// Process a function and produce the result variable and initialization
-    ///
-    /// @param[in] FunDecl
-    ///     The function to process.
-    //----------------------------------------------------------------------
-    bool SynthesizeResult(clang::FunctionDecl *FunDecl);
-    
-    clang::ASTContext *m_ast_context;           ///< The AST context to use for identifiers and types.
-    clang::ASTConsumer *m_passthrough;          ///< The ASTConsumer down the chain, for passthrough.  NULL if it's a SemaConsumer.
-    clang::SemaConsumer *m_passthrough_sema;    ///< The SemaConsumer down the chain, for passthrough.  NULL if it's an ASTConsumer.
-    clang::Sema *m_sema;                        ///< The Sema to use.
-    clang::Action *m_action;                    ///< The Sema to use, cast to an Action so it's usable.
-};
-
-}
-
-#endif
\ No newline at end of file

Added: lldb/trunk/include/lldb/Expression/ClangUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangUserExpression.h?rev=112249&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangUserExpression.h (added)
+++ lldb/trunk/include/lldb/Expression/ClangUserExpression.h Thu Aug 26 20:01:44 2010
@@ -0,0 +1,160 @@
+//===-- ClangUserExpression.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_ClangUserExpression_h_
+#define liblldb_ClangUserExpression_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <map>
+#include <memory>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Expression/ClangExpression.h"
+
+#include "llvm/ExecutionEngine/JITMemoryManager.h"
+
+namespace lldb_private 
+{
+
+//----------------------------------------------------------------------
+/// @class ClangUserExpression ClangUserExpression.h "lldb/Expression/ClangUserExpression.h"
+/// @brief Encapsulates a single expression for use with Clang
+///
+/// LLDB uses expressions for various purposes, notably to call functions
+/// and as a backend for the expr command.  ClangUserExpression encapsulates
+/// the objects needed to parse and interpret or JIT an expression.  It
+/// uses the Clang parser to produce LLVM IR from the expression.
+//----------------------------------------------------------------------
+class ClangUserExpression : public ClangExpression
+{
+public:
+    //------------------------------------------------------------------
+    /// Constructor
+    //------------------------------------------------------------------
+    ClangUserExpression (const char *expr);
+    
+    //------------------------------------------------------------------
+    /// Parse the expression
+    ///
+    /// @param[in] error_stream
+    ///     A stream to print parse errors and warnings to.
+    ///
+    /// @param[in] exe_ctx
+    ///     The execution context to use when looking up entities that
+    ///     are needed for parsing (locations of functions, types of
+    ///     variables, persistent variables, etc.)
+    ///
+    /// @return
+    ///     True on success (no errors); false otherwise.
+    //------------------------------------------------------------------
+    bool
+    Parse (Stream &error_stream, ExecutionContext &exe_ctx);
+    
+    //------------------------------------------------------------------
+    /// Execute the parsed expression
+    ///
+    /// @param[in] error_stream
+    ///     A stream to print errors to.
+    ///
+    /// @param[in] exe_ctx
+    ///     The execution context to use when looking up entities that
+    ///     are needed for parsing (locations of variables, etc.)
+    ///
+    /// @param[in] result
+    ///     A pointer to direct at the persistent variable in which the
+    ///     expression's result is stored.
+    ///
+    /// @return
+    ///     True on success; false otherwise.
+    //------------------------------------------------------------------
+    bool
+    Execute (Stream &error_stream,
+             ExecutionContext &exe_ctx,
+             ClangExpressionVariable *& result);
+    
+    //------------------------------------------------------------------
+    /// Return the string that the parser should parse.  Must be a full
+    /// translation unit.
+    //------------------------------------------------------------------
+    const char *
+    Text ()
+    {
+        return m_transformed_text.c_str();
+    }
+    
+    //------------------------------------------------------------------
+    /// Return the function name that should be used for executing the
+    /// expression.  Text() should contain the definition of this
+    /// function.
+    //------------------------------------------------------------------
+    const char *
+    FunctionName ()
+    {
+        return "___clang_expr";
+    }
+    
+    //------------------------------------------------------------------
+    /// Return the object that the parser should use when resolving external
+    /// values.  May be NULL if everything should be self-contained.
+    //------------------------------------------------------------------
+    ClangExpressionDeclMap *
+    DeclMap ()
+    {
+        return m_expr_decl_map.get();
+    }
+    
+    //------------------------------------------------------------------
+    /// Return the object that the parser should use when registering
+    /// local variables.  May be NULL if the Expression doesn't care.
+    //------------------------------------------------------------------
+    ClangExpressionVariableStore *
+    LocalVariables ()
+    {
+        return m_local_variables.get();
+    }
+    
+    //------------------------------------------------------------------
+    /// Return the object that the parser should allow to access ASTs.
+    /// May be NULL if the ASTs do not need to be transformed.
+    ///
+    /// @param[in] passthrough
+    ///     The ASTConsumer that the returned transformer should send
+    ///     the ASTs to after transformation.
+    //------------------------------------------------------------------
+    clang::ASTConsumer *
+    ASTTransformer (clang::ASTConsumer *passthrough);
+    
+    //------------------------------------------------------------------
+    /// Return the stream that the parser should use to write DWARF
+    /// opcodes.
+    //------------------------------------------------------------------
+    StreamString &
+    DwarfOpcodeStream ();
+
+private:
+    std::string                                 m_expr_text;            ///< The text of the expression, as typed by the user
+    std::string                                 m_transformed_text;     ///< The text of the expression, as send to the parser
+    
+    std::auto_ptr<ClangExpressionDeclMap>       m_expr_decl_map;        ///< The map to use when parsing and materializing the expression.
+    std::auto_ptr<ClangExpressionVariableStore> 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.
+    lldb::addr_t                                m_jit_addr;             ///< The address of the JITted code.  LLDB_INVALID_ADDRESS if invalid.
+};
+    
+} // namespace lldb_private
+
+#endif  // liblldb_ClangUserExpression_h_

Modified: lldb/trunk/include/lldb/Expression/IRForTarget.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/IRForTarget.h?rev=112249&r1=112248&r2=112249&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/IRForTarget.h (original)
+++ lldb/trunk/include/lldb/Expression/IRForTarget.h Thu Aug 26 20:01:44 2010
@@ -60,9 +60,13 @@
     ///     The data layout information for the target.  This information is
     ///     used to determine the sizes of types that have been lowered into
     ///     IR types.
+    ///
+    /// @param[in] func_name
+    ///     The name of the function to prepare for execution in the target.
     //------------------------------------------------------------------
     IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map,
-                const llvm::TargetData *target_data);
+                const llvm::TargetData *target_data,
+                const char* func_name = "___clang_expr");
     
     //------------------------------------------------------------------
     /// Destructor
@@ -96,7 +100,7 @@
     //------------------------------------------------------------------
     /// A function-level pass to take the generated global value
     /// ___clang_expr_result and make it into a persistent variable.
-    /// Also see ClangResultSynthesizer.
+    /// Also see ASTResultSynthesizer.
     //------------------------------------------------------------------
 
     //------------------------------------------------------------------
@@ -294,6 +298,7 @@
     bool replaceVariables(llvm::Module &M,
                           llvm::Function &F);
     
+    std::string m_func_name;                            ///< The name of the function to translate
     lldb_private::ClangExpressionDeclMap *m_decl_map;   ///< The DeclMap containing the Decls 
     const llvm::TargetData *m_target_data;              ///< The TargetData for use in determining type sizes
     llvm::Constant *m_sel_registerName;                 ///< The address of the function sel_registerName, cast to the appropriate function pointer type

Modified: lldb/trunk/include/lldb/Expression/IRToDWARF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/IRToDWARF.h?rev=112249&r1=112248&r2=112249&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/IRToDWARF.h (original)
+++ lldb/trunk/include/lldb/Expression/IRToDWARF.h Thu Aug 26 20:01:44 2010
@@ -19,7 +19,7 @@
 }
 
 namespace lldb_private {
-    class ClangExpressionVariableList;
+    class ClangExpressionVariableStore;
     class ClangExpressionDeclMap;
     class StreamString;
 }
@@ -50,7 +50,7 @@
     //------------------------------------------------------------------
     /// Constructor
     ///
-    /// @param[in] variable_list
+    /// @param[in] local_vars
     ///     A list of variables to populate with the local variables this
     ///     expression uses.
     ///
@@ -60,10 +60,14 @@
     ///
     /// @param[in] stream
     ///     The stream to dump DWARF bytecode onto.
+    ///
+    /// @param[in] func_name
+    ///     The name of the function to translate to DWARF.
     //------------------------------------------------------------------
-    IRToDWARF(lldb_private::ClangExpressionVariableList &variable_list, 
+    IRToDWARF(lldb_private::ClangExpressionVariableStore &local_vars, 
               lldb_private::ClangExpressionDeclMap *decl_map,
-              lldb_private::StreamString &strm);
+              lldb_private::StreamString &strm,
+              const char* func_name = "___clang_expr");
     
     //------------------------------------------------------------------
     /// Destructor
@@ -108,7 +112,8 @@
     //------------------------------------------------------------------
     bool runOnBasicBlock(llvm::BasicBlock &BB, Relocator &Relocator);
     
-    lldb_private::ClangExpressionVariableList &m_variable_list; ///< The list of local variables to populate while transforming
+    std::string m_func_name;                                    ///< The name of the function to translate
+    lldb_private::ClangExpressionVariableStore &m_local_vars;   ///< The list of local variables to populate while transforming
     lldb_private::ClangExpressionDeclMap *m_decl_map;           ///< The list of external variables
     lldb_private::StreamString &m_strm;                         ///< The stream to write bytecode to
 };

Modified: lldb/trunk/include/lldb/Expression/RecordingMemoryManager.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/RecordingMemoryManager.h?rev=112249&r1=112248&r2=112249&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/RecordingMemoryManager.h (original)
+++ lldb/trunk/include/lldb/Expression/RecordingMemoryManager.h Thu Aug 26 20:01:44 2010
@@ -24,6 +24,7 @@
 #include "lldb/Core/Log.h"
 #include "llvm/ExecutionEngine/JITMemoryManager.h"
 #include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangExpressionParser.h"
 
 namespace lldb_private {
 
@@ -51,7 +52,7 @@
 //----------------------------------------------------------------------
 class RecordingMemoryManager : public llvm::JITMemoryManager
 {
-friend bool ClangExpression::WriteJITCode (const ExecutionContext &exc_context);
+friend Error ClangExpressionParser::MakeJIT (uint64_t &, ExecutionContext &);
 
 public:
     //------------------------------------------------------------------

Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=112249&r1=112248&r2=112249&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Thu Aug 26 20:01:44 2010
@@ -41,6 +41,7 @@
 class   ClangExpression;
 class   ClangExpressionDeclMap;
 class   ClangExpressionVariableList;
+class   ClangExpressionVariableStore;
 class   Debugger;
 class   CommandInterpreter;
 class   CommandObject;

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=112249&r1=112248&r2=112249&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Thu Aug 26 20:01:44 2010
@@ -152,7 +152,7 @@
 		26D5B0BA11B07550009A862E /* ValueObjectList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9C10F1B85900F91463 /* ValueObjectList.cpp */; };
 		26D5B0BB11B07550009A862E /* ValueObjectVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9D10F1B85900F91463 /* ValueObjectVariable.cpp */; };
 		26D5B0BC11B07550009A862E /* VMRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9E10F1B85900F91463 /* VMRange.cpp */; };
-		26D5B0BD11B07550009A862E /* ClangExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7ED510F1B86700F91463 /* ClangExpression.cpp */; };
+		26D5B0BD11B07550009A862E /* ClangUserExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7ED510F1B86700F91463 /* ClangUserExpression.cpp */; };
 		26D5B0BE11B07550009A862E /* ClangExpressionVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7ED610F1B86700F91463 /* ClangExpressionVariable.cpp */; };
 		26D5B0C111B07550009A862E /* Condition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7EE710F1B88F00F91463 /* Condition.cpp */; };
 		26D5B0C211B07550009A862E /* Host.mm in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7EE810F1B88F00F91463 /* Host.mm */; };
@@ -287,7 +287,6 @@
 		26D5B14711B07550009A862E /* ThreadPlanCallFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49EC3E98118F90AC00B1265E /* ThreadPlanCallFunction.cpp */; };
 		26D5B14811B07550009A862E /* ClangFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C98D3DA118FB96F00E575D0 /* ClangFunction.cpp */; };
 		26D5B14911B07550009A862E /* RecordingMemoryManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C98D3DB118FB96F00E575D0 /* RecordingMemoryManager.cpp */; settings = {COMPILER_FLAGS = "-fno-rtti"; }; };
-		26D5B14A11B07550009A862E /* CommandObjectCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C98D3E4118FB9B100E575D0 /* CommandObjectCall.cpp */; };
 		26D5B14B11B07550009A862E /* CommandObjectTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 269416AD119A024800FF2715 /* CommandObjectTarget.cpp */; };
 		26D5B14C11B07550009A862E /* PathMappingList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 495BBACB119A0DBE00418BEA /* PathMappingList.cpp */; };
 		26D5B14D11B07550009A862E /* StringExtractorGDBRemote.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2676A093119C93C8008A98EF /* StringExtractorGDBRemote.cpp */; };
@@ -330,10 +329,15 @@
 		26F5C32D10F3DFDD009D5894 /* libtermcap.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32B10F3DFDD009D5894 /* libtermcap.dylib */; };
 		26F5C37510F3F61B009D5894 /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C37410F3F61B009D5894 /* libobjc.dylib */; };
 		26F5C39110F3FA26009D5894 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C39010F3FA26009D5894 /* CoreFoundation.framework */; };
+		4911934C1226383D00578B7F /* ASTStructExtractor.h in Headers */ = {isa = PBXBuildFile; fileRef = 4911934B1226383D00578B7F /* ASTStructExtractor.h */; };
+		491193521226386000578B7F /* ASTStructExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491193501226386000578B7F /* ASTStructExtractor.cpp */; };
 		49307AAE11DEA4D90081F992 /* IRForTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49307AAD11DEA4D90081F992 /* IRForTarget.cpp */; };
 		49307AB211DEA4F20081F992 /* IRForTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 49307AB111DEA4F20081F992 /* IRForTarget.h */; };
-		49A8A3A011D568A300AD3B68 /* ClangResultSynthesizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49A8A39F11D568A300AD3B68 /* ClangResultSynthesizer.cpp */; };
-		49A8A3A411D568BF00AD3B68 /* ClangResultSynthesizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 49A8A3A311D568BF00AD3B68 /* ClangResultSynthesizer.h */; };
+		49445C2612245E3600C11A81 /* ClangExpressionParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49445C2512245E3600C11A81 /* ClangExpressionParser.cpp */; };
+		49445C2A12245E5500C11A81 /* ClangExpressionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 49445C2912245E5500C11A81 /* ClangExpressionParser.h */; };
+		49445E351225AB6A00C11A81 /* ClangUserExpression.h in Headers */ = {isa = PBXBuildFile; fileRef = 49445E341225AB6A00C11A81 /* ClangUserExpression.h */; };
+		49A8A3A011D568A300AD3B68 /* ASTResultSynthesizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49A8A39F11D568A300AD3B68 /* ASTResultSynthesizer.cpp */; };
+		49A8A3A411D568BF00AD3B68 /* ASTResultSynthesizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 49A8A3A311D568BF00AD3B68 /* ASTResultSynthesizer.h */; };
 		49BB309611F79450001A4197 /* TaggedASTType.h in Headers */ = {isa = PBXBuildFile; fileRef = 49BB309511F79450001A4197 /* TaggedASTType.h */; };
 		49D4FE831210B5FB00CDB854 /* ClangPersistentVariables.h in Headers */ = {isa = PBXBuildFile; fileRef = 49D4FE821210B5FB00CDB854 /* ClangPersistentVariables.h */; };
 		49D4FE891210B61C00CDB854 /* ClangPersistentVariables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D4FE871210B61C00CDB854 /* ClangPersistentVariables.cpp */; };
@@ -792,7 +796,7 @@
 		26BC7E9C10F1B85900F91463 /* ValueObjectList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectList.cpp; path = source/Core/ValueObjectList.cpp; sourceTree = "<group>"; };
 		26BC7E9D10F1B85900F91463 /* ValueObjectVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectVariable.cpp; path = source/Core/ValueObjectVariable.cpp; sourceTree = "<group>"; };
 		26BC7E9E10F1B85900F91463 /* VMRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VMRange.cpp; path = source/Core/VMRange.cpp; sourceTree = "<group>"; };
-		26BC7ED510F1B86700F91463 /* ClangExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExpression.cpp; path = source/Expression/ClangExpression.cpp; sourceTree = "<group>"; };
+		26BC7ED510F1B86700F91463 /* ClangUserExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangUserExpression.cpp; path = source/Expression/ClangUserExpression.cpp; sourceTree = "<group>"; };
 		26BC7ED610F1B86700F91463 /* ClangExpressionVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExpressionVariable.cpp; path = source/Expression/ClangExpressionVariable.cpp; sourceTree = "<group>"; };
 		26BC7ED810F1B86700F91463 /* DWARFExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DWARFExpression.cpp; path = source/Expression/DWARFExpression.cpp; sourceTree = "<group>"; };
 		26BC7EE710F1B88F00F91463 /* Condition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Condition.cpp; path = source/Host/posix/Condition.cpp; sourceTree = "<group>"; };
@@ -902,10 +906,15 @@
 		26F996A8119B79C300412154 /* ARM_GCC_Registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARM_GCC_Registers.h; path = source/Utility/ARM_GCC_Registers.h; sourceTree = "<group>"; };
 		26FE25221146CADE00F4085A /* GDBRemoteCommunication.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GDBRemoteCommunication.cpp; path = "source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp"; sourceTree = "<group>"; };
 		26FE25231146CADE00F4085A /* GDBRemoteCommunication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GDBRemoteCommunication.h; path = "source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h"; sourceTree = "<group>"; };
+		4911934B1226383D00578B7F /* ASTStructExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTStructExtractor.h; path = include/lldb/Expression/ASTStructExtractor.h; sourceTree = "<group>"; };
+		491193501226386000578B7F /* ASTStructExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTStructExtractor.cpp; path = source/Expression/ASTStructExtractor.cpp; sourceTree = "<group>"; };
 		49307AAD11DEA4D90081F992 /* IRForTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRForTarget.cpp; path = source/Expression/IRForTarget.cpp; sourceTree = "<group>"; };
 		49307AB111DEA4F20081F992 /* IRForTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRForTarget.h; path = include/lldb/Expression/IRForTarget.h; sourceTree = "<group>"; };
 		493C63F01189203300914D5E /* ABISysV_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ABISysV_x86_64.h; path = "ABI/SysV-x86_64/ABISysV_x86_64.h"; sourceTree = "<group>"; };
 		493C63F11189203300914D5E /* ABISysV_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ABISysV_x86_64.cpp; path = "ABI/SysV-x86_64/ABISysV_x86_64.cpp"; sourceTree = "<group>"; };
+		49445C2512245E3600C11A81 /* ClangExpressionParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExpressionParser.cpp; path = source/Expression/ClangExpressionParser.cpp; sourceTree = "<group>"; };
+		49445C2912245E5500C11A81 /* ClangExpressionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangExpressionParser.h; path = include/lldb/Expression/ClangExpressionParser.h; sourceTree = "<group>"; };
+		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>"; };
 		497650CE11A21BEE008DDB57 /* ABIMacOSX_i386.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ABIMacOSX_i386.cpp; path = "ABI/MacOSX-i386/ABIMacOSX_i386.cpp"; sourceTree = "<group>"; };
@@ -914,8 +923,8 @@
 		497E7B9D1188F6690065CCA1 /* ABI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ABI.cpp; path = source/Target/ABI.cpp; sourceTree = "<group>"; };
 		499F381E11A5B3F300F5CE02 /* CommandObjectArgs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectArgs.h; path = source/Commands/CommandObjectArgs.h; sourceTree = "<group>"; };
 		499F381F11A5B3F300F5CE02 /* CommandObjectArgs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectArgs.cpp; path = source/Commands/CommandObjectArgs.cpp; sourceTree = "<group>"; };
-		49A8A39F11D568A300AD3B68 /* ClangResultSynthesizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangResultSynthesizer.cpp; path = source/Expression/ClangResultSynthesizer.cpp; sourceTree = "<group>"; };
-		49A8A3A311D568BF00AD3B68 /* ClangResultSynthesizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangResultSynthesizer.h; path = include/lldb/Expression/ClangResultSynthesizer.h; sourceTree = "<group>"; };
+		49A8A39F11D568A300AD3B68 /* ASTResultSynthesizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTResultSynthesizer.cpp; path = source/Expression/ASTResultSynthesizer.cpp; sourceTree = "<group>"; };
+		49A8A3A311D568BF00AD3B68 /* ASTResultSynthesizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTResultSynthesizer.h; path = include/lldb/Expression/ASTResultSynthesizer.h; sourceTree = "<group>"; };
 		49BB309511F79450001A4197 /* TaggedASTType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TaggedASTType.h; path = include/lldb/Symbol/TaggedASTType.h; sourceTree = "<group>"; };
 		49BF48DC11ADF356008863BD /* ObjCObjectPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjCObjectPrinter.cpp; path = source/Target/ObjCObjectPrinter.cpp; sourceTree = "<group>"; };
 		49BF48E011ADF37D008863BD /* ObjCObjectPrinter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ObjCObjectPrinter.h; path = include/lldb/Target/ObjCObjectPrinter.h; sourceTree = "<group>"; };
@@ -1845,19 +1854,24 @@
 				49D7072611B5AD03001AD875 /* ClangASTSource.h */,
 				49D7072811B5AD11001AD875 /* ClangASTSource.cpp */,
 				26BC7DC010F1B79500F91463 /* ClangExpression.h */,
-				26BC7ED510F1B86700F91463 /* ClangExpression.cpp */,
+				49445E341225AB6A00C11A81 /* ClangUserExpression.h */,
+				26BC7ED510F1B86700F91463 /* ClangUserExpression.cpp */,
 				4C98D3E0118FB98F00E575D0 /* ClangFunction.h */,
 				4C98D3DA118FB96F00E575D0 /* ClangFunction.cpp */,
 				49F1A74911B338AE003ED505 /* ClangExpressionDeclMap.h */,
 				49F1A74511B3388F003ED505 /* ClangExpressionDeclMap.cpp */,
+				49445C2912245E5500C11A81 /* ClangExpressionParser.h */,
+				49445C2512245E3600C11A81 /* ClangExpressionParser.cpp */,
 				26BC7DC110F1B79500F91463 /* ClangExpressionVariable.h */,
 				26BC7ED610F1B86700F91463 /* ClangExpressionVariable.cpp */,
 				49D4FE821210B5FB00CDB854 /* ClangPersistentVariables.h */,
 				49D4FE871210B61C00CDB854 /* ClangPersistentVariables.cpp */,
-				49A8A3A311D568BF00AD3B68 /* ClangResultSynthesizer.h */,
-				49A8A39F11D568A300AD3B68 /* ClangResultSynthesizer.cpp */,
 				26BC7DC310F1B79500F91463 /* DWARFExpression.h */,
 				26BC7ED810F1B86700F91463 /* DWARFExpression.cpp */,
+				49A8A3A311D568BF00AD3B68 /* ASTResultSynthesizer.h */,
+				49A8A39F11D568A300AD3B68 /* ASTResultSynthesizer.cpp */,
+				4911934B1226383D00578B7F /* ASTStructExtractor.h */,
+				491193501226386000578B7F /* ASTStructExtractor.cpp */,
 				49307AB111DEA4F20081F992 /* IRForTarget.h */,
 				49307AAD11DEA4D90081F992 /* IRForTarget.cpp */,
 				49DA743411DE6BB2006AEF7E /* IRToDWARF.h */,
@@ -2215,7 +2229,7 @@
 				49D7072711B5AD03001AD875 /* ClangASTSource.h in Headers */,
 				261B5A5511C3F2AD00AABD0A /* SharingPtr.h in Headers */,
 				4C08CDEC11C81F1E001610A8 /* ThreadSpec.h in Headers */,
-				49A8A3A411D568BF00AD3B68 /* ClangResultSynthesizer.h in Headers */,
+				49A8A3A411D568BF00AD3B68 /* ASTResultSynthesizer.h in Headers */,
 				49DA743511DE6BB2006AEF7E /* IRToDWARF.h in Headers */,
 				49307AB211DEA4F20081F992 /* IRForTarget.h in Headers */,
 				4C5DBBC911E3FEC60035160F /* CommandObjectCommands.h in Headers */,
@@ -2226,6 +2240,9 @@
 				2615DB851208A9C90021781D /* StopInfo.h in Headers */,
 				2615DBCB1208B5FC0021781D /* StopInfoMachException.h in Headers */,
 				49D4FE831210B5FB00CDB854 /* ClangPersistentVariables.h in Headers */,
+				49445C2A12245E5500C11A81 /* ClangExpressionParser.h in Headers */,
+				49445E351225AB6A00C11A81 /* ClangUserExpression.h in Headers */,
+				4911934C1226383D00578B7F /* ASTStructExtractor.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -2480,7 +2497,7 @@
 				26D5B0BA11B07550009A862E /* ValueObjectList.cpp in Sources */,
 				26D5B0BB11B07550009A862E /* ValueObjectVariable.cpp in Sources */,
 				26D5B0BC11B07550009A862E /* VMRange.cpp in Sources */,
-				26D5B0BD11B07550009A862E /* ClangExpression.cpp in Sources */,
+				26D5B0BD11B07550009A862E /* ClangUserExpression.cpp in Sources */,
 				26D5B0BE11B07550009A862E /* ClangExpressionVariable.cpp in Sources */,
 				26D5B0C111B07550009A862E /* Condition.cpp in Sources */,
 				26D5B0C211B07550009A862E /* Host.mm in Sources */,
@@ -2615,7 +2632,6 @@
 				26D5B14711B07550009A862E /* ThreadPlanCallFunction.cpp in Sources */,
 				26D5B14811B07550009A862E /* ClangFunction.cpp in Sources */,
 				26D5B14911B07550009A862E /* RecordingMemoryManager.cpp in Sources */,
-				26D5B14A11B07550009A862E /* CommandObjectCall.cpp in Sources */,
 				26D5B14B11B07550009A862E /* CommandObjectTarget.cpp in Sources */,
 				26D5B14C11B07550009A862E /* PathMappingList.cpp in Sources */,
 				26D5B14D11B07550009A862E /* StringExtractorGDBRemote.cpp in Sources */,
@@ -2672,7 +2688,7 @@
 				AF94005911C03F6500085DB9 /* SymbolVendor.cpp in Sources */,
 				261B5A5411C3F2AD00AABD0A /* SharingPtr.cpp in Sources */,
 				4C08CDE811C81EF8001610A8 /* ThreadSpec.cpp in Sources */,
-				49A8A3A011D568A300AD3B68 /* ClangResultSynthesizer.cpp in Sources */,
+				49A8A3A011D568A300AD3B68 /* ASTResultSynthesizer.cpp in Sources */,
 				49DA743011DE6A5A006AEF7E /* IRToDWARF.cpp in Sources */,
 				49307AAE11DEA4D90081F992 /* IRForTarget.cpp in Sources */,
 				4C5DBBC811E3FEC60035160F /* CommandObjectCommands.cpp in Sources */,
@@ -2682,6 +2698,8 @@
 				2615DBCA1208B5FC0021781D /* StopInfoMachException.cpp in Sources */,
 				49D4FE891210B61C00CDB854 /* ClangPersistentVariables.cpp in Sources */,
 				49FB515E121481B000DF8983 /* DWARFExpression.cpp in Sources */,
+				49445C2612245E3600C11A81 /* ClangExpressionParser.cpp in Sources */,
+				491193521226386000578B7F /* ASTStructExtractor.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: lldb/trunk/source/Commands/CommandObjectCall.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectCall.cpp?rev=112249&r1=112248&r2=112249&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectCall.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectCall.cpp Thu Aug 26 20:01:44 2010
@@ -263,15 +263,8 @@
         ClangFunction::ExecutionResults return_status;
         Value return_value;
         
-        if (m_options.use_abi)
-        {
-            return_status = clang_fun.ExecuteFunctionWithABI(exe_ctx, errors, return_value);
-        }
-        else 
-        {
-            bool stop_others = true;
-            return_status = clang_fun.ExecuteFunction(exe_ctx, errors, stop_others, NULL, return_value);
-        }
+        bool stop_others = true;
+        return_status = clang_fun.ExecuteFunction(exe_ctx, errors, stop_others, NULL, return_value);
 
         // Now figure out what to do with the return value.
         if (return_status == ClangFunction::eExecutionSetupError)

Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=112249&r1=112248&r2=112249&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Thu Aug 26 20:01:44 2010
@@ -16,10 +16,8 @@
 #include "lldb/Interpreter/Args.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Core/InputReader.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangExpressionDeclMap.h"
 #include "lldb/Expression/ClangExpressionVariable.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
+#include "lldb/Expression/ClangUserExpression.h"
 #include "lldb/Expression/ClangFunction.h"
 #include "lldb/Expression/DWARFExpression.h"
 #include "lldb/Host/Host.h"
@@ -192,192 +190,22 @@
 CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream &output_stream, Stream &error_stream,
                                              CommandReturnObject *result)
 {
-    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-
-    ////////////////////////////////////
-    // Set up the target and compiler
-    //
-        
-    Target *target = m_exe_ctx.target;
-    
-    if (!target)
-    {
-        error_stream.PutCString ("error: invalid target\n");
-        return false;
-    }
+    ClangUserExpression user_expression (expr);
     
-    ConstString target_triple;
-
-    target->GetTargetTriple (target_triple);
-
-    if (!target_triple)
-        target_triple = Host::GetTargetTriple ();
-    
-    if (!target_triple)
+    if (!user_expression.Parse (error_stream, m_exe_ctx))
     {
-        error_stream.PutCString ("error: invalid target triple\n");
+        error_stream.Printf ("Couldn't parse the expresssion");
         return false;
     }
     
-    ClangExpressionDeclMap expr_decl_map (&m_exe_ctx);
-    ClangExpression clang_expr (target_triple.AsCString (), &expr_decl_map);
-    
-    //////////////////////////
-    // Parse the expression
-    //
-    
-    unsigned num_errors;
-    
-    if (bare)
-        num_errors = clang_expr.ParseBareExpression (llvm::StringRef (expr), error_stream);
-    else
-        num_errors = clang_expr.ParseExpression (expr, error_stream, true);
-
-    if (num_errors)
-    {
-        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
-        return false;
-    }
-    
-    ///////////////////////////////////////////////
-    // Convert the output of the parser to DWARF
-    //
-    
-    StreamString dwarf_opcodes;
-    dwarf_opcodes.SetByteOrder (eByteOrderHost);
-    dwarf_opcodes.GetFlags ().Set (Stream::eBinary);
-    
-    ClangExpressionVariableList expr_local_vars;
-
-    bool success;
-    bool canInterpret = false;
-    
-    ClangExpressionVariable *expr_result = 0;
-    Error expr_error;
-    
-    canInterpret = clang_expr.ConvertIRToDWARF (expr_local_vars, dwarf_opcodes);
-    
-    if (canInterpret)
-    {
-        if (log)
-            log->Printf("Code can be interpreted.");
-        success = true;
-    }
-    else
-    {
-        if (log)
-            log->Printf("Code cannot be interpreted and must be run in the target.");
-        success = clang_expr.PrepareIRForTarget ();
-    }
-    
-    if (!success)
-    {
-        error_stream.PutCString ("error: expression couldn't be converted to IR\n");
-        return false;
-    }
+    ClangExpressionVariable *expr_result;
     
-    if (canInterpret)
+    if (!user_expression.Execute (error_stream, m_exe_ctx, expr_result))
     {
-        // TODO interpret IR
+        error_stream.Printf ("Couldn't execute the expresssion");
         return false;
     }
-    else
-    {
-        if (!clang_expr.JITFunction ())
-        {
-            error_stream.PutCString ("error: IR could not be JIT compiled\n");
-            return false;
-        }
         
-        if (!clang_expr.WriteJITCode (m_exe_ctx))
-        {
-            error_stream.PutCString ("error: JIT code could not be written to the target\n");
-            return false;
-        }
-        
-        lldb::addr_t function_address(clang_expr.GetFunctionAddress ());
-        
-        if (function_address == LLDB_INVALID_ADDRESS)
-        {
-            error_stream.PutCString ("JIT compiled code's address couldn't be found\n");
-            return false;
-        }
-        
-        lldb::addr_t struct_address;
-        
-        if (!expr_decl_map.Materialize(&m_exe_ctx, struct_address, expr_error))
-        {
-            error_stream.Printf ("Couldn't materialize struct: %s\n", expr_error.AsCString("unknown error"));
-            return false;
-        }
-        
-        if (log)
-        {
-            log->Printf("Function address  : 0x%llx", (uint64_t)function_address);
-            log->Printf("Structure address : 0x%llx", (uint64_t)struct_address);
-            
-            StreamString insns;
-
-            Error err = clang_expr.DisassembleFunction(insns, m_exe_ctx);
-            
-            if (!err.Success())
-            {
-                log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
-            }
-            else
-            {
-                log->Printf("Function disassembly:\n%s", insns.GetData());
-            }
-            
-            StreamString args;
-            
-            if (!expr_decl_map.DumpMaterializedStruct(&m_exe_ctx, args, err))
-            {
-                log->Printf("Couldn't extract variable values : %s", err.AsCString("unknown error"));
-            }
-            else
-            {
-                log->Printf("Structure contents:\n%s", args.GetData());
-            }
-        }
-                    
-        ClangFunction::ExecutionResults execution_result = 
-            ClangFunction::ExecuteFunction (m_exe_ctx, function_address, struct_address, true, true, 10000, error_stream);
-        
-        if (execution_result != ClangFunction::eExecutionCompleted)
-        {
-            const char *result_name;
-            
-            switch (execution_result)
-            {
-            case ClangFunction::eExecutionCompleted:
-                result_name = "eExecutionCompleted";
-                break;
-            case ClangFunction::eExecutionDiscarded:
-                result_name = "eExecutionDiscarded";
-                break;
-            case ClangFunction::eExecutionInterrupted:
-                result_name = "eExecutionInterrupted";
-                break;
-            case ClangFunction::eExecutionSetupError:
-                result_name = "eExecutionSetupError";
-                break;
-            case ClangFunction::eExecutionTimedOut:
-                result_name = "eExecutionTimedOut";
-                break;
-            }
-            
-            error_stream.Printf ("Couldn't execute function; result was %s\n", result_name);
-            return false;
-        }
-                    
-        if (!expr_decl_map.Dematerialize(&m_exe_ctx, expr_result, expr_error))
-        {
-            error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
-            return false;
-        }
-    }
-    
     if (expr_result)
     {
         StreamString ss;

Copied: lldb/trunk/source/Expression/ASTResultSynthesizer.cpp (from r112086, lldb/trunk/source/Expression/ClangResultSynthesizer.cpp)
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ASTResultSynthesizer.cpp?p2=lldb/trunk/source/Expression/ASTResultSynthesizer.cpp&p1=lldb/trunk/source/Expression/ClangResultSynthesizer.cpp&r1=112086&r2=112249&rev=112249&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangResultSynthesizer.cpp (original)
+++ lldb/trunk/source/Expression/ASTResultSynthesizer.cpp Thu Aug 26 20:01:44 2010
@@ -1,4 +1,4 @@
-//===-- ClangResultSynthesizer.cpp ------------------------------*- C++ -*-===//
+//===-- ASTResultSynthesizer.cpp --------------------------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -20,13 +20,13 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/raw_ostream.h"
 #include "lldb/Core/Log.h"
-#include "lldb/Expression/ClangResultSynthesizer.h"
+#include "lldb/Expression/ASTResultSynthesizer.h"
 
 using namespace llvm;
 using namespace clang;
 using namespace lldb_private;
 
-ClangResultSynthesizer::ClangResultSynthesizer(ASTConsumer *passthrough) :
+ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough) :
     m_ast_context (NULL),
     m_passthrough (passthrough),
     m_passthrough_sema (NULL),
@@ -39,12 +39,12 @@
     m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
 }
 
-ClangResultSynthesizer::~ClangResultSynthesizer()
+ASTResultSynthesizer::~ASTResultSynthesizer()
 {
 }
 
 void
-ClangResultSynthesizer::Initialize(ASTContext &Context) 
+ASTResultSynthesizer::Initialize(ASTContext &Context) 
 {
     m_ast_context = &Context;
     
@@ -53,7 +53,7 @@
 }
 
 void
-ClangResultSynthesizer::TransformTopLevelDecl(Decl* D)
+ASTResultSynthesizer::TransformTopLevelDecl(Decl* D)
 {
     LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D);
     
@@ -81,7 +81,7 @@
 }
 
 void 
-ClangResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D)
+ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D)
 {
     DeclGroupRef::iterator decl_iterator;
     
@@ -99,7 +99,7 @@
 }
 
 bool 
-ClangResultSynthesizer::SynthesizeResult (FunctionDecl *FunDecl)
+ASTResultSynthesizer::SynthesizeResult (FunctionDecl *FunDecl)
 {
     ASTContext &Ctx(*m_ast_context);
     
@@ -210,42 +210,42 @@
 }
 
 void
-ClangResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
+ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
 {    
     if (m_passthrough)
         m_passthrough->HandleTranslationUnit(Ctx);
 }
 
 void 
-ClangResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
+ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
 {
     if (m_passthrough)
         m_passthrough->HandleTagDeclDefinition(D);
 }
 
 void
-ClangResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
+ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
 {
     if (m_passthrough)
         m_passthrough->CompleteTentativeDefinition(D);
 }
 
 void 
-ClangResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) 
+ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) 
 {
     if (m_passthrough)
         m_passthrough->HandleVTable(RD, DefinitionRequired);
 }
 
 void
-ClangResultSynthesizer::PrintStats() 
+ASTResultSynthesizer::PrintStats() 
 {
     if (m_passthrough)
         m_passthrough->PrintStats();
 }
 
 void
-ClangResultSynthesizer::InitializeSema(Sema &S)
+ASTResultSynthesizer::InitializeSema(Sema &S)
 {
     m_sema = &S;
     m_action = reinterpret_cast<Action*>(m_sema);
@@ -255,7 +255,7 @@
 }
 
 void 
-ClangResultSynthesizer::ForgetSema() 
+ASTResultSynthesizer::ForgetSema() 
 {
     m_sema = NULL;
     m_action = NULL;

Added: lldb/trunk/source/Expression/ASTStructExtractor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ASTStructExtractor.cpp?rev=112249&view=auto
==============================================================================
--- lldb/trunk/source/Expression/ASTStructExtractor.cpp (added)
+++ lldb/trunk/source/Expression/ASTStructExtractor.cpp Thu Aug 26 20:01:44 2010
@@ -0,0 +1,191 @@
+//===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "stdlib.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Parse/Action.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/Scope.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Expression/ASTStructExtractor.h"
+
+using namespace llvm;
+using namespace clang;
+using namespace lldb_private;
+
+ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough,
+                                       const char *struct_name,
+                                       ClangFunction &function) :
+    m_ast_context (NULL),
+    m_passthrough (passthrough),
+    m_passthrough_sema (NULL),
+    m_sema (NULL),
+    m_action (NULL),
+    m_struct_name (struct_name),
+    m_function (function)
+{
+    if (!m_passthrough)
+        return;
+    
+    m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
+}
+
+ASTStructExtractor::~ASTStructExtractor()
+{
+}
+
+void
+ASTStructExtractor::Initialize(ASTContext &Context) 
+{
+    m_ast_context = &Context;
+    
+    if (m_passthrough)
+        m_passthrough->Initialize(Context);
+}
+
+void
+ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F)
+{
+    DeclarationName struct_name(&m_ast_context->Idents.get(m_struct_name.c_str()));
+    RecordDecl::lookup_result struct_lookup = F->lookup(struct_name);
+    
+    if (struct_lookup.first == struct_lookup.second)
+        return;
+    
+    RecordDecl *struct_decl = dyn_cast<RecordDecl>(*(struct_lookup.first));
+    
+    if (!struct_decl)
+        return;
+    
+    const ASTRecordLayout* struct_layout(&m_ast_context->getASTRecordLayout (struct_decl));
+    
+    if (!struct_layout)
+        return;
+    
+    m_function.m_struct_size = struct_layout->getSize() / 8; // Clang returns sizes in bits.    
+    m_function.m_return_offset = struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8;
+    m_function.m_return_size = (struct_layout->getDataSize() / 8) - m_function.m_return_offset;
+    
+    for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount();
+         field_index < num_fields;
+         ++field_index)
+    {
+        m_function.m_member_offsets.push_back(struct_layout->getFieldOffset(field_index) / 8);
+    }
+    
+    m_function.m_struct_valid = true;
+}
+
+void
+ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D)
+{
+    LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D);
+    
+    if (linkage_spec_decl)
+    {
+        RecordDecl::decl_iterator decl_iterator;
+        
+        for (decl_iterator = linkage_spec_decl->decls_begin();
+             decl_iterator != linkage_spec_decl->decls_end();
+             ++decl_iterator)
+        {
+            ExtractFromTopLevelDecl(*decl_iterator);
+        }
+    }
+    
+    FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D);
+    
+    if (m_ast_context &&
+        function_decl &&
+        !m_function.m_wrapper_function_name.compare(function_decl->getNameAsCString()))
+    {
+        ExtractFromFunctionDecl(function_decl);
+    }
+}
+
+void 
+ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D)
+{
+    DeclGroupRef::iterator decl_iterator;
+    
+    for (decl_iterator = D.begin();
+         decl_iterator != D.end();
+         ++decl_iterator)
+    {
+        Decl *decl = *decl_iterator;
+        
+        ExtractFromTopLevelDecl(decl);
+    }
+    
+    if (m_passthrough)
+        m_passthrough->HandleTopLevelDecl(D);
+}
+
+void
+ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx)
+{    
+    if (m_passthrough)
+        m_passthrough->HandleTranslationUnit(Ctx);
+}
+
+void 
+ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D)
+{
+    if (m_passthrough)
+        m_passthrough->HandleTagDeclDefinition(D);
+}
+
+void
+ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D)
+{
+    if (m_passthrough)
+        m_passthrough->CompleteTentativeDefinition(D);
+}
+
+void 
+ASTStructExtractor::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) 
+{
+    if (m_passthrough)
+        m_passthrough->HandleVTable(RD, DefinitionRequired);
+}
+
+void
+ASTStructExtractor::PrintStats() 
+{
+    if (m_passthrough)
+        m_passthrough->PrintStats();
+}
+
+void
+ASTStructExtractor::InitializeSema(Sema &S)
+{
+    m_sema = &S;
+    m_action = reinterpret_cast<Action*>(m_sema);
+    
+    if (m_passthrough_sema)
+        m_passthrough_sema->InitializeSema(S);
+}
+
+void 
+ASTStructExtractor::ForgetSema() 
+{
+    m_sema = NULL;
+    m_action = NULL;
+    
+    if (m_passthrough_sema)
+        m_passthrough_sema->ForgetSema();
+}

Removed: lldb/trunk/source/Expression/ClangExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpression.cpp?rev=112248&view=auto
==============================================================================
--- lldb/trunk/source/Expression/ClangExpression.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpression.cpp (removed)
@@ -1,748 +0,0 @@
-//===-- ClangExpression.cpp -------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <stdio.h>
-#if HAVE_SYS_TYPES_H
-#  include <sys/types.h>
-#endif
-
-// C++ Includes
-#include <cstdlib>
-#include <string>
-#include <map>
-
-// Other libraries and framework includes
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/ExternalASTSource.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/Version.h"
-#include "clang/Checker/FrontendActions.h"
-#include "clang/CodeGen/CodeGenAction.h"
-#include "clang/CodeGen/ModuleBuilder.h"
-#include "clang/Driver/CC1Options.h"
-#include "clang/Driver/OptTable.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/CompilerInvocation.h"
-#include "clang/Frontend/FrontendActions.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
-#include "clang/Frontend/FrontendPluginRegistry.h"
-#include "clang/Frontend/TextDiagnosticBuffer.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
-#include "clang/Frontend/VerifyDiagnosticsClient.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Rewrite/FrontendActions.h"
-#include "clang/Sema/ParseAST.h"
-#include "clang/Sema/SemaConsumer.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/JIT.h"
-#include "llvm/Module.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/LLVMContext.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/System/DynamicLibrary.h"
-#include "llvm/System/Host.h"
-#include "llvm/System/Signals.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/TargetSelect.h"
-
-// Project includes
-#include "lldb/Core/Log.h"
-#include "lldb/Core/ClangForward.h"
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/Disassembler.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangASTSource.h"
-#include "lldb/Expression/ClangResultSynthesizer.h"
-#include "lldb/Expression/IRForTarget.h"
-#include "lldb/Expression/IRToDWARF.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Expression/RecordingMemoryManager.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/Target.h"
-
-#include "lldb/Core/StreamString.h"
-#include "lldb/Host/Mutex.h"
-
-
-using namespace lldb_private;
-using namespace clang;
-using namespace llvm;
-
-
-//===----------------------------------------------------------------------===//
-// Utility Methods
-//===----------------------------------------------------------------------===//
-
-std::string GetBuiltinIncludePath(const char *Argv0) {
-  llvm::sys::Path P =
-    llvm::sys::Path::GetMainExecutable(Argv0,
-                                       (void*)(intptr_t) GetBuiltinIncludePath);
-
-  if (!P.isEmpty()) {
-    P.eraseComponent();  // Remove /clang from foo/bin/clang
-    P.eraseComponent();  // Remove /bin   from foo/bin
-
-    // Get foo/lib/clang/<version>/include
-    P.appendComponent("lib");
-    P.appendComponent("clang");
-    P.appendComponent(CLANG_VERSION_STRING);
-    P.appendComponent("include");
-  }
-
-  return P.str();
-}
-
-
-//===----------------------------------------------------------------------===//
-// Main driver
-//===----------------------------------------------------------------------===//
-
-static void LLVMErrorHandler(void *UserData, const std::string &Message) {
-  Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
-
-  Diags.Report(diag::err_fe_error_backend) << Message;
-
-  // We cannot recover from llvm errors.
-  exit(1);
-}
-
-static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
-  using namespace clang::frontend;
-
-  switch (CI.getFrontendOpts().ProgramAction) {
-  default:
-    llvm_unreachable("Invalid program action!");
-
-  case ASTDump:                return new ASTDumpAction();
-  case ASTPrint:               return new ASTPrintAction();
-  case ASTPrintXML:            return new ASTPrintXMLAction();
-  case ASTView:                return new ASTViewAction();
-  case BoostCon:               return new BoostConAction();
-  case DumpRawTokens:          return new DumpRawTokensAction();
-  case DumpTokens:             return new DumpTokensAction();
-  case EmitAssembly:           return new EmitAssemblyAction();
-  case EmitBC:                 return new EmitBCAction();
-  case EmitHTML:               return new HTMLPrintAction();
-  case EmitLLVM:               return new EmitLLVMAction();
-  case EmitLLVMOnly:           return new EmitLLVMOnlyAction();
-  case EmitCodeGenOnly:        return new EmitCodeGenOnlyAction();
-  case EmitObj:                return new EmitObjAction();
-  case FixIt:                  return new FixItAction();
-  case GeneratePCH:            return new GeneratePCHAction();
-  case GeneratePTH:            return new GeneratePTHAction();
-  case InheritanceView:        return new InheritanceViewAction();
-  case InitOnly:               return new InitOnlyAction();
-  case ParseSyntaxOnly:        return new SyntaxOnlyAction();
-
-  case PluginAction: {
-    for (FrontendPluginRegistry::iterator it =
-           FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
-         it != ie; ++it) {
-      if (it->getName() == CI.getFrontendOpts().ActionName) {
-        llvm::OwningPtr<PluginASTAction> P(it->instantiate());
-        if (!P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs))
-          return 0;
-        return P.take();
-      }
-    }
-
-    CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
-      << CI.getFrontendOpts().ActionName;
-    return 0;
-  }
-
-  case PrintDeclContext:       return new DeclContextPrintAction();
-  case PrintPreamble:          return new PrintPreambleAction();
-  case PrintPreprocessedInput: return new PrintPreprocessedAction();
-  case RewriteMacros:          return new RewriteMacrosAction();
-  case RewriteObjC:            return new RewriteObjCAction();
-  case RewriteTest:            return new RewriteTestAction();
-  case RunAnalysis:            return new AnalysisAction();
-  case RunPreprocessorOnly:    return new PreprocessOnlyAction();
-  }
-}
-
-static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
-  // Create the underlying action.
-  FrontendAction *Act = CreateFrontendBaseAction(CI);
-  if (!Act)
-    return 0;
-
-  // If there are any AST files to merge, create a frontend action
-  // adaptor to perform the merge.
-  if (!CI.getFrontendOpts().ASTMergeFiles.empty())
-    Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0],
-                             CI.getFrontendOpts().ASTMergeFiles.size());
-
-  return Act;
-}
-
-//----------------------------------------------------------------------
-// ClangExpression constructor
-//----------------------------------------------------------------------
-ClangExpression::ClangExpression(const char *target_triple,
-                                 ClangExpressionDeclMap *decl_map) :
-    m_target_triple (),
-    m_decl_map (decl_map),
-    m_clang_ap (),
-    m_code_generator_ptr (NULL),
-    m_jit_mm_ptr (NULL),
-    m_execution_engine (),
-    m_jitted_functions ()
-{
-    if (target_triple && target_triple[0])
-        m_target_triple = target_triple;
-    else
-        m_target_triple = llvm::sys::getHostTriple();
-}
-
-
-//----------------------------------------------------------------------
-// Destructor
-//----------------------------------------------------------------------
-ClangExpression::~ClangExpression()
-{
-    if (m_code_generator_ptr && !m_execution_engine.get())
-        delete m_code_generator_ptr;
-}
-
-bool
-ClangExpression::CreateCompilerInstance ()
-{
-    // Initialize targets first, so that --version shows registered targets.
-    static struct InitializeLLVM {
-        InitializeLLVM() {
-            llvm::InitializeAllTargets();
-            llvm::InitializeAllAsmPrinters();
-        }
-    } InitializeLLVM;
-
-    // 1. Create a new compiler instance.
-    m_clang_ap.reset(new CompilerInstance());    
-    m_clang_ap->setLLVMContext(new LLVMContext());
-    
-    // 2. Set options.
-
-    // Parse expressions as Objective C++ regardless of context.
-    // Our hook into Clang's lookup mechanism only works in C++.
-    m_clang_ap->getLangOpts().CPlusPlus = true;
-    m_clang_ap->getLangOpts().ObjC1 = true;
-    m_clang_ap->getLangOpts().ThreadsafeStatics = false;
-    m_clang_ap->getLangOpts().AccessControl = false; // Debuggers get universal access
-    m_clang_ap->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name
-    
-    // Set CodeGen options
-    m_clang_ap->getCodeGenOpts().EmitDeclMetadata = true;
-    m_clang_ap->getCodeGenOpts().InstrumentFunctions = false;
-
-    // Disable some warnings.
-    m_clang_ap->getDiagnosticOpts().Warnings.push_back("no-unused-value");
-    
-    // Set the target triple.
-    m_clang_ap->getTargetOpts().Triple = m_target_triple;
-    
-    // 3. Set up various important bits of infrastructure.
-    
-    m_clang_ap->createDiagnostics(0, 0);
-
-    // Create the target instance.
-    m_clang_ap->setTarget(TargetInfo::CreateTargetInfo(m_clang_ap->getDiagnostics(),
-                                                       m_clang_ap->getTargetOpts()));
-    if (!m_clang_ap->hasTarget())
-    {
-        m_clang_ap.reset();
-        return false;
-    }
-
-    // Inform the target of the language options
-    //
-    // FIXME: We shouldn't need to do this, the target should be immutable once
-    // created. This complexity should be lifted elsewhere.
-    m_clang_ap->getTarget().setForcedLangOptions(m_clang_ap->getLangOpts());
-
-    return m_clang_ap.get();
-}
-
-Mutex &
-ClangExpression::GetClangMutex ()
-{
-    static Mutex g_clang_mutex(Mutex::eMutexTypeRecursive);  // Control access to the clang compiler
-    return g_clang_mutex;
-}
-
-
-clang::ASTContext *
-ClangExpression::GetASTContext ()
-{
-    CompilerInstance *compiler_instance = GetCompilerInstance();
-    if (compiler_instance)
-        return &compiler_instance->getASTContext();
-    return NULL;
-}
-
-unsigned
-ClangExpression::ParseExpression (const char *expr_text,
-                                  Stream &stream,
-                                  bool add_result_var)
-{
-    // HACK: for now we have to make a function body around our expression
-    // since there is no way to parse a single expression line in LLVM/Clang.
-    std::string func_expr("extern \"C\" void ___clang_expr(void *___clang_arg)\n{\n\t");
-    func_expr.append(expr_text);
-    func_expr.append(";\n}");
-    return ParseBareExpression (func_expr, stream, add_result_var);
-
-}
-
-unsigned
-ClangExpression::ParseBareExpression (llvm::StringRef expr_text, 
-                                      Stream &stream,
-                                      bool add_result_var)
-{
-    Mutex::Locker locker(GetClangMutex ());
-
-    TextDiagnosticBuffer text_diagnostic_buffer;
-
-    if (!CreateCompilerInstance ())
-    {
-        stream.Printf("error: couldn't create compiler instance\n");
-        return 1;
-    }
-    
-    // This code is matched below by a setClient to NULL.
-    // We cannot return out of this code without doing that.
-    m_clang_ap->getDiagnostics().setClient(&text_diagnostic_buffer);
-    text_diagnostic_buffer.FlushDiagnostics (m_clang_ap->getDiagnostics());
-    
-    MemoryBuffer *memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__);
-
-    if (!m_clang_ap->hasSourceManager())
-        m_clang_ap->createSourceManager();
-
-    m_clang_ap->createFileManager();
-    m_clang_ap->createPreprocessor();
-    
-    // Build the ASTContext.  Most of this we inherit from the
-    // CompilerInstance, but we also want to give the context
-    // an ExternalASTSource.
-    SelectorTable selector_table;
-    std::auto_ptr<Builtin::Context> builtin_ap(new Builtin::Context(m_clang_ap->getTarget()));
-    ASTContext *Context = new ASTContext(m_clang_ap->getLangOpts(),
-                                         m_clang_ap->getSourceManager(),
-                                         m_clang_ap->getTarget(),
-                                         m_clang_ap->getPreprocessor().getIdentifierTable(),
-                                         selector_table,
-                                         *builtin_ap.get(),
-                                         0);
-    
-    llvm::OwningPtr<ExternalASTSource> ASTSource(new ClangASTSource(*Context, *m_decl_map));
-
-    if (m_decl_map)
-    {
-        Context->setExternalSource(ASTSource);
-    }
-    
-    m_clang_ap->setASTContext(Context);
-
-    FileID memory_buffer_file_id = m_clang_ap->getSourceManager().createMainFileIDForMemBuffer (memory_buffer);
-    std::string module_name("test_func");
-    text_diagnostic_buffer.BeginSourceFile(m_clang_ap->getLangOpts(), &m_clang_ap->getPreprocessor());
-
-    if (m_code_generator_ptr)
-        delete m_code_generator_ptr;
-    
-    m_code_generator_ptr = CreateLLVMCodeGen(m_clang_ap->getDiagnostics(),
-                                             module_name,
-                                             m_clang_ap->getCodeGenOpts(),
-                                             m_clang_ap->getLLVMContext());
-
-
-    // - CodeGeneration ASTConsumer (include/clang/ModuleBuilder.h), which will be passed in when you call...
-    // - Call clang::ParseAST (in lib/Sema/ParseAST.cpp) to parse the buffer. The CodeGenerator will generate code for __dbg_expr.
-    // - Once ParseAST completes, you can grab the llvm::Module from the CodeGenerator, which will have an llvm::Function you can hand off to the JIT.
-    
-    if (add_result_var)
-    {
-        ClangResultSynthesizer result_synthesizer(m_code_generator_ptr);
-        ParseAST(m_clang_ap->getPreprocessor(), &result_synthesizer, m_clang_ap->getASTContext());
-    }
-    else 
-    {
-        ParseAST(m_clang_ap->getPreprocessor(), m_code_generator_ptr, m_clang_ap->getASTContext());
-    }
-
-    
-    text_diagnostic_buffer.EndSourceFile();
-
-    //compiler_instance->getASTContext().getTranslationUnitDecl()->dump();
-
-    //if (compiler_instance->getFrontendOpts().ShowStats) {
-    //    compiler_instance->getFileManager().PrintStats();
-    //    fprintf(stderr, "\n");
-    //}
-    
-    // This code resolves the setClient above.
-    m_clang_ap->getDiagnostics().setClient(0);
-    
-    TextDiagnosticBuffer::const_iterator diag_iterator;
-    
-    int num_errors = 0;
-
-#ifdef COUNT_WARNINGS_AND_ERRORS
-    int num_warnings = 0;
-    
-    for (diag_iterator = text_diagnostic_buffer.warn_begin();
-         diag_iterator != text_diagnostic_buffer.warn_end();
-         ++diag_iterator)
-        num_warnings++;
-    
-    for (diag_iterator = text_diagnostic_buffer.err_begin();
-         diag_iterator != text_diagnostic_buffer.err_end();
-         ++diag_iterator)
-        num_errors++;    
-    
-    if (num_warnings || num_errors)
-    {
-        if (num_warnings)
-            stream.Printf("%u warning%s%s", num_warnings, (num_warnings == 1 ? "" : "s"), (num_errors ? " and " : ""));
-        if (num_errors)
-            stream.Printf("%u error%s", num_errors, (num_errors == 1 ? "" : "s"));
-        stream.Printf("\n");
-    }
-#endif
-    
-    for (diag_iterator = text_diagnostic_buffer.warn_begin();
-         diag_iterator != text_diagnostic_buffer.warn_end();
-         ++diag_iterator)
-        stream.Printf("warning: %s\n", (*diag_iterator).second.c_str());
-    
-    num_errors = 0;
-    
-    for (diag_iterator = text_diagnostic_buffer.err_begin();
-         diag_iterator != text_diagnostic_buffer.err_end();
-         ++diag_iterator)
-    {
-        num_errors++;
-        stream.Printf("error: %s\n", (*diag_iterator).second.c_str());
-    }
-    
-    return num_errors;
-}
-
-bool
-ClangExpression::ConvertIRToDWARF (ClangExpressionVariableList &expr_local_variable_list,
-                                   StreamString &dwarf_opcode_strm)
-{
-    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-    
-    llvm::Module *module = m_code_generator_ptr->GetModule();
-        
-    if (!module)
-    {
-        if (log)
-            log->Printf("IR doesn't contain a module");
-        
-        return 1;
-    }
-    
-    IRToDWARF ir_to_dwarf(expr_local_variable_list, m_decl_map, dwarf_opcode_strm);
-    
-    return ir_to_dwarf.runOnModule(*module);
-}
-
-bool
-ClangExpression::PrepareIRForTarget ()
-{
-    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-    
-    llvm::Module *module = m_code_generator_ptr->GetModule();
-    
-    if (!module)
-    {
-        if (log)
-            log->Printf("IR doesn't contain a module");
-        
-        return 1;
-    }
-    
-    llvm::Triple target_triple = m_clang_ap->getTarget().getTriple();
-    
-    std::string err;
-    
-    const llvm::Target *target = llvm::TargetRegistry::lookupTarget(m_target_triple, err);
-    
-    if (!target)
-    {
-        if (log)
-            log->Printf("Couldn't find a target for %s", m_target_triple.c_str());
-        
-        return 1;
-    }
-    
-    std::auto_ptr<llvm::TargetMachine> target_machine(target->createTargetMachine(m_target_triple, ""));
-    
-    IRForTarget ir_for_target(m_decl_map, target_machine->getTargetData());
-    
-    return ir_for_target.runOnModule(*module);
-}
-
-bool
-ClangExpression::JITFunction (const char *name)
-{
-    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-
-    llvm::Module *module = m_code_generator_ptr->GetModule();
-
-    if (module)
-    {
-        std::string error;
-
-        if (m_jit_mm_ptr == NULL)
-            m_jit_mm_ptr = new RecordingMemoryManager();
-
-        //llvm::InitializeNativeTarget();
-        
-        if (log)
-        {
-            const char *relocation_model_string;
-            
-            switch (llvm::TargetMachine::getRelocationModel())
-            {
-                case llvm::Reloc::Default:
-                    relocation_model_string = "Default";
-                    break;
-                case llvm::Reloc::Static:
-                    relocation_model_string = "Static";
-                    break;
-                case llvm::Reloc::PIC_:
-                    relocation_model_string = "PIC_";
-                    break;
-                case llvm::Reloc::DynamicNoPIC:
-                    relocation_model_string = "DynamicNoPIC";
-                    break;
-            }
-            
-            log->Printf("Target machine's relocation model: %s", relocation_model_string);
-        }
-                        
-        if (m_execution_engine.get() == 0)
-            m_execution_engine.reset(llvm::ExecutionEngine::createJIT (module, 
-                                                                       &error, 
-                                                                       m_jit_mm_ptr,
-                                                                       CodeGenOpt::Default,
-                                                                       true,
-                                                                       CodeModel::Small)); // set to small so RIP-relative relocations work in PIC
-        
-        m_execution_engine->DisableLazyCompilation();
-        llvm::Function *function = module->getFunction (llvm::StringRef (name));
-            
-        // We don't actually need the function pointer here, this just forces it to get resolved.
-        void *fun_ptr = m_execution_engine->getPointerToFunction(function);
-        // Note, you probably won't get here on error, since the LLVM JIT tends to just
-        // exit on error at present...  So be careful.
-        if (fun_ptr == 0)
-            return false;
-        m_jitted_functions.push_back(ClangExpression::JittedFunction(name, (lldb::addr_t) fun_ptr));
-
-    }
-    return true;
-}
-
-bool
-ClangExpression::WriteJITCode (const ExecutionContext &exc_context)
-{
-    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-
-    if (m_jit_mm_ptr == NULL)
-        return false;
-
-    if (exc_context.process == NULL)
-        return false;
-
-    // Look over the regions allocated for the function compiled.  The JIT
-    // tries to allocate the functions & stubs close together, so we should try to
-    // write them that way too...
-    // For now I only write functions with no stubs, globals, exception tables,
-    // etc.  So I only need to write the functions.
-
-    size_t alloc_size = 0;
-    std::map<uint8_t *, uint8_t *>::iterator fun_pos, fun_end = m_jit_mm_ptr->m_functions.end();
-    for (fun_pos = m_jit_mm_ptr->m_functions.begin(); fun_pos != fun_end; fun_pos++)
-    {
-        alloc_size += (*fun_pos).second - (*fun_pos).first;
-    }
-
-    Error error;
-    lldb::addr_t target_addr = exc_context.process->AllocateMemory (alloc_size, lldb::ePermissionsReadable|lldb::ePermissionsExecutable, error);
-
-    if (target_addr == LLDB_INVALID_ADDRESS)
-        return false;
-
-    lldb::addr_t cursor = target_addr;
-    for (fun_pos = m_jit_mm_ptr->m_functions.begin(); fun_pos != fun_end; fun_pos++)
-    {
-        if (log)
-            log->Printf("Reading [%p-%p] from m_functions", fun_pos->first, fun_pos->second);
-        
-        lldb::addr_t lstart = (lldb::addr_t) (*fun_pos).first;
-        lldb::addr_t lend = (lldb::addr_t) (*fun_pos).second;
-        size_t size = lend - lstart;
-        exc_context.process->WriteMemory(cursor, (void *) lstart, size, error);
-        m_jit_mm_ptr->AddToLocalToRemoteMap (lstart, size, cursor);
-        cursor += size;
-    }
-
-    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
-
-    for (pos = m_jitted_functions.begin(); pos != end; pos++)
-    {
-        (*pos).m_remote_addr = m_jit_mm_ptr->GetRemoteAddressForLocal ((*pos).m_local_addr);
-    }
-    return true;
-}
-
-lldb::addr_t
-ClangExpression::GetFunctionAddress (const char *name)
-{
-    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
-
-    for (pos = m_jitted_functions.begin(); pos < end; pos++)
-    {
-        if (strcmp ((*pos).m_name.c_str(), name) == 0)
-            return (*pos).m_remote_addr;
-    }
-    return LLDB_INVALID_ADDRESS;
-}
-
-Error
-ClangExpression::DisassembleFunction (Stream &stream, ExecutionContext &exe_ctx, const char *name)
-{
-    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-
-    Error ret;
-    
-    ret.Clear();
-    
-    lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
-    lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
-    
-    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
-    
-    for (pos = m_jitted_functions.begin(); pos < end; pos++)
-    {
-        if (strcmp(pos->m_name.c_str(), name) == 0)
-        {
-            func_local_addr = pos->m_local_addr;
-            func_remote_addr = pos->m_remote_addr;
-        }
-    }
-    
-    if (func_local_addr == LLDB_INVALID_ADDRESS)
-    {
-        ret.SetErrorToGenericError();
-        ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", name);
-        return ret;
-    }
-    
-    if(log)
-        log->Printf("Found function, has local address 0x%llx and remote address 0x%llx", (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
-        
-    std::pair <lldb::addr_t, lldb::addr_t> func_range;
-    
-    func_range = m_jit_mm_ptr->GetRemoteRangeForLocal(func_local_addr);
-    
-    if (func_range.first == 0 && func_range.second == 0)
-    {
-        ret.SetErrorToGenericError();
-        ret.SetErrorStringWithFormat("Couldn't find code range for function %s", name);
-        return ret;
-    }
-    
-    if(log)
-        log->Printf("Function's code range is [0x%llx-0x%llx]", func_range.first, func_range.second);
-    
-    if (!exe_ctx.target)
-    {
-        ret.SetErrorToGenericError();
-        ret.SetErrorString("Couldn't find the target");
-    }
-    
-    lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second - func_remote_addr, 0));
-        
-    Error err;
-    exe_ctx.process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);
-    
-    if (!err.Success())
-    {
-        ret.SetErrorToGenericError();
-        ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
-        return ret;
-    }
-    
-    ArchSpec arch(exe_ctx.target->GetArchitecture());
-    
-    Disassembler *disassembler = Disassembler::FindPlugin(arch);
-    
-    if (disassembler == NULL)
-    {
-        ret.SetErrorToGenericError();
-        ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.AsCString());
-        return ret;
-    }
-    
-    if (!exe_ctx.process)
-    {
-        ret.SetErrorToGenericError();
-        ret.SetErrorString("Couldn't find the process");
-        return ret;
-    }
-    
-    DataExtractor extractor(buffer_sp, 
-                            exe_ctx.process->GetByteOrder(),
-                            exe_ctx.target->GetArchitecture().GetAddressByteSize());
-    
-    if(log)
-    {
-        log->Printf("Function data has contents:");
-        extractor.PutToLog (log,
-                            0,
-                            extractor.GetByteSize(),
-                            func_remote_addr,
-                            16,
-                            DataExtractor::TypeUInt8);
-    }
-            
-    disassembler->DecodeInstructions(extractor, 0, UINT32_MAX);
-    
-    Disassembler::InstructionList &instruction_list = disassembler->GetInstructionList();
-    
-    uint32_t bytes_offset = 0;
-    
-    for (uint32_t instruction_index = 0, num_instructions = instruction_list.GetSize(); 
-         instruction_index < num_instructions; 
-         ++instruction_index)
-    {
-        Disassembler::Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index);
-        Address addr(NULL, func_remote_addr + bytes_offset);
-        instruction->Dump (&stream,
-                           &addr,
-                           &extractor, 
-                           bytes_offset, 
-                           exe_ctx, 
-                           true);
-        stream.PutChar('\n');
-        bytes_offset += instruction->GetByteSize();
-    }
-    
-    return ret;
-}

Added: lldb/trunk/source/Expression/ClangExpressionParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionParser.cpp?rev=112249&view=auto
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionParser.cpp (added)
+++ lldb/trunk/source/Expression/ClangExpressionParser.cpp Thu Aug 26 20:01:44 2010
@@ -0,0 +1,640 @@
+//===-- ClangExpressionParser.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/ClangExpressionParser.h"
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Expression/ClangASTSource.h"
+#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/IRForTarget.h"
+#include "lldb/Expression/IRToDWARF.h"
+#include "lldb/Expression/RecordingMemoryManager.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Version.h"
+#include "clang/Checker/FrontendActions.h"
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Driver/CC1Options.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendPluginRegistry.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Frontend/VerifyDiagnosticsClient.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Rewrite/FrontendActions.h"
+#include "clang/Sema/ParseAST.h"
+#include "clang/Sema/SemaConsumer.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/Module.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/System/DynamicLibrary.h"
+#include "llvm/System/Host.h"
+#include "llvm/System/Signals.h"
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Target/TargetSelect.h"
+
+using namespace clang;
+using namespace llvm;
+using namespace lldb_private;
+
+//===----------------------------------------------------------------------===//
+// Utility Methods for Clang
+//===----------------------------------------------------------------------===//
+
+std::string GetBuiltinIncludePath(const char *Argv0) {
+    llvm::sys::Path P =
+    llvm::sys::Path::GetMainExecutable(Argv0,
+                                       (void*)(intptr_t) GetBuiltinIncludePath);
+    
+    if (!P.isEmpty()) {
+        P.eraseComponent();  // Remove /clang from foo/bin/clang
+        P.eraseComponent();  // Remove /bin   from foo/bin
+        
+        // Get foo/lib/clang/<version>/include
+        P.appendComponent("lib");
+        P.appendComponent("clang");
+        P.appendComponent(CLANG_VERSION_STRING);
+        P.appendComponent("include");
+    }
+    
+    return P.str();
+}
+
+
+//===----------------------------------------------------------------------===//
+// Main driver for Clang
+//===----------------------------------------------------------------------===//
+
+static void LLVMErrorHandler(void *UserData, const std::string &Message) {
+    Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
+    
+    Diags.Report(diag::err_fe_error_backend) << Message;
+    
+    // We cannot recover from llvm errors.
+    exit(1);
+}
+
+static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
+    using namespace clang::frontend;
+    
+    switch (CI.getFrontendOpts().ProgramAction) {
+        default:
+            llvm_unreachable("Invalid program action!");
+            
+        case ASTDump:                return new ASTDumpAction();
+        case ASTPrint:               return new ASTPrintAction();
+        case ASTPrintXML:            return new ASTPrintXMLAction();
+        case ASTView:                return new ASTViewAction();
+        case BoostCon:               return new BoostConAction();
+        case DumpRawTokens:          return new DumpRawTokensAction();
+        case DumpTokens:             return new DumpTokensAction();
+        case EmitAssembly:           return new EmitAssemblyAction();
+        case EmitBC:                 return new EmitBCAction();
+        case EmitHTML:               return new HTMLPrintAction();
+        case EmitLLVM:               return new EmitLLVMAction();
+        case EmitLLVMOnly:           return new EmitLLVMOnlyAction();
+        case EmitCodeGenOnly:        return new EmitCodeGenOnlyAction();
+        case EmitObj:                return new EmitObjAction();
+        case FixIt:                  return new FixItAction();
+        case GeneratePCH:            return new GeneratePCHAction();
+        case GeneratePTH:            return new GeneratePTHAction();
+        case InheritanceView:        return new InheritanceViewAction();
+        case InitOnly:               return new InitOnlyAction();
+        case ParseSyntaxOnly:        return new SyntaxOnlyAction();
+            
+        case PluginAction: {
+            for (FrontendPluginRegistry::iterator it =
+                 FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
+                 it != ie; ++it) {
+                if (it->getName() == CI.getFrontendOpts().ActionName) {
+                    llvm::OwningPtr<PluginASTAction> P(it->instantiate());
+                    if (!P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs))
+                        return 0;
+                    return P.take();
+                }
+            }
+            
+            CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
+            << CI.getFrontendOpts().ActionName;
+            return 0;
+        }
+            
+        case PrintDeclContext:       return new DeclContextPrintAction();
+        case PrintPreamble:          return new PrintPreambleAction();
+        case PrintPreprocessedInput: return new PrintPreprocessedAction();
+        case RewriteMacros:          return new RewriteMacrosAction();
+        case RewriteObjC:            return new RewriteObjCAction();
+        case RewriteTest:            return new RewriteTestAction();
+        case RunAnalysis:            return new AnalysisAction();
+        case RunPreprocessorOnly:    return new PreprocessOnlyAction();
+    }
+}
+
+static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
+    // Create the underlying action.
+    FrontendAction *Act = CreateFrontendBaseAction(CI);
+    if (!Act)
+        return 0;
+    
+    // If there are any AST files to merge, create a frontend action
+    // adaptor to perform the merge.
+    if (!CI.getFrontendOpts().ASTMergeFiles.empty())
+        Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0],
+                                 CI.getFrontendOpts().ASTMergeFiles.size());
+    
+    return Act;
+}
+
+//===----------------------------------------------------------------------===//
+// Implementation of ClangExpressionParser
+//===----------------------------------------------------------------------===//
+
+ClangExpressionParser::ClangExpressionParser(const char *target_triple,
+                                             ClangExpression &expr) :
+    m_expr(expr),
+    m_target_triple (),
+    m_compiler (),
+    m_code_generator (NULL),
+    m_execution_engine (),
+    m_jitted_functions ()
+{
+    // Initialize targets first, so that --version shows registered targets.
+    static struct InitializeLLVM {
+        InitializeLLVM() {
+            llvm::InitializeAllTargets();
+            llvm::InitializeAllAsmPrinters();
+        }
+    } InitializeLLVM;
+    
+    if (target_triple && target_triple[0])
+        m_target_triple = target_triple;
+    else
+        m_target_triple = llvm::sys::getHostTriple();
+    
+    // 1. Create a new compiler instance.
+    m_compiler.reset(new CompilerInstance());    
+    m_compiler->setLLVMContext(new LLVMContext());
+    
+    // 2. Set options.
+    
+    // Parse expressions as Objective C++ regardless of context.
+    // Our hook into Clang's lookup mechanism only works in C++.
+    m_compiler->getLangOpts().CPlusPlus = true;
+    m_compiler->getLangOpts().ObjC1 = true;
+    m_compiler->getLangOpts().ThreadsafeStatics = false;
+    m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access
+    m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name
+    
+    // Set CodeGen options
+    m_compiler->getCodeGenOpts().EmitDeclMetadata = true;
+    m_compiler->getCodeGenOpts().InstrumentFunctions = false;
+    
+    // Disable some warnings.
+    m_compiler->getDiagnosticOpts().Warnings.push_back("no-unused-value");
+    
+    // Set the target triple.
+    m_compiler->getTargetOpts().Triple = m_target_triple;
+    
+    // 3. Set up various important bits of infrastructure.
+    m_compiler->createDiagnostics(0, 0);
+    
+    // Create the target instance.
+    m_compiler->setTarget(TargetInfo::CreateTargetInfo(m_compiler->getDiagnostics(),
+                                                       m_compiler->getTargetOpts()));
+    
+    assert (m_compiler->hasTarget());
+    
+    // Inform the target of the language options
+    //
+    // FIXME: We shouldn't need to do this, the target should be immutable once
+    // created. This complexity should be lifted elsewhere.
+    m_compiler->getTarget().setForcedLangOptions(m_compiler->getLangOpts());
+    
+    // 4. Set up the diagnostic buffer for reporting errors
+    
+    m_diagnostic_buffer.reset(new clang::TextDiagnosticBuffer);
+    m_compiler->getDiagnostics().setClient(m_diagnostic_buffer.get());
+    
+    // 5. Set up the source management objects inside the compiler
+    
+    if (!m_compiler->hasSourceManager())
+        m_compiler->createSourceManager();
+    
+    m_compiler->createFileManager();
+    m_compiler->createPreprocessor();
+    
+    // 6. Most of this we get from the CompilerInstance, but we 
+    // also want to give the context an ExternalASTSource.
+    SelectorTable selector_table;
+    m_builtin_context.reset(new Builtin::Context(m_compiler->getTarget()));
+    
+    std::auto_ptr<clang::ASTContext> ast_context(new ASTContext(m_compiler->getLangOpts(),
+                                                                m_compiler->getSourceManager(),
+                                                                m_compiler->getTarget(),
+                                                                m_compiler->getPreprocessor().getIdentifierTable(),
+                                                                selector_table,
+                                                                *m_builtin_context.get(),
+                                                                0));
+    
+    ClangExpressionDeclMap *decl_map = m_expr.DeclMap();
+    
+    if (decl_map)
+    {
+        OwningPtr<clang::ExternalASTSource> ast_source(new ClangASTSource(*ast_context, *decl_map));
+        ast_context->setExternalSource(ast_source);
+    }
+    
+    m_compiler->setASTContext(ast_context.release());
+    
+    std::string module_name("___clang_module");
+
+    m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(),
+                                             module_name,
+                                             m_compiler->getCodeGenOpts(),
+                                             m_compiler->getLLVMContext()));
+}
+
+ClangExpressionParser::~ClangExpressionParser()
+{
+}
+
+unsigned
+ClangExpressionParser::Parse (Stream &stream)
+{
+    m_diagnostic_buffer->FlushDiagnostics (m_compiler->getDiagnostics());
+    
+    MemoryBuffer *memory_buffer = MemoryBuffer::getMemBufferCopy(m_expr.Text(), __FUNCTION__);
+    FileID memory_buffer_file_id = m_compiler->getSourceManager().createMainFileIDForMemBuffer (memory_buffer);
+    
+    m_diagnostic_buffer->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor());
+    
+    ASTConsumer *ast_transformer = m_expr.ASTTransformer(m_code_generator.get());
+    
+    if (ast_transformer)
+        ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext());
+    else 
+        ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext());    
+    
+    m_diagnostic_buffer->EndSourceFile();
+    
+    TextDiagnosticBuffer::const_iterator diag_iterator;
+    
+    int num_errors = 0;
+        
+    for (diag_iterator = m_diagnostic_buffer->warn_begin();
+         diag_iterator != m_diagnostic_buffer->warn_end();
+         ++diag_iterator)
+        stream.Printf("warning: %s\n", (*diag_iterator).second.c_str());
+    
+    num_errors = 0;
+    
+    for (diag_iterator = m_diagnostic_buffer->err_begin();
+         diag_iterator != m_diagnostic_buffer->err_end();
+         ++diag_iterator)
+    {
+        num_errors++;
+        stream.Printf("error: %s\n", (*diag_iterator).second.c_str());
+    }
+    
+    return num_errors;
+}
+
+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;
+    }
+    
+    ClangExpressionVariableStore *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;
+    }
+    
+    IRToDWARF ir_to_dwarf(*local_variables, decl_map, m_expr.DwarfOpcodeStream());
+    
+    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_addr, ExecutionContext &exe_ctx)
+{
+    Error err;
+    
+    llvm::Module *module = m_code_generator->ReleaseModule();
+
+    if (!module)
+    {
+        err.SetErrorToGenericError();
+        err.SetErrorString("IR doesn't contain a module");
+        return err;
+    }
+    
+    ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL
+    
+    if (decl_map)
+    {
+        std::string target_error;
+        
+        const llvm::Target *target = llvm::TargetRegistry::lookupTarget(m_target_triple, target_error);
+        
+        if (!target)
+        {
+            err.SetErrorToGenericError();
+            err.SetErrorStringWithFormat("Couldn't find a target for %s", m_target_triple.c_str());
+            return err;
+        }
+        
+        std::auto_ptr<llvm::TargetMachine> target_machine(target->createTargetMachine(m_target_triple, ""));
+        
+        IRForTarget ir_for_target(decl_map, target_machine->getTargetData(), m_expr.FunctionName());
+        
+        if (!ir_for_target.runOnModule(*module))
+        {
+            err.SetErrorToGenericError();
+            err.SetErrorString("Couldn't convert the expression to DWARF");
+            return err;
+        }
+    }
+    
+    m_jit_mm = new RecordingMemoryManager();
+    
+    std::string error_string;
+    
+    m_execution_engine.reset(llvm::ExecutionEngine::createJIT (module, 
+                                                               &error_string, 
+                                                               m_jit_mm,
+                                                               CodeGenOpt::Default,
+                                                               true,
+                                                               CodeModel::Small));
+    
+    if (!m_execution_engine.get())
+    {
+        err.SetErrorToGenericError();
+        err.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
+        return err;
+    }
+    
+    m_execution_engine->DisableLazyCompilation();
+    
+    llvm::Function *function = module->getFunction (m_expr.FunctionName());
+    
+    // We don't actually need the function pointer here, this just forces it to get resolved.
+    
+    void *fun_ptr = m_execution_engine->getPointerToFunction(function);
+    
+    // Errors usually cause failures in the JIT, but if we're lucky we get here.
+    
+    if (!fun_ptr)
+    {
+        err.SetErrorToGenericError();
+        err.SetErrorString("Couldn't JIT the function");
+        return err;
+    }
+    
+    m_jitted_functions.push_back (ClangExpressionParser::JittedFunction(m_expr.FunctionName(), (lldb::addr_t)fun_ptr));
+    
+    ExecutionContext &exc_context(exe_ctx);
+    
+    if (exc_context.process == NULL)
+    {
+        err.SetErrorToGenericError();
+        err.SetErrorString("Couldn't write the JIT compiled code into the target because there is no target");
+        return err;
+    }
+    
+    // Look over the regions allocated for the function compiled.  The JIT
+    // tries to allocate the functions & stubs close together, so we should try to
+    // write them that way too...
+    // For now I only write functions with no stubs, globals, exception tables,
+    // etc.  So I only need to write the functions.
+    
+    size_t alloc_size = 0;
+    
+    std::map<uint8_t *, uint8_t *>::iterator fun_pos = m_jit_mm->m_functions.begin();
+    std::map<uint8_t *, uint8_t *>::iterator fun_end = m_jit_mm->m_functions.end();
+    
+    for (; fun_pos != fun_end; ++fun_pos)
+        alloc_size += (*fun_pos).second - (*fun_pos).first;
+    
+    Error alloc_error;
+    lldb::addr_t target_addr = exc_context.process->AllocateMemory (alloc_size, lldb::ePermissionsReadable|lldb::ePermissionsExecutable, alloc_error);
+    
+    if (target_addr == LLDB_INVALID_ADDRESS)
+    {
+        err.SetErrorToGenericError();
+        err.SetErrorStringWithFormat("Couldn't allocate memory for the JITted function: %s", alloc_error.AsCString("unknown error"));
+        return err;
+    }
+    
+    lldb::addr_t cursor = target_addr;
+        
+    for (fun_pos = m_jit_mm->m_functions.begin(); fun_pos != fun_end; fun_pos++)
+    {
+        lldb::addr_t lstart = (lldb::addr_t) (*fun_pos).first;
+        lldb::addr_t lend = (lldb::addr_t) (*fun_pos).second;
+        size_t size = lend - lstart;
+        
+        Error write_error;
+        
+        if (exc_context.process->WriteMemory(cursor, (void *) lstart, size, write_error) != size)
+        {
+            err.SetErrorToGenericError();
+            err.SetErrorStringWithFormat("Couldn't copy JITted function into the target: %s", write_error.AsCString("unknown error"));
+            return err;
+        }
+            
+        m_jit_mm->AddToLocalToRemoteMap (lstart, size, cursor);
+        cursor += size;
+    }
+    
+    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
+    
+    for (pos = m_jitted_functions.begin(); pos != end; pos++)
+    {
+        (*pos).m_remote_addr = m_jit_mm->GetRemoteAddressForLocal ((*pos).m_local_addr);
+    
+        if (!(*pos).m_name.compare(m_expr.FunctionName()))
+            func_addr = (*pos).m_remote_addr;
+    }
+    
+    err.Clear();
+    return err;
+}
+
+Error
+ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &exe_ctx)
+{
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+    
+    const char *name = m_expr.FunctionName();
+    
+    Error ret;
+    
+    ret.Clear();
+    
+    lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
+    lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
+    
+    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
+    
+    for (pos = m_jitted_functions.begin(); pos < end; pos++)
+    {
+        if (strcmp(pos->m_name.c_str(), name) == 0)
+        {
+            func_local_addr = pos->m_local_addr;
+            func_remote_addr = pos->m_remote_addr;
+        }
+    }
+    
+    if (func_local_addr == LLDB_INVALID_ADDRESS)
+    {
+        ret.SetErrorToGenericError();
+        ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", name);
+        return ret;
+    }
+    
+    if(log)
+        log->Printf("Found function, has local address 0x%llx and remote address 0x%llx", (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
+    
+    std::pair <lldb::addr_t, lldb::addr_t> func_range;
+    
+    func_range = m_jit_mm->GetRemoteRangeForLocal(func_local_addr);
+    
+    if (func_range.first == 0 && func_range.second == 0)
+    {
+        ret.SetErrorToGenericError();
+        ret.SetErrorStringWithFormat("Couldn't find code range for function %s", name);
+        return ret;
+    }
+    
+    if(log)
+        log->Printf("Function's code range is [0x%llx-0x%llx]", func_range.first, func_range.second);
+    
+    if (!exe_ctx.target)
+    {
+        ret.SetErrorToGenericError();
+        ret.SetErrorString("Couldn't find the target");
+    }
+    
+    lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second - func_remote_addr, 0));
+    
+    Error err;
+    exe_ctx.process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);
+    
+    if (!err.Success())
+    {
+        ret.SetErrorToGenericError();
+        ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
+        return ret;
+    }
+    
+    ArchSpec arch(exe_ctx.target->GetArchitecture());
+    
+    Disassembler *disassembler = Disassembler::FindPlugin(arch);
+    
+    if (disassembler == NULL)
+    {
+        ret.SetErrorToGenericError();
+        ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.AsCString());
+        return ret;
+    }
+    
+    if (!exe_ctx.process)
+    {
+        ret.SetErrorToGenericError();
+        ret.SetErrorString("Couldn't find the process");
+        return ret;
+    }
+    
+    DataExtractor extractor(buffer_sp, 
+                            exe_ctx.process->GetByteOrder(),
+                            exe_ctx.target->GetArchitecture().GetAddressByteSize());
+    
+    if(log)
+    {
+        log->Printf("Function data has contents:");
+        extractor.PutToLog (log,
+                            0,
+                            extractor.GetByteSize(),
+                            func_remote_addr,
+                            16,
+                            DataExtractor::TypeUInt8);
+    }
+    
+    disassembler->DecodeInstructions(extractor, 0, UINT32_MAX);
+    
+    Disassembler::InstructionList &instruction_list = disassembler->GetInstructionList();
+    
+    uint32_t bytes_offset = 0;
+    
+    for (uint32_t instruction_index = 0, num_instructions = instruction_list.GetSize(); 
+         instruction_index < num_instructions; 
+         ++instruction_index)
+    {
+        Disassembler::Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index);
+        Address addr(NULL, func_remote_addr + bytes_offset);
+        instruction->Dump (&stream,
+                           &addr,
+                           &extractor, 
+                           bytes_offset, 
+                           exe_ctx, 
+                           true);
+        stream.PutChar('\n');
+        bytes_offset += instruction->GetByteSize();
+    }
+    
+    return ret;
+}

Modified: lldb/trunk/source/Expression/ClangFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangFunction.cpp?rev=112249&r1=112248&r2=112249&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangFunction.cpp (original)
+++ lldb/trunk/source/Expression/ClangFunction.cpp Thu Aug 26 20:01:44 2010
@@ -22,6 +22,8 @@
 #include "llvm/Module.h"
 
 // Project includes
+#include "lldb/Expression/ASTStructExtractor.h"
+#include "lldb/Expression/ClangExpressionParser.h"
 #include "lldb/Expression/ClangFunction.h"
 #include "lldb/Symbol/Type.h"
 #include "lldb/Core/DataExtractor.h"
@@ -40,11 +42,12 @@
 #include "lldb/Core/Log.h"
 
 using namespace lldb_private;
+
 //----------------------------------------------------------------------
 // ClangFunction constructor
 //----------------------------------------------------------------------
 ClangFunction::ClangFunction(const char *target_triple, ClangASTContext *ast_context, void *return_qualtype, const Address& functionAddress, const ValueList &arg_value_list) :
-    ClangExpression (target_triple, NULL),
+    m_target_triple (target_triple),
     m_function_ptr (NULL),
     m_function_addr (functionAddress),
     m_function_return_qual_type(return_qualtype),
@@ -53,18 +56,14 @@
     m_wrapper_struct_name ("__lldb_caller_struct"),
     m_wrapper_function_addr (),
     m_wrapper_args_addrs (),
-    m_struct_layout (NULL),
     m_arg_values (arg_value_list),
-    m_value_struct_size (0),
-    m_return_offset(0),
-    m_return_size (0),
     m_compiled (false),
     m_JITted (false)
 {
 }
 
 ClangFunction::ClangFunction(const char *target_triple, Function &function, ClangASTContext *ast_context, const ValueList &arg_value_list) :
-    ClangExpression (target_triple, NULL),
+    m_target_triple (target_triple),
     m_function_ptr (&function),
     m_function_addr (),
     m_function_return_qual_type (),
@@ -73,11 +72,7 @@
     m_wrapper_struct_name ("__lldb_caller_struct"),
     m_wrapper_function_addr (),
     m_wrapper_args_addrs (),
-    m_struct_layout (NULL),
     m_arg_values (arg_value_list),
-    m_value_struct_size (0),
-    m_return_offset (0),
-    m_return_size (0),
     m_compiled (false),
     m_JITted (false)
 {
@@ -95,154 +90,125 @@
 unsigned
 ClangFunction::CompileFunction (Stream &errors)
 {
+    if (m_compiled)
+        return 0;
+    
     // FIXME: How does clang tell us there's no return value?  We need to handle that case.
     unsigned num_errors = 0;
     
-    if (!m_compiled)
+    std::string return_type_str = ClangASTContext::GetTypeName(m_function_return_qual_type);
+    
+    // Cons up the function we're going to wrap our call in, then compile it...
+    // We declare the function "extern "C"" because the compiler might be in C++
+    // mode which would mangle the name and then we couldn't find it again...
+    m_wrapper_function_text.clear();
+    m_wrapper_function_text.append ("extern \"C\" void ");
+    m_wrapper_function_text.append (m_wrapper_function_name);
+    m_wrapper_function_text.append (" (void *input)\n{\n    struct ");
+    m_wrapper_function_text.append (m_wrapper_struct_name);
+    m_wrapper_function_text.append (" \n  {\n");
+    m_wrapper_function_text.append ("    ");
+    m_wrapper_function_text.append (return_type_str);
+    m_wrapper_function_text.append (" (*fn_ptr) (");
+
+    // Get the number of arguments.  If we have a function type and it is prototyped,
+    // trust that, otherwise use the values we were given.
+
+    // FIXME: This will need to be extended to handle Variadic functions.  We'll need
+    // to pull the defined arguments out of the function, then add the types from the
+    // arguments list for the variable arguments.
+
+    uint32_t num_args = UINT32_MAX;
+    bool trust_function = false;
+    // GetArgumentCount returns -1 for an unprototyped function.
+    if (m_function_ptr)
+    {
+        int num_func_args = m_function_ptr->GetArgumentCount();
+        if (num_func_args >= 0)
+            trust_function = true;
+        else
+            num_args = num_func_args;
+    }
+
+    if (num_args == UINT32_MAX)
+        num_args = m_arg_values.GetSize();
+
+    std::string args_buffer;  // This one stores the definition of all the args in "struct caller".
+    std::string args_list_buffer;  // This one stores the argument list called from the structure.
+    for (size_t i = 0; i < num_args; i++)
     {
-        std::string return_type_str = ClangASTContext::GetTypeName(m_function_return_qual_type);
-        
-        // Cons up the function we're going to wrap our call in, then compile it...
-        // We declare the function "extern "C"" because the compiler might be in C++
-        // mode which would mangle the name and then we couldn't find it again...
-        std::string expression;
-        expression.append ("extern \"C\" void ");
-        expression.append (m_wrapper_function_name);
-        expression.append (" (void *input)\n{\n    struct ");
-        expression.append (m_wrapper_struct_name);
-        expression.append (" \n  {\n");
-        expression.append ("    ");
-        expression.append (return_type_str);
-        expression.append (" (*fn_ptr) (");
-
-        // Get the number of arguments.  If we have a function type and it is prototyped,
-        // trust that, otherwise use the values we were given.
-
-        // FIXME: This will need to be extended to handle Variadic functions.  We'll need
-        // to pull the defined arguments out of the function, then add the types from the
-        // arguments list for the variable arguments.
-
-        uint32_t num_args = UINT32_MAX;
-        bool trust_function = false;
-        // GetArgumentCount returns -1 for an unprototyped function.
-        if (m_function_ptr)
+        const char *type_string;
+        std::string type_stdstr;
+
+        if (trust_function)
         {
-            int num_func_args = m_function_ptr->GetArgumentCount();
-            if (num_func_args >= 0)
-                trust_function = true;
-            else
-                num_args = num_func_args;
+            type_string = m_function_ptr->GetArgumentTypeAtIndex(i).GetName().AsCString();
         }
-
-        if (num_args == UINT32_MAX)
-            num_args = m_arg_values.GetSize();
-
-        std::string args_buffer;  // This one stores the definition of all the args in "struct caller".
-        std::string args_list_buffer;  // This one stores the argument list called from the structure.
-        for (size_t i = 0; i < num_args; i++)
+        else
         {
-            const char *type_string;
-            std::string type_stdstr;
-
-            if (trust_function)
+            Value *arg_value = m_arg_values.GetValueAtIndex(i);
+            void *clang_qual_type = arg_value->GetOpaqueClangQualType ();
+            if (clang_qual_type != NULL)
             {
-                type_string = m_function_ptr->GetArgumentTypeAtIndex(i).GetName().AsCString();
+                type_stdstr = ClangASTContext::GetTypeName(clang_qual_type);
+                type_string = type_stdstr.c_str();
             }
             else
-            {
-                Value *arg_value = m_arg_values.GetValueAtIndex(i);
-                void *clang_qual_type = arg_value->GetOpaqueClangQualType ();
-                if (clang_qual_type != NULL)
-                {
-                    type_stdstr = ClangASTContext::GetTypeName(clang_qual_type);
-                    type_string = type_stdstr.c_str();
-                }
-                else
-                {   
-                    errors.Printf("Could not determine type of input value %d.", i);
-                    return 1;
-                }
+            {   
+                errors.Printf("Could not determine type of input value %d.", i);
+                return 1;
             }
-
-
-            expression.append (type_string);
-            if (i < num_args - 1)
-                expression.append (", ");
-
-            char arg_buf[32];
-            args_buffer.append ("    ");
-            args_buffer.append (type_string);
-            snprintf(arg_buf, 31, "arg_%zd", i);
-            args_buffer.push_back (' ');
-            args_buffer.append (arg_buf);
-            args_buffer.append (";\n");
-
-            args_list_buffer.append ("__lldb_fn_data->");
-            args_list_buffer.append (arg_buf);
-            if (i < num_args - 1)
-                args_list_buffer.append (", ");
-
         }
-        expression.append (");\n"); // Close off the function calling prototype.
 
-        expression.append (args_buffer);
+        m_wrapper_function_text.append (type_string);
+        if (i < num_args - 1)
+            m_wrapper_function_text.append (", ");
+
+        char arg_buf[32];
+        args_buffer.append ("    ");
+        args_buffer.append (type_string);
+        snprintf(arg_buf, 31, "arg_%zd", i);
+        args_buffer.push_back (' ');
+        args_buffer.append (arg_buf);
+        args_buffer.append (";\n");
+
+        args_list_buffer.append ("__lldb_fn_data->");
+        args_list_buffer.append (arg_buf);
+        if (i < num_args - 1)
+            args_list_buffer.append (", ");
+
+    }
+    m_wrapper_function_text.append (");\n"); // Close off the function calling prototype.
+
+    m_wrapper_function_text.append (args_buffer);
+
+    m_wrapper_function_text.append ("    ");
+    m_wrapper_function_text.append (return_type_str);
+    m_wrapper_function_text.append (" return_value;");
+    m_wrapper_function_text.append ("\n  };\n  struct ");
+    m_wrapper_function_text.append (m_wrapper_struct_name);
+    m_wrapper_function_text.append ("* __lldb_fn_data = (struct ");
+    m_wrapper_function_text.append (m_wrapper_struct_name);
+    m_wrapper_function_text.append (" *) input;\n");
+
+    m_wrapper_function_text.append ("  __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr (");
+    m_wrapper_function_text.append (args_list_buffer);
+    m_wrapper_function_text.append (");\n}\n");
 
-        expression.append ("    ");
-        expression.append (return_type_str);
-        expression.append (" return_value;");
-        expression.append ("\n  };\n  struct ");
-        expression.append (m_wrapper_struct_name);
-        expression.append ("* __lldb_fn_data = (struct ");
-        expression.append (m_wrapper_struct_name);
-        expression.append (" *) input;\n");
-
-        expression.append ("  __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr (");
-        expression.append (args_list_buffer);
-        expression.append (");\n}\n");
-
-        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
-        if (log)
-            log->Printf ("Expression: \n\n%s\n\n", expression.c_str());
-            
-        // Okay, now compile this expression:
-        num_errors = ParseBareExpression (expression.c_str(), errors);
-        m_compiled = (num_errors == 0);
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+    if (log)
+        log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str());
         
-        if (m_compiled)
-        {
-            using namespace clang;
-            CompilerInstance *compiler_instance = GetCompilerInstance();
-            ASTContext &ast_context = compiler_instance->getASTContext();
-
-            DeclarationName wrapper_func_name(&ast_context.Idents.get(m_wrapper_function_name.c_str()));
-            FunctionDecl::lookup_result func_lookup = ast_context.getTranslationUnitDecl()->lookup(wrapper_func_name);
-            if (func_lookup.first == func_lookup.second)
-                return false;
-
-            FunctionDecl *wrapper_func = dyn_cast<FunctionDecl> (*(func_lookup.first));
-            if (!wrapper_func)
-                return false;
-
-            DeclarationName wrapper_struct_name(&ast_context.Idents.get(m_wrapper_struct_name.c_str()));
-            RecordDecl::lookup_result struct_lookup = wrapper_func->lookup(wrapper_struct_name);
-            if (struct_lookup.first == struct_lookup.second)
-                return false;
-
-            RecordDecl *wrapper_struct = dyn_cast<RecordDecl>(*(struct_lookup.first));
-
-            if (!wrapper_struct)
-                return false;
-
-            m_struct_layout = &ast_context.getASTRecordLayout (wrapper_struct);
-            if (!m_struct_layout)
-            {
-                m_compiled = false;
-                return 1;
-            }
-            m_return_offset = m_struct_layout->getFieldOffset(m_struct_layout->getFieldCount() - 1);
-            m_return_size = (m_struct_layout->getDataSize() - m_return_offset)/8;
-        }
-    }
+    // Okay, now compile this expression
+    
+    m_parser.reset(new ClangExpressionParser(m_target_triple.c_str(), *this));
+    
+    num_errors = m_parser->Parse (errors);
+    
+    m_compiled = (num_errors == 0);
+    
+    if (!m_compiled)
+        return num_errors;
 
     return num_errors;
 }
@@ -252,24 +218,18 @@
 {
     Process *process = exe_ctx.process;
 
-    if (process == NULL)
+    if (!process)
+        return false;
+    
+    if (!m_compiled)
         return false;
 
-    if (!m_JITted)
-    {
-        // Next we should JIT it and insert the result into the target program.
-        if (!JITFunction (m_wrapper_function_name.c_str()))
-            return false;
-
-        if (!WriteJITCode (exe_ctx))
-            return false;
-
-        m_JITted = true;
-    }
-
-    // Next get the call address for the function:
-    m_wrapper_function_addr = GetFunctionAddress (m_wrapper_function_name.c_str());
-    if (m_wrapper_function_addr == LLDB_INVALID_ADDRESS)
+    if (m_JITted)
+        return true;
+    
+    Error jit_error = m_parser->MakeJIT(m_wrapper_function_addr, exe_ctx);
+    
+    if (!jit_error.Success())
         return false;
 
     return true;
@@ -286,12 +246,14 @@
 bool
 ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Address function_address, ValueList &arg_values, Stream &errors)
 {
-    // Otherwise, allocate space for the argument passing struct, and write it.
-    // We use the information in the expression parser AST to
-    // figure out how to do this...
-    // We should probably transcode this in this object so we can ditch the compiler instance
-    // and all its associated data, and just keep the JITTed bytes.
-
+    // All the information to reconstruct the struct is provided by the
+    // StructExtractor.
+    if (!m_struct_valid)
+    {
+        errors.Printf("Argument information was not correctly parsed, so the function cannot be called.");
+        return false;
+    }
+        
     Error error;
     using namespace clang;
     ExecutionResults return_value = eExecutionSetupError;
@@ -300,12 +262,10 @@
 
     if (process == NULL)
         return return_value;
-        
-    uint64_t struct_size = m_struct_layout->getSize()/8; // Clang returns sizes in bytes.
-    
+                
     if (args_addr_ref == LLDB_INVALID_ADDRESS)
     {
-        args_addr_ref = process->AllocateMemory(struct_size, lldb::ePermissionsReadable|lldb::ePermissionsWritable, error);
+        args_addr_ref = process->AllocateMemory(m_struct_size, lldb::ePermissionsReadable|lldb::ePermissionsWritable, error);
         if (args_addr_ref == LLDB_INVALID_ADDRESS)
             return false;
         m_wrapper_args_addrs.push_back (args_addr_ref);
@@ -323,7 +283,7 @@
     // Make a data extractor and put the address into the right byte order & size.
 
     uint64_t fun_addr = function_address.GetLoadAddress(exe_ctx.process);
-    int first_offset = m_struct_layout->getFieldOffset(0)/8;
+    int first_offset = m_member_offsets[0];
     process->WriteMemory(args_addr_ref + first_offset, &fun_addr, 8, error);
 
     // FIXME: We will need to extend this for Variadic functions.
@@ -341,7 +301,7 @@
     {
         // FIXME: We should sanity check sizes.
 
-        int offset = m_struct_layout->getFieldOffset(i+1)/8; // Clang sizes are in bytes.
+        int offset = m_member_offsets[i+1]; // Clang sizes are in bytes.
         Value *arg_value = arg_values.GetValueAtIndex(i);
         
         // FIXME: For now just do scalars:
@@ -419,7 +379,7 @@
     data_buffer.resize(m_return_size);
     Process *process = exe_ctx.process;
     Error error;
-    size_t bytes_read = process->ReadMemory(args_addr + m_return_offset/8, &data_buffer.front(), m_return_size, error);
+    size_t bytes_read = process->ReadMemory(args_addr + m_return_offset, &data_buffer.front(), m_return_size, error);
 
     if (bytes_read == 0)
     {
@@ -717,69 +677,8 @@
     return eExecutionCompleted;
 }
 
-ClangFunction::ExecutionResults
-ClangFunction::ExecuteFunctionWithABI(ExecutionContext &exe_ctx, Stream &errors, Value &results)
+clang::ASTConsumer *
+ClangFunction::ASTTransformer (clang::ASTConsumer *passthrough)
 {
-    // FIXME: Use the errors Stream for better error reporting. 
-    using namespace clang;
-    ExecutionResults return_value = eExecutionSetupError;
-    
-    Process *process = exe_ctx.process;
-    
-    if (process == NULL)
-    {
-        errors.Printf("Can't call a function without a process.");
-        return return_value;
-    }
-    
-    //unsigned int num_args = m_arg_values.GetSize();
-    //unsigned int arg_index;
-    
-    //for (arg_index = 0; arg_index < num_args; ++arg_index)
-    //    m_arg_values.GetValueAtIndex(arg_index)->ResolveValue(&exe_ctx, GetASTContext());
-    
-    ThreadPlan *call_plan = exe_ctx.thread->QueueThreadPlanForCallFunction (false,
-                                                                                m_function_addr,
-                                                                                m_arg_values,
-                                                                                true);
-    if (call_plan == NULL)
-        return return_value;
-    
-    call_plan->SetPrivate(true);
-    
-    // We need to call the function synchronously, so spin waiting for it to return.
-    // If we get interrupted while executing, we're going to lose our context, and 
-    // won't be able to gather the result at this point.
-    
-    process->Resume ();
-    
-    while (1)
-    {
-        lldb::EventSP event_sp;
-        
-        // Now wait for the process to stop again:
-        // FIXME: Probably want a time out.
-        lldb::StateType stop_state =  process->WaitForStateChangedEvents (NULL, event_sp);
-        if (stop_state == lldb::eStateRunning || stop_state == lldb::eStateStepping)
-            continue;
-        
-        if (exe_ctx.thread->IsThreadPlanDone (call_plan))
-        {
-            return_value = eExecutionCompleted;
-            break;
-        }
-        else if (exe_ctx.thread->WasThreadPlanDiscarded (call_plan))
-        {
-            return_value = eExecutionDiscarded;
-            break;
-        }
-        else
-        {
-            return_value = eExecutionInterrupted;
-            break;
-        }
-        
-    }
-    
-    return eExecutionCompleted;
+    return new ASTStructExtractor(passthrough, m_wrapper_struct_name.c_str(), *this);
 }

Removed: lldb/trunk/source/Expression/ClangResultSynthesizer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangResultSynthesizer.cpp?rev=112248&view=auto
==============================================================================
--- lldb/trunk/source/Expression/ClangResultSynthesizer.cpp (original)
+++ lldb/trunk/source/Expression/ClangResultSynthesizer.cpp (removed)
@@ -1,265 +0,0 @@
-//===-- ClangResultSynthesizer.cpp ------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "stdlib.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclGroup.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/Stmt.h"
-#include "clang/Parse/Action.h"
-#include "clang/Parse/Parser.h"
-#include "clang/Parse/Scope.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/raw_ostream.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Expression/ClangResultSynthesizer.h"
-
-using namespace llvm;
-using namespace clang;
-using namespace lldb_private;
-
-ClangResultSynthesizer::ClangResultSynthesizer(ASTConsumer *passthrough) :
-    m_ast_context (NULL),
-    m_passthrough (passthrough),
-    m_passthrough_sema (NULL),
-    m_sema (NULL),
-    m_action (NULL)
-{
-    if (!m_passthrough)
-        return;
-    
-    m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
-}
-
-ClangResultSynthesizer::~ClangResultSynthesizer()
-{
-}
-
-void
-ClangResultSynthesizer::Initialize(ASTContext &Context) 
-{
-    m_ast_context = &Context;
-    
-    if (m_passthrough)
-        m_passthrough->Initialize(Context);
-}
-
-void
-ClangResultSynthesizer::TransformTopLevelDecl(Decl* D)
-{
-    LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D);
-    
-    if (linkage_spec_decl)
-    {
-        RecordDecl::decl_iterator decl_iterator;
-        
-        for (decl_iterator = linkage_spec_decl->decls_begin();
-             decl_iterator != linkage_spec_decl->decls_end();
-             ++decl_iterator)
-        {
-            TransformTopLevelDecl(*decl_iterator);
-        }
-    }
-    
-    FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D);
-    
-    if (m_ast_context &&
-        function_decl &&
-        !strcmp(function_decl->getNameAsCString(),
-                "___clang_expr"))
-    {
-        SynthesizeResult(function_decl);
-    }
-}
-
-void 
-ClangResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D)
-{
-    DeclGroupRef::iterator decl_iterator;
-    
-    for (decl_iterator = D.begin();
-         decl_iterator != D.end();
-         ++decl_iterator)
-    {
-        Decl *decl = *decl_iterator;
-        
-        TransformTopLevelDecl(decl);
-    }
-    
-    if (m_passthrough)
-        m_passthrough->HandleTopLevelDecl(D);
-}
-
-bool 
-ClangResultSynthesizer::SynthesizeResult (FunctionDecl *FunDecl)
-{
-    ASTContext &Ctx(*m_ast_context);
-    
-    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-    
-    if (!m_sema)
-        return false;
-
-    FunctionDecl *function_decl = FunDecl;
-    
-    if (!function_decl)
-        return false;
-    
-    Stmt *function_body = function_decl->getBody();
-    CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body);
-    
-    if (!compound_stmt)
-        return false;
-    
-    if (compound_stmt->body_empty())
-        return false;
-    
-    Stmt **last_stmt_ptr = compound_stmt->body_end() - 1;
-    Stmt *last_stmt = *last_stmt_ptr;
-    
-    Expr *last_expr = dyn_cast<Expr>(last_stmt);
-    
-    if (!last_expr)
-        // No auxiliary variable necessary; expression returns void
-        return true;
-    
-    QualType expr_qual_type = last_expr->getType();
-    clang::Type *expr_type = expr_qual_type.getTypePtr();
-    
-    if (!expr_type)
-        return false;
-    
-    if (expr_type->isVoidType())
-        return true;
-    
-    if (log)
-    {
-        std::string s = expr_qual_type.getAsString();
-        
-        log->Printf("Last statement's type: %s", s.c_str());
-    }
-    
-    IdentifierInfo &result_id = Ctx.Idents.get("___clang_expr_result");
-        
-    clang::VarDecl *result_decl = VarDecl::Create(Ctx, 
-                                                  function_decl, 
-                                                  SourceLocation(), 
-                                                  &result_id, 
-                                                  expr_qual_type, 
-                                                  NULL, 
-                                                  VarDecl::Static, 
-                                                  VarDecl::Static);
-    
-    if (!result_decl)
-        return false;
-    
-    function_decl->addDecl(result_decl);
-    
-    ///////////////////////////////
-    // call AddInitializerToDecl
-    //
-    
-    Parser::DeclPtrTy result_decl_ptr;
-    result_decl_ptr.set(result_decl);
-    
-    m_action->AddInitializerToDecl(result_decl_ptr, Parser::ExprArg(*m_action, last_expr));
-    
-    /////////////////////////////////
-    // call ConvertDeclToDeclGroup
-    //
-    
-    Parser::DeclGroupPtrTy result_decl_group_ptr;
-    
-    result_decl_group_ptr = m_action->ConvertDeclToDeclGroup(result_decl_ptr);
-    
-    ////////////////////////
-    // call ActOnDeclStmt
-    //
-    
-    Parser::OwningStmtResult result_initialization_stmt_result(m_action->ActOnDeclStmt(result_decl_group_ptr,
-                                                                                       SourceLocation(),
-                                                                                       SourceLocation()));
-    
-    ////////////////////////////////////////////////
-    // replace the old statement with the new one
-    //
-    
-    *last_stmt_ptr = reinterpret_cast<Stmt*>(result_initialization_stmt_result.take());
-
-    if (log)
-    {
-        std::string s;
-        raw_string_ostream os(s);
-        
-        function_decl->print(os);
-        
-        os.flush();
-        
-        log->Printf("Transformed function AST:\n%s", s.c_str());
-    }
-    
-    return true;
-}
-
-void
-ClangResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
-{    
-    if (m_passthrough)
-        m_passthrough->HandleTranslationUnit(Ctx);
-}
-
-void 
-ClangResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
-{
-    if (m_passthrough)
-        m_passthrough->HandleTagDeclDefinition(D);
-}
-
-void
-ClangResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
-{
-    if (m_passthrough)
-        m_passthrough->CompleteTentativeDefinition(D);
-}
-
-void 
-ClangResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) 
-{
-    if (m_passthrough)
-        m_passthrough->HandleVTable(RD, DefinitionRequired);
-}
-
-void
-ClangResultSynthesizer::PrintStats() 
-{
-    if (m_passthrough)
-        m_passthrough->PrintStats();
-}
-
-void
-ClangResultSynthesizer::InitializeSema(Sema &S)
-{
-    m_sema = &S;
-    m_action = reinterpret_cast<Action*>(m_sema);
-    
-    if (m_passthrough_sema)
-        m_passthrough_sema->InitializeSema(S);
-}
-
-void 
-ClangResultSynthesizer::ForgetSema() 
-{
-    m_sema = NULL;
-    m_action = NULL;
-    
-    if (m_passthrough_sema)
-        m_passthrough_sema->ForgetSema();
-}

Copied: lldb/trunk/source/Expression/ClangUserExpression.cpp (from r111952, lldb/trunk/source/Expression/ClangExpression.cpp)
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUserExpression.cpp?p2=lldb/trunk/source/Expression/ClangUserExpression.cpp&p1=lldb/trunk/source/Expression/ClangExpression.cpp&r1=111952&r2=112249&rev=112249&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpression.cpp (original)
+++ lldb/trunk/source/Expression/ClangUserExpression.cpp Thu Aug 26 20:01:44 2010
@@ -1,4 +1,4 @@
-//===-- ClangExpression.cpp -------------------------------------*- C++ -*-===//
+//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -18,731 +18,240 @@
 #include <string>
 #include <map>
 
-// Other libraries and framework includes
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/ExternalASTSource.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/Version.h"
-#include "clang/Checker/FrontendActions.h"
-#include "clang/CodeGen/CodeGenAction.h"
-#include "clang/CodeGen/ModuleBuilder.h"
-#include "clang/Driver/CC1Options.h"
-#include "clang/Driver/OptTable.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/CompilerInvocation.h"
-#include "clang/Frontend/FrontendActions.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
-#include "clang/Frontend/FrontendPluginRegistry.h"
-#include "clang/Frontend/TextDiagnosticBuffer.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
-#include "clang/Frontend/VerifyDiagnosticsClient.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Rewrite/FrontendActions.h"
-#include "clang/Sema/ParseAST.h"
-#include "clang/Sema/SemaConsumer.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/JIT.h"
-#include "llvm/Module.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/LLVMContext.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/System/DynamicLibrary.h"
-#include "llvm/System/Host.h"
-#include "llvm/System/Signals.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/TargetSelect.h"
-
-// Project includes
+#include "lldb/Core/ConstString.h"
 #include "lldb/Core/Log.h"
-#include "lldb/Core/ClangForward.h"
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/Disassembler.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangASTSource.h"
-#include "lldb/Expression/ClangResultSynthesizer.h"
-#include "lldb/Expression/IRForTarget.h"
-#include "lldb/Expression/IRToDWARF.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Expression/RecordingMemoryManager.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "lldb/Expression/ClangExpressionParser.h"
+#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Expression/ASTResultSynthesizer.h"
+#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Host/Host.h"
 #include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
 
-#include "lldb/Core/StreamString.h"
-#include "lldb/Host/Mutex.h"
-
-
 using namespace lldb_private;
-using namespace clang;
-using namespace llvm;
-
 
-//===----------------------------------------------------------------------===//
-// Utility Methods
-//===----------------------------------------------------------------------===//
-
-std::string GetBuiltinIncludePath(const char *Argv0) {
-  llvm::sys::Path P =
-    llvm::sys::Path::GetMainExecutable(Argv0,
-                                       (void*)(intptr_t) GetBuiltinIncludePath);
-
-  if (!P.isEmpty()) {
-    P.eraseComponent();  // Remove /clang from foo/bin/clang
-    P.eraseComponent();  // Remove /bin   from foo/bin
-
-    // Get foo/lib/clang/<version>/include
-    P.appendComponent("lib");
-    P.appendComponent("clang");
-    P.appendComponent(CLANG_VERSION_STRING);
-    P.appendComponent("include");
-  }
-
-  return P.str();
-}
-
-
-//===----------------------------------------------------------------------===//
-// Main driver
-//===----------------------------------------------------------------------===//
-
-static void LLVMErrorHandler(void *UserData, const std::string &Message) {
-  Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
-
-  Diags.Report(diag::err_fe_error_backend) << Message;
-
-  // We cannot recover from llvm errors.
-  exit(1);
-}
-
-static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
-  using namespace clang::frontend;
-
-  switch (CI.getFrontendOpts().ProgramAction) {
-  default:
-    llvm_unreachable("Invalid program action!");
-
-  case ASTDump:                return new ASTDumpAction();
-  case ASTPrint:               return new ASTPrintAction();
-  case ASTPrintXML:            return new ASTPrintXMLAction();
-  case ASTView:                return new ASTViewAction();
-  case BoostCon:               return new BoostConAction();
-  case DumpRawTokens:          return new DumpRawTokensAction();
-  case DumpTokens:             return new DumpTokensAction();
-  case EmitAssembly:           return new EmitAssemblyAction();
-  case EmitBC:                 return new EmitBCAction();
-  case EmitHTML:               return new HTMLPrintAction();
-  case EmitLLVM:               return new EmitLLVMAction();
-  case EmitLLVMOnly:           return new EmitLLVMOnlyAction();
-  case EmitCodeGenOnly:        return new EmitCodeGenOnlyAction();
-  case EmitObj:                return new EmitObjAction();
-  case FixIt:                  return new FixItAction();
-  case GeneratePCH:            return new GeneratePCHAction();
-  case GeneratePTH:            return new GeneratePTHAction();
-  case InheritanceView:        return new InheritanceViewAction();
-  case InitOnly:               return new InitOnlyAction();
-  case ParseSyntaxOnly:        return new SyntaxOnlyAction();
-
-  case PluginAction: {
-    for (FrontendPluginRegistry::iterator it =
-           FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
-         it != ie; ++it) {
-      if (it->getName() == CI.getFrontendOpts().ActionName) {
-        llvm::OwningPtr<PluginASTAction> P(it->instantiate());
-        if (!P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs))
-          return 0;
-        return P.take();
-      }
-    }
-
-    CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
-      << CI.getFrontendOpts().ActionName;
-    return 0;
-  }
-
-  case PrintDeclContext:       return new DeclContextPrintAction();
-  case PrintPreamble:          return new PrintPreambleAction();
-  case PrintPreprocessedInput: return new PrintPreprocessedAction();
-  case RewriteMacros:          return new RewriteMacrosAction();
-  case RewriteObjC:            return new RewriteObjCAction();
-  case RewriteTest:            return new RewriteTestAction();
-  case RunAnalysis:            return new AnalysisAction();
-  case RunPreprocessorOnly:    return new PreprocessOnlyAction();
-  }
-}
-
-static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
-  // Create the underlying action.
-  FrontendAction *Act = CreateFrontendBaseAction(CI);
-  if (!Act)
-    return 0;
-
-  // If there are any AST files to merge, create a frontend action
-  // adaptor to perform the merge.
-  if (!CI.getFrontendOpts().ASTMergeFiles.empty())
-    Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0],
-                             CI.getFrontendOpts().ASTMergeFiles.size());
-
-  return Act;
-}
-
-//----------------------------------------------------------------------
-// ClangExpression constructor
-//----------------------------------------------------------------------
-ClangExpression::ClangExpression(const char *target_triple,
-                                 ClangExpressionDeclMap *decl_map) :
-    m_target_triple (),
-    m_decl_map (decl_map),
-    m_clang_ap (),
-    m_code_generator_ptr (NULL),
-    m_jit_mm_ptr (NULL),
-    m_execution_engine (),
-    m_jitted_functions ()
+ClangUserExpression::ClangUserExpression (const char *expr) :
+    m_expr_text(expr),
+    m_jit_addr(LLDB_INVALID_ADDRESS)
 {
-    if (target_triple && target_triple[0])
-        m_target_triple = target_triple;
-    else
-        m_target_triple = llvm::sys::getHostTriple();
+    StreamString m_transformed_stream;
+    
+    m_transformed_stream.Printf("extern \"C\" void %s(void *___clang_arg) { %s; }\n",
+                                FunctionName(),
+                                m_expr_text.c_str());
+    
+    m_transformed_text = m_transformed_stream.GetData();
 }
 
-
-//----------------------------------------------------------------------
-// Destructor
-//----------------------------------------------------------------------
-ClangExpression::~ClangExpression()
+clang::ASTConsumer *
+ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
 {
-    if (m_code_generator_ptr && !m_execution_engine.get())
-        delete m_code_generator_ptr;
+    return new ASTResultSynthesizer(passthrough);
 }
 
-bool
-ClangExpression::CreateCompilerInstance ()
+bool 
+ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx)
 {
-    // Initialize targets first, so that --version shows registered targets.
-    static struct InitializeLLVM {
-        InitializeLLVM() {
-            llvm::InitializeAllTargets();
-            llvm::InitializeAllAsmPrinters();
-        }
-    } InitializeLLVM;
-
-    // 1. Create a new compiler instance.
-    m_clang_ap.reset(new CompilerInstance());    
-    m_clang_ap->setLLVMContext(new LLVMContext());
-    
-    // 2. Set options.
-
-    // Parse expressions as Objective C++ regardless of context.
-    // Our hook into Clang's lookup mechanism only works in C++.
-    m_clang_ap->getLangOpts().CPlusPlus = true;
-    m_clang_ap->getLangOpts().ObjC1 = true;
-    m_clang_ap->getLangOpts().ThreadsafeStatics = false;
-    m_clang_ap->getLangOpts().AccessControl = false; // Debuggers get universal access
-    m_clang_ap->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name
-    
-    // Set CodeGen options
-    m_clang_ap->getCodeGenOpts().EmitDeclMetadata = true;
-    m_clang_ap->getCodeGenOpts().InstrumentFunctions = false;
-
-    // Disable some warnings.
-    m_clang_ap->getDiagnosticOpts().Warnings.push_back("no-unused-value");
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
     
-    // Set the target triple.
-    m_clang_ap->getTargetOpts().Triple = m_target_triple;
+    ////////////////////////////////////
+    // Set up the target and compiler
+    //
     
-    // 3. Set up various important bits of infrastructure.
+    Target *target = exe_ctx.target;
     
-    m_clang_ap->createDiagnostics(0, 0);
-
-    // Create the target instance.
-    m_clang_ap->setTarget(TargetInfo::CreateTargetInfo(m_clang_ap->getDiagnostics(),
-                                                       m_clang_ap->getTargetOpts()));
-    if (!m_clang_ap->hasTarget())
+    if (!target)
     {
-        m_clang_ap.reset();
+        error_stream.PutCString ("error: invalid target\n");
         return false;
     }
-
-    // Inform the target of the language options
-    //
-    // FIXME: We shouldn't need to do this, the target should be immutable once
-    // created. This complexity should be lifted elsewhere.
-    m_clang_ap->getTarget().setForcedLangOptions(m_clang_ap->getLangOpts());
-
-    return m_clang_ap.get();
-}
-
-Mutex &
-ClangExpression::GetClangMutex ()
-{
-    static Mutex g_clang_mutex(Mutex::eMutexTypeRecursive);  // Control access to the clang compiler
-    return g_clang_mutex;
-}
-
-
-clang::ASTContext *
-ClangExpression::GetASTContext ()
-{
-    CompilerInstance *compiler_instance = GetCompilerInstance();
-    if (compiler_instance)
-        return &compiler_instance->getASTContext();
-    return NULL;
-}
-
-unsigned
-ClangExpression::ParseExpression (const char *expr_text,
-                                  Stream &stream,
-                                  bool add_result_var)
-{
-    // HACK: for now we have to make a function body around our expression
-    // since there is no way to parse a single expression line in LLVM/Clang.
-    std::string func_expr("extern \"C\" void ___clang_expr(void *___clang_arg)\n{\n\t");
-    func_expr.append(expr_text);
-    func_expr.append(";\n}");
-    return ParseBareExpression (func_expr, stream, add_result_var);
-
-}
-
-unsigned
-ClangExpression::ParseBareExpression (llvm::StringRef expr_text, 
-                                      Stream &stream,
-                                      bool add_result_var)
-{
-    Mutex::Locker locker(GetClangMutex ());
-
-    TextDiagnosticBuffer text_diagnostic_buffer;
-
-    if (!CreateCompilerInstance ())
-    {
-        stream.Printf("error: couldn't create compiler instance\n");
-        return 1;
-    }
     
-    // This code is matched below by a setClient to NULL.
-    // We cannot return out of this code without doing that.
-    m_clang_ap->getDiagnostics().setClient(&text_diagnostic_buffer);
-    text_diagnostic_buffer.FlushDiagnostics (m_clang_ap->getDiagnostics());
-    
-    MemoryBuffer *memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__);
-
-    if (!m_clang_ap->hasSourceManager())
-        m_clang_ap->createSourceManager();
-
-    m_clang_ap->createFileManager();
-    m_clang_ap->createPreprocessor();
-    
-    // Build the ASTContext.  Most of this we inherit from the
-    // CompilerInstance, but we also want to give the context
-    // an ExternalASTSource.
-    SelectorTable selector_table;
-    std::auto_ptr<Builtin::Context> builtin_ap(new Builtin::Context(m_clang_ap->getTarget()));
-    ASTContext *Context = new ASTContext(m_clang_ap->getLangOpts(),
-                                         m_clang_ap->getSourceManager(),
-                                         m_clang_ap->getTarget(),
-                                         m_clang_ap->getPreprocessor().getIdentifierTable(),
-                                         selector_table,
-                                         *builtin_ap.get(),
-                                         0);
+    ConstString target_triple;
     
-    llvm::OwningPtr<ExternalASTSource> ASTSource(new ClangASTSource(*Context, *m_decl_map));
-
-    if (m_decl_map)
-    {
-        Context->setExternalSource(ASTSource);
-    }
+    target->GetTargetTriple (target_triple);
     
-    m_clang_ap->setASTContext(Context);
-
-    FileID memory_buffer_file_id = m_clang_ap->getSourceManager().createMainFileIDForMemBuffer (memory_buffer);
-    std::string module_name("test_func");
-    text_diagnostic_buffer.BeginSourceFile(m_clang_ap->getLangOpts(), &m_clang_ap->getPreprocessor());
-
-    if (m_code_generator_ptr)
-        delete m_code_generator_ptr;
+    if (!target_triple)
+        target_triple = Host::GetTargetTriple ();
     
-    m_code_generator_ptr = CreateLLVMCodeGen(m_clang_ap->getDiagnostics(),
-                                             module_name,
-                                             m_clang_ap->getCodeGenOpts(),
-                                             m_clang_ap->getLLVMContext());
-
-
-    // - CodeGeneration ASTConsumer (include/clang/ModuleBuilder.h), which will be passed in when you call...
-    // - Call clang::ParseAST (in lib/Sema/ParseAST.cpp) to parse the buffer. The CodeGenerator will generate code for __dbg_expr.
-    // - Once ParseAST completes, you can grab the llvm::Module from the CodeGenerator, which will have an llvm::Function you can hand off to the JIT.
-    
-    if (add_result_var)
+    if (!target_triple)
     {
-        ClangResultSynthesizer result_synthesizer(m_code_generator_ptr);
-        ParseAST(m_clang_ap->getPreprocessor(), &result_synthesizer, m_clang_ap->getASTContext());
-    }
-    else 
-    {
-        ParseAST(m_clang_ap->getPreprocessor(), m_code_generator_ptr, m_clang_ap->getASTContext());
+        error_stream.PutCString ("error: invalid target triple\n");
+        return false;
     }
-
-    
-    text_diagnostic_buffer.EndSourceFile();
-
-    //compiler_instance->getASTContext().getTranslationUnitDecl()->dump();
-
-    //if (compiler_instance->getFrontendOpts().ShowStats) {
-    //    compiler_instance->getFileManager().PrintStats();
-    //    fprintf(stderr, "\n");
-    //}
-    
-    // This code resolves the setClient above.
-    m_clang_ap->getDiagnostics().setClient(0);
-    
-    TextDiagnosticBuffer::const_iterator diag_iterator;
+        
+    //////////////////////////
+    // Parse the expression
+    //
     
-    int num_errors = 0;
-
-#ifdef COUNT_WARNINGS_AND_ERRORS
-    int num_warnings = 0;
+    m_expr_decl_map.reset(new ClangExpressionDeclMap(&exe_ctx));
     
-    for (diag_iterator = text_diagnostic_buffer.warn_begin();
-         diag_iterator != text_diagnostic_buffer.warn_end();
-         ++diag_iterator)
-        num_warnings++;
+    ClangExpressionParser parser(target_triple.GetCString(), *this);
     
-    for (diag_iterator = text_diagnostic_buffer.err_begin();
-         diag_iterator != text_diagnostic_buffer.err_end();
-         ++diag_iterator)
-        num_errors++;    
+    unsigned num_errors = parser.Parse (error_stream);
     
-    if (num_warnings || num_errors)
+    if (num_errors)
     {
-        if (num_warnings)
-            stream.Printf("%u warning%s%s", num_warnings, (num_warnings == 1 ? "" : "s"), (num_errors ? " and " : ""));
-        if (num_errors)
-            stream.Printf("%u error%s", num_errors, (num_errors == 1 ? "" : "s"));
-        stream.Printf("\n");
-    }
-#endif
-    
-    for (diag_iterator = text_diagnostic_buffer.warn_begin();
-         diag_iterator != text_diagnostic_buffer.warn_end();
-         ++diag_iterator)
-        stream.Printf("warning: %s\n", (*diag_iterator).second.c_str());
-    
-    num_errors = 0;
-    
-    for (diag_iterator = text_diagnostic_buffer.err_begin();
-         diag_iterator != text_diagnostic_buffer.err_end();
-         ++diag_iterator)
-    {
-        num_errors++;
-        stream.Printf("error: %s\n", (*diag_iterator).second.c_str());
+        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
+        return false;
     }
     
-    return num_errors;
-}
+    ///////////////////////////////////////////////
+    // Convert the output of the parser to DWARF
+    //
 
-bool
-ClangExpression::ConvertIRToDWARF (ClangExpressionVariableList &expr_local_variable_list,
-                                   StreamString &dwarf_opcode_strm)
-{
-    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+    m_dwarf_opcodes.reset(new StreamString);
+    m_dwarf_opcodes->SetByteOrder (lldb::eByteOrderHost);
+    m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);
     
-    llvm::Module *module = m_code_generator_ptr->GetModule();
-        
-    if (!module)
+    m_local_variables.reset(new ClangExpressionVariableStore());
+            
+    Error dwarf_error = parser.MakeDWARF ();
+    
+    if (dwarf_error.Success())
     {
         if (log)
-            log->Printf("IR doesn't contain a module");
+            log->Printf("Code can be interpreted.");
         
-        return 1;
+        return true;
     }
     
-    IRToDWARF ir_to_dwarf(expr_local_variable_list, m_decl_map, dwarf_opcode_strm);
+    //////////////////////////////////
+    // JIT the output of the parser
+    //
     
-    return ir_to_dwarf.runOnModule(*module);
-}
-
-bool
-ClangExpression::PrepareIRForTarget ()
-{
-    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+    m_dwarf_opcodes.reset();
     
-    llvm::Module *module = m_code_generator_ptr->GetModule();
+    Error jit_error = parser.MakeJIT (m_jit_addr, exe_ctx);
     
-    if (!module)
+    if (jit_error.Success())
     {
         if (log)
-            log->Printf("IR doesn't contain a module");
+        {
+            log->Printf("Code can be run in the target.");
+            
+            StreamString disassembly_stream;
+            
+            Error err = parser.DisassembleFunction(disassembly_stream, exe_ctx);
+            
+            if (!err.Success())
+            {
+                log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
+            }
+            else
+            {
+                log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
+            }
+        }
         
-        return 1;
+        return true;
     }
-    
-    llvm::Triple target_triple = m_clang_ap->getTarget().getTriple();
-    
-    std::string err;
-    
-    const llvm::Target *target = llvm::TargetRegistry::lookupTarget(m_target_triple, err);
-    
-    if (!target)
+    else
     {
-        if (log)
-            log->Printf("Couldn't find a target for %s", m_target_triple.c_str());
-        
-        return 1;
+        error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors);
+        return false;
     }
-    
-    std::auto_ptr<llvm::TargetMachine> target_machine(target->createTargetMachine(m_target_triple, ""));
-    
-    IRForTarget ir_for_target(m_decl_map, target_machine->getTargetData());
-    
-    return ir_for_target.runOnModule(*module);
 }
 
 bool
-ClangExpression::JITFunction (const char *name)
+ClangUserExpression::Execute (Stream &error_stream,
+                              ExecutionContext &exe_ctx,
+                              ClangExpressionVariable *&result)
 {
     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
 
-    llvm::Module *module = m_code_generator_ptr->GetModule();
-
-    if (module)
+    if (m_dwarf_opcodes.get())
     {
-        std::string error;
-
-        if (m_jit_mm_ptr == NULL)
-            m_jit_mm_ptr = new RecordingMemoryManager();
-
-        //llvm::InitializeNativeTarget();
+        // TODO execute the JITted opcodes
+        
+        error_stream.Printf("We don't currently support executing DWARF expressions");
+        
+        return false;
+    }
+    else if (m_jit_addr != LLDB_INVALID_ADDRESS)
+    {
+        lldb::addr_t struct_address;
+        
+        Error materialize_error;
+        
+        if (!m_expr_decl_map->Materialize(&exe_ctx, struct_address, materialize_error))
+        {
+            error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString("unknown error"));
+            return false;
+        }
         
         if (log)
         {
-            const char *relocation_model_string;
+            log->Printf("Function address  : 0x%llx", (uint64_t)m_jit_addr);
+            log->Printf("Structure address : 0x%llx", (uint64_t)struct_address);
+                    
+            StreamString args;
             
-            switch (llvm::TargetMachine::getRelocationModel())
+            Error dump_error;
+            
+            if (!m_expr_decl_map->DumpMaterializedStruct(&exe_ctx, args, dump_error))
+            {
+                log->Printf("Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
+            }
+            else
             {
-                case llvm::Reloc::Default:
-                    relocation_model_string = "Default";
+                log->Printf("Structure contents:\n%s", args.GetData());
+            }
+        }
+        
+        ClangFunction::ExecutionResults execution_result = 
+        ClangFunction::ExecuteFunction (exe_ctx, m_jit_addr, struct_address, true, true, 10000, error_stream);
+        
+        if (execution_result != ClangFunction::eExecutionCompleted)
+        {
+            const char *result_name;
+            
+            switch (execution_result)
+            {
+                case ClangFunction::eExecutionCompleted:
+                    result_name = "eExecutionCompleted";
+                    break;
+                case ClangFunction::eExecutionDiscarded:
+                    result_name = "eExecutionDiscarded";
                     break;
-                case llvm::Reloc::Static:
-                    relocation_model_string = "Static";
+                case ClangFunction::eExecutionInterrupted:
+                    result_name = "eExecutionInterrupted";
                     break;
-                case llvm::Reloc::PIC_:
-                    relocation_model_string = "PIC_";
+                case ClangFunction::eExecutionSetupError:
+                    result_name = "eExecutionSetupError";
                     break;
-                case llvm::Reloc::DynamicNoPIC:
-                    relocation_model_string = "DynamicNoPIC";
+                case ClangFunction::eExecutionTimedOut:
+                    result_name = "eExecutionTimedOut";
                     break;
             }
             
-            log->Printf("Target machine's relocation model: %s", relocation_model_string);
+            error_stream.Printf ("Couldn't execute function; result was %s\n", result_name);
+            return false;
         }
-                        
-        if (m_execution_engine.get() == 0)
-            m_execution_engine.reset(llvm::ExecutionEngine::createJIT (module, 
-                                                                       &error, 
-                                                                       m_jit_mm_ptr,
-                                                                       CodeGenOpt::Default,
-                                                                       true,
-                                                                       CodeModel::Small)); // set to small so RIP-relative relocations work in PIC
         
-        m_execution_engine->DisableLazyCompilation();
-        llvm::Function *function = module->getFunction (llvm::StringRef (name));
-            
-        // We don't actually need the function pointer here, this just forces it to get resolved.
-        void *fun_ptr = m_execution_engine->getPointerToFunction(function);
-        // Note, you probably won't get here on error, since the LLVM JIT tends to just
-        // exit on error at present...  So be careful.
-        if (fun_ptr == 0)
+        Error expr_error;
+        
+        if (!m_expr_decl_map->Dematerialize(&exe_ctx, result, expr_error))
+        {
+            error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
             return false;
-        m_jitted_functions.push_back(ClangExpression::JittedFunction(name, (lldb::addr_t) fun_ptr));
-
-    }
-    return true;
-}
-
-bool
-ClangExpression::WriteJITCode (const ExecutionContext &exc_context)
-{
-    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-
-    if (m_jit_mm_ptr == NULL)
-        return false;
-
-    if (exc_context.process == NULL)
-        return false;
-
-    // Look over the regions allocated for the function compiled.  The JIT
-    // tries to allocate the functions & stubs close together, so we should try to
-    // write them that way too...
-    // For now I only write functions with no stubs, globals, exception tables,
-    // etc.  So I only need to write the functions.
-
-    size_t alloc_size = 0;
-    std::map<uint8_t *, uint8_t *>::iterator fun_pos, fun_end = m_jit_mm_ptr->m_functions.end();
-    for (fun_pos = m_jit_mm_ptr->m_functions.begin(); fun_pos != fun_end; fun_pos++)
-    {
-        alloc_size += (*fun_pos).second - (*fun_pos).first;
-    }
-
-    Error error;
-    lldb::addr_t target_addr = exc_context.process->AllocateMemory (alloc_size, lldb::ePermissionsReadable|lldb::ePermissionsExecutable, error);
-
-    if (target_addr == LLDB_INVALID_ADDRESS)
-        return false;
-
-    lldb::addr_t cursor = target_addr;
-    for (fun_pos = m_jit_mm_ptr->m_functions.begin(); fun_pos != fun_end; fun_pos++)
-    {
-        if (log)
-            log->Printf("Reading [%p-%p] from m_functions", fun_pos->first, fun_pos->second);
+        }
         
-        lldb::addr_t lstart = (lldb::addr_t) (*fun_pos).first;
-        lldb::addr_t lend = (lldb::addr_t) (*fun_pos).second;
-        size_t size = lend - lstart;
-        exc_context.process->WriteMemory(cursor, (void *) lstart, size, error);
-        m_jit_mm_ptr->AddToLocalToRemoteMap (lstart, size, cursor);
-        cursor += size;
-    }
-
-    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
-
-    for (pos = m_jitted_functions.begin(); pos != end; pos++)
-    {
-        (*pos).m_remote_addr = m_jit_mm_ptr->GetRemoteAddressForLocal ((*pos).m_local_addr);
+        return true;
     }
-    return true;
-}
-
-lldb::addr_t
-ClangExpression::GetFunctionAddress (const char *name)
-{
-    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
-
-    for (pos = m_jitted_functions.begin(); pos < end; pos++)
+    else
     {
-        if (strcmp ((*pos).m_name.c_str(), name) == 0)
-            return (*pos).m_remote_addr;
+        error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function are present");
+        return false;
     }
-    return LLDB_INVALID_ADDRESS;
 }
 
-Error
-ClangExpression::DisassembleFunction (Stream &stream, ExecutionContext &exe_ctx, const char *name)
+StreamString &
+ClangUserExpression::DwarfOpcodeStream ()
 {
-    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-
-    Error ret;
-    
-    ret.Clear();
-    
-    lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
-    lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
-    
-    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
-    
-    for (pos = m_jitted_functions.begin(); pos < end; pos++)
-    {
-        if (strcmp(pos->m_name.c_str(), name) == 0)
-        {
-            func_local_addr = pos->m_local_addr;
-            func_remote_addr = pos->m_remote_addr;
-        }
-    }
-    
-    if (func_local_addr == LLDB_INVALID_ADDRESS)
-    {
-        ret.SetErrorToGenericError();
-        ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", name);
-        return ret;
-    }
-    
-    if(log)
-        log->Printf("Found function, has local address 0x%llx and remote address 0x%llx", (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
-        
-    std::pair <lldb::addr_t, lldb::addr_t> func_range;
-    
-    func_range = m_jit_mm_ptr->GetRemoteRangeForLocal(func_local_addr);
-    
-    if (func_range.first == 0 && func_range.second == 0)
-    {
-        ret.SetErrorToGenericError();
-        ret.SetErrorStringWithFormat("Couldn't find code range for function %s", name);
-        return ret;
-    }
-    
-    if(log)
-        log->Printf("Function's code range is [0x%llx-0x%llx]", func_range.first, func_range.second);
-    
-    if (!exe_ctx.target)
-    {
-        ret.SetErrorToGenericError();
-        ret.SetErrorString("Couldn't find the target");
-    }
-    
-    lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second - func_remote_addr, 0));
-        
-    Error err;
-    exe_ctx.process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);
-    
-    if (!err.Success())
-    {
-        ret.SetErrorToGenericError();
-        ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
-        return ret;
-    }
-    
-    ArchSpec arch(exe_ctx.target->GetArchitecture());
-    
-    Disassembler *disassembler = Disassembler::FindPlugin(arch);
-    
-    if (disassembler == NULL)
-    {
-        ret.SetErrorToGenericError();
-        ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.AsCString());
-        return ret;
-    }
-    
-    if (!exe_ctx.process)
-    {
-        ret.SetErrorToGenericError();
-        ret.SetErrorString("Couldn't find the process");
-        return ret;
-    }
-    
-    DataExtractor extractor(buffer_sp, 
-                            exe_ctx.process->GetByteOrder(),
-                            exe_ctx.target->GetArchitecture().GetAddressByteSize());
-    
-    if(log)
-    {
-        log->Printf("Function data has contents:");
-        extractor.PutToLog (log,
-                            0,
-                            extractor.GetByteSize(),
-                            func_remote_addr,
-                            16,
-                            DataExtractor::TypeUInt8);
-    }
-            
-    disassembler->DecodeInstructions(extractor, 0, UINT32_MAX);
-    
-    Disassembler::InstructionList &instruction_list = disassembler->GetInstructionList();
-    
-    uint32_t bytes_offset = 0;
-    
-    for (uint32_t instruction_index = 0, num_instructions = instruction_list.GetSize(); 
-         instruction_index < num_instructions; 
-         ++instruction_index)
-    {
-        Disassembler::Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index);
-        Address addr(NULL, func_remote_addr + bytes_offset);
-        instruction->Dump (&stream,
-                           &addr,
-                           &extractor, 
-                           bytes_offset, 
-                           exe_ctx, 
-                           true);
-        stream.PutChar('\n');
-        bytes_offset += instruction->GetByteSize();
-    }
+    if (!m_dwarf_opcodes.get())
+        m_dwarf_opcodes.reset(new StreamString());
     
-    return ret;
+    return *m_dwarf_opcodes.get();
 }

Modified: lldb/trunk/source/Expression/IRForTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRForTarget.cpp?rev=112249&r1=112248&r2=112249&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRForTarget.cpp (original)
+++ lldb/trunk/source/Expression/IRForTarget.cpp Thu Aug 26 20:01:44 2010
@@ -31,11 +31,13 @@
 static char ID;
 
 IRForTarget::IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map,
-                         const TargetData *target_data) :
+                         const TargetData *target_data,
+                         const char *func_name) :
     ModulePass(&ID),
     m_decl_map(decl_map),
     m_target_data(target_data),
-    m_sel_registerName(NULL)
+    m_sel_registerName(NULL),
+    m_func_name(func_name)
 {
 }
 
@@ -910,12 +912,12 @@
 {
     lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
     
-    Function* function = M.getFunction(StringRef("___clang_expr"));
+    Function* function = M.getFunction(StringRef(m_func_name.c_str()));
     
     if (!function)
     {
         if (log)
-            log->Printf("Couldn't find ___clang_expr() in the module");
+            log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
         
         return false;
     }

Modified: lldb/trunk/source/Expression/IRToDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRToDWARF.cpp?rev=112249&r1=112248&r2=112249&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRToDWARF.cpp (original)
+++ lldb/trunk/source/Expression/IRToDWARF.cpp Thu Aug 26 20:01:44 2010
@@ -26,13 +26,15 @@
 
 static char ID;
 
-IRToDWARF::IRToDWARF(lldb_private::ClangExpressionVariableList &variable_list, 
+IRToDWARF::IRToDWARF(lldb_private::ClangExpressionVariableStore &local_vars, 
                      lldb_private::ClangExpressionDeclMap *decl_map,
-                     lldb_private::StreamString &strm) :
+                     lldb_private::StreamString &strm,
+                     const char *func_name) :
     ModulePass(&ID),
-    m_variable_list(variable_list),
+    m_local_vars(local_vars),
     m_decl_map(decl_map),
-    m_strm(strm)
+    m_strm(strm),
+    m_func_name(func_name)
 {
 }
 
@@ -171,14 +173,14 @@
 {
     lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
     
-    llvm::Function* function = M.getFunction(StringRef("___clang_expr"));
+    llvm::Function* function = M.getFunction(StringRef(m_func_name.c_str()));
     
     if (!function)
     {
         if (log)
-            log->Printf("Couldn't find ___clang_expr() in the module");
+            log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
         
-        return 1;
+        return false;
     }
     
     Relocator relocator;

Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=112249&r1=112248&r2=112249&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Thu Aug 26 20:01:44 2010
@@ -16,7 +16,7 @@
 #include "../Commands/CommandObjectApropos.h"
 #include "../Commands/CommandObjectArgs.h"
 #include "../Commands/CommandObjectBreakpoint.h"
-#include "../Commands/CommandObjectCall.h"
+//#include "../Commands/CommandObjectCall.h"
 #include "../Commands/CommandObjectDelete.h"
 #include "../Commands/CommandObjectDisassemble.h"
 #include "../Commands/CommandObjectExpression.h"
@@ -207,7 +207,7 @@
     m_command_dict["append"]    = CommandObjectSP (new CommandObjectAppend ());
     m_command_dict["apropos"]   = CommandObjectSP (new CommandObjectApropos ());
     m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this));
-    m_command_dict["call"]      = CommandObjectSP (new CommandObjectCall ());
+    //m_command_dict["call"]      = CommandObjectSP (new CommandObjectCall ());
     m_command_dict["commands"]  = CommandObjectSP (new CommandObjectMultiwordCommands (*this));
     m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble ());
     m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression ());





More information about the lldb-commits mailing list