EwanCrawford created this revision.
EwanCrawford added reviewers: jingham, clayborg.
EwanCrawford added subscribers: lldb-commits, domipheus, ADodds, dean.
EwanCrawford set the repository for this revision to rL LLVM.
Herald added subscribers: srhines, danalbert, tberghammer.

This patch adds a new command 'language renderscript allocation list' for 
printing the details of all loaded RS allocations.

In order to work out this information lldb JITs the runtime for the data it 
wants. 
This has a penalty of a couple seconds latency, so is only done once for each 
allocation and the results cached. 

If the user later wants to recalculate this information however, they can force 
lldb to do so with the --refresh flag.

Repository:
  rL LLVM

http://reviews.llvm.org/D13247

Files:
  RenderScriptRuntime.cpp
  RenderScriptRuntime.h

Index: RenderScriptRuntime.h
===================================================================
--- RenderScriptRuntime.h
+++ RenderScriptRuntime.h
@@ -202,6 +202,8 @@
 
     void DumpKernels(Stream &strm) const;
 
+    void ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute);
+
     void AttemptBreakpointAtKernelName(Stream &strm, const char *name, Error &error, lldb::TargetSP target);
 
     void SetBreakAllKernels(bool do_break, lldb::TargetSP target);
@@ -220,6 +222,9 @@
     
   protected:
 
+    struct ScriptDetails;
+    struct AllocationDetails;
+
     void InitSearchFilter(lldb::TargetSP target)
     {
         if (!m_filtersp)
@@ -230,6 +235,10 @@
 
     void LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind);
 
+    bool RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr);
+
+    bool EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result);
+
     lldb::BreakpointSP CreateKernelBreakpoint(const ConstString& name);
 
     void BreakOnModuleKernels(const lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
@@ -256,9 +265,6 @@
     
     typedef std::shared_ptr<RuntimeHook> RuntimeHookSP;
 
-    struct ScriptDetails;
-    struct AllocationDetails;
-
     lldb::ModuleSP m_libRS;
     lldb::ModuleSP m_libRSDriver;
     lldb::ModuleSP m_libRSCpuRef;
@@ -292,6 +298,18 @@
     void CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context);
     void CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context);
 
+    //
+    // Helper functions for jitting the runtime
+    //
+    bool JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr,
+                        unsigned int x = 0, unsigned int y = 0, unsigned int z = 0);
+
+    bool JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr);
+
+    bool JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr);
+
+    bool JITElementPacked(AllocationDetails* allocation, StackFrame* frame_ptr);
+
     // Search for a script detail object using a target address.
     // If a script does not currently exist this function will return nullptr.
     // If 'create' is true and there is no previous script with this address,
Index: RenderScriptRuntime.cpp
===================================================================
--- RenderScriptRuntime.cpp
+++ RenderScriptRuntime.cpp
@@ -25,7 +25,7 @@
 #include "lldb/Interpreter/CommandObjectMultiword.h"
 #include "lldb/Breakpoint/StoppointCallbackContext.h"
 #include "lldb/Target/RegisterContext.h"
-
+#include "lldb/Expression/UserExpression.h"
 #include "lldb/Symbol/VariableList.h"
 
 using namespace lldb;
