Fixed DataExtractor to correctly display Intel extended doubles.

This means that "register read stmm0 --format f" actually works now.

This isn't the best fix, but doing anything better would be hard with the 
formatting framework LLDB currently has. There are two separate problems at 
work here:

Firstly, LLDB assumes the host C++ compiler uses IEEE floats for 'float' and 
'double', which isn't standard but would probably happen to work most of the 
time. It also assumes that 'long double' is an IEEE standardized format, which 
it is not. There are also many points in the code where it assumes the host's 
float format is the same as the target's (e.g. search for "sizeof(long 
double)"), which is really bad. A long double can often be 16-bytes on Intel 
when padding is included, but there are other 16-byte float formats that aren't 
Intel's (e.g. PPC double-double, IEEE quad, etc).

Secondly, the 'Format' enum used to decide display formats is a little confused 
over how to decode data. Right now it has options such as 
'decimal/octal/float/OSType/CString/etc', which confuses two different ideas; 
the type of the underlying data and the way to display it. DataExtractor then 
has to additionally use the byte_size of the item in conjunction with the 
format and current target in order to know how to actually print it.

It seems to me that this is wrong; I don't believe it's right that 
DataExtractor should in any way be guessing as to what it's data format is, I 
think the inputs should all be completely explicit.

I think the best plan would be to make it take as input: a Clang type to say 
what the data storage format is, a display type ('number/OSType/CString/etc' 
with no int/float mentioned), and a base ('bin/dec/oct/hex'). So then if 
somebody wanted to display a C99 hex float, they could just set the base to 
'hex'. And if they wanted to e.g. force a float to be displayed as an int 
instead, they could just pass a different Clang type in.

Having a more flexible format here would also allow for options that are not 
available on the current codebase, such as printing a uint32_t[] vector as 
hexadecimal.

Feedback welcome!


http://llvm-reviews.chandlerc.com/D1386

Files:
  source/Core/DataExtractor.cpp
  test/functionalities/register/TestRegisters.py

Index: source/Core/DataExtractor.cpp
===================================================================
--- source/Core/DataExtractor.cpp
+++ source/Core/DataExtractor.cpp
@@ -777,24 +777,12 @@
 long double
 DataExtractor::GetLongDouble (offset_t *offset_ptr) const
 {
-    typedef long double float_type;
-    float_type val = 0.0;
-    const size_t src_size = sizeof(float_type);
-    const float_type *src = (const float_type *)GetData (offset_ptr, src_size);
-    if (src)
-    {
-        if (m_byte_order != lldb::endian::InlHostByteOrder())
-        {
-            const uint8_t *src_data = (const uint8_t *)src;
-            uint8_t *dst_data = (uint8_t *)&val;
-            for (size_t i=0; i<sizeof(float_type); ++i)
-                dst_data[sizeof(float_type) - 1 - i] = src_data[i];
-        }
-        else
-        {
-            val = *src;
-        }
-    }
+    long double val = 0.0;
+#if defined (__i386__) || defined (__amd64__) || defined (__x86_64__) || 
defined(_M_IX86) || defined(_M_IA64) || defined(_M_X64)
+    *offset_ptr += CopyByteOrderedData (*offset_ptr, 10, &val, sizeof(val), 
lldb::endian::InlHostByteOrder());
+#else
+    *offset_ptr += CopyByteOrderedData (*offset_ptr, sizeof(val), &val, 
sizeof(val), lldb::endian::InlHostByteOrder());
+#endif
     return val;
 }
 
@@ -1842,7 +1830,7 @@
                         ss.precision(std::numeric_limits<double>::digits10);
                         ss << GetDouble(&offset);
                     }
-                    else if (item_byte_size == sizeof(long double))
+                    else if (item_byte_size == sizeof(long double) || 
item_byte_size == 10)
                     {
                         ss.precision(std::numeric_limits<long 
double>::digits10);
                         ss << GetLongDouble(&offset);
Index: test/functionalities/register/TestRegisters.py
===================================================================
--- test/functionalities/register/TestRegisters.py
+++ test/functionalities/register/TestRegisters.py
@@ -180,6 +180,10 @@
         new_value = "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 
0x2f 0x2f 0x2f 0x0e 0x0f}"
         self.vector_write_and_read(currentFrame, "xmm15", new_value, False)
 
+        self.runCmd("register write stmm0 \"{0x00 0x00 0x00 0x00 0x00 0x00 
0x40 0x9a 0x09 0x40}\"")
+        self.expect("register read stmm0 --format f",
+            substrs = ['stmm0 = 1234'])
+
         has_avx = False 
         registerSets = currentFrame.GetRegisters() # Returns an SBValueList.
         for registerSet in registerSets:
Index: source/Core/DataExtractor.cpp
===================================================================
--- source/Core/DataExtractor.cpp
+++ source/Core/DataExtractor.cpp
@@ -777,24 +777,12 @@
 long double
 DataExtractor::GetLongDouble (offset_t *offset_ptr) const
 {
-    typedef long double float_type;
-    float_type val = 0.0;
-    const size_t src_size = sizeof(float_type);
-    const float_type *src = (const float_type *)GetData (offset_ptr, src_size);
-    if (src)
-    {
-        if (m_byte_order != lldb::endian::InlHostByteOrder())
-        {
-            const uint8_t *src_data = (const uint8_t *)src;
-            uint8_t *dst_data = (uint8_t *)&val;
-            for (size_t i=0; i<sizeof(float_type); ++i)
-                dst_data[sizeof(float_type) - 1 - i] = src_data[i];
-        }
-        else
-        {
-            val = *src;
-        }
-    }
+    long double val = 0.0;
+#if defined (__i386__) || defined (__amd64__) || defined (__x86_64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_X64)
+    *offset_ptr += CopyByteOrderedData (*offset_ptr, 10, &val, sizeof(val), lldb::endian::InlHostByteOrder());
+#else
+    *offset_ptr += CopyByteOrderedData (*offset_ptr, sizeof(val), &val, sizeof(val), lldb::endian::InlHostByteOrder());
+#endif
     return val;
 }
 
@@ -1842,7 +1830,7 @@
                         ss.precision(std::numeric_limits<double>::digits10);
                         ss << GetDouble(&offset);
                     }
-                    else if (item_byte_size == sizeof(long double))
+                    else if (item_byte_size == sizeof(long double) || item_byte_size == 10)
                     {
                         ss.precision(std::numeric_limits<long double>::digits10);
                         ss << GetLongDouble(&offset);
Index: test/functionalities/register/TestRegisters.py
===================================================================
--- test/functionalities/register/TestRegisters.py
+++ test/functionalities/register/TestRegisters.py
@@ -180,6 +180,10 @@
         new_value = "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}"
         self.vector_write_and_read(currentFrame, "xmm15", new_value, False)
 
+        self.runCmd("register write stmm0 \"{0x00 0x00 0x00 0x00 0x00 0x00 0x40 0x9a 0x09 0x40}\"")
+        self.expect("register read stmm0 --format f",
+            substrs = ['stmm0 = 1234'])
+
         has_avx = False 
         registerSets = currentFrame.GetRegisters() # Returns an SBValueList.
         for registerSet in registerSets:
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to