Fixed the IRInterpreter's handling of "this" and
authorSean Callanan <scallanan@apple.com>
Tue, 11 Dec 2012 22:39:36 +0000 (22:39 +0000)
committerSean Callanan <scallanan@apple.com>
Tue, 11 Dec 2012 22:39:36 +0000 (22:39 +0000)
"self" when those pointers are in registers.
Previously in this case the IRInterpreter would
handle them just as if the user had typed in
"$rdi", which isn't safe because $rdi is passed
in through the argument struct.

Now we correctly break out all three cases (i.e.,
normal variables in registers, $reg, and this/self),
and handle them in a way that's a little bit easier
to read and change.

This results in more accurate printing of "this" and
"self" pointers all around.  I have strengthened the
optimized-code test case for Objective-C to ensure
that we catch regressions in this area reliably in
the future.

<rdar://problem/12693963>

llvm-svn: 169924

lldb/source/Expression/IRInterpreter.cpp
lldb/test/lang/objc/objc-optimized/TestObjcOptimized.py

index b812875..626e270 100644 (file)
@@ -619,7 +619,7 @@ public:
         // array then we need to build an extra level of indirection
         // for it.  This is the default; only magic arguments like
         // "this", "self", and "_cmd" are direct.
-        bool indirect_variable = true; 
+        bool variable_is_this = false;
         
         // Attempt to resolve the value using the program's data.
         // If it is, the values to be created are:
@@ -664,69 +664,121 @@ public:
                     name_str == "_cmd")
                     resolved_value = m_decl_map.GetSpecialValue(lldb_private::ConstString(name_str.c_str()));
                 
-                indirect_variable = false;
+                variable_is_this = true;
             }
             
             if (resolved_value.GetScalar().GetType() != lldb_private::Scalar::e_void)
             {
                 if (resolved_value.GetContextType() == lldb_private::Value::eContextTypeRegisterInfo)
                 {
-                    bool bare_register = (flags & lldb_private::ClangExpressionVariable::EVBareRegister);
-
-                    if (bare_register)
-                        indirect_variable = false;
-                    
-                    lldb_private::RegisterInfo *reg_info = resolved_value.GetRegisterInfo();
-                    Memory::Region data_region = (reg_info->encoding == lldb::eEncodingVector) ?
+                    if (variable_is_this)
+                    {
+                        Memory::Region data_region = m_memory.Place(value->getType(), resolved_value.GetScalar().ULongLong(), resolved_value);
+                        
+                        lldb_private::Value origin;
+                        
+                        origin.SetValueType(lldb_private::Value::eValueTypeLoadAddress);
+                        origin.SetContext(lldb_private::Value::eContextTypeInvalid, NULL);
+                        origin.GetScalar() = resolved_value.GetScalar();
+                        
+                        data_region.m_allocation->m_origin = origin;
+                        
+                        Memory::Region ref_region = m_memory.Malloc(value->getType());
+                         
+                        if (ref_region.IsInvalid())
+                            return Memory::Region();
+                        
+                        DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region);
+                        
+                        if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX)
+                            return Memory::Region();
+                        
+                        if (log)
+                        {
+                            log->Printf("Made an allocation for \"this\" register variable %s", PrintValue(value).c_str());
+                            log->Printf("  Data region    : %llx", (unsigned long long)data_region.m_base);
+                            log->Printf("  Ref region     : %llx", (unsigned long long)ref_region.m_base);
+                        }
+                        
+                        m_values[value] = ref_region;
+                        return ref_region;
+                    }
+                    else if (flags & lldb_private::ClangExpressionVariable::EVBareRegister)
+                    {                        
+                        lldb_private::RegisterInfo *reg_info = resolved_value.GetRegisterInfo();
+                        Memory::Region data_region = (reg_info->encoding == lldb::eEncodingVector) ?
                         m_memory.Malloc(reg_info->byte_size, m_target_data.getPrefTypeAlignment(value->getType())) :
                         m_memory.Malloc(value->getType());
-
-                    data_region.m_allocation->m_origin = resolved_value;
-                    Memory::Region ref_region = m_memory.Malloc(value->getType());
-                    Memory::Region pointer_region;
-                    
-                    if (indirect_variable)
+                        
+                        data_region.m_allocation->m_origin = resolved_value;
+                        Memory::Region ref_region = m_memory.Malloc(value->getType());
+                        
+                        if (!Cache(data_region.m_allocation, value->getType()))
+                            return Memory::Region();
+                        
+                        if (ref_region.IsInvalid())
+                            return Memory::Region();
+                        
+                        DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region);
+                        
+                        if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX)
+                            return Memory::Region();
+                        
+                        if (log)
+                        {
+                            log->Printf("Made an allocation for bare register variable %s", PrintValue(value).c_str());
+                            log->Printf("  Data contents  : %s", m_memory.PrintData(data_region.m_base, data_region.m_extent).c_str());
+                            log->Printf("  Data region    : %llx", (unsigned long long)data_region.m_base);
+                            log->Printf("  Ref region     : %llx", (unsigned long long)ref_region.m_base);
+                        }
+                        
+                        m_values[value] = ref_region;
+                        return ref_region;
+                    }
+                    else
+                    {                        
+                        lldb_private::RegisterInfo *reg_info = resolved_value.GetRegisterInfo();
+                        Memory::Region data_region = (reg_info->encoding == lldb::eEncodingVector) ?
+                        m_memory.Malloc(reg_info->byte_size, m_target_data.getPrefTypeAlignment(value->getType())) :
+                        m_memory.Malloc(value->getType());
+                        
+                        data_region.m_allocation->m_origin = resolved_value;
+                        Memory::Region ref_region = m_memory.Malloc(value->getType());
+                        Memory::Region pointer_region;
+                        
                         pointer_region = m_memory.Malloc(value->getType());
-                    
-                    if (!Cache(data_region.m_allocation, value->getType()))
-                        return Memory::Region();
-
-                    if (ref_region.IsInvalid())
-                        return Memory::Region();
-                    
-                    if (pointer_region.IsInvalid() && indirect_variable)
-                        return Memory::Region();
-                    
-                    DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region);
-                    
-                    if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX)
-                        return Memory::Region();
-                    
-                    if (log)
-                    {
-                        log->Printf("Made an allocation for register variable %s", PrintValue(value).c_str());
-                        log->Printf("  Data contents  : %s", m_memory.PrintData(data_region.m_base, data_region.m_extent).c_str());
-                        log->Printf("  Data region    : %llx", (unsigned long long)data_region.m_base);
-                        log->Printf("  Ref region     : %llx", (unsigned long long)ref_region.m_base);
-                        if (indirect_variable)
+                        
+                        if (!Cache(data_region.m_allocation, value->getType()))
+                            return Memory::Region();
+                        
+                        if (ref_region.IsInvalid())
+                            return Memory::Region();
+                        
+                        if (pointer_region.IsInvalid())
+                            return Memory::Region();
+                        
+                        DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region);
+                        
+                        if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX)
+                            return Memory::Region();
+                        
+                        if (log)
+                        {
+                            log->Printf("Made an allocation for ordinary register variable %s", PrintValue(value).c_str());
+                            log->Printf("  Data contents  : %s", m_memory.PrintData(data_region.m_base, data_region.m_extent).c_str());
+                            log->Printf("  Data region    : %llx", (unsigned long long)data_region.m_base);
+                            log->Printf("  Ref region     : %llx", (unsigned long long)ref_region.m_base);
                             log->Printf("  Pointer region : %llx", (unsigned long long)pointer_region.m_base);
-                    }
-                    
-                    if (indirect_variable)
-                    {
-                        DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region);
+                        }
                         
