<div dir="ltr">This revision seems to have created a hang on startup on Windows.  LLDB now hangs during global static initialization on this line:<div><br></div><div><font size="1" face="monospace, monospace">const ConstString RenderScriptRuntime::Element::FallbackStructName("struct");</font><br></div><div><font size="1" face="monospace, monospace"><br></font></div><div><font face="arial, helvetica, sans-serif">Perhaps its an initialization order problem?</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">Adrian.</font></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Nov 30, 2015 at 2:29 AM, Ewan Crawford via lldb-commits <span dir="ltr"><<a href="mailto:lldb-commits@lists.llvm.org" target="_blank">lldb-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: ewancrawford<br>
Date: Mon Nov 30 04:29:49 2015<br>
New Revision: 254294<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=254294&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=254294&view=rev</a><br>
Log:<br>
[RS] Support RenderScript struct allocations<br>
<br>
This patch adds functionality for dumping allocations of struct elements. This involves:<br>
<br>
    + Jitting the runtime for details on all the struct fields.<br>
<br>
    + Finding the name of the struct type by looking for a global variable of the same type, which will have been reflected back to the java host code.<br>
<br>
    + Using this struct type name to pass into expression evaluation for pretty printing the data for the dump command.<br>
<br>
Modified:<br>
    lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp<br>
    lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h<br>
<br>
Modified: lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp?rev=254294&r1=254293&r2=254294&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp?rev=254294&r1=254293&r2=254294&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp (original)<br>
+++ lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp Mon Nov 30 04:29:49 2015<br>
@@ -18,7 +18,9 @@<br>
 #include "lldb/Core/Error.h"<br>
 #include "lldb/Core/Log.h"<br>
 #include "lldb/Core/PluginManager.h"<br>
+#include "lldb/Core/ValueObjectVariable.h"<br>
 #include "lldb/Core/RegularExpression.h"<br>
+#include "lldb/DataFormatters/DumpValueObjectOptions.h"<br>
 #include "lldb/Host/StringConvert.h"<br>
 #include "lldb/Symbol/Symbol.h"<br>
 #include "lldb/Symbol/Type.h"<br>
@@ -133,42 +135,61 @@ struct RenderScriptRuntime::ScriptDetail<br>
     empirical_type<lldb::addr_t> script;<br>
 };<br>
<br>
+// This Element class represents the Element object in RS,<br>
+// defining the type associated with an Allocation.<br>
+struct RenderScriptRuntime::Element<br>
+{<br>
+    // Taken from rsDefines.h<br>
+    enum DataKind<br>
+    {<br>
+        RS_KIND_USER,<br>
+        RS_KIND_PIXEL_L = 7,<br>
+        RS_KIND_PIXEL_A,<br>
+        RS_KIND_PIXEL_LA,<br>
+        RS_KIND_PIXEL_RGB,<br>
+        RS_KIND_PIXEL_RGBA,<br>
+        RS_KIND_PIXEL_DEPTH,<br>
+        RS_KIND_PIXEL_YUV,<br>
+        RS_KIND_INVALID = 100<br>
+    };<br>
+<br>
+    // Taken from rsDefines.h<br>
+    enum DataType<br>
+    {<br>
+        RS_TYPE_NONE = 0,<br>
+        RS_TYPE_FLOAT_16,<br>
+        RS_TYPE_FLOAT_32,<br>
+        RS_TYPE_FLOAT_64,<br>
+        RS_TYPE_SIGNED_8,<br>
+        RS_TYPE_SIGNED_16,<br>
+        RS_TYPE_SIGNED_32,<br>
+        RS_TYPE_SIGNED_64,<br>
+        RS_TYPE_UNSIGNED_8,<br>
+        RS_TYPE_UNSIGNED_16,<br>
+        RS_TYPE_UNSIGNED_32,<br>
+        RS_TYPE_UNSIGNED_64,<br>
+        RS_TYPE_BOOLEAN<br>
+    };<br>
+<br>
+    std::vector<Element> children;                       // Child Element fields for structs<br>
+    empirical_type<lldb::addr_t> element_ptr;            // Pointer to the RS Element of the Type<br>
+    empirical_type<DataType> type;                       // Type of each data pointer stored by the allocation<br>
+    empirical_type<DataKind> type_kind;                  // Defines pixel type if Allocation is created from an image<br>
+    empirical_type<uint32_t> type_vec_size;              // Vector size of each data point, e.g '4' for uchar4<br>
+    empirical_type<uint32_t> field_count;                // Number of Subelements<br>
+    empirical_type<uint32_t> datum_size;                 // Size of a single Element with padding<br>
+    empirical_type<uint32_t> padding;                    // Number of padding bytes<br>
+    empirical_type<uint32_t> array_size;                 // Number of items in array, only needed for strucrs<br>
+    ConstString type_name;                               // Name of type, only needed for structs<br>
+<br>
+    static const ConstString FallbackStructName;         // Print this as the type name of a struct Element<br>
+                                                         // If we can't resolve the actual struct name<br>
+};<br>
+<br>
 // This AllocationDetails class collects data associated with a single<br>
 // allocation instance.<br>
 struct RenderScriptRuntime::AllocationDetails<br>
 {<br>
-   // Taken from rsDefines.h<br>
-   enum DataKind<br>
-   {<br>
-       RS_KIND_USER,<br>
-       RS_KIND_PIXEL_L = 7,<br>
-       RS_KIND_PIXEL_A,<br>
-       RS_KIND_PIXEL_LA,<br>
-       RS_KIND_PIXEL_RGB,<br>
-       RS_KIND_PIXEL_RGBA,<br>
-       RS_KIND_PIXEL_DEPTH,<br>
-       RS_KIND_PIXEL_YUV,<br>
-       RS_KIND_INVALID = 100<br>
-   };<br>
-<br>
-   // Taken from rsDefines.h<br>
-   enum DataType<br>
-   {<br>
-       RS_TYPE_NONE = 0,<br>
-       RS_TYPE_FLOAT_16,<br>
-       RS_TYPE_FLOAT_32,<br>
-       RS_TYPE_FLOAT_64,<br>
-       RS_TYPE_SIGNED_8,<br>
-       RS_TYPE_SIGNED_16,<br>
-       RS_TYPE_SIGNED_32,<br>
-       RS_TYPE_SIGNED_64,<br>
-       RS_TYPE_UNSIGNED_8,<br>
-       RS_TYPE_UNSIGNED_16,<br>
-       RS_TYPE_UNSIGNED_32,<br>
-       RS_TYPE_UNSIGNED_64,<br>
-       RS_TYPE_BOOLEAN<br>
-    };<br>
-<br>
     struct Dimension<br>
     {<br>
         uint32_t dim_1;<br>
@@ -214,14 +235,11 @@ struct RenderScriptRuntime::AllocationDe<br>
     // for commands to reference it.<br>
     const unsigned int id;<br>
<br>
-    empirical_type<DataType> type;            // Type of each data pointer stored by the allocation<br>
-    empirical_type<DataKind> type_kind;       // Defines pixel type if Allocation is created from an image<br>
-    empirical_type<uint32_t> type_vec_size;   // Vector size of each data point, e.g '4' for uchar4<br>
+    RenderScriptRuntime::Element element;     // Allocation Element type<br>
     empirical_type<Dimension> dimension;      // Dimensions of the Allocation<br>
     empirical_type<lldb::addr_t> address;     // Pointer to address of the RS Allocation<br>
     empirical_type<lldb::addr_t> data_ptr;    // Pointer to the data held by the Allocation<br>
     empirical_type<lldb::addr_t> type_ptr;    // Pointer to the RS Type of the Allocation<br>
-    empirical_type<lldb::addr_t> element_ptr; // Pointer to the RS Element of the Type<br>
     empirical_type<lldb::addr_t> context;     // Pointer to the RS Context of the Allocation<br>
     empirical_type<uint32_t> size;            // Size of the allocation<br>
     empirical_type<uint32_t> stride;          // Stride between rows of the allocation<br>
@@ -232,6 +250,8 @@ struct RenderScriptRuntime::AllocationDe<br>
     }<br>
 };<br>
