Implemented a feature where the expression parser
can avoid running the code in the target if the
expression's result is known and the expression
has no side effects.

Right now this feature is quite conservative in
its guess about side effects, and it only computes
integer results, but the machinery to make it more
sophisticated is there.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@121952 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/IRForTarget.cpp b/source/Expression/IRForTarget.cpp
index 34f146f..ab3afeb 100644
--- a/source/Expression/IRForTarget.cpp
+++ b/source/Expression/IRForTarget.cpp
@@ -34,13 +34,16 @@
 
 IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
                           bool resolve_vars,
+                          lldb::ClangExpressionVariableSP *const_result,
                           const char *func_name) :
     ModulePass(ID),
     m_decl_map(decl_map),
     m_CFStringCreateWithBytes(NULL),
     m_sel_registerName(NULL),
     m_func_name(func_name),
-    m_resolve_vars(resolve_vars)
+    m_resolve_vars(resolve_vars),
+    m_const_result(const_result),
+    m_has_side_effects(NULL)
 {
 }
 
@@ -75,6 +78,64 @@
 }
 
 bool 
+IRForTarget::HasSideEffects (llvm::Module &llvm_module,
+                             llvm::Function &llvm_function)
+{
+    llvm::Function::iterator bbi;
+    BasicBlock::iterator ii;
+    
+    for (bbi = llvm_function.begin();
+         bbi != llvm_function.end();
+         ++bbi)
+    {
+        BasicBlock &basic_block = *bbi;
+        
+        for (ii = basic_block.begin();
+             ii != basic_block.end();
+             ++ii)
+        {      
+            switch (ii->getOpcode())
+            {
+            default:
+                return true;
+            case Instruction::Store:
+                {
+                    StoreInst *store_inst = dyn_cast<StoreInst>(ii);
+                    
+                    Value *store_ptr = store_inst->getPointerOperand();
+                    
+                    if (!isa <AllocaInst> (store_ptr))
+                        return true;
+                    else
+                        break;
+                }
+            case Instruction::Load:
+            case Instruction::Alloca:
+            case Instruction::GetElementPtr:
+            case Instruction::Ret:
+                break;
+            }
+        }
+    }
+    
+    return false;
+}
+
+void 
+IRForTarget::MaybeSetConstantResult (llvm::Constant *initializer,
+                                     const lldb_private::ConstString &name,
+                                     lldb_private::TypeFromParser type)
+{
+    if (!m_const_result)
+        return;
+    
+    if (llvm::ConstantInt *init_int = dyn_cast<llvm::ConstantInt>(initializer))
+    {
+        *m_const_result = m_decl_map->BuildIntegerVariable(name, type, init_int->getValue());
+    }
+}
+
+bool 
 IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &llvm_function)
 {
     lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -239,6 +300,16 @@
         }
         
         Constant *initializer = result_global->getInitializer();
+        
+        // Here we write the initializer into a result variable assuming it
+        // can be computed statically.
+        
+        if (!m_has_side_effects)
+        {
+            MaybeSetConstantResult (initializer, 
+                                    new_result_name, 
+                                    result_decl_type);
+        }
                 
         StoreInst *synthesized_store = new StoreInst::StoreInst(initializer,
                                                                 new_result_global,
@@ -1442,6 +1513,8 @@
         
     Function::iterator bbi;
     
+    m_has_side_effects = HasSideEffects(llvm_module, *function);
+    
     ////////////////////////////////////////////////////////////
     // Replace $__lldb_expr_result with a persistent variable
     //
@@ -1456,19 +1529,7 @@
     ///////////////////////////////////////////////////////////////////////////////
     // Fix all Objective-C constant strings to use NSStringWithCString:encoding:
     //
-    
-    if (log)
-    {
-        std::string s;
-        raw_string_ostream oss(s);
         
-        llvm_module.print(oss, NULL);
-        
-        oss.flush();
-        
-        log->Printf("Module after creating the result variable: \n\"%s\"", s.c_str());
-    }
-    
     if (!RewriteObjCConstStrings(llvm_module, *function))
     {
         if (log)
@@ -1476,18 +1537,6 @@
         return false;
     }
     
-    if (log)
-    {
-        std::string s;
-        raw_string_ostream oss(s);
-        
-        llvm_module.print(oss, NULL);
-        
-        oss.flush();
-        
-        log->Printf("Module after rewriting Objective-C const strings: \n\"%s\"", s.c_str());
-    }
-    
     //////////////////////////////////
     // Run basic-block level passes
     //