+                        DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region);
+                            
                         if (pointer_encoder->PutAddress(0, ref_region.m_base) == UINT32_MAX)
                             return Memory::Region();
                         
                         m_values[value] = pointer_region;
                         return pointer_region;
                     }
-                    else
-                    {
-                        m_values[value] = ref_region;
-                        return ref_region;
-                    }
                 }
                 else
                 {
@@ -734,13 +786,13 @@ public:
                     Memory::Region ref_region = m_memory.Malloc(value->getType());
                     Memory::Region pointer_region;
                     
-                    if (indirect_variable)
+                    if (!variable_is_this)
                         pointer_region = m_memory.Malloc(value->getType());
                            
                     if (ref_region.IsInvalid())
                         return Memory::Region();
                     
-                    if (pointer_region.IsInvalid() && indirect_variable)
+                    if (pointer_region.IsInvalid() && !variable_is_this)
                         return Memory::Region();
                     
                     DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region);
@@ -748,7 +800,7 @@ public:
                     if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX)
                         return Memory::Region();
                     
-                    if (indirect_variable)
+                    if (!variable_is_this)
                     {
                         DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region);
                     
@@ -764,14 +816,14 @@ public:
                         log->Printf("  Data contents  : %s", m_memory.PrintData(data_region.m_base, data_region.m_extent).c_str());
                         log->Printf("  Data region    : %llx", (unsigned long long)data_region.m_base);
                         log->Printf("  Ref region     : %llx", (unsigned long long)ref_region.m_base);
-                        if (indirect_variable)
+                        if (!variable_is_this)
                             log->Printf("  Pointer region : %llx", (unsigned long long)pointer_region.m_base);
                     }
                     
-                    if (indirect_variable)
-                        return pointer_region;
-                    else 
+                    if (variable_is_this)
                         return ref_region;
+                    else
+                        return pointer_region;
                 }
             }
         }
index 59d1f4e..a7a9d23 100644 (file)
@@ -12,6 +12,7 @@ import unittest2
 import lldb
 from lldbtest import *
 import lldbutil
+import re
 
 # rdar://problem/9087739
 # test failure: objc_optimized does not work for "-C clang -A i386"
@@ -50,8 +51,21 @@ class ObjcOptimizedTestCase(TestBase):
         self.expect('expression member',
             startstr = "(int) $0 = 5")
 
-        self.expect('expression self',
-            startstr = "(%s *) $1 = " % self.myclass)
+        # <rdar://problem/12693963>
+        interp = self.dbg.GetCommandInterpreter()
+        result = lldb.SBCommandReturnObject()
+        interp.HandleCommand('frame variable self', result)
+        output = result.GetOutput()
+
+        desired_pointer = "0x0"
+
+        mo = re.search("0x[0-9a-f]+", output)
+
+        if mo:
+            desired_pointer = mo.group(0)
+
+        self.expect('expression (self)',
+            substrs = [("(%s *) $1 = " % self.myclass), desired_pointer])
 
         self.expect('expression self->non_member', error=True,
             substrs = ["does not have a member named 'non_member'"])