This commit changes the way LLDB executes user
expressions.  

Previously, ClangUserExpression assumed that if
there was a constant result for an expression 
then it could be determined during parsing.  In
particular, the IRInterpreter ran while parser
state (in particular, ClangExpressionDeclMap) 
was present.  This approach is flawed, because
the IRInterpreter actually is capable of using
external variables, and hence the result might
be different each run.  Until now, we papered
over this flaw by re-parsing the expression each
time we ran it.

I have rewritten the IRInterpreter to be 
completely independent of the ClangExpressionDeclMap.
Instead of special-casing external variable lookup,
which ties the IRInterpreter closely to LLDB,
we now interpret the exact same IR that the JIT
would see.  This IR assumes that materialization
has occurred; hence the recent implementation of the
Materializer, which does not require parser state
(in the form of ClangExpressionDeclMap) to be 
present.

Materialization, interpretation, and dematerialization
are now all independent of parsing.  This means that
in theory we can parse expressions once and run them
many times.  I have three outstanding tasks before
shutting this down:

    - First, I will ensure that all of this works with
      core files.  Core files have a Process but do not
      allow allocating memory, which currently confuses
      materialization.

    - Second, I will make expression breakpoint 
      conditions remember their ClangUserExpression and
      re-use it.

    - Third, I will tear out all the redundant code
      (for example, materialization logic in
      ClangExpressionDeclMap) that is no longer used.

While implementing this fix, I also found a bug in
IRForTarget's handling of floating-point constants.  
This should be fixed.

llvm-svn: 179801
diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp
index 6f65b11..083f67a 100644
--- a/lldb/source/Expression/ClangUserExpression.cpp
+++ b/lldb/source/Expression/ClangUserExpression.cpp
@@ -30,6 +30,7 @@
 #include "lldb/Expression/ClangUserExpression.h"
 #include "lldb/Expression/ExpressionSourceCode.h"
 #include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Expression/IRInterpreter.h"
 #include "lldb/Expression/Materializer.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Symbol/Block.h"
@@ -67,8 +68,7 @@
     m_needs_object_ptr (false),
     m_const_object (false),
     m_target (NULL),
-    m_evaluated_statically (false),
-    m_const_result ()
+    m_can_interpret (false)
 {
     switch (m_language)
     {
@@ -469,8 +469,7 @@
                                                   m_jit_end_addr,
                                                   m_execution_unit_ap,
                                                   exe_ctx,
-                                                  m_evaluated_statically,
-                                                  m_const_result,
+                                                  m_can_interpret,
                                                   execution_policy);
         
     if (jit_error.Success())
@@ -490,6 +489,46 @@
     }
 }
 
+static lldb::addr_t
+GetObjectPointer (lldb::StackFrameSP frame_sp,
+                  ConstString &object_name,
+                  Error &err)
+{
+    err.Clear();
+    
+    if (!frame_sp)
+    {
+        err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString());
+        return LLDB_INVALID_ADDRESS;
+    }
+    
+    lldb::VariableSP var_sp;
+    lldb::ValueObjectSP valobj_sp;
+    
+    valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(),
+                                                            lldb::eNoDynamicValues,
+                                                            StackFrame::eExpressionPathOptionCheckPtrVsMember ||
+                                                            StackFrame::eExpressionPathOptionsAllowDirectIVarAccess ||
+                                                            StackFrame::eExpressionPathOptionsNoFragileObjcIvar ||
+                                                            StackFrame::eExpressionPathOptionsNoSyntheticChildren ||
+                                                            StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
+                                                            var_sp,
+                                                            err);
+    
+    if (!err.Success())
+        return LLDB_INVALID_ADDRESS;
+    
+    lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+    
+    if (ret == LLDB_INVALID_ADDRESS)
+    {
+        err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString());
+        return LLDB_INVALID_ADDRESS;
+    }
+    
+    return ret;
+}
+
 bool
 ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
                                                     ExecutionContext &exe_ctx,
@@ -497,8 +536,6 @@
                                                     lldb::addr_t &object_ptr,
                                                     lldb::addr_t &cmd_ptr)
 {
-    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
     lldb::TargetSP target;
     lldb::ProcessSP process;
     lldb::StackFrameSP frame;
@@ -512,10 +549,8 @@
         return false;
     }
     