@@ -130,28 +130,118 @@
 // allocation instance.
 struct RenderScriptRuntime::AllocationDetails
 {
-    ~AllocationDetails () {};
+   // Taken from rsDefines.h
+   enum DataKind
+   {
+       RS_KIND_USER,
+       RS_KIND_PIXEL_L = 7,
+       RS_KIND_PIXEL_A,
+       RS_KIND_PIXEL_LA,
+       RS_KIND_PIXEL_RGB,
+       RS_KIND_PIXEL_RGBA,
+       RS_KIND_PIXEL_DEPTH,
+       RS_KIND_PIXEL_YUV,
+       RS_KIND_INVALID = 100
+   };
 
-    enum DataType
-    {
-        eInt,
+   // Taken from rsDefines.h
+   enum DataType
+   {
+       RS_TYPE_NONE = 0,
+       RS_TYPE_FLOAT_16,
+       RS_TYPE_FLOAT_32,
+       RS_TYPE_FLOAT_64,
+       RS_TYPE_SIGNED_8,
+       RS_TYPE_SIGNED_16,
+       RS_TYPE_SIGNED_32,
+       RS_TYPE_SIGNED_64,
+       RS_TYPE_UNSIGNED_8,
+       RS_TYPE_UNSIGNED_16,
+       RS_TYPE_UNSIGNED_32,
+       RS_TYPE_UNSIGNED_64,
+       RS_TYPE_BOOLEAN
     };
 
-    enum Dimension
+    struct Dimension
     {
-        e1d,
-        e2d,
-        e3d,
-        eCubeMap,
+        uint32_t dim_1;
+        uint32_t dim_2;
+        uint32_t dim_3;
+        uint32_t cubeMap;
+
+        Dimension()
+        {
+             dim_1 = 0;
+             dim_2 = 0;
+             dim_3 = 0;
+             cubeMap = 0;
+        }
     };
 
-    empirical_type<DataType> type;
-    empirical_type<Dimension> dimension;
-    empirical_type<lldb::addr_t> address;
-    empirical_type<lldb::addr_t> dataPtr;
-    empirical_type<lldb::addr_t> context;
+    // Monotonically increasing from 1
+    static unsigned int ID;
+
+    // Maps Allocation DataType enum and vector size to printable strings
+    // using mapping from RenderScript numerical types summary documentation
+    static const char* RsDataTypeToString[][4];
+
+    // Maps Allocation DataKind enum to printable strings
+    static const char* RsDataKindToString[];
+
+    // Give each allocation an ID as a way
+    // for commands to reference it.
+    const unsigned int id;
+
+    empirical_type<DataType> type;            // Type of each data pointer stored by the allocation
+    empirical_type<DataKind> type_kind;       // Defines pixel type if Allocation is created from an image
+    empirical_type<uint32_t> type_vec_size;   // Vector size of each data point, e.g '4' for uchar4
+    empirical_type<Dimension> dimension;      // Dimensions of the Allocation
+    empirical_type<lldb::addr_t> address;     // Pointer to address of the RS Allocation
+    empirical_type<lldb::addr_t> data_ptr;    // Pointer to the data held by the Allocation
+    empirical_type<lldb::addr_t> type_ptr;    // Pointer to the RS Type of the Allocation
+    empirical_type<lldb::addr_t> element_ptr; // Pointer to the RS Element of the Type
+    empirical_type<lldb::addr_t> context;     // Pointer to the RS Context of the Allocation
+
+    // Give each allocation an id, so we can reference it in user commands.
+    AllocationDetails(): id(ID++)
+    {
+    }
+
 };
 
+unsigned int RenderScriptRuntime::AllocationDetails::ID = 1;
+
+const char* RenderScriptRuntime::AllocationDetails::RsDataKindToString[] =
+{
+   "User",
+   "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7
+   "Undefined", "Undefined", "Undefined",
+   "L Pixel",
+   "A Pixel",
+   "LA Pixel",
+   "RGB Pixel",
+   "RGBA Pixel",
+   "Pixel Depth",
+   "YUV Pixel"
+};
+
+const char* RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] =
+{
+    {"None", "None", "None", "None"},
+    {"half", "half2", "half3", "half4"},
+    {"float", "float2", "float3", "float4"},
+    {"double", "double2", "double3", "double4"},
+    {"char", "char2", "char3", "char4"},
+    {"short", "short2", "short3", "short4"},
+    {"int", "int2", "int3", "int4"},
+    {"long", "long2", "long3", "long4"},
+    {"uchar", "uchar2", "uchar3", "uchar4"},
+    {"ushort", "ushort2", "ushort3", "ushort4"},
+    {"uint", "uint2", "uint3", "uint4"},
+    {"ulong", "ulong2", "ulong3", "ulong4"},
+    {"bool", "bool2", "bool3", "bool4"}
+};
+
 //------------------------------------------------------------------
 // Static Functions
 //------------------------------------------------------------------
@@ -250,7 +340,7 @@
             return eModuleKindDriver;
         }
 
-        const ConstString rs_cpureflib("libRSCPURef.so");
+        const ConstString rs_cpureflib("libRSCpuRef.so");
         if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib)
         {
             return eModuleKindImpl;
@@ -820,7 +910,331 @@
     }
 }
 
+// Uses the Target API to evaluate the expression passed as a parameter to the function
+// The result of that expression is returned an unsigned 64 bit int, via the result* paramter.
+// Function returns true on success, and false on failure
 bool
