<rdar://problem/13695846>

Enabling LLDB to write to variables that are stored in registers
Previously, this would not work since the Value's Context loses the notion of the data being in a register
We now store an "original" context that comes out of DWARF parsing, and use that context's data when attempting a write

llvm-svn: 180803
diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp
index 164592d..8204f11 100644
--- a/lldb/source/Core/ValueObjectVariable.cpp
+++ b/lldb/source/Core/ValueObjectVariable.cpp
@@ -15,6 +15,7 @@
 // Other libraries and framework includes
 // Project includes
 #include "lldb/Core/Module.h"
+#include "lldb/Core/RegisterValue.h"
 #include "lldb/Core/ValueObjectList.h"
 #include "lldb/Core/Value.h"
 
@@ -138,6 +139,8 @@
             m_value.SetContext(Value::eContextTypeVariable, variable);
         else
             m_error.SetErrorString ("empty constant data");
+        // constant bytes can't be edited - sorry
+        m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL);
     }
     else
     {
@@ -161,6 +164,7 @@
         Value old_value(m_value);
         if (expr.Evaluate (&exe_ctx, GetClangAST(), NULL, NULL, NULL, loclist_base_load_addr, NULL, m_value, &m_error))
         {
+            m_resolved_value = m_value;
             m_value.SetContext(Value::eContextTypeVariable, variable);
 
             Value::ValueType value_type = m_value.GetValueType();
@@ -249,6 +253,11 @@
 
             SetValueIsValid (m_error.Success());
         }
+        else
+        {
+            // could not find location, won't allow editing
+            m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL);
+        }
     }
     return m_error.Success();
 }
@@ -313,3 +322,74 @@
     }
     return false;
 }
+
+const char *
+ValueObjectVariable::GetLocationAsCString ()
+{
+    return GetLocationAsCStringImpl(m_resolved_value,
+                                    m_data);
+}
+
+bool
+ValueObjectVariable::SetValueFromCString (const char *value_str, Error& error)
+{
+    if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo)
+    {
+        RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo();
+        ExecutionContext exe_ctx(GetExecutionContextRef());
+        RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
+        RegisterValue reg_value;
+        if (!reg_info || !reg_ctx)
+        {
+            error.SetErrorString("unable to retrieve register info");
+            return false;
+        }
+        error = reg_value.SetValueFromCString(reg_info, value_str);
+        if (error.Fail())
+            return false;
+        if (reg_ctx->WriteRegister (reg_info, reg_value))
+        {
+            SetNeedsUpdate();
+            return true;
+        }
+        else
+        {
+            error.SetErrorString("unable to write back to register");
+            return false;
+        }
+    }
+    else
+        return ValueObject::SetValueFromCString(value_str, error);
+}
+
+bool
+ValueObjectVariable::SetData (DataExtractor &data, Error &error)
+{
+    if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo)
+    {
+        RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo();
+        ExecutionContext exe_ctx(GetExecutionContextRef());
+        RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
+        RegisterValue reg_value;
+        if (!reg_info || !reg_ctx)
+        {
+            error.SetErrorString("unable to retrieve register info");
+            return false;
+        }
+        error = reg_value.SetValueFromData(reg_info, data, 0, false);
+        if (error.Fail())
+            return false;
+        if (reg_ctx->WriteRegister (reg_info, reg_value))
+        {
+            SetNeedsUpdate();
+            return true;
+        }
+        else
+        {
+            error.SetErrorString("unable to write back to register");
+            return false;
+        }
+    }
+    else
+        return ValueObject::SetData(data, error);
+}