-    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
-    {
-        Error materialize_error;
-        
+    if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
+    {        
         if (m_needs_object_ptr)
         {
             ConstString object_name;
@@ -534,9 +569,13 @@
                 return false;
             }
             
-            if (!(m_expr_decl_map->GetObjectPointer(object_ptr, object_name, materialize_error)))
+            Error object_ptr_error;
+            
+            object_ptr = GetObjectPointer(frame, object_name, object_ptr_error);
+            
+            if (!object_ptr_error.Success())
             {
-                error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", materialize_error.AsCString());
+                error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
                 object_ptr = 0;
             }
             
@@ -544,53 +583,41 @@
             {
                 ConstString cmd_name("_cmd");
                 
-                if (!(m_expr_decl_map->GetObjectPointer(cmd_ptr, cmd_name, materialize_error, true)))
+                cmd_ptr = GetObjectPointer(frame, cmd_name, object_ptr_error);
+                
+                if (!object_ptr_error.Success())
                 {
-                    error_stream.Printf("warning: couldn't get object pointer (substituting NULL): %s\n", materialize_error.AsCString());
+                    error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
                     cmd_ptr = 0;
                 }
             }
         }
-                
-        if (!m_expr_decl_map->Materialize(*m_execution_unit_ap, struct_address, materialize_error))
+        
+        Error alloc_error;
+        
+        struct_address = m_execution_unit_ap->Malloc(m_materializer_ap->GetStructByteSize(),
+                                                     m_materializer_ap->GetStructAlignment(),
+                                                     lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+                                                     IRMemoryMap::eAllocationPolicyMirror,
+                                                     alloc_error);
+        
+        if (!alloc_error.Success())
+        {
+            error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString());
+            return false;
+        }
+        
+        m_materialized_address = struct_address;
+        
+        Error materialize_error;
+        
+        m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_ap, struct_address, materialize_error);
+        
+        if (!materialize_error.Success())
         {
             error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
             return false;
         }
-
-#if 0
-		// jingham: look here
-        StreamFile logfile ("/tmp/exprs.txt", "a");
-        logfile.Printf("0x%16.16" PRIx64 ": thread = 0x%4.4x, expr = '%s'\n", m_jit_start_addr, exe_ctx.thread ? exe_ctx.thread->GetID() : -1, m_expr_text.c_str());
-#endif
-        
-        if (log)
-        {
-            log->Printf("-- [ClangUserExpression::PrepareToExecuteJITExpression] Materializing for execution --");
-            
-            log->Printf("  Function address  : 0x%" PRIx64, (uint64_t)m_jit_start_addr);
-            
-            if (m_needs_object_ptr)
-                log->Printf("  Object pointer    : 0x%" PRIx64, (uint64_t)object_ptr);
-            
-            log->Printf("  Structure address : 0x%" PRIx64, (uint64_t)struct_address);
-                    
-            StreamString args;
-            
-            Error dump_error;
-            
-            if (struct_address)
-            {
-                if (!m_expr_decl_map->DumpMaterializedStruct(args, dump_error))
-                {
-                    log->Printf("  Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
-                }
-                else
-                {
-                    log->Printf("  Structure contents:\n%s", args.GetData());
-                }
-            }
-        }
     }
     return true;
 }
@@ -635,35 +662,31 @@
     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
     
     if (log)
-    {
         log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");
     
-        StreamString args;
-        
-        Error dump_error;
-        
-        if (!m_expr_decl_map->DumpMaterializedStruct(args, dump_error))
-        {
-            log->Printf("  Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
-        }
-        else
-        {
-            log->Printf("  Structure contents:\n%s", args.GetData());
-        }
-    }
-    
     lldb::addr_t function_stack_bottom = function_stack_pointer - Host::GetPageSize();
     
-        
-    if (!m_expr_decl_map->Dematerialize(result, *m_execution_unit_ap, function_stack_pointer, function_stack_bottom, expr_error))
+    if (!m_dematerializer_sp)
+    {
+        error_stream.Printf ("Couldn't dematerialize struct : no dematerializer is present");
+        return false;
+    }
+    
+    Error dematerialize_error;
+    
+    m_dematerializer_sp->Dematerialize(dematerialize_error, result, function_stack_pointer, function_stack_bottom);
+
+    if (!dematerialize_error.Success())
     {
         error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
         return false;
     }
-    
+        
     if (result)
         result->TransferAddress();
     
+    m_dematerializer_sp.reset();
+    
     return true;
 }        
 
@@ -681,7 +704,7 @@
     // expression, it's quite convenient to have these logs come out with the STEP log as well.
     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
 
-    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
+    if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
     {
         lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
                 
@@ -694,73 +717,115 @@
             return eExecutionSetupError;
         }
         
-        const bool stop_others = true;
-        const bool try_all_threads = run_others;
+        lldb::addr_t function_stack_pointer = NULL;
         