+RenderScriptRuntime::EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result)
+{
+    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+    if (log)
+        log->Printf("RenderScriptRuntime::EvalRSExpression(%s)", expression);
+
+    ValueObjectSP expr_result;
+    // Perform the actual expression evaluation
+    GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result);
+
+    if (!expr_result)
+    {
+       if (log)
+           log->Printf("RenderScriptRuntime::EvalRSExpression -  Error: Couldn't evaluate expression");
+       return false;
+    }
+
+    // The result of the expression is invalid
+    if (!expr_result->GetError().Success())
+    {
+        Error err = expr_result->GetError();
+        if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success
+        {
+            if (log)
+                log->Printf("RenderScriptRuntime::EvalRSExpression - Expression returned void");
+
+            result = nullptr;
+            return true;
+        }
+
+        if (log)
+            log->Printf("RenderScriptRuntime::EvalRSExpression - Error evaluating expression result: %s", err.AsCString());
+        return false;
+    }
+
+    bool success = false;
+    *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an unsigned int.
+
+    if (!success)
+    {
+       if (log)
+           log->Printf("RenderScriptRuntime::EvalRSExpression -  Error: Couldn't convert expression result to unsigned int");
+       return false;
+    }
+
+    return true;
+}
+
+// Used to index expression format strings
+enum ExpressionStrings
+{
+   eExprGetOffsetPtr = 0,
+   eExprAllocGetType,
+   eExprTypeDimX,
+   eExprTypeDimY,
+   eExprTypeDimZ,
+   eExprTypeElemPtr,
+   eExprElementType,
+   eExprElementKind,
+   eExprElementVec
+};
+
+// Format strings containing the expressions we may need to evaluate.
+const char runtimeExpressions[][256] =
+{
+ // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
+ "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace(0x%lx, %u, %u, %u, 0, 0)",
+
+ // Type* rsaAllocationGetType(Context*, Allocation*)
+ "(void*)rsaAllocationGetType(0x%lx, 0x%lx)",
+
+ // rsaTypeGetNativeData(Context*, Type*, void* typeData, size)
+ // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ;
+ // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
+ // Need to specify 32 or 64 bit for uint_t since this differs between devices
+ "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[0]", // X dim
+ "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[1]", // Y dim
+ "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[2]", // Z dim
+ "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[5]", // Element ptr
+
+ // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
+ // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData
+ "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type
+ "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind
+ "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]"  // Vector Size
+};
+
+// JITs the RS runtime for the internal data pointer of an allocation.
+// Is passed x,y,z coordinates for the pointer to a specific element.
+// Then sets the data_ptr member in Allocation with the result.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr,
+                                    unsigned int x, unsigned int y, unsigned int z)
+{
+    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+    if (!allocation->address.isValid())
+    {
+        if (log)
+            log->Printf("RenderScriptRuntime::JITDataPointer - Failed to find allocation details");
+        return false;
+    }
+
+    const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
+    const int max_expr_size = 512; // Max expression size
+    char buffer[max_expr_size];
+
+    int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(), x, y, z);
+    if (chars_written < 0)
+    {
+        if (log)
+            log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
+        return false;
+    }
+    else if (chars_written >= max_expr_size)
+    {
+        if (log)
+            log->Printf("RenderScriptRuntime::JITDataPointer - Expression too long");
+        return false;
+    }
+
+    uint64_t result = 0;
+    if (!EvalRSExpression(buffer, frame_ptr, &result))
+        return false;
+
+    addr_t mem_ptr = static_cast<lldb::addr_t>(result);
+    allocation->data_ptr = mem_ptr;
+
+    return true;
+}
+
+// JITs the RS runtime for the internal pointer to the RS Type of an allocation
+// Then sets the type_ptr member in Allocation with the result.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+    if (!allocation->address.isValid() || !allocation->context.isValid())
+    {
+        if (log)
+            log->Printf("RenderScriptRuntime::JITTypePointer - Failed to find allocation details");
+        return false;
+    }
+
+    const char* expr_cstr = runtimeExpressions[eExprAllocGetType];
+    const int max_expr_size = 512; // Max expression size
+    char buffer[max_expr_size];
+
+    int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get());
+    if (chars_written < 0)
+    {
+        if (log)
+            log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
+        return false;
+    }
+    else if (chars_written >= max_expr_size)
+    {
+        if (log)
+            log->Printf("RenderScriptRuntime::JITTypePointer - Expression too long");
+        return false;
+    }
+
+    uint64_t result = 0;
+    if (!EvalRSExpression(buffer, frame_ptr, &result))
+        return false;
+
+    addr_t type_ptr = static_cast<lldb::addr_t>(result);
+    allocation->type_ptr = type_ptr;
+
+    return true;
+}
+
+// JITs the RS runtime for information about the dimensions and type of an allocation
+// Then sets dimension and element_ptr members in Allocation with the result.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+    if (!allocation->type_ptr.isValid() || !allocation->context.isValid())
+    {
+        if (log)
+            log->Printf("RenderScriptRuntime::JITTypePacked - Failed to find allocation details");
+        return false;
+    }
+
+    // Expression is different depending on if device is 32 or 64 bit
+    uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
+    const unsigned int bits = archByteSize == 4 ? 32 : 64;
+
+    // We want 4 elements from packed data
+    const unsigned int num_exprs = 4;
+    assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions");
+
+    const int max_expr_size = 512; // Max expression size
+    char buffer[num_exprs][max_expr_size];
+    uint64_t results[num_exprs];
+
+    for (unsigned int i = 0; i < num_exprs; ++i)
+    {
+        int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprTypeDimX + i], bits,
+                                     *allocation->context.get(), *allocation->type_ptr.get());
+        if (chars_written < 0)
+        {
+            if (log)
+                log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
+            return false;
+        }
+        else if (chars_written >= max_expr_size)
+        {
+            if (log)
+                log->Printf("RenderScriptRuntime::JITTypePacked - Expression too long");
+            return false;
+        }
+
+        // Perform expression evaluation
+        if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
+            return false;
+    }
+
+    // Assign results to allocation members
+    AllocationDetails::Dimension dims;
+    dims.dim_1 = static_cast<uint32_t>(results[0]);
+    dims.dim_2 = static_cast<uint32_t>(results[1]);
+    dims.dim_3 = static_cast<uint32_t>(results[2]);
+    allocation->dimension = dims;
+
+    addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]);
+    allocation->element_ptr = elem_ptr;
+
+    if (log)
+        log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64,
+                    dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr);
+
+    return true;
+}
+
+// JITs the RS runtime for information about the Element of an allocation
+// Then sets type, type_vec_size, and type_kind members in Allocation with the result.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITElementPacked(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+    if (!allocation->element_ptr.isValid() || !allocation->context.isValid())
+    {
+        if (log)
+            log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details");
+        return false;
+    }
+
+    // We want 3 elements from packed data
+    const unsigned int num_exprs = 3;
+    assert(num_exprs == (eExprElementVec - eExprElementType + 1) && "Invalid number of expressions");
+
+    const int max_expr_size = 512; // Max expression size
+    char buffer[num_exprs][max_expr_size];
+    uint64_t results[num_exprs];
+
+    for (unsigned int i = 0; i < num_exprs; i++)
+    {
+        int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprElementType + i], *allocation->context.get(), *allocation->element_ptr.get());
+        if (chars_written < 0)
+        {
+            if (log)
+                log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
+            return false;
+        }
+        else if (chars_written >= max_expr_size)
+        {
+            if (log)
+                log->Printf("RenderScriptRuntime::JITElementPacked - Expression too long");
+            return false;
+        }
+
+        // Perform expression evaluation
+        if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
+            return false;
+    }
+
+    // Assign results to allocation members
+    allocation->type = static_cast<RenderScriptRuntime::AllocationDetails::DataType>(results[0]);
+    allocation->type_kind = static_cast<RenderScriptRuntime::AllocationDetails::DataKind>(results[1]);
+    allocation->type_vec_size = static_cast<uint32_t>(results[2]);
+
+    if (log)
+        log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u",
+                    *allocation->type.get(), *allocation->type_kind.get(), *allocation->type_vec_size.get());
+
+    return true;
+}
+
+// JIT all the current runtime info regarding an allocation
+bool
+RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+    // GetOffsetPointer()
+    if (!JITDataPointer(allocation, frame_ptr))
+        return false;
+
+    // rsaAllocationGetType()
+    if (!JITTypePointer(allocation, frame_ptr))
+        return false;
+
+    // rsaTypeGetNativeData()
+    if (!JITTypePacked(allocation, frame_ptr))
+        return false;
+
+    // rsaElementGetNativeData()
+    if (!JITElementPacked(allocation, frame_ptr))
+        return false;
+
+    return true;
+}
+
+bool
 RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
 {
     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
@@ -1114,6 +1528,89 @@
     strm.IndentLess();
 }
 