<br>
+const ConstString RenderScriptRuntime::Element::FallbackStructName("struct");<br>
+<br>
 unsigned int RenderScriptRuntime::AllocationDetails::ID = 1;<br>
<br>
 const char* RenderScriptRuntime::AllocationDetails::RsDataKindToString[] =<br>
@@ -1099,7 +1119,11 @@ enum ExpressionStrings<br>
    eExprTypeElemPtr,<br>
    eExprElementType,<br>
    eExprElementKind,<br>
-   eExprElementVec<br>
+   eExprElementVec,<br>
+   eExprElementFieldCount,<br>
+   eExprSubelementsId,<br>
+   eExprSubelementsName,<br>
+   eExprSubelementsArrSize<br>
 };<br>
<br>
 // Format strings containing the expressions we may need to evaluate.<br>
@@ -1122,9 +1146,22 @@ const char runtimeExpressions[][256] =<br>
<br>
  // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)<br>
  // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData<br>
- "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type<br>
- "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind<br>
- "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]"  // Vector Size<br>
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type<br>
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind<br>
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]", // Vector Size<br>
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[4]", // Field Count<br>
+<br>
+  // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids, const char **names,<br>
+  // size_t *arraySizes, uint32_t dataSize)<br>
+  // Needed for Allocations of structs to gather details about fields/Subelements<br>
+ "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"<br>
+ "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); ids[%u]",     // Element* of field<br>
+<br>
+ "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"<br>
+ "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); names[%u]",   // Name of field<br>
+<br>
+ "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"<br>
+ "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); arr_size[%u]" // Array size of field<br>
 };<br>
<br>
 // JITs the RS runtime for the internal data pointer of an allocation.<br>
@@ -1272,7 +1309,7 @@ RenderScriptRuntime::JITTypePacked(Alloc<br>
     allocation->dimension = dims;<br>
<br>
     addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]);<br>
-    allocation->element_ptr = elem_ptr;<br>
+    allocation->element.element_ptr = elem_ptr;<br>
<br>
     if (log)<br>
         log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64,<br>
@@ -1282,23 +1319,23 @@ RenderScriptRuntime::JITTypePacked(Alloc<br>
 }<br>
<br>
 // JITs the RS runtime for information about the Element of an allocation<br>
-// Then sets type, type_vec_size, and type_kind members in Allocation with the result.<br>
+// Then sets type, type_vec_size, field_count and type_kind members in Element with the result.<br>
 // Returns true on success, false otherwise<br>
 bool<br>