-        Address wrapper_address (m_jit_start_addr);
-        lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(), 
-                                                                          wrapper_address, 
-                                                                          struct_address, 
-                                                                          stop_others, 
-                                                                          unwind_on_error,
-                                                                          ignore_breakpoints,
-                                                                          (m_needs_object_ptr ? &object_ptr : NULL),
-                                                                          ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
-                                                                          shared_ptr_to_me));
-        
-        if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
-            return eExecutionSetupError;
-        
-        lldb::addr_t function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer();
-
-        if (log)
-            log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
-        
-        if (exe_ctx.GetProcessPtr())
-            exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
+        if (m_can_interpret)
+        {            
+            llvm::Module *module = m_execution_unit_ap->GetModule();
+            llvm::Function *function = m_execution_unit_ap->GetFunction();
             
-        ExecutionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, 
-                                                                                   call_plan_sp, 
-                                                                                   stop_others, 
-                                                                                   try_all_threads, 
-                                                                                   unwind_on_error,
-                                                                                   ignore_breakpoints,
-                                                                                   timeout_usec, 
-                                                                                   error_stream);
-        
-        if (exe_ctx.GetProcessPtr())
-            exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
-            
-        if (log)
-            log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
-
-        if (execution_result == eExecutionInterrupted || execution_result == eExecutionHitBreakpoint)
-        {
-            const char *error_desc = NULL;
-            
-            if (call_plan_sp)
+            if (!module || !function)
             {
-                lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
-                if (real_stop_info_sp)
-                    error_desc = real_stop_info_sp->GetDescription();
+                error_stream.Printf("Supposed to interpret, but nothing is there");
+                return eExecutionSetupError;
             }
-            if (error_desc)
-                error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
-            else
-                error_stream.Printf ("Execution was interrupted.");
-                
-            if ((execution_result == eExecutionInterrupted && unwind_on_error)
-                || (execution_result == eExecutionHitBreakpoint && ignore_breakpoints))
-                error_stream.Printf ("\nThe process has been returned to the state before expression evaluation.");
-            else
-                error_stream.Printf ("\nThe process has been left at the point where it was interrupted, use \"thread return -x\" to return to the state before expression evaluation.");
 
-            return execution_result;
+            Error interpreter_error;
+            
+            llvm::SmallVector <lldb::addr_t, 3> args;
+            
+            if (m_needs_object_ptr)
+            {
+                args.push_back(object_ptr);
+                
+                if (m_objectivec)
+                    args.push_back(cmd_ptr);
+            }
+            
+            args.push_back(struct_address);
+            
+            IRInterpreter::Interpret (*module,
+                                      *function,
+                                      args,
+                                      *m_execution_unit_ap.get(),
+                                      interpreter_error);
+            
+            if (!interpreter_error.Success())
+            {
+                error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString());
+                return eExecutionDiscarded;
+            }
         }
-        else if (execution_result != eExecutionCompleted)
+        else
         {
-            error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
-            return execution_result;
+            const bool stop_others = true;
+            const bool try_all_threads = run_others;
+            
+            Address wrapper_address (m_jit_start_addr);
+            lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(), 
+                                                                              wrapper_address, 
+                                                                              struct_address, 
+                                                                              stop_others, 
+                                                                              unwind_on_error,
+                                                                              ignore_breakpoints,
+                                                                              (m_needs_object_ptr ? &object_ptr : NULL),
+                                                                              ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
+                                                                              shared_ptr_to_me));
+            
+            if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
+                return eExecutionSetupError;
+            
+            function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer();
+
+            if (log)
+                log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
+            
+            if (exe_ctx.GetProcessPtr())
+                exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
+                
+            ExecutionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, 
+                                                                                       call_plan_sp, 
+                                                                                       stop_others, 
+                                                                                       try_all_threads, 
+                                                                                       unwind_on_error,
+                                                                                       ignore_breakpoints,
+                                                                                       timeout_usec, 
+                                                                                       error_stream);
+            
+            if (exe_ctx.GetProcessPtr())
+                exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
+                
+            if (log)
+                log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
+
+            if (execution_result == eExecutionInterrupted || execution_result == eExecutionHitBreakpoint)
+            {
+                const char *error_desc = NULL;
+                
+                if (call_plan_sp)
+                {
+                    lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
+                    if (real_stop_info_sp)
+                        error_desc = real_stop_info_sp->GetDescription();
+                }
+                if (error_desc)
+                    error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
+                else
+                    error_stream.Printf ("Execution was interrupted.");
+                    
+                if ((execution_result == eExecutionInterrupted && unwind_on_error)
+                    || (execution_result == eExecutionHitBreakpoint && ignore_breakpoints))
+                    error_stream.Printf ("\nThe process has been returned to the state before expression evaluation.");
+                else
+                    error_stream.Printf ("\nThe process has been left at the point where it was interrupted, use \"thread return -x\" to return to the state before expression evaluation.");
+
+                return execution_result;
+            }
+            else if (execution_result != eExecutionCompleted)
+            {
+                error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
+                return execution_result;
+            }
         }
         
         if  (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_pointer))
@@ -862,19 +927,8 @@
     {
         lldb::ClangExpressionVariableSP expr_result;
 
-        if (user_expression_sp->EvaluatedStatically())
-        {
-            if (log)
-                log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
-            
-            if (user_expression_sp->m_const_result)
-                result_valobj_sp = user_expression_sp->m_const_result->GetValueObject();
-            else
-                error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
-            
-            execution_results = eExecutionCompleted;
-        }
-        else if (execution_policy == eExecutionPolicyNever)
+        if (execution_policy == eExecutionPolicyNever &&
+            !user_expression_sp->CanInterpret())
         {
             if (log)
                 log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");