+// Prints infomation regarding all the currently loaded allocations.
+// These details are gathered by jitting the runtime, which has as latency.
+void
+RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute)
+{
+    strm.Printf("RenderScript Allocations:");
+    strm.EOL();
+    strm.IndentMore();
+
+    for (auto &alloc : m_allocations)
+    {
+        // JIT the allocation info if we haven't done it, or the user forces us to.
+        bool do_refresh = !alloc->data_ptr.isValid() || recompute;
+
+        // JIT current allocation information
+        if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr))
+        {
+            strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id);
+            continue;
+        }
+
+        strm.Printf("%u:\n",alloc->id);
+        strm.IndentMore();
+
+        strm.Indent("Context: ");
+        if (!alloc->context.isValid())
+            strm.Printf("unknown\n");
+        else
+            strm.Printf("0x%" PRIx64 "\n", *alloc->context.get());
+
+        strm.Indent("Address: ");
+        if (!alloc->address.isValid())
+            strm.Printf("unknown\n");
+        else
+            strm.Printf("0x%" PRIx64 "\n", *alloc->address.get());
+
+        strm.Indent("Data pointer: ");
+        if (!alloc->data_ptr.isValid())
+            strm.Printf("unknown\n");
+        else
+            strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get());
+
+        strm.Indent("Dimensions: ");
+        if (!alloc->dimension.isValid())
+            strm.Printf("unknown\n");
+        else
+            strm.Printf("(%d, %d, %d)\n", alloc->dimension.get()->dim_1,
+                                          alloc->dimension.get()->dim_2,
+                                          alloc->dimension.get()->dim_3);
+
+        strm.Indent("Data Type: ");
+        if (!alloc->type.isValid() || !alloc->type_vec_size.isValid())
+            strm.Printf("unknown\n");
+        else
+        {
+            const int vector_size = *alloc->type_vec_size.get();
+            const AllocationDetails::DataType type = *alloc->type.get();
+
+            if (vector_size > 4 || vector_size < 1 ||
+                type < AllocationDetails::RS_TYPE_NONE || type > AllocationDetails::RS_TYPE_BOOLEAN)
+                strm.Printf("invalid type\n");
+            else
+                strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<unsigned int>(type)][vector_size-1]);
+        }
+
+        strm.Indent("Data Kind: ");
+        if (!alloc->type_kind.isValid())
+            strm.Printf("unknown\n");
+        else
+        {
+            const AllocationDetails::DataKind kind = *alloc->type_kind.get();
+            if (kind < AllocationDetails::RS_KIND_USER || kind > AllocationDetails::RS_KIND_PIXEL_YUV)
+                strm.Printf("invalid kind\n");
+            else
+                strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]);
+        }
+
+        strm.EOL();
+        strm.IndentLess();
+    }
+    strm.IndentLess();
+}
+
 // Set breakpoints on every kernel found in RS module
 void
 RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp)