-RenderScriptRuntime::JITElementPacked(AllocationDetails* allocation, StackFrame* frame_ptr)<br>
+RenderScriptRuntime::JITElementPacked(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr)<br>
 {<br>
     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));<br>
<br>
-    if (!allocation->element_ptr.isValid() || !allocation->context.isValid())<br>
+    if (!elem.element_ptr.isValid())<br>
     {<br>
         if (log)<br>
             log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details");<br>
         return false;<br>
     }<br>
<br>
-    // We want 3 elements from packed data<br>
-    const unsigned int num_exprs = 3;<br>
-    assert(num_exprs == (eExprElementVec - eExprElementType + 1) && "Invalid number of expressions");<br>
+    // We want 4 elements from packed data<br>
+    const unsigned int num_exprs = 4;<br>
+    assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1) && "Invalid number of expressions");<br>
<br>
     const int max_expr_size = 512; // Max expression size<br>
     char buffer[num_exprs][max_expr_size];<br>
@@ -1306,11 +1343,11 @@ RenderScriptRuntime::JITElementPacked(Al<br>
<br>
     for (unsigned int i = 0; i < num_exprs; i++)<br>
     {<br>
-        int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprElementType + i], *allocation->context.get(), *allocation->element_ptr.get());<br>
+        int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprElementType + i], context, *elem.element_ptr.get());<br>
         if (chars_written < 0)<br>
         {<br>
             if (log)<br>
-                log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");<br>
+                log->Printf("RenderScriptRuntime::JITElementPacked - Encoding error in snprintf()");<br>
             return false;<br>
         }<br>
         else if (chars_written >= max_expr_size)<br>
@@ -1326,13 +1363,109 @@ RenderScriptRuntime::JITElementPacked(Al<br>
     }<br>
<br>
     // Assign results to allocation members<br>
-    allocation->type = static_cast<RenderScriptRuntime::AllocationDetails::DataType>(results[0]);<br>
-    allocation->type_kind = static_cast<RenderScriptRuntime::AllocationDetails::DataKind>(results[1]);<br>
-    allocation->type_vec_size = static_cast<uint32_t>(results[2]);<br>
+    elem.type = static_cast<RenderScriptRuntime::Element::DataType>(results[0]);<br>
+    elem.type_kind = static_cast<RenderScriptRuntime::Element::DataKind>(results[1]);<br>
+    elem.type_vec_size = static_cast<uint32_t>(results[2]);<br>
+    elem.field_count = static_cast<uint32_t>(results[3]);<br>
<br>
     if (log)<br>
-        log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u",<br>
-                    *allocation->type.get(), *allocation->type_kind.get(), *allocation->type_vec_size.get());<br>
+        log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u, field count %u",<br>
+                    *elem.type.get(), *elem.type_kind.get(), *elem.type_vec_size.get(), *elem.field_count.get());<br>
+<br>
+    // If this Element has subelements then JIT rsaElementGetSubElements() for details about its fields<br>
+    if (*elem.field_count.get() > 0 && !JITSubelements(elem, context, frame_ptr))<br>
+        return false;<br>
+<br>
+    return true;<br>
+}<br>
+<br>
+// JITs the RS runtime for information about the subelements/fields of a struct allocation<br>
+// This is necessary for infering the struct type so we can pretty print the allocation's contents.<br>
+// Returns true on success, false otherwise<br>
+bool<br>
+RenderScriptRuntime::JITSubelements(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr)<br>
+{<br>
+    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));<br>
+<br>
+    if (!elem.element_ptr.isValid() || !elem.field_count.isValid())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("RenderScriptRuntime::JITSubelements - Failed to find allocation details");<br>
+        return false;<br>
+    }<br>
+<br>
+    const short num_exprs = 3;<br>
+    assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1) && "Invalid number of expressions");<br>
+<br>
+    const int max_expr_size = 512; // Max expression size<br>
+    char expr_buffer[max_expr_size];<br>
+    uint64_t results;<br>
+<br>
+    // Iterate over struct fields.<br>
+    const uint32_t field_count = *elem.field_count.get();<br>
+    for (unsigned int field_index = 0; field_index < field_count; ++field_index)<br>
+    {<br>
+        Element child;<br>
+        for (unsigned int expr_index = 0; expr_index < num_exprs; ++expr_index)<br>
+        {<br>
+            int chars_written = snprintf(expr_buffer, max_expr_size, runtimeExpressions[eExprSubelementsId + expr_index],<br>
+                                         field_count, field_count, field_count,<br>
+                                         context, *elem.element_ptr.get(), field_count, field_index);<br>
+            if (chars_written < 0)<br>
+            {<br>
+                if (log)<br>
+                    log->Printf("RenderScriptRuntime::JITSubelements - Encoding error in snprintf()");<br>
+                return false;<br>
+            }<br>
+            else if (chars_written >= max_expr_size)<br>
+            {<br>
+                if (log)<br>
+                    log->Printf("RenderScriptRuntime::JITSubelements - Expression too long");<br>
+                return false;<br>
+            }<br>
+<br>
+            // Perform expression evaluation<br>
+            if (!EvalRSExpression(expr_buffer, frame_ptr, &results))<br>
+                return false;<br>
+<br>
+            if (log)<br>
+                log->Printf("RenderScriptRuntime::JITSubelements - Expr result 0x%" PRIx64, results);<br>
+<br>
+            switch(expr_index)<br>
+            {<br>
+                case 0: // Element* of child<br>
+                    child.element_ptr = static_cast<addr_t>(results);<br>
+                    break;<br>
+                case 1: // Name of child<br>
+                {<br>
+                    lldb::addr_t address = static_cast<addr_t>(results);<br>
+                    Error err;<br>
+                    std::string name;<br>
+                    GetProcess()->ReadCStringFromMemory(address, name, err);<br>
+                    if (!err.Fail())<br>
+                        child.type_name = ConstString(name);<br>
+                    else<br>
+                    {<br>
+                        if (log)<br>
+                            log->Printf("RenderScriptRuntime::JITSubelements - Warning: Couldn't read field name");<br>
+                    }<br>
+                    break;<br>
+                }<br>
+                case 2: // Array size of child<br>
+                    child.array_size = static_cast<uint32_t>(results);<br>
+                    break;<br>
+            }<br>
+        }<br>
+<br>
+        // We need to recursively JIT each Element field of the struct since<br>
+        // structs can be nested inside structs.<br>
+        if (!JITElementPacked(child, context, frame_ptr))<br>
+            return false;<br>
+        elem.children.push_back(child);<br>
+    }<br>
+<br>
+    // Try to infer the name of the struct type so we can pretty print the allocation contents.<br>
+    FindStructTypeName(elem, frame_ptr);<br>
<br>
     return true;<br>
 }<br>
@@ -1343,28 +1476,43 @@ RenderScriptRuntime::JITElementPacked(Al<br>
 // Using this offset minus the starting address we can calculate the size of the allocation.<br>
 // Returns true on success, false otherwise<br>
 bool<br>
-RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr,<br>
-                                       const uint32_t elem_size)<br>
+RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr)<br>
 {<br>
     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));<br>
<br>
     if (!allocation->address.isValid() || !allocation->dimension.isValid()<br>
-        || !allocation->data_ptr.isValid())<br>
+        || !allocation->data_ptr.isValid() || !allocation->element.datum_size.isValid())<br>
     {<br>
         if (log)<br>
             log->Printf("RenderScriptRuntime::JITAllocationSize - Failed to find allocation details");<br>
         return false;<br>
     }<br>
<br>
-    const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];<br>
-    const int max_expr_size = 512; // Max expression size<br>
-    char buffer[max_expr_size];<br>
-<br>
     // Find dimensions<br>
     unsigned int dim_x = allocation->dimension.get()->dim_1;<br>
     unsigned int dim_y = allocation->dimension.get()->dim_2;<br>
     unsigned int dim_z = allocation->dimension.get()->dim_3;<br>
<br>
+    // Our plan of jitting the last element address doesn't seem to work for struct Allocations<br>
+    // Instead try to infer the size ourselves without any inter element padding.<br>
+    if (allocation->element.children.size() > 0)<br>
+    {<br>
+        if (dim_x == 0) dim_x = 1;<br>
+        if (dim_y == 0) dim_y = 1;<br>
+        if (dim_z == 0) dim_z = 1;<br>
+<br>
+        allocation->size = dim_x * dim_y * dim_z * *allocation->element.datum_size.get();<br>
+<br>
+        if (log)<br>
+            log->Printf("RenderScriptRuntime::JITAllocationSize - Infered size of struct allocation %u", *allocation->size.get());<br>
+<br>
+        return true;<br>
+    }<br>
+<br>
+    const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];<br>
+    const int max_expr_size = 512;<br>
+    char buffer[max_expr_size];<br>
+<br>
     // Calculate last element<br>
     dim_x = dim_x == 0 ? 0 : dim_x - 1;<br>
     dim_y = dim_y == 0 ? 0 : dim_y - 1;<br>
@@ -1391,7 +1539,7 @@ RenderScriptRuntime::JITAllocationSize(A<br>
<br>
     addr_t mem_ptr = static_cast<lldb::addr_t>(result);<br>
     // Find pointer to last element and add on size of an element<br>
-    allocation->size = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) + elem_size;<br>
+    allocation->size = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) + *allocation->element.datum_size.get();<br>
<br>
     return true;<br>
 }<br>
@@ -1457,31 +1605,140 @@ RenderScriptRuntime::RefreshAllocation(A<br>
         return false;<br>
<br>
     // rsaElementGetNativeData()<br>
-    if (!JITElementPacked(allocation, frame_ptr))<br>
+    if (!JITElementPacked(allocation->element, *allocation->context.get(), frame_ptr))<br>
         return false;<br>
<br>
+    // Sets the datum_size member in Element<br>
+    SetElementSize(allocation->element);<br>
+<br>
     // Use GetOffsetPointer() to infer size of the allocation<br>
-    const unsigned int element_size = GetElementSize(allocation);<br>
-    if (!JITAllocationSize(allocation, frame_ptr, element_size))<br>
+    if (!JITAllocationSize(allocation, frame_ptr))<br>
         return false;<br>
<br>
     return true;<br>
 }<br>