@@ -1608,6 +2105,108 @@
     ~CommandObjectRenderScriptRuntimeContext() {}
 };
 
+class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed
+{
+  public:
+    CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter)
+        : CommandObjectParsed(interpreter, "renderscript allocation list",
+                              "List renderscript allocations and their information.", "renderscript allocation list",
+                              eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
+    {
+    }
+
+    virtual Options*
+    GetOptions()
+    {
+        return &m_options;
+    }
+
+    class CommandOptions : public Options
+    {
+      public:
+        CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false)
+        {
+        }
+
+        virtual
+        ~CommandOptions()
+        {
+        }
+
+        virtual Error
+        SetOptionValue(uint32_t option_idx, const char *option_arg)
+        {
+            Error error;
+            const int short_option = m_getopt_table[option_idx].val;
+
+            switch (short_option)
+            {
+                case 'r':
+                    m_refresh = true;
+                    break;
+                default:
+                    error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
+                    break;
+            }
+            return error;
+        }
+
+        void
+        OptionParsingStarting()
+        {
+            m_refresh = false;
+        }
+
+        const OptionDefinition*
+        GetDefinitions()
+        {
+            return g_option_table;
+        }
+
+        static OptionDefinition g_option_table[];
+        bool m_refresh;
+    };
+
+    ~CommandObjectRenderScriptRuntimeAllocationList() {}
+
+    bool
+    DoExecute(Args &command, CommandReturnObject &result)
+    {
+        RenderScriptRuntime *runtime =
+          static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
+        runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh);
+        result.SetStatus(eReturnStatusSuccessFinishResult);
+        return true;
+    }
+
+  private:
+    CommandOptions m_options;
+};
+
+OptionDefinition
+CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] =
+{
+    { LLDB_OPT_SET_1, false, "refresh", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
+      "Recompute allocation details."},
+    { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
+
+class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword
+{
+  private:
+  public:
+    CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter)
+        : CommandObjectMultiword(interpreter, "renderscript allocation", "Commands that deal with renderscript allocations.",
+                                 NULL)
+    {
+        LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter)));
+    }
+
+    ~CommandObjectRenderScriptRuntimeAllocation() {}
+};
+
+
 class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
 {
   private:
@@ -1643,6 +2242,7 @@
         LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter)));
         LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter)));
         LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter)));
+        LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
     }
 
     ~CommandObjectRenderScriptRuntime() {}
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to