<br>
-// Returns the size of a single allocation element including padding.<br>
+// Function attempts to set the type_name member of the paramaterised Element object.<br>
+// This string should be the name of the struct type the Element represents.<br>
+// We need this string for pretty printing the Element to users.<br>
+void<br>
+RenderScriptRuntime::FindStructTypeName(Element& elem, StackFrame* frame_ptr)<br>
+{<br>
+    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));<br>
+<br>
+    if (!elem.type_name.IsEmpty()) // Name already set<br>
+        return;<br>
+    else<br>
+        elem.type_name = Element::FallbackStructName; // Default type name if we don't succeed<br>
+<br>
+    // Find all the global variables from the script rs modules<br>
+    VariableList variable_list;<br>
+    for (auto module_sp : m_rsmodules)<br>
+        module_sp->m_module->FindGlobalVariables(RegularExpression("."), true, UINT32_MAX, variable_list);<br>
+<br>
+    // Iterate over all the global variables looking for one with a matching type to the Element.<br>
+    // We make the assumption a match exists since there needs to be a global variable to reflect the<br>
+    // struct type back into java host code.<br>
+    for (uint32_t var_index = 0; var_index < variable_list.GetSize(); ++var_index)<br>
+    {<br>
+        const VariableSP var_sp(variable_list.GetVariableAtIndex(var_index));<br>
+        if (!var_sp)<br>
+           continue;<br>
+<br>
+        ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp);<br>
+        if (!valobj_sp)<br>
+            continue;<br>
+<br>
+        // Find the number of variable fields.<br>
+        // If it has no fields, or more fields than our Element, then it can't be the struct we're looking for.<br>
+        // Don't check for equality since RS can add extra struct members for padding.<br>
+        size_t num_children = valobj_sp->GetNumChildren();<br>
+        if (num_children > elem.children.size() || num_children == 0)<br>
+            continue;<br>
+<br>
+        // Iterate over children looking for members with matching field names.<br>
+        // If all the field names match, this is likely the struct we want.<br>
+        //<br>
+        //   TODO: This could be made more robust by also checking children data sizes, or array size<br>
+        bool found = true;<br>
+        for (size_t child_index = 0; child_index < num_children; ++child_index)<br>
+        {<br>
+            ValueObjectSP child = valobj_sp->GetChildAtIndex(child_index, true);<br>
+            if (!child || (child->GetName() != elem.children[child_index].type_name))<br>
+            {<br>
+                found = false;<br>
+                break;<br>
+            }<br>
+        }<br>
+<br>
+        // RS can add extra struct members for padding in the format '#rs_padding_[0-9]+'<br>
+        if (found && num_children < elem.children.size())<br>
+        {<br>
+            const unsigned int size_diff = elem.children.size() - num_children;<br>
+            if (log)<br>
+                log->Printf("RenderScriptRuntime::FindStructTypeName - %u padding struct entries", size_diff);<br>
+<br>
+            for (unsigned int padding_index = 0; padding_index < size_diff; ++padding_index)<br>
+            {<br>
+                const ConstString& name = elem.children[num_children + padding_index].type_name;<br>
+                if (strcmp(name.AsCString(), "#rs_padding") < 0)<br>
+                    found = false;<br>
+            }<br>
+        }<br>
+<br>
+        // We've found a global var with matching type<br>
+        if (found)<br>
+        {<br>
+            // Dereference since our Element type isn't a pointer.<br>
+            if (valobj_sp->IsPointerType())<br>
+            {<br>
+                Error err;<br>
+                ValueObjectSP deref_valobj = valobj_sp->Dereference(err);<br>
+                if (!err.Fail())<br>
+                    valobj_sp = deref_valobj;<br>
+            }<br>
+<br>
+            // Save name of variable in Element.<br>
+            elem.type_name = valobj_sp->GetTypeName();<br>
+            if (log)<br>
+                log->Printf("RenderScriptRuntime::FindStructTypeName - Element name set to %s", elem.type_name.AsCString());<br>
+<br>
+            return;<br>
+        }<br>
+    }<br>
+}<br>
+<br>
+// Function sets the datum_size member of Element. Representing the size of a single instance including padding.<br>
 // Assumes the relevant allocation information has already been jitted.<br>
-unsigned int<br>
-RenderScriptRuntime::GetElementSize(const AllocationDetails* allocation)<br>
+void<br>
+RenderScriptRuntime::SetElementSize(Element& elem)<br>
 {<br>
-    const AllocationDetails::DataType type = *allocation->type.get();<br>
-    assert(type >= AllocationDetails::RS_TYPE_NONE && type <= AllocationDetails::RS_TYPE_BOOLEAN<br>
+    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));<br>
+    const Element::DataType type = *elem.type.get();<br>
+    assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_BOOLEAN<br>
                                                    && "Invalid allocation type");<br>
<br>
-    const unsigned int vec_size = *allocation->type_vec_size.get();<br>
-    const unsigned int data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];<br>
+    const unsigned int vec_size = *elem.type_vec_size.get();<br>
+    unsigned int data_size = 0;<br>
     const unsigned int padding = vec_size == 3 ? AllocationDetails::RSTypeToFormat[type][eElementSize] : 0;<br>
<br>
-    return data_size + padding;<br>
+    // Element is of a struct type, calculate size recursively.<br>
+    if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0))<br>
+    {<br>
+        for (Element& child : elem.children)<br>
+        {<br>
+            SetElementSize(child);<br>
+            const unsigned int array_size = child.array_size.isValid() ? *child.array_size.get() : 1;<br>
+            data_size += *child.datum_size.get() * array_size;<br>
+        }<br>
+    }<br>
+    else<br>
+        data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];<br>
+<br>
+    elem.padding = padding;<br>
+    elem.datum_size = data_size + padding;<br>
+    if (log)<br>
+        log->Printf("RenderScriptRuntime::SetElementSize - element size set to %u", data_size + padding);<br>
 }<br>
<br>
 // Given an allocation, this function copies the allocation contents from device into a buffer on the heap.<br>
@@ -1492,8 +1749,8 @@ RenderScriptRuntime::GetAllocationData(A<br>
     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));<br>
<br>
     // JIT all the allocation details<br>
-    if (!allocation->data_ptr.isValid() || !allocation->type.isValid() || !allocation->type_vec_size.isValid()<br>
-        || !allocation->size.isValid())<br>
+    if (!allocation->data_ptr.isValid() || !allocation->element.type.isValid()<br>
+        || !allocation->element.type_vec_size.isValid() || !allocation->size.isValid())<br>
     {<br>
         if (log)<br>
             log->Printf("RenderScriptRuntime::GetAllocationData - Allocation details not calculated yet, jitting info");<br>
@@ -1506,7 +1763,7 @@ RenderScriptRuntime::GetAllocationData(A<br>
         }<br>
     }<br>
<br>
-    assert(allocation->data_ptr.isValid() && allocation->type.isValid() && allocation->type_vec_size.isValid()<br>
+    assert(allocation->data_ptr.isValid() && allocation->element.type.isValid() && allocation->element.type_vec_size.isValid()<br>
            && allocation->size.isValid() && "Allocation information not available");<br>
<br>
     // Allocate a buffer to copy data into<br>
@@ -1551,7 +1808,8 @@ RenderScriptRuntime::LoadAllocation(Stre<br>
         log->Printf("RenderScriptRuntime::LoadAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());<br>
<br>
     // JIT all the allocation details<br>
-    if (!alloc->data_ptr.isValid() || !alloc->type.isValid() || !alloc->type_vec_size.isValid() || !alloc->size.isValid())<br>
+    if (!alloc->data_ptr.isValid() || !alloc->element.type.isValid() || !alloc->element.datum_size.isValid()<br>
+        || !alloc->element.type_vec_size.isValid() || !alloc->size.isValid())<br>
     {<br>
         if (log)<br>
             log->Printf("RenderScriptRuntime::LoadAllocation - Allocation details not calculated yet, jitting info");<br>
@@ -1564,8 +1822,8 @@ RenderScriptRuntime::LoadAllocation(Stre<br>
         }<br>
     }<br>
<br>
-    assert(alloc->data_ptr.isValid() && alloc->type.isValid() && alloc->type_vec_size.isValid() && alloc->size.isValid()<br>
-           && "Allocation information not available");<br>
+    assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid()<br>
+           && alloc->size.isValid() && alloc->element.datum_size.isValid() && "Allocation information not available");<br>
<br>
     // Check we can read from file<br>
     FileSpec file(filename, true);<br>
@@ -1598,16 +1856,15 @@ RenderScriptRuntime::LoadAllocation(Stre<br>
                     head->type, head->element_size);<br>
<br>
     // Check if the target allocation and file both have the same number of bytes for an Element<br>
-    const unsigned int elem_size = GetElementSize(alloc);<br>
-    if (elem_size != head->element_size)<br>
+    if (*alloc->element.datum_size.get() != head->element_size)<br>
     {<br>
         strm.Printf("Warning: Mismatched Element sizes - file %u bytes, allocation %u bytes",<br>
-                    head->element_size, elem_size);<br>
+                    head->element_size, *alloc->element.datum_size.get());<br>
         strm.EOL();<br>
     }<br>
<br>
     // Check if the target allocation and file both have the same integral type<br>
-    const unsigned int type = static_cast<unsigned int>(*alloc->type.get());<br>
+    const unsigned int type = static_cast<unsigned int>(*alloc->element.type.get());<br>
     if (type != head->type)<br>
     {<br>
         const char* file_type_cstr = AllocationDetails::RsDataTypeToString[head->type][0];<br>
@@ -1665,8 +1922,8 @@ RenderScriptRuntime::SaveAllocation(Stre<br>
         log->Printf("RenderScriptRuntime::SaveAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());<br>
<br>
      // JIT all the allocation details<br>
-    if (!alloc->data_ptr.isValid() || !alloc->type.isValid() || !alloc->type_vec_size.isValid()<br>
-        || !alloc->type_kind.isValid() || !alloc->dimension.isValid())<br>
+    if (!alloc->data_ptr.isValid() || !alloc->element.type.isValid() || !alloc->element.type_vec_size.isValid()<br>
+        || !alloc->element.type_kind.isValid() || !alloc->dimension.isValid())<br>
     {<br>
         if (log)<br>
             log->Printf("RenderScriptRuntime::SaveAllocation - Allocation details not calculated yet, jitting info");<br>
@@ -1679,8 +1936,8 @@ RenderScriptRuntime::SaveAllocation(Stre<br>
         }<br>
     }<br>
<br>
-    assert(alloc->data_ptr.isValid() && alloc->type.isValid() && alloc->type_vec_size.isValid() && alloc->type_kind.isValid()<br>
-           && alloc->dimension.isValid() && "Allocation information not available");<br>
+    assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid() && alloc->element.datum_size.get()<br>
+           && alloc->element.type_kind.isValid() && alloc->dimension.isValid() && "Allocation information not available");<br>
<br>
     // Check we can create writable file<br>
     FileSpec file_spec(filename, true);<br>
@@ -1705,12 +1962,12 @@ RenderScriptRuntime::SaveAllocation(Stre<br>
     AllocationDetails::FileHeader head;<br>
     head.ident[0] = 'R'; head.ident[1] = 'S'; head.ident[2] = 'A'; head.ident[3] = 'D';<br>
     head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader));<br>
-    head.type = static_cast<uint16_t>(*alloc->type.get());<br>
-    head.kind = static_cast<uint32_t>(*alloc->type_kind.get());<br>
+    head.type = static_cast<uint16_t>(*alloc->element.type.get());<br>
+    head.kind = static_cast<uint32_t>(*alloc->element.type_kind.get());<br>
     head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);<br>
     head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);<br>
     head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);<br>
-    head.element_size = static_cast<uint32_t>(GetElementSize(alloc));<br>
+    head.element_size = static_cast<uint32_t>(*alloc->element.datum_size.get());<br>
<br>
     // Write the file header<br>
     size_t num_bytes = sizeof(AllocationDetails::FileHeader);<br>
@@ -2080,8 +2337,8 @@ RenderScriptRuntime::DumpAllocation(Stre<br>
         log->Printf("RenderScriptRuntime::DumpAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());<br>
<br>
     // Check we have information about the allocation, if not calculate it<br>
-    if (!alloc->data_ptr.isValid() || !alloc->type.isValid() ||<br>
-        !alloc->type_vec_size.isValid() || !alloc->dimension.isValid())<br>
+    if (!alloc->data_ptr.isValid() || !alloc->element.type.isValid() ||<br>
+        !alloc->element.type_vec_size.isValid() || !alloc->dimension.isValid() || !alloc->element.datum_size.isValid())<br>
     {<br>
         if (log)<br>
             log->Printf("RenderScriptRuntime::DumpAllocation - Allocation details not calculated yet, jitting info");<br>
@@ -2096,22 +2353,19 @@ RenderScriptRuntime::DumpAllocation(Stre<br>
     }<br>
<br>
     // Establish format and size of each data element<br>
-    const unsigned int vec_size = *alloc->type_vec_size.get();<br>
-    const AllocationDetails::DataType type = *alloc->type.get();<br>
+    const unsigned int vec_size = *alloc->element.type_vec_size.get();<br>
+    const Element::DataType type = *alloc->element.type.get();<br>
<br>
-    assert(type >= AllocationDetails::RS_TYPE_NONE && type <= AllocationDetails::RS_TYPE_BOOLEAN<br>
+    assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_BOOLEAN<br>
                                                    && "Invalid allocation type");<br>
<br>
     lldb::Format format = vec_size == 1 ? static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatSingle])<br>
                                         : static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatVector]);<br>
<br>
-    const unsigned int data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];<br>
-    // Renderscript pads vector 3 elements to vector 4<br>
-    const unsigned int elem_padding = vec_size == 3 ? AllocationDetails::RSTypeToFormat[type][eElementSize] : 0;<br>
+    const unsigned int data_size = *alloc->element.datum_size.get();<br>
<br>
     if (log)<br>
-        log->Printf("RenderScriptRuntime::DumpAllocation - Element size %u bytes, element padding %u bytes",<br>
-                    data_size, elem_padding);<br>
+        log->Printf("RenderScriptRuntime::DumpAllocation - Element size %u bytes, including padding", data_size);<br>
<br>
     // Allocate a buffer to copy data into<br>
     std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);<br>
@@ -2136,10 +2390,10 @@ RenderScriptRuntime::DumpAllocation(Stre<br>
         }<br>
     }<br>
     const unsigned int stride = *alloc->stride.get();<br>
-    const unsigned int size = *alloc->size.get(); //size of last element<br>
-<br>
+    const unsigned int size = *alloc->size.get(); // Size of whole allocation<br>
+    const unsigned int padding = alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0;<br>
     if (log)<br>
-        log->Printf("RenderScriptRuntime::DumpAllocation - stride %u bytes, size %u bytes", stride, size);<br>
+        log->Printf("RenderScriptRuntime::DumpAllocation - stride %u bytes, size %u bytes, padding %u", stride, size, padding);<br>
<br>
     // Find dimensions used to index loops, so need to be non-zero<br>
     unsigned int dim_x = alloc->dimension.get()->dim_1;<br>
@@ -2173,8 +2427,41 @@ RenderScriptRuntime::DumpAllocation(Stre<br>
             for (unsigned int x = 0; x < dim_x; ++x)<br>
             {<br>
                 strm.Printf("\n(%u, %u, %u) = ", x, y, z);<br>
-                alloc_data.Dump(&strm, offset, format, data_size, 1, 1, LLDB_INVALID_ADDRESS, 0, 0);<br>
-                offset += data_size + elem_padding;<br>
+                if ((type == Element::RS_TYPE_NONE) && (alloc->element.children.size() > 0) &&<br>
+                    (alloc->element.type_name != Element::FallbackStructName))<br>
+                {<br>
+                    // Here we are dumping an Element of struct type.<br>
+                    // This is done using expression evaluation with the name of the struct type and pointer to element.<br>
+<br>
+                    // Don't print the name of the resulting expression, since this will be '$[0-9]+'<br>
+                    DumpValueObjectOptions expr_options;<br>
+                    expr_options.SetHideName(true);<br>
+<br>
+                    // Setup expression as derefrencing a pointer cast to element address.<br>
+                    const int max_expr_size = 512;<br>
+                    char expr_char_buffer[max_expr_size];<br>
+                    int chars_written = snprintf(expr_char_buffer, max_expr_size, "*(%s*) 0x%" PRIx64,<br>
+                                        alloc->element.type_name.AsCString(), *alloc->data_ptr.get() + offset);<br>
+<br>
+                    if (chars_written < 0 || chars_written >= max_expr_size)<br>
+                    {<br>
+                        if (log)<br>
+                            log->Printf("RenderScriptRuntime::DumpAllocation- Error in snprintf()");<br>
+                        continue;<br>
+                    }<br>
+<br>
+                    // Evaluate expression<br>
+                    ValueObjectSP expr_result;<br>
+                    GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer, frame_ptr, expr_result);<br>
+<br>
+                    // Print the results to our stream.<br>
+                    expr_result->Dump(strm, expr_options);<br>
+                }<br>
+                else<br>
+                {<br>
+                    alloc_data.Dump(&strm, offset, format, data_size - padding, 1, 1, LLDB_INVALID_ADDRESS, 0, 0);<br>
+                }<br>
+                offset += data_size;<br>
             }<br>
         }<br>
     }<br>
@@ -2234,27 +2521,29 @@ RenderScriptRuntime::ListAllocations(Str<br>
                                           alloc->dimension.get()->dim_3);<br>
<br>
         strm.Indent("Data Type: ");<br>
-        if (!alloc->type.isValid() || !alloc->type_vec_size.isValid())<br>
+        if (!alloc->element.type.isValid() || !alloc->element.type_vec_size.isValid())<br>
             strm.Printf("unknown\n");<br>
         else<br>
         {<br>
-            const int vector_size = *alloc->type_vec_size.get();<br>
-            const AllocationDetails::DataType type = *alloc->type.get();<br>
+            const int vector_size = *alloc->element.type_vec_size.get();<br>
+            const Element::DataType type = *alloc->element.type.get();<br>
<br>
-            if (vector_size > 4 || vector_size < 1 ||<br>
-                type < AllocationDetails::RS_TYPE_NONE || type > AllocationDetails::RS_TYPE_BOOLEAN)<br>
+            if (!alloc->element.type_name.IsEmpty())<br>
+                strm.Printf("%s\n", alloc->element.type_name.AsCString());<br>
+            else if (vector_size > 4 || vector_size < 1 ||<br>
+                type < Element::RS_TYPE_NONE || type > Element::RS_TYPE_BOOLEAN)<br>
                 strm.Printf("invalid type\n");<br>
             else<br>
                 strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<unsigned int>(type)][vector_size-1]);<br>
         }<br>
<br>
         strm.Indent("Data Kind: ");<br>
-        if (!alloc->type_kind.isValid())<br>
+        if (!alloc->element.type_kind.isValid())<br>
             strm.Printf("unknown\n");<br>
         else<br>
         {<br>
-            const AllocationDetails::DataKind kind = *alloc->type_kind.get();<br>
-            if (kind < AllocationDetails::RS_KIND_USER || kind > AllocationDetails::RS_KIND_PIXEL_YUV)<br>
+            const Element::DataKind kind = *alloc->element.type_kind.get();<br>
+            if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV)<br>
                 strm.Printf("invalid kind\n");<br>
             else<br>
                 strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]);<br>
<br>
Modified: lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h?rev=254294&r1=254293&r2=254294&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h?rev=254294&r1=254293&r2=254294&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h (original)<br>
+++ lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h Mon Nov 30 04:29:49 2015<br>
@@ -231,6 +231,7 @@ public:<br>
 protected:<br>
     struct ScriptDetails;<br>
     struct AllocationDetails;<br>
+    struct Element;<br>
<br>
     void InitSearchFilter(lldb::TargetSP target)<br>
     {<br>
@@ -311,8 +312,9 @@ private:<br>
<br>
     AllocationDetails* FindAllocByID(Stream &strm, const uint32_t alloc_id);<br>
     std::shared_ptr<uint8_t> GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr);<br>
-    unsigned int GetElementSize(const AllocationDetails* allocation);<br>
+    void SetElementSize(Element& elem);<br>
     static bool GetFrameVarAsUnsigned(const lldb::StackFrameSP, const char* var_name, uint64_t& val);<br>
+    void FindStructTypeName(Element& elem, StackFrame* frame_ptr);<br>
<br>
     //<br>
     // Helper functions for jitting the runtime<br>
@@ -324,9 +326,11 @@ private:<br>
<br>
     bool JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr);<br>
<br>
-    bool JITElementPacked(AllocationDetails* allocation, StackFrame* frame_ptr);<br>
+    bool JITElementPacked(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr);<br>
<br>
-    bool JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr, const uint32_t elem_size);<br>
+    bool JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr);<br>
+<br>
+    bool JITSubelements(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr);<br>
<br>
     bool JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr);<br>
<br>
<br>
<br>
_______________________________________________<br>
lldb-commits mailing list<br>
<a href="mailto:lldb-commits@lists.llvm.org">lldb-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits</a><br>
</blockquote></div><br></div>