//===-- RenderScriptRuntime.cpp -------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "RenderScriptRuntime.h"
#include "RenderScriptScriptGroup.h"

#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/DumpValueObjectOptions.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Status.h"

#include "llvm/ADT/StringSwitch.h"

#include <memory>

using namespace lldb;
using namespace lldb_private;
using namespace lldb_renderscript;

LLDB_PLUGIN_DEFINE(RenderScriptRuntime)

#define FMT_COORD "(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")"

char RenderScriptRuntime::ID = 0;

namespace {

// The empirical_type adds a basic level of validation to arbitrary data
// allowing us to track if data has been discovered and stored or not. An
// empirical_type will be marked as valid only if it has been explicitly
// assigned to.
template <typename type_t> class empirical_type {
public:
  // Ctor. Contents is invalid when constructed.
  empirical_type() = default;

  // Return true and copy contents to out if valid, else return false.
  bool get(type_t &out) const {
    if (valid)
      out = data;
    return valid;
  }

  // Return a pointer to the contents or nullptr if it was not valid.
  const type_t *get() const { return valid ? &data : nullptr; }

  // Assign data explicitly.
  void set(const type_t in) {
    data = in;
    valid = true;
  }

  // Mark contents as invalid.
  void invalidate() { valid = false; }

  // Returns true if this type contains valid data.
  bool isValid() const { return valid; }

  // Assignment operator.
  empirical_type<type_t> &operator=(const type_t in) {
    set(in);
    return *this;
  }

  // Dereference operator returns contents.
  // Warning: Will assert if not valid so use only when you know data is valid.
  const type_t &operator*() const {
    assert(valid);
    return data;
  }

protected:
  bool valid = false;
  type_t data;
};

// ArgItem is used by the GetArgs() function when reading function arguments
// from the target.
struct ArgItem {
  enum { ePointer, eInt32, eInt64, eLong, eBool } type;

  uint64_t value;

  explicit operator uint64_t() const { return value; }
};

// Context structure to be passed into GetArgsXXX(), argument reading functions
// below.
struct GetArgsCtx {
  RegisterContext *reg_ctx;
  Process *process;
};

bool GetArgsX86(const GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
  Log *log = GetLog(LLDBLog::Language);

  Status err;

  // get the current stack pointer
  uint64_t sp = ctx.reg_ctx->GetSP();

  for (size_t i = 0; i < num_args; ++i) {
    ArgItem &arg = arg_list[i];
    // advance up the stack by one argument
    sp += sizeof(uint32_t);
    // get the argument type size
    size_t arg_size = sizeof(uint32_t);
    // read the argument from memory
    arg.value = 0;
    Status err;
    size_t read =
        ctx.process->ReadMemory(sp, &arg.value, sizeof(uint32_t), err);
    if (read != arg_size || !err.Success()) {
      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 " '%s'",
                __FUNCTION__, uint64_t(i), err.AsCString());
      return false;
    }
  }
  return true;
}

bool GetArgsX86_64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
  Log *log = GetLog(LLDBLog::Language);

  // number of arguments passed in registers
  static const uint32_t args_in_reg = 6;
  // register passing order
  static const std::array<const char *, args_in_reg> reg_names{
      {"rdi", "rsi", "rdx", "rcx", "r8", "r9"}};
  // argument type to size mapping
  static const std::array<size_t, 5> arg_size{{
      8, // ePointer,
      4, // eInt32,
      8, // eInt64,
      8, // eLong,
      4, // eBool,
  }};

  Status err;

  // get the current stack pointer
  uint64_t sp = ctx.reg_ctx->GetSP();
  // step over the return address
  sp += sizeof(uint64_t);

  // check the stack alignment was correct (16 byte aligned)
  if ((sp & 0xf) != 0x0) {
    LLDB_LOGF(log, "%s - stack misaligned", __FUNCTION__);
    return false;
  }

  // find the start of arguments on the stack
  uint64_t sp_offset = 0;
  for (uint32_t i = args_in_reg; i < num_args; ++i) {
    sp_offset += arg_size[arg_list[i].type];
  }
  // round up to multiple of 16
  sp_offset = (sp_offset + 0xf) & 0xf;
  sp += sp_offset;

  for (size_t i = 0; i < num_args; ++i) {
    bool success = false;
    ArgItem &arg = arg_list[i];
    // arguments passed in registers
    if (i < args_in_reg) {
      const RegisterInfo *reg =
          ctx.reg_ctx->GetRegisterInfoByName(reg_names[i]);
      RegisterValue reg_val;
      if (ctx.reg_ctx->ReadRegister(reg, reg_val))
        arg.value = reg_val.GetAsUInt64(0, &success);
    }
    // arguments passed on the stack
    else {
      // get the argument type size
      const size_t size = arg_size[arg_list[i].type];
      // read the argument from memory
      arg.value = 0;
      // note: due to little endian layout reading 4 or 8 bytes will give the
      // correct value.
      size_t read = ctx.process->ReadMemory(sp, &arg.value, size, err);
      success = (err.Success() && read == size);
      // advance past this argument
      sp -= size;
    }
    // fail if we couldn't read this argument
    if (!success) {
      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s",
                __FUNCTION__, uint64_t(i), err.AsCString("n/a"));
      return false;
    }
  }
  return true;
}

bool GetArgsArm(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
  // number of arguments passed in registers
  static const uint32_t args_in_reg = 4;

  Log *log = GetLog(LLDBLog::Language);

  Status err;

  // get the current stack pointer
  uint64_t sp = ctx.reg_ctx->GetSP();

  for (size_t i = 0; i < num_args; ++i) {
    bool success = false;
    ArgItem &arg = arg_list[i];
    // arguments passed in registers
    if (i < args_in_reg) {
      const RegisterInfo *reg = ctx.reg_ctx->GetRegisterInfoAtIndex(i);
      RegisterValue reg_val;
      if (ctx.reg_ctx->ReadRegister(reg, reg_val))
        arg.value = reg_val.GetAsUInt32(0, &success);
    }
    // arguments passed on the stack
    else {
      // get the argument type size
      const size_t arg_size = sizeof(uint32_t);
      // clear all 64bits
      arg.value = 0;
      // read this argument from memory
      size_t bytes_read =
          ctx.process->ReadMemory(sp, &arg.value, arg_size, err);
      success = (err.Success() && bytes_read == arg_size);
      // advance the stack pointer
      sp += sizeof(uint32_t);
    }
    // fail if we couldn't read this argument
    if (!success) {
      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s",
                __FUNCTION__, uint64_t(i), err.AsCString("n/a"));
      return false;
    }
  }
  return true;
}

bool GetArgsAarch64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
  // number of arguments passed in registers
  static const uint32_t args_in_reg = 8;

  Log *log = GetLog(LLDBLog::Language);

  for (size_t i = 0; i < num_args; ++i) {
    bool success = false;
    ArgItem &arg = arg_list[i];
    // arguments passed in registers
    if (i < args_in_reg) {
      const RegisterInfo *reg = ctx.reg_ctx->GetRegisterInfoAtIndex(i);
      RegisterValue reg_val;
      if (ctx.reg_ctx->ReadRegister(reg, reg_val))
        arg.value = reg_val.GetAsUInt64(0, &success);
    }
    // arguments passed on the stack
    else {
      LLDB_LOGF(log, "%s - reading arguments spilled to stack not implemented",
                __FUNCTION__);
    }
    // fail if we couldn't read this argument
    if (!success) {
      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64, __FUNCTION__,
                uint64_t(i));
      return false;
    }
  }
  return true;
}

bool GetArgsMipsel(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
  // number of arguments passed in registers
  static const uint32_t args_in_reg = 4;
  // register file offset to first argument
  static const uint32_t reg_offset = 4;

  Log *log = GetLog(LLDBLog::Language);

  Status err;

  // find offset to arguments on the stack (+16 to skip over a0-a3 shadow
  // space)
  uint64_t sp = ctx.reg_ctx->GetSP() + 16;

  for (size_t i = 0; i < num_args; ++i) {
    bool success = false;
    ArgItem &arg = arg_list[i];
    // arguments passed in registers
    if (i < args_in_reg) {
      const RegisterInfo *reg =
          ctx.reg_ctx->GetRegisterInfoAtIndex(i + reg_offset);
      RegisterValue reg_val;
      if (ctx.reg_ctx->ReadRegister(reg, reg_val))
        arg.value = reg_val.GetAsUInt64(0, &success);
    }
    // arguments passed on the stack
    else {
      const size_t arg_size = sizeof(uint32_t);
      arg.value = 0;
      size_t bytes_read =
          ctx.process->ReadMemory(sp, &arg.value, arg_size, err);
      success = (err.Success() && bytes_read == arg_size);
      // advance the stack pointer
      sp += arg_size;
    }
    // fail if we couldn't read this argument
    if (!success) {
      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s",
                __FUNCTION__, uint64_t(i), err.AsCString("n/a"));
      return false;
    }
  }
  return true;
}

bool GetArgsMips64el(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
  // number of arguments passed in registers
  static const uint32_t args_in_reg = 8;
  // register file offset to first argument
  static const uint32_t reg_offset = 4;

  Log *log = GetLog(LLDBLog::Language);

  Status err;

  // get the current stack pointer
  uint64_t sp = ctx.reg_ctx->GetSP();

  for (size_t i = 0; i < num_args; ++i) {
    bool success = false;
    ArgItem &arg = arg_list[i];
    // arguments passed in registers
    if (i < args_in_reg) {
      const RegisterInfo *reg =
          ctx.reg_ctx->GetRegisterInfoAtIndex(i + reg_offset);
      RegisterValue reg_val;
      if (ctx.reg_ctx->ReadRegister(reg, reg_val))
        arg.value = reg_val.GetAsUInt64(0, &success);
    }
    // arguments passed on the stack
    else {
      // get the argument type size
      const size_t arg_size = sizeof(uint64_t);
      // clear all 64bits
      arg.value = 0;
      // read this argument from memory
      size_t bytes_read =
          ctx.process->ReadMemory(sp, &arg.value, arg_size, err);
      success = (err.Success() && bytes_read == arg_size);
      // advance the stack pointer
      sp += arg_size;
    }
    // fail if we couldn't read this argument
    if (!success) {
      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s",
                __FUNCTION__, uint64_t(i), err.AsCString("n/a"));
      return false;
    }
  }
  return true;
}

bool GetArgs(ExecutionContext &exe_ctx, ArgItem *arg_list, size_t num_args) {
  Log *log = GetLog(LLDBLog::Language);

  // verify that we have a target
  if (!exe_ctx.GetTargetPtr()) {
    LLDB_LOGF(log, "%s - invalid target", __FUNCTION__);
    return false;
  }

  GetArgsCtx ctx = {exe_ctx.GetRegisterContext(), exe_ctx.GetProcessPtr()};
  assert(ctx.reg_ctx && ctx.process);

  // dispatch based on architecture
  switch (exe_ctx.GetTargetPtr()->GetArchitecture().GetMachine()) {
  case llvm::Triple::ArchType::x86:
    return GetArgsX86(ctx, arg_list, num_args);

  case llvm::Triple::ArchType::x86_64:
    return GetArgsX86_64(ctx, arg_list, num_args);

  case llvm::Triple::ArchType::arm:
    return GetArgsArm(ctx, arg_list, num_args);

  case llvm::Triple::ArchType::aarch64:
    return GetArgsAarch64(ctx, arg_list, num_args);

  case llvm::Triple::ArchType::mipsel:
    return GetArgsMipsel(ctx, arg_list, num_args);

  case llvm::Triple::ArchType::mips64el:
    return GetArgsMips64el(ctx, arg_list, num_args);

  default:
    // unsupported architecture
    if (log) {
      LLDB_LOGF(log, "%s - architecture not supported: '%s'", __FUNCTION__,
                exe_ctx.GetTargetRef().GetArchitecture().GetArchitectureName());
    }
    return false;
  }
}

bool IsRenderScriptScriptModule(ModuleSP module) {
  if (!module)
    return false;
  return module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"),
                                                eSymbolTypeData) != nullptr;
}

bool ParseCoordinate(llvm::StringRef coord_s, RSCoordinate &coord) {
  // takes an argument of the form 'num[,num][,num]'. Where 'coord_s' is a
  // comma separated 1,2 or 3-dimensional coordinate with the whitespace
  // trimmed. Missing coordinates are defaulted to zero. If parsing of any
  // elements fails the contents of &coord are undefined and `false` is
  // returned, `true` otherwise

  llvm::SmallVector<llvm::StringRef, 4> matches;

  if (!RegularExpression("^([0-9]+),([0-9]+),([0-9]+)$")
           .Execute(coord_s, &matches) &&
      !RegularExpression("^([0-9]+),([0-9]+)$").Execute(coord_s, &matches) &&
      !RegularExpression("^([0-9]+)$").Execute(coord_s, &matches))
    return false;

  auto get_index = [&](size_t idx, uint32_t &i) -> bool {
    std::string group;
    errno = 0;
    if (idx + 1 < matches.size()) {
      return !llvm::StringRef(matches[idx + 1]).getAsInteger<uint32_t>(10, i);
    }
    return true;
  };

  return get_index(0, coord.x) && get_index(1, coord.y) &&
         get_index(2, coord.z);
}

bool SkipPrologue(lldb::ModuleSP &module, Address &addr) {
  Log *log = GetLog(LLDBLog::Language);
  SymbolContext sc;
  uint32_t resolved_flags =
      module->ResolveSymbolContextForAddress(addr, eSymbolContextFunction, sc);
  if (resolved_flags & eSymbolContextFunction) {
    if (sc.function) {
      const uint32_t offset = sc.function->GetPrologueByteSize();
      ConstString name = sc.GetFunctionName();
      if (offset)
        addr.Slide(offset);
      LLDB_LOGF(log, "%s: Prologue offset for %s is %" PRIu32, __FUNCTION__,
                name.AsCString(), offset);
    }
    return true;
  } else
    return false;
}
} // anonymous namespace

// The ScriptDetails class collects data associated with a single script
// instance.
struct RenderScriptRuntime::ScriptDetails {
  ~ScriptDetails() = default;

  enum ScriptType { eScript, eScriptC };

  // The derived type of the script.
  empirical_type<ScriptType> type;
  // The name of the original source file.
  empirical_type<std::string> res_name;
  // Path to script .so file on the device.
  empirical_type<std::string> shared_lib;
  // Directory where kernel objects are cached on device.
  empirical_type<std::string> cache_dir;
  // Pointer to the context which owns this script.
  empirical_type<lldb::addr_t> context;
  // Pointer to the script object itself.
  empirical_type<lldb::addr_t> script;
};

// This Element class represents the Element object in RS, defining the type
// associated with an Allocation.
struct RenderScriptRuntime::Element {
  // 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
  };

  // 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,

    RS_TYPE_UNSIGNED_5_6_5,
    RS_TYPE_UNSIGNED_5_5_5_1,
    RS_TYPE_UNSIGNED_4_4_4_4,

    RS_TYPE_MATRIX_4X4,
    RS_TYPE_MATRIX_3X3,
    RS_TYPE_MATRIX_2X2,

    RS_TYPE_ELEMENT = 1000,
    RS_TYPE_TYPE,
    RS_TYPE_ALLOCATION,
    RS_TYPE_SAMPLER,
    RS_TYPE_SCRIPT,
    RS_TYPE_MESH,
    RS_TYPE_PROGRAM_FRAGMENT,
    RS_TYPE_PROGRAM_VERTEX,
    RS_TYPE_PROGRAM_RASTER,
    RS_TYPE_PROGRAM_STORE,
    RS_TYPE_FONT,

    RS_TYPE_INVALID = 10000
  };

  std::vector<Element> children; // Child Element fields for structs
  empirical_type<lldb::addr_t>
      element_ptr; // Pointer to the RS Element of the Type
  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<uint32_t> field_count; // Number of Subelements
  empirical_type<uint32_t> datum_size;  // Size of a single Element with padding
  empirical_type<uint32_t> padding;     // Number of padding bytes
  empirical_type<uint32_t>
      array_size;        // Number of items in array, only needed for structs
  ConstString type_name; // Name of type, only needed for structs

  static ConstString 
  GetFallbackStructName(); // Print this as the type name of a struct Element
                           // If we can't resolve the actual struct name

  bool ShouldRefresh() const {
    const bool valid_ptr = element_ptr.isValid() && *element_ptr.get() != 0x0;
    const bool valid_type =
        type.isValid() && type_vec_size.isValid() && type_kind.isValid();
    return !valid_ptr || !valid_type || !datum_size.isValid();
  }
};

// This AllocationDetails class collects data associated with a single
// allocation instance.
struct RenderScriptRuntime::AllocationDetails {
  struct Dimension {
    uint32_t dim_1;
    uint32_t dim_2;
    uint32_t dim_3;
    uint32_t cube_map;

    Dimension() {
      dim_1 = 0;
      dim_2 = 0;
      dim_3 = 0;
      cube_map = 0;
    }
  };

  // The FileHeader struct specifies the header we use for writing allocations
  // to a binary file. Our format begins with the ASCII characters "RSAD",
  // identifying the file as an allocation dump. Member variables dims and
  // hdr_size are then written consecutively, immediately followed by an
  // instance of the ElementHeader struct. Because Elements can contain
  // subelements, there may be more than one instance of the ElementHeader
  // struct. With this first instance being the root element, and the other
  // instances being the root's descendants. To identify which instances are an
  // ElementHeader's children, each struct is immediately followed by a
  // sequence of consecutive offsets to the start of its child structs. These
  // offsets are
  // 4 bytes in size, and the 0 offset signifies no more children.
  struct FileHeader {
    uint8_t ident[4];  // ASCII 'RSAD' identifying the file
    uint32_t dims[3];  // Dimensions
    uint16_t hdr_size; // Header size in bytes, including all element headers
  };

  struct ElementHeader {
    uint16_t type;         // DataType enum
    uint32_t kind;         // DataKind enum
    uint32_t element_size; // Size of a single element, including padding
    uint16_t vector_size;  // Vector width
    uint32_t array_size;   // Number of elements in array
  };

  // Monotonically increasing from 1
  static uint32_t 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[];

  // Maps allocation types to format sizes for printing.
  static const uint32_t RSTypeToFormat[][3];

  // Give each allocation an ID as a way
  // for commands to reference it.
  const uint32_t id;

  // Allocation Element type
  RenderScriptRuntime::Element element;
  // Dimensions of the Allocation
  empirical_type<Dimension> dimension;
  // Pointer to address of the RS Allocation
  empirical_type<lldb::addr_t> address;
  // Pointer to the data held by the Allocation
  empirical_type<lldb::addr_t> data_ptr;
  // Pointer to the RS Type of the Allocation
  empirical_type<lldb::addr_t> type_ptr;
  // Pointer to the RS Context of the Allocation
  empirical_type<lldb::addr_t> context;
  // Size of the allocation
  empirical_type<uint32_t> size;
  // Stride between rows of the allocation
  empirical_type<uint32_t> stride;

  // Give each allocation an id, so we can reference it in user commands.
  AllocationDetails() : id(ID++) {}

  bool ShouldRefresh() const {
    bool valid_ptrs = data_ptr.isValid() && *data_ptr.get() != 0x0;
    valid_ptrs = valid_ptrs && type_ptr.isValid() && *type_ptr.get() != 0x0;
    return !valid_ptrs || !dimension.isValid() || !size.isValid() ||
           element.ShouldRefresh();
  }
};

ConstString RenderScriptRuntime::Element::GetFallbackStructName() {
  static const ConstString FallbackStructName("struct");
  return FallbackStructName;
}

uint32_t RenderScriptRuntime::AllocationDetails::ID = 1;

const char *RenderScriptRuntime::AllocationDetails::RsDataKindToString[] = {
    "User",       "Undefined",   "Undefined", "Undefined",
    "Undefined",  "Undefined",   "Undefined", // Enum jumps from 0 to 7
    "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"},
    {"packed_565", "packed_565", "packed_565", "packed_565"},
    {"packed_5551", "packed_5551", "packed_5551", "packed_5551"},
    {"packed_4444", "packed_4444", "packed_4444", "packed_4444"},
    {"rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4"},
    {"rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3"},
    {"rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2"},

    // Handlers
    {"RS Element", "RS Element", "RS Element", "RS Element"},
    {"RS Type", "RS Type", "RS Type", "RS Type"},
    {"RS Allocation", "RS Allocation", "RS Allocation", "RS Allocation"},
    {"RS Sampler", "RS Sampler", "RS Sampler", "RS Sampler"},
    {"RS Script", "RS Script", "RS Script", "RS Script"},

    // Deprecated
    {"RS Mesh", "RS Mesh", "RS Mesh", "RS Mesh"},
    {"RS Program Fragment", "RS Program Fragment", "RS Program Fragment",
     "RS Program Fragment"},
    {"RS Program Vertex", "RS Program Vertex", "RS Program Vertex",
     "RS Program Vertex"},
    {"RS Program Raster", "RS Program Raster", "RS Program Raster",
     "RS Program Raster"},
    {"RS Program Store", "RS Program Store", "RS Program Store",
     "RS Program Store"},
    {"RS Font", "RS Font", "RS Font", "RS Font"}};

// Used as an index into the RSTypeToFormat array elements
enum TypeToFormatIndex { eFormatSingle = 0, eFormatVector, eElementSize };

// { format enum of single element, format enum of element vector, size of
// element}
const uint32_t RenderScriptRuntime::AllocationDetails::RSTypeToFormat[][3] = {
    // RS_TYPE_NONE
    {eFormatHex, eFormatHex, 1},
    // RS_TYPE_FLOAT_16
    {eFormatFloat, eFormatVectorOfFloat16, 2},
    // RS_TYPE_FLOAT_32
    {eFormatFloat, eFormatVectorOfFloat32, sizeof(float)},
    // RS_TYPE_FLOAT_64
    {eFormatFloat, eFormatVectorOfFloat64, sizeof(double)},
    // RS_TYPE_SIGNED_8
    {eFormatDecimal, eFormatVectorOfSInt8, sizeof(int8_t)},
    // RS_TYPE_SIGNED_16
    {eFormatDecimal, eFormatVectorOfSInt16, sizeof(int16_t)},
    // RS_TYPE_SIGNED_32
    {eFormatDecimal, eFormatVectorOfSInt32, sizeof(int32_t)},
    // RS_TYPE_SIGNED_64
    {eFormatDecimal, eFormatVectorOfSInt64, sizeof(int64_t)},
    // RS_TYPE_UNSIGNED_8
    {eFormatDecimal, eFormatVectorOfUInt8, sizeof(uint8_t)},
    // RS_TYPE_UNSIGNED_16
    {eFormatDecimal, eFormatVectorOfUInt16, sizeof(uint16_t)},
    // RS_TYPE_UNSIGNED_32
    {eFormatDecimal, eFormatVectorOfUInt32, sizeof(uint32_t)},
    // RS_TYPE_UNSIGNED_64
    {eFormatDecimal, eFormatVectorOfUInt64, sizeof(uint64_t)},
    // RS_TYPE_BOOL
    {eFormatBoolean, eFormatBoolean, 1},
    // RS_TYPE_UNSIGNED_5_6_5
    {eFormatHex, eFormatHex, sizeof(uint16_t)},
    // RS_TYPE_UNSIGNED_5_5_5_1
    {eFormatHex, eFormatHex, sizeof(uint16_t)},
    // RS_TYPE_UNSIGNED_4_4_4_4
    {eFormatHex, eFormatHex, sizeof(uint16_t)},
    // RS_TYPE_MATRIX_4X4
    {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 16},
    // RS_TYPE_MATRIX_3X3
    {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 9},
    // RS_TYPE_MATRIX_2X2
    {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 4}};

// Static Functions
LanguageRuntime *
RenderScriptRuntime::CreateInstance(Process *process,
                                    lldb::LanguageType language) {

  if (language == eLanguageTypeExtRenderScript)
    return new RenderScriptRuntime(process);
  else
    return nullptr;
}

// Callback with a module to search for matching symbols. We first check that
// the module contains RS kernels. Then look for a symbol which matches our
// kernel name. The breakpoint address is finally set using the address of this
// symbol.
Searcher::CallbackReturn
RSBreakpointResolver::SearchCallback(SearchFilter &filter,
                                     SymbolContext &context, Address *) {
  BreakpointSP breakpoint_sp = GetBreakpoint();
  assert(breakpoint_sp);

  ModuleSP module = context.module_sp;

  if (!module || !IsRenderScriptScriptModule(module))
    return Searcher::eCallbackReturnContinue;

  // Attempt to set a breakpoint on the kernel name symbol within the module
  // library. If it's not found, it's likely debug info is unavailable - try to
  // set a breakpoint on <name>.expand.
  const Symbol *kernel_sym =
      module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode);
  if (!kernel_sym) {
    std::string kernel_name_expanded(m_kernel_name.AsCString());
    kernel_name_expanded.append(".expand");
    kernel_sym = module->FindFirstSymbolWithNameAndType(
        ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
  }

  if (kernel_sym) {
    Address bp_addr = kernel_sym->GetAddress();
    if (filter.AddressPasses(bp_addr))
      breakpoint_sp->AddLocation(bp_addr);
  }

  return Searcher::eCallbackReturnContinue;
}

Searcher::CallbackReturn
RSReduceBreakpointResolver::SearchCallback(lldb_private::SearchFilter &filter,
                                           lldb_private::SymbolContext &context,
                                           Address *) {
  BreakpointSP breakpoint_sp = GetBreakpoint();
  assert(breakpoint_sp);

  // We need to have access to the list of reductions currently parsed, as
  // reduce names don't actually exist as symbols in a module. They are only
  // identifiable by parsing the .rs.info packet, or finding the expand symbol.
  // We therefore need access to the list of parsed rs modules to properly
  // resolve reduction names.
  Log *log = GetLog(LLDBLog::Breakpoints);
  ModuleSP module = context.module_sp;

  if (!module || !IsRenderScriptScriptModule(module))
    return Searcher::eCallbackReturnContinue;

  if (!m_rsmodules)
    return Searcher::eCallbackReturnContinue;

  for (const auto &module_desc : *m_rsmodules) {
    if (module_desc->m_module != module)
      continue;

    for (const auto &reduction : module_desc->m_reductions) {
      if (reduction.m_reduce_name != m_reduce_name)
        continue;

      std::array<std::pair<ConstString, int>, 5> funcs{
          {{reduction.m_init_name, eKernelTypeInit},
           {reduction.m_accum_name, eKernelTypeAccum},
           {reduction.m_comb_name, eKernelTypeComb},
           {reduction.m_outc_name, eKernelTypeOutC},
           {reduction.m_halter_name, eKernelTypeHalter}}};

      for (const auto &kernel : funcs) {
        // Skip constituent functions that don't match our spec
        if (!(m_kernel_types & kernel.second))
          continue;

        const auto kernel_name = kernel.first;
        const auto symbol = module->FindFirstSymbolWithNameAndType(
            kernel_name, eSymbolTypeCode);
        if (!symbol)
          continue;

        auto address = symbol->GetAddress();
        if (filter.AddressPasses(address)) {
          bool new_bp;
          if (!SkipPrologue(module, address)) {
            LLDB_LOGF(log, "%s: Error trying to skip prologue", __FUNCTION__);
          }
          breakpoint_sp->AddLocation(address, &new_bp);
          LLDB_LOGF(log, "%s: %s reduction breakpoint on %s in %s",
                    __FUNCTION__, new_bp ? "new" : "existing",
                    kernel_name.GetCString(),
                    address.GetModule()->GetFileSpec().GetCString());
        }
      }
    }
  }
  return eCallbackReturnContinue;
}

Searcher::CallbackReturn RSScriptGroupBreakpointResolver::SearchCallback(
    SearchFilter &filter, SymbolContext &context, Address *addr) {

  BreakpointSP breakpoint_sp = GetBreakpoint();
  if (!breakpoint_sp)
    return eCallbackReturnContinue;

  Log *log = GetLog(LLDBLog::Breakpoints);
  ModuleSP &module = context.module_sp;

  if (!module || !IsRenderScriptScriptModule(module))
    return Searcher::eCallbackReturnContinue;

  std::vector<std::string> names;
  Breakpoint& breakpoint = *breakpoint_sp;
  breakpoint.GetNames(names);
  if (names.empty())
    return eCallbackReturnContinue;

  for (auto &name : names) {
    const RSScriptGroupDescriptorSP sg = FindScriptGroup(ConstString(name));
    if (!sg) {
      LLDB_LOGF(log, "%s: could not find script group for %s", __FUNCTION__,
                name.c_str());
      continue;
    }

    LLDB_LOGF(log, "%s: Found ScriptGroup for %s", __FUNCTION__, name.c_str());

    for (const RSScriptGroupDescriptor::Kernel &k : sg->m_kernels) {
      if (log) {
        LLDB_LOGF(log, "%s: Adding breakpoint for %s", __FUNCTION__,
                  k.m_name.AsCString());
        LLDB_LOGF(log, "%s: Kernel address 0x%" PRIx64, __FUNCTION__, k.m_addr);
      }

      const lldb_private::Symbol *sym =
          module->FindFirstSymbolWithNameAndType(k.m_name, eSymbolTypeCode);
      if (!sym) {
        LLDB_LOGF(log, "%s: Unable to find symbol for %s", __FUNCTION__,
                  k.m_name.AsCString());
        continue;
      }

      if (log) {
        LLDB_LOGF(log, "%s: Found symbol name is %s", __FUNCTION__,
                  sym->GetName().AsCString());
      }

      auto address = sym->GetAddress();
      if (!SkipPrologue(module, address)) {
        LLDB_LOGF(log, "%s: Error trying to skip prologue", __FUNCTION__);
      }

      bool new_bp;
      breakpoint.AddLocation(address, &new_bp);

      LLDB_LOGF(log, "%s: Placed %sbreakpoint on %s", __FUNCTION__,
                new_bp ? "new " : "", k.m_name.AsCString());

      // exit after placing the first breakpoint if we do not intend to stop on
      // all kernels making up this script group
      if (!m_stop_on_all)
        break;
    }
  }

  return eCallbackReturnContinue;
}

void RenderScriptRuntime::Initialize() {
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                "RenderScript language support", CreateInstance,
                                GetCommandObject);
}

void RenderScriptRuntime::Terminate() {
  PluginManager::UnregisterPlugin(CreateInstance);
}

RenderScriptRuntime::ModuleKind
RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp) {
  if (module_sp) {
    if (IsRenderScriptScriptModule(module_sp))
      return eModuleKindKernelObj;

    // Is this the main RS runtime library
    const ConstString rs_lib("libRS.so");
    if (module_sp->GetFileSpec().GetFilename() == rs_lib) {
      return eModuleKindLibRS;
    }

    const ConstString rs_driverlib("libRSDriver.so");
    if (module_sp->GetFileSpec().GetFilename() == rs_driverlib) {
      return eModuleKindDriver;
    }

    const ConstString rs_cpureflib("libRSCpuRef.so");
    if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib) {
      return eModuleKindImpl;
    }
  }
  return eModuleKindIgnored;
}

bool RenderScriptRuntime::IsRenderScriptModule(
    const lldb::ModuleSP &module_sp) {
  return GetModuleKind(module_sp) != eModuleKindIgnored;
}

void RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list) {
  std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());

  size_t num_modules = module_list.GetSize();
  for (size_t i = 0; i < num_modules; i++) {
    auto mod = module_list.GetModuleAtIndex(i);
    if (IsRenderScriptModule(mod)) {
      LoadModule(mod);
    }
  }
}

bool RenderScriptRuntime::GetDynamicTypeAndAddress(
    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
    TypeAndOrName &class_type_or_name, Address &address,
    Value::ValueType &value_type) {
  return false;
}

TypeAndOrName
RenderScriptRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
                                      ValueObject &static_value) {
  return type_and_or_name;
}

bool RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
  return false;
}

lldb::BreakpointResolverSP
RenderScriptRuntime::CreateExceptionResolver(const lldb::BreakpointSP &bp,
                                             bool catch_bp, bool throw_bp) {
  BreakpointResolverSP resolver_sp;
  return resolver_sp;
}

const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] =
    {
        // rsdScript
        {"rsdScriptInit", "_Z13rsdScriptInitPKN7android12renderscript7ContextEP"
                          "NS0_7ScriptCEPKcS7_PKhjj",
         "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_"
         "7ScriptCEPKcS7_PKhmj",
         0, RenderScriptRuntime::eModuleKindDriver,
         &lldb_private::RenderScriptRuntime::CaptureScriptInit},
        {"rsdScriptInvokeForEachMulti",
         "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0"
         "_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall",
         "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0"
         "_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall",
         0, RenderScriptRuntime::eModuleKindDriver,
         &lldb_private::RenderScriptRuntime::CaptureScriptInvokeForEachMulti},
        {"rsdScriptSetGlobalVar", "_Z21rsdScriptSetGlobalVarPKN7android12render"
                                  "script7ContextEPKNS0_6ScriptEjPvj",
         "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_"
         "6ScriptEjPvm",
         0, RenderScriptRuntime::eModuleKindDriver,
         &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar},

        // rsdAllocation
        {"rsdAllocationInit", "_Z17rsdAllocationInitPKN7android12renderscript7C"
                              "ontextEPNS0_10AllocationEb",
         "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_"
         "10AllocationEb",
         0, RenderScriptRuntime::eModuleKindDriver,
         &lldb_private::RenderScriptRuntime::CaptureAllocationInit},
        {"rsdAllocationRead2D",
         "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_"
         "10AllocationEjjj23RsAllocationCubemapFacejjPvjj",
         "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_"
         "10AllocationEjjj23RsAllocationCubemapFacejjPvmm",
         0, RenderScriptRuntime::eModuleKindDriver, nullptr},
        {"rsdAllocationDestroy", "_Z20rsdAllocationDestroyPKN7android12rendersc"
                                 "ript7ContextEPNS0_10AllocationE",
         "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_"
         "10AllocationE",
         0, RenderScriptRuntime::eModuleKindDriver,
         &lldb_private::RenderScriptRuntime::CaptureAllocationDestroy},

        // renderscript script groups
        {"rsdDebugHintScriptGroup2", "_ZN7android12renderscript21debugHintScrip"
                                     "tGroup2EPKcjPKPFvPK24RsExpandKernelDriver"
                                     "InfojjjEj",
         "_ZN7android12renderscript21debugHintScriptGroup2EPKcjPKPFvPK24RsExpan"
         "dKernelDriverInfojjjEj",
         0, RenderScriptRuntime::eModuleKindImpl,
         &lldb_private::RenderScriptRuntime::CaptureDebugHintScriptGroup2}};

const size_t RenderScriptRuntime::s_runtimeHookCount =
    sizeof(s_runtimeHookDefns) / sizeof(s_runtimeHookDefns[0]);

bool RenderScriptRuntime::HookCallback(void *baton,
                                       StoppointCallbackContext *ctx,
                                       lldb::user_id_t break_id,
                                       lldb::user_id_t break_loc_id) {
  RuntimeHook *hook = (RuntimeHook *)baton;
  ExecutionContext exe_ctx(ctx->exe_ctx_ref);

  RenderScriptRuntime *lang_rt = llvm::cast<RenderScriptRuntime>(
      exe_ctx.GetProcessPtr()->GetLanguageRuntime(
          eLanguageTypeExtRenderScript));

  lang_rt->HookCallback(hook, exe_ctx);

  return false;
}

void RenderScriptRuntime::HookCallback(RuntimeHook *hook,
                                       ExecutionContext &exe_ctx) {
  Log *log = GetLog(LLDBLog::Language);

  LLDB_LOGF(log, "%s - '%s'", __FUNCTION__, hook->defn->name);

  if (hook->defn->grabber) {
    (this->*(hook->defn->grabber))(hook, exe_ctx);
  }
}

void RenderScriptRuntime::CaptureDebugHintScriptGroup2(
    RuntimeHook *hook_info, ExecutionContext &context) {
  Log *log = GetLog(LLDBLog::Language);

  enum {
    eGroupName = 0,
    eGroupNameSize,
    eKernel,
    eKernelCount,
  };

  std::array<ArgItem, 4> args{{
      {ArgItem::ePointer, 0}, // const char         *groupName
      {ArgItem::eInt32, 0},   // const uint32_t      groupNameSize
      {ArgItem::ePointer, 0}, // const ExpandFuncTy *kernel
      {ArgItem::eInt32, 0},   // const uint32_t      kernelCount
  }};

  if (!GetArgs(context, args.data(), args.size())) {
    LLDB_LOGF(log, "%s - Error while reading the function parameters",
              __FUNCTION__);
    return;
  } else if (log) {
    LLDB_LOGF(log, "%s - groupName    : 0x%" PRIx64, __FUNCTION__,
              addr_t(args[eGroupName]));
    LLDB_LOGF(log, "%s - groupNameSize: %" PRIu64, __FUNCTION__,
              uint64_t(args[eGroupNameSize]));
    LLDB_LOGF(log, "%s - kernel       : 0x%" PRIx64, __FUNCTION__,
              addr_t(args[eKernel]));
    LLDB_LOGF(log, "%s - kernelCount  : %" PRIu64, __FUNCTION__,
              uint64_t(args[eKernelCount]));
  }

  // parse script group name
  ConstString group_name;
  {
    Status err;
    const uint64_t len = uint64_t(args[eGroupNameSize]);
    std::unique_ptr<char[]> buffer(new char[uint32_t(len + 1)]);
    m_process->ReadMemory(addr_t(args[eGroupName]), buffer.get(), len, err);
    buffer.get()[len] = '\0';
    if (!err.Success()) {
      LLDB_LOGF(log, "Error reading scriptgroup name from target");
      return;
    } else {
      LLDB_LOGF(log, "Extracted scriptgroup name %s", buffer.get());
    }
    // write back the script group name
    group_name.SetCString(buffer.get());
  }

  // create or access existing script group
  RSScriptGroupDescriptorSP group;
  {
    // search for existing script group
    for (auto sg : m_scriptGroups) {
      if (sg->m_name == group_name) {
        group = sg;
        break;
      }
    }
    if (!group) {
      group = std::make_shared<RSScriptGroupDescriptor>();
      group->m_name = group_name;
      m_scriptGroups.push_back(group);
    } else {
      // already have this script group
      LLDB_LOGF(log, "Attempt to add duplicate script group %s",
                group_name.AsCString());
      return;
    }
  }
  assert(group);

  const uint32_t target_ptr_size = m_process->GetAddressByteSize();
  std::vector<addr_t> kernels;
  // parse kernel addresses in script group
  for (uint64_t i = 0; i < uint64_t(args[eKernelCount]); ++i) {
    RSScriptGroupDescriptor::Kernel kernel;
    // extract script group kernel addresses from the target
    const addr_t ptr_addr = addr_t(args[eKernel]) + i * target_ptr_size;
    uint64_t kernel_addr = 0;
    Status err;
    size_t read =
        m_process->ReadMemory(ptr_addr, &kernel_addr, target_ptr_size, err);
    if (!err.Success() || read != target_ptr_size) {
      LLDB_LOGF(log, "Error parsing kernel address %" PRIu64 " in script group",
                i);
      return;
    }
    LLDB_LOGF(log, "Extracted scriptgroup kernel address - 0x%" PRIx64,
              kernel_addr);
    kernel.m_addr = kernel_addr;

    // try to resolve the associated kernel name
    if (!ResolveKernelName(kernel.m_addr, kernel.m_name)) {
      LLDB_LOGF(log, "Parsed scriptgroup kernel %" PRIu64 " - 0x%" PRIx64, i,
                kernel_addr);
      return;
    }

    // try to find the non '.expand' function
    {
      const llvm::StringRef expand(".expand");
      const llvm::StringRef name_ref = kernel.m_name.GetStringRef();
      if (name_ref.endswith(expand)) {
        const ConstString base_kernel(name_ref.drop_back(expand.size()));
        // verify this function is a valid kernel
        if (IsKnownKernel(base_kernel)) {
          kernel.m_name = base_kernel;
          LLDB_LOGF(log, "%s - found non expand version '%s'", __FUNCTION__,
                    base_kernel.GetCString());
        }
      }
    }
    // add to a list of script group kernels we know about
    group->m_kernels.push_back(kernel);
  }

  // Resolve any pending scriptgroup breakpoints
  {
    Target &target = m_process->GetTarget();
    const BreakpointList &list = target.GetBreakpointList();
    const size_t num_breakpoints = list.GetSize();
    LLDB_LOGF(log, "Resolving %zu breakpoints", num_breakpoints);
    for (size_t i = 0; i < num_breakpoints; ++i) {
      const BreakpointSP bp = list.GetBreakpointAtIndex(i);
      if (bp) {
        if (bp->MatchesName(group_name.AsCString())) {
          LLDB_LOGF(log, "Found breakpoint with name %s",
                    group_name.AsCString());
          bp->ResolveBreakpoint();
        }
      }
    }
  }
}

void RenderScriptRuntime::CaptureScriptInvokeForEachMulti(
    RuntimeHook *hook, ExecutionContext &exe_ctx) {
  Log *log = GetLog(LLDBLog::Language);

  enum {
    eRsContext = 0,
    eRsScript,
    eRsSlot,
    eRsAIns,
    eRsInLen,
    eRsAOut,
    eRsUsr,
    eRsUsrLen,
    eRsSc,
  };

  std::array<ArgItem, 9> args{{
      ArgItem{ArgItem::ePointer, 0}, // const Context       *rsc
      ArgItem{ArgItem::ePointer, 0}, // Script              *s
      ArgItem{ArgItem::eInt32, 0},   // uint32_t             slot
      ArgItem{ArgItem::ePointer, 0}, // const Allocation   **aIns
      ArgItem{ArgItem::eInt32, 0},   // size_t               inLen
      ArgItem{ArgItem::ePointer, 0}, // Allocation          *aout
      ArgItem{ArgItem::ePointer, 0}, // const void          *usr
      ArgItem{ArgItem::eInt32, 0},   // size_t               usrLen
      ArgItem{ArgItem::ePointer, 0}, // const RsScriptCall  *sc
  }};

  bool success = GetArgs(exe_ctx, &args[0], args.size());
  if (!success) {
    LLDB_LOGF(log, "%s - Error while reading the function parameters",
              __FUNCTION__);
    return;
  }

  const uint32_t target_ptr_size = m_process->GetAddressByteSize();
  Status err;
  std::vector<uint64_t> allocs;

  // traverse allocation list
  for (uint64_t i = 0; i < uint64_t(args[eRsInLen]); ++i) {
    // calculate offest to allocation pointer
    const addr_t addr = addr_t(args[eRsAIns]) + i * target_ptr_size;

    // Note: due to little endian layout, reading 32bits or 64bits into res
    // will give the correct results.
    uint64_t result = 0;
    size_t read = m_process->ReadMemory(addr, &result, target_ptr_size, err);
    if (read != target_ptr_size || !err.Success()) {
      LLDB_LOGF(log,
                "%s - Error while reading allocation list argument %" PRIu64,
                __FUNCTION__, i);
    } else {
      allocs.push_back(result);
    }
  }

  // if there is an output allocation track it
  if (uint64_t alloc_out = uint64_t(args[eRsAOut])) {
    allocs.push_back(alloc_out);
  }

  // for all allocations we have found
  for (const uint64_t alloc_addr : allocs) {
    AllocationDetails *alloc = LookUpAllocation(alloc_addr);
    if (!alloc)
      alloc = CreateAllocation(alloc_addr);

    if (alloc) {
      // save the allocation address
      if (alloc->address.isValid()) {
        // check the allocation address we already have matches
        assert(*alloc->address.get() == alloc_addr);
      } else {
        alloc->address = alloc_addr;
      }

      // save the context
      if (log) {
        if (alloc->context.isValid() &&
            *alloc->context.get() != addr_t(args[eRsContext]))
          LLDB_LOGF(log, "%s - Allocation used by multiple contexts",
                    __FUNCTION__);
      }
      alloc->context = addr_t(args[eRsContext]);
    }
  }

  // make sure we track this script object
  if (lldb_private::RenderScriptRuntime::ScriptDetails *script =
          LookUpScript(addr_t(args[eRsScript]), true)) {
    if (log) {
      if (script->context.isValid() &&
          *script->context.get() != addr_t(args[eRsContext]))
        LLDB_LOGF(log, "%s - Script used by multiple contexts", __FUNCTION__);
    }
    script->context = addr_t(args[eRsContext]);
  }
}

void RenderScriptRuntime::CaptureSetGlobalVar(RuntimeHook *hook,
                                              ExecutionContext &context) {
  Log *log = GetLog(LLDBLog::Language);

  enum {
    eRsContext,
    eRsScript,
    eRsId,
    eRsData,
    eRsLength,
  };

  std::array<ArgItem, 5> args{{
      ArgItem{ArgItem::ePointer, 0}, // eRsContext
      ArgItem{ArgItem::ePointer, 0}, // eRsScript
      ArgItem{ArgItem::eInt32, 0},   // eRsId
      ArgItem{ArgItem::ePointer, 0}, // eRsData
      ArgItem{ArgItem::eInt32, 0},   // eRsLength
  }};

  bool success = GetArgs(context, &args[0], args.size());
  if (!success) {
    LLDB_LOGF(log, "%s - error reading the function parameters.", __FUNCTION__);
    return;
  }

  if (log) {
    LLDB_LOGF(log,
              "%s - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64
              ":%" PRIu64 "bytes.",
              __FUNCTION__, uint64_t(args[eRsContext]),
              uint64_t(args[eRsScript]), uint64_t(args[eRsId]),
              uint64_t(args[eRsData]), uint64_t(args[eRsLength]));

    addr_t script_addr = addr_t(args[eRsScript]);
    if (m_scriptMappings.find(script_addr) != m_scriptMappings.end()) {
      auto rsm = m_scriptMappings[script_addr];
      if (uint64_t(args[eRsId]) < rsm->m_globals.size()) {
        auto rsg = rsm->m_globals[uint64_t(args[eRsId])];
        LLDB_LOGF(log, "%s - Setting of '%s' within '%s' inferred",
                  __FUNCTION__, rsg.m_name.AsCString(),
                  rsm->m_module->GetFileSpec().GetFilename().AsCString());
      }
    }
  }
}

void RenderScriptRuntime::CaptureAllocationInit(RuntimeHook *hook,
                                                ExecutionContext &exe_ctx) {
  Log *log = GetLog(LLDBLog::Language);

  enum { eRsContext, eRsAlloc, eRsForceZero };

  std::array<ArgItem, 3> args{{
      ArgItem{ArgItem::ePointer, 0}, // eRsContext
      ArgItem{ArgItem::ePointer, 0}, // eRsAlloc
      ArgItem{ArgItem::eBool, 0},    // eRsForceZero
  }};

  bool success = GetArgs(exe_ctx, &args[0], args.size());
  if (!success) {
    LLDB_LOGF(log, "%s - error while reading the function parameters",
              __FUNCTION__);
    return;
  }

  LLDB_LOGF(log, "%s - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .",
            __FUNCTION__, uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc]),
            uint64_t(args[eRsForceZero]));

  AllocationDetails *alloc = CreateAllocation(uint64_t(args[eRsAlloc]));
  if (alloc)
    alloc->context = uint64_t(args[eRsContext]);
}

void RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook *hook,
                                                   ExecutionContext &exe_ctx) {
  Log *log = GetLog(LLDBLog::Language);

  enum {
    eRsContext,
    eRsAlloc,
  };

  std::array<ArgItem, 2> args{{
      ArgItem{ArgItem::ePointer, 0}, // eRsContext
      ArgItem{ArgItem::ePointer, 0}, // eRsAlloc
  }};

  bool success = GetArgs(exe_ctx, &args[0], args.size());
  if (!success) {
    LLDB_LOGF(log, "%s - error while reading the function parameters.",
              __FUNCTION__);
    return;
  }

  LLDB_LOGF(log, "%s - 0x%" PRIx64 ", 0x%" PRIx64 ".", __FUNCTION__,
            uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc]));

  for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter) {
    auto &allocation_up = *iter; // get the unique pointer
    if (allocation_up->address.isValid() &&
        *allocation_up->address.get() == addr_t(args[eRsAlloc])) {
      m_allocations.erase(iter);
      LLDB_LOGF(log, "%s - deleted allocation entry.", __FUNCTION__);
      return;
    }
  }

  LLDB_LOGF(log, "%s - couldn't find destroyed allocation.", __FUNCTION__);
}

void RenderScriptRuntime::CaptureScriptInit(RuntimeHook *hook,
                                            ExecutionContext &exe_ctx) {
  Log *log = GetLog(LLDBLog::Language);

  Status err;
  Process *process = exe_ctx.GetProcessPtr();

  enum { eRsContext, eRsScript, eRsResNamePtr, eRsCachedDirPtr };

  std::array<ArgItem, 4> args{
      {ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0},
       ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0}}};
  bool success = GetArgs(exe_ctx, &args[0], args.size());
  if (!success) {
    LLDB_LOGF(log, "%s - error while reading the function parameters.",
              __FUNCTION__);
    return;
  }

  std::string res_name;
  process->ReadCStringFromMemory(addr_t(args[eRsResNamePtr]), res_name, err);
  if (err.Fail()) {
    LLDB_LOGF(log, "%s - error reading res_name: %s.", __FUNCTION__,
              err.AsCString());
  }

  std::string cache_dir;
  process->ReadCStringFromMemory(addr_t(args[eRsCachedDirPtr]), cache_dir, err);
  if (err.Fail()) {
    LLDB_LOGF(log, "%s - error reading cache_dir: %s.", __FUNCTION__,
              err.AsCString());
  }

  LLDB_LOGF(log, "%s - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .",
            __FUNCTION__, uint64_t(args[eRsContext]), uint64_t(args[eRsScript]),
            res_name.c_str(), cache_dir.c_str());

  if (res_name.size() > 0) {
    StreamString strm;
    strm.Printf("librs.%s.so", res_name.c_str());

    ScriptDetails *script = LookUpScript(addr_t(args[eRsScript]), true);
    if (script) {
      script->type = ScriptDetails::eScriptC;
      script->cache_dir = cache_dir;
      script->res_name = res_name;
      script->shared_lib = std::string(strm.GetString());
      script->context = addr_t(args[eRsContext]);
    }

    LLDB_LOGF(log,
              "%s - '%s' tagged with context 0x%" PRIx64
              " and script 0x%" PRIx64 ".",
              __FUNCTION__, strm.GetData(), uint64_t(args[eRsContext]),
              uint64_t(args[eRsScript]));
  } else if (log) {
    LLDB_LOGF(log, "%s - resource name invalid, Script not tagged.",
              __FUNCTION__);
  }
}

void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module,
                                           ModuleKind kind) {
  Log *log = GetLog(LLDBLog::Language);

  if (!module) {
    return;
  }

  Target &target = GetProcess()->GetTarget();
  const llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine();

  if (machine != llvm::Triple::ArchType::x86 &&
      machine != llvm::Triple::ArchType::arm &&
      machine != llvm::Triple::ArchType::aarch64 &&
      machine != llvm::Triple::ArchType::mipsel &&
      machine != llvm::Triple::ArchType::mips64el &&
      machine != llvm::Triple::ArchType::x86_64) {
    LLDB_LOGF(log, "%s - unable to hook runtime functions.", __FUNCTION__);
    return;
  }

  const uint32_t target_ptr_size =
      target.GetArchitecture().GetAddressByteSize();

  std::array<bool, s_runtimeHookCount> hook_placed;
  hook_placed.fill(false);

  for (size_t idx = 0; idx < s_runtimeHookCount; idx++) {
    const HookDefn *hook_defn = &s_runtimeHookDefns[idx];
    if (hook_defn->kind != kind) {
      continue;
    }

    const char *symbol_name = (target_ptr_size == 4)
                                  ? hook_defn->symbol_name_m32
                                  : hook_defn->symbol_name_m64;

    const Symbol *sym = module->FindFirstSymbolWithNameAndType(
        ConstString(symbol_name), eSymbolTypeCode);
    if (!sym) {
      if (log) {
        LLDB_LOGF(log, "%s - symbol '%s' related to the function %s not found",
                  __FUNCTION__, symbol_name, hook_defn->name);
      }
      continue;
    }

    addr_t addr = sym->GetLoadAddress(&target);
    if (addr == LLDB_INVALID_ADDRESS) {
      LLDB_LOGF(log,
                "%s - unable to resolve the address of hook function '%s' "
                "with symbol '%s'.",
                __FUNCTION__, hook_defn->name, symbol_name);
      continue;
    } else {
      LLDB_LOGF(log, "%s - function %s, address resolved at 0x%" PRIx64,
                __FUNCTION__, hook_defn->name, addr);
    }

    RuntimeHookSP hook(new RuntimeHook());
    hook->address = addr;
    hook->defn = hook_defn;
    hook->bp_sp = target.CreateBreakpoint(addr, true, false);
    hook->bp_sp->SetCallback(HookCallback, hook.get(), true);
    m_runtimeHooks[addr] = hook;
    if (log) {
      LLDB_LOGF(log,
                "%s - successfully hooked '%s' in '%s' version %" PRIu64
                " at 0x%" PRIx64 ".",
                __FUNCTION__, hook_defn->name,
                module->GetFileSpec().GetFilename().AsCString(),
                (uint64_t)hook_defn->version, (uint64_t)addr);
    }
    hook_placed[idx] = true;
  }

  // log any unhooked function
  if (log) {
    for (size_t i = 0; i < hook_placed.size(); ++i) {
      if (hook_placed[i])
        continue;
      const HookDefn &hook_defn = s_runtimeHookDefns[i];
      if (hook_defn.kind != kind)
        continue;
      LLDB_LOGF(log, "%s - function %s was not hooked", __FUNCTION__,
                hook_defn.name);
    }
  }
}

void RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) {
  if (!rsmodule_sp)
    return;

  Log *log = GetLog(LLDBLog::Language);

  const ModuleSP module = rsmodule_sp->m_module;
  const FileSpec &file = module->GetPlatformFileSpec();

  // Iterate over all of the scripts that we currently know of. Note: We cant
  // push or pop to m_scripts here or it may invalidate rs_script.
  for (const auto &rs_script : m_scripts) {
    // Extract the expected .so file path for this script.
    std::string shared_lib;
    if (!rs_script->shared_lib.get(shared_lib))
      continue;

    // Only proceed if the module that has loaded corresponds to this script.
    if (file.GetFilename() != ConstString(shared_lib.c_str()))
      continue;

    // Obtain the script address which we use as a key.
    lldb::addr_t script;
    if (!rs_script->script.get(script))
      continue;

    // If we have a script mapping for the current script.
    if (m_scriptMappings.find(script) != m_scriptMappings.end()) {
      // if the module we have stored is different to the one we just received.
      if (m_scriptMappings[script] != rsmodule_sp) {
        LLDB_LOGF(
            log,
            "%s - script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
            __FUNCTION__, (uint64_t)script,
            rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
      }
    }
    // We don't have a script mapping for the current script.
    else {
      // Obtain the script resource name.
      std::string res_name;
      if (rs_script->res_name.get(res_name))
        // Set the modules resource name.
        rsmodule_sp->m_resname = res_name;
      // Add Script/Module pair to map.
      m_scriptMappings[script] = rsmodule_sp;
      LLDB_LOGF(log, "%s - script %" PRIx64 " associated with rsmodule '%s'.",
                __FUNCTION__, (uint64_t)script,
                rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
    }
  }
}

// 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* parameter. Function returns true on success, and false on
// failure
bool RenderScriptRuntime::EvalRSExpression(const char *expr,
                                           StackFrame *frame_ptr,
                                           uint64_t *result) {
  Log *log = GetLog(LLDBLog::Language);
  LLDB_LOGF(log, "%s(%s)", __FUNCTION__, expr);

  ValueObjectSP expr_result;
  EvaluateExpressionOptions options;
  options.SetLanguage(lldb::eLanguageTypeC_plus_plus);
  // Perform the actual expression evaluation
  auto &target = GetProcess()->GetTarget();
  target.EvaluateExpression(expr, frame_ptr, expr_result, options);

  if (!expr_result) {
    LLDB_LOGF(log, "%s: couldn't evaluate expression.", __FUNCTION__);
    return false;
  }

  // The result of the expression is invalid
  if (!expr_result->GetError().Success()) {
    Status err = expr_result->GetError();
    // Expression returned is void, so this is actually a success
    if (err.GetError() == UserExpression::kNoResult) {
      LLDB_LOGF(log, "%s - expression returned void.", __FUNCTION__);

      result = nullptr;
      return true;
    }

    LLDB_LOGF(log, "%s - error evaluating expression result: %s", __FUNCTION__,
              err.AsCString());
    return false;
  }

  bool success = false;
  // We only read the result as an uint32_t.
  *result = expr_result->GetValueAsUnsigned(0, &success);

  if (!success) {
    LLDB_LOGF(log, "%s - couldn't convert expression result to uint32_t",
              __FUNCTION__);
    return false;
  }

  return true;
}

namespace {
// Used to index expression format strings
enum ExpressionStrings {
  eExprGetOffsetPtr = 0,
  eExprAllocGetType,
  eExprTypeDimX,
  eExprTypeDimY,
  eExprTypeDimZ,
  eExprTypeElemPtr,
  eExprElementType,
  eExprElementKind,
  eExprElementVec,
  eExprElementFieldCount,
  eExprSubelementsId,
  eExprSubelementsName,
  eExprSubelementsArrSize,

  _eExprLast // keep at the end, implicit size of the array runtime_expressions
};

// max length of an expanded expression
const int jit_max_expr_size = 512;

// Retrieve the string to JIT for the given expression
#define JIT_TEMPLATE_CONTEXT "void* ctxt = (void*)rsDebugGetContextWrapper(0x%" PRIx64 "); "
const char *JITTemplate(ExpressionStrings e) {
  // Format strings containing the expressions we may need to evaluate.
  static std::array<const char *, _eExprLast> runtime_expressions = {
      {// Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
       "(int*)_"
       "Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocation"
       "CubemapFace"
       "(0x%" PRIx64 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", 0, 0)", // eExprGetOffsetPtr

       // Type* rsaAllocationGetType(Context*, Allocation*)
       JIT_TEMPLATE_CONTEXT "(void*)rsaAllocationGetType(ctxt, 0x%" PRIx64 ")", // eExprAllocGetType

       // 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
       JIT_TEMPLATE_CONTEXT
       "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 6); data[0]", // eExprTypeDimX
       JIT_TEMPLATE_CONTEXT
       "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 6); data[1]", // eExprTypeDimY
       JIT_TEMPLATE_CONTEXT
       "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 6); data[2]", // eExprTypeDimZ
       JIT_TEMPLATE_CONTEXT
       "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 6); data[5]", // eExprTypeElemPtr

       // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
       // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into
       // elemData
       JIT_TEMPLATE_CONTEXT
       "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 5); data[0]", // eExprElementType
       JIT_TEMPLATE_CONTEXT
       "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 5); data[1]", // eExprElementKind
       JIT_TEMPLATE_CONTEXT
       "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 5); data[3]", // eExprElementVec
       JIT_TEMPLATE_CONTEXT
       "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 5); data[4]", // eExprElementFieldCount

       // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t
       // *ids, const char **names, size_t *arraySizes, uint32_t dataSize)
       // Needed for Allocations of structs to gather details about
       // fields/Subelements Element* of field
       JIT_TEMPLATE_CONTEXT "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
       "]; size_t arr_size[%" PRIu32 "];"
       "(void*)rsaElementGetSubElements(ctxt, 0x%" PRIx64
       ", ids, names, arr_size, %" PRIu32 "); ids[%" PRIu32 "]", // eExprSubelementsId

       // Name of field
       JIT_TEMPLATE_CONTEXT "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
       "]; size_t arr_size[%" PRIu32 "];"
       "(void*)rsaElementGetSubElements(ctxt, 0x%" PRIx64
       ", ids, names, arr_size, %" PRIu32 "); names[%" PRIu32 "]", // eExprSubelementsName

       // Array size of field
       JIT_TEMPLATE_CONTEXT "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
       "]; size_t arr_size[%" PRIu32 "];"
       "(void*)rsaElementGetSubElements(ctxt, 0x%" PRIx64
       ", ids, names, arr_size, %" PRIu32 "); arr_size[%" PRIu32 "]"}}; // eExprSubelementsArrSize

  return runtime_expressions[e];
}
} // end of the anonymous namespace

// 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 *alloc,
                                         StackFrame *frame_ptr, uint32_t x,
                                         uint32_t y, uint32_t z) {
  Log *log = GetLog(LLDBLog::Language);

  if (!alloc->address.isValid()) {
    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
    return false;
  }

  const char *fmt_str = JITTemplate(eExprGetOffsetPtr);
  char expr_buf[jit_max_expr_size];

  int written = snprintf(expr_buf, jit_max_expr_size, fmt_str,
                         *alloc->address.get(), x, y, z);
  if (written < 0) {
    LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
    return false;
  } else if (written >= jit_max_expr_size) {
    LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
    return false;
  }

  uint64_t result = 0;
  if (!EvalRSExpression(expr_buf, frame_ptr, &result))
    return false;

  addr_t data_ptr = static_cast<lldb::addr_t>(result);
  alloc->data_ptr = data_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 *alloc,
                                         StackFrame *frame_ptr) {
  Log *log = GetLog(LLDBLog::Language);

  if (!alloc->address.isValid() || !alloc->context.isValid()) {
    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
    return false;
  }

  const char *fmt_str = JITTemplate(eExprAllocGetType);
  char expr_buf[jit_max_expr_size];

  int written = snprintf(expr_buf, jit_max_expr_size, fmt_str,
                         *alloc->context.get(), *alloc->address.get());
  if (written < 0) {
    LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
    return false;
  } else if (written >= jit_max_expr_size) {
    LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
    return false;
  }

  uint64_t result = 0;
  if (!EvalRSExpression(expr_buf, frame_ptr, &result))
    return false;

  addr_t type_ptr = static_cast<lldb::addr_t>(result);
  alloc->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 *alloc,
                                        StackFrame *frame_ptr) {
  Log *log = GetLog(LLDBLog::Language);

  if (!alloc->type_ptr.isValid() || !alloc->context.isValid()) {
    LLDB_LOGF(log, "%s - Failed to find allocation details.", __FUNCTION__);
    return false;
  }

  // Expression is different depending on if device is 32 or 64 bit
  uint32_t target_ptr_size =
      GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
  const uint32_t bits = target_ptr_size == 4 ? 32 : 64;

  // We want 4 elements from packed data
  const uint32_t num_exprs = 4;
  static_assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1),
                "Invalid number of expressions");

  char expr_bufs[num_exprs][jit_max_expr_size];
  uint64_t results[num_exprs];

  for (uint32_t i = 0; i < num_exprs; ++i) {
    const char *fmt_str = JITTemplate(ExpressionStrings(eExprTypeDimX + i));
    int written = snprintf(expr_bufs[i], jit_max_expr_size, fmt_str,
                           *alloc->context.get(), bits, *alloc->type_ptr.get());
    if (written < 0) {
      LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
      return false;
    } else if (written >= jit_max_expr_size) {
      LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
      return false;
    }

    // Perform expression evaluation
    if (!EvalRSExpression(expr_bufs[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]);
  alloc->dimension = dims;

  addr_t element_ptr = static_cast<lldb::addr_t>(results[3]);
  alloc->element.element_ptr = element_ptr;

  LLDB_LOGF(log,
            "%s - dims (%" PRIu32 ", %" PRIu32 ", %" PRIu32
            ") Element*: 0x%" PRIx64 ".",
            __FUNCTION__, dims.dim_1, dims.dim_2, dims.dim_3, element_ptr);

  return true;
}

// JITs the RS runtime for information about the Element of an allocation Then
// sets type, type_vec_size, field_count and type_kind members in Element with
// the result. Returns true on success, false otherwise
bool RenderScriptRuntime::JITElementPacked(Element &elem,
                                           const lldb::addr_t context,
                                           StackFrame *frame_ptr) {
  Log *log = GetLog(LLDBLog::Language);

  if (!elem.element_ptr.isValid()) {
    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
    return false;
  }

  // We want 4 elements from packed data
  const uint32_t num_exprs = 4;
  static_assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1),
                "Invalid number of expressions");

  char expr_bufs[num_exprs][jit_max_expr_size];
  uint64_t results[num_exprs];

  for (uint32_t i = 0; i < num_exprs; i++) {
    const char *fmt_str = JITTemplate(ExpressionStrings(eExprElementType + i));
    int written = snprintf(expr_bufs[i], jit_max_expr_size, fmt_str, context,
                           *elem.element_ptr.get());
    if (written < 0) {
      LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
      return false;
    } else if (written >= jit_max_expr_size) {
      LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
      return false;
    }

    // Perform expression evaluation
    if (!EvalRSExpression(expr_bufs[i], frame_ptr, &results[i]))
      return false;
  }

  // Assign results to allocation members
  elem.type = static_cast<RenderScriptRuntime::Element::DataType>(results[0]);
  elem.type_kind =
      static_cast<RenderScriptRuntime::Element::DataKind>(results[1]);
  elem.type_vec_size = static_cast<uint32_t>(results[2]);
  elem.field_count = static_cast<uint32_t>(results[3]);

  LLDB_LOGF(log,
            "%s - data type %" PRIu32 ", pixel type %" PRIu32
            ", vector size %" PRIu32 ", field count %" PRIu32,
            __FUNCTION__, *elem.type.get(), *elem.type_kind.get(),
            *elem.type_vec_size.get(), *elem.field_count.get());

  // If this Element has subelements then JIT rsaElementGetSubElements() for
  // details about its fields
  return !(*elem.field_count.get() > 0 &&
           !JITSubelements(elem, context, frame_ptr));
}

// JITs the RS runtime for information about the subelements/fields of a struct
// allocation This is necessary for infering the struct type so we can pretty
// print the allocation's contents. Returns true on success, false otherwise
bool RenderScriptRuntime::JITSubelements(Element &elem,
                                         const lldb::addr_t context,
                                         StackFrame *frame_ptr) {
  Log *log = GetLog(LLDBLog::Language);

  if (!elem.element_ptr.isValid() || !elem.field_count.isValid()) {
    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
    return false;
  }

  const short num_exprs = 3;
  static_assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1),
                "Invalid number of expressions");

  char expr_buffer[jit_max_expr_size];
  uint64_t results;

  // Iterate over struct fields.
  const uint32_t field_count = *elem.field_count.get();
  for (uint32_t field_index = 0; field_index < field_count; ++field_index) {
    Element child;
    for (uint32_t expr_index = 0; expr_index < num_exprs; ++expr_index) {
      const char *fmt_str =
          JITTemplate(ExpressionStrings(eExprSubelementsId + expr_index));
      int written = snprintf(expr_buffer, jit_max_expr_size, fmt_str,
                             context, field_count, field_count, field_count,
                             *elem.element_ptr.get(), field_count, field_index);
      if (written < 0) {
        LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
        return false;
      } else if (written >= jit_max_expr_size) {
        LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
        return false;
      }

      // Perform expression evaluation
      if (!EvalRSExpression(expr_buffer, frame_ptr, &results))
        return false;

      LLDB_LOGF(log, "%s - expr result 0x%" PRIx64 ".", __FUNCTION__, results);

      switch (expr_index) {
      case 0: // Element* of child
        child.element_ptr = static_cast<addr_t>(results);
        break;
      case 1: // Name of child
      {
        lldb::addr_t address = static_cast<addr_t>(results);
        Status err;
        std::string name;
        GetProcess()->ReadCStringFromMemory(address, name, err);
        if (!err.Fail())
          child.type_name = ConstString(name);
        else {
          LLDB_LOGF(log, "%s - warning: Couldn't read field name.",
                    __FUNCTION__);
        }
        break;
      }
      case 2: // Array size of child
        child.array_size = static_cast<uint32_t>(results);
        break;
      }
    }

    // We need to recursively JIT each Element field of the struct since
    // structs can be nested inside structs.
    if (!JITElementPacked(child, context, frame_ptr))
      return false;
    elem.children.push_back(child);
  }

  // Try to infer the name of the struct type so we can pretty print the
  // allocation contents.
  FindStructTypeName(elem, frame_ptr);

  return true;
}

// JITs the RS runtime for the address of the last element in the allocation.
// The `elem_size` parameter represents the size of a single element, including
// padding. Which is needed as an offset from the last element pointer. Using
// this offset minus the starting address we can calculate the size of the
// allocation. Returns true on success, false otherwise
bool RenderScriptRuntime::JITAllocationSize(AllocationDetails *alloc,
                                            StackFrame *frame_ptr) {
  Log *log = GetLog(LLDBLog::Language);

  if (!alloc->address.isValid() || !alloc->dimension.isValid() ||
      !alloc->data_ptr.isValid() || !alloc->element.datum_size.isValid()) {
    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
    return false;
  }

  // Find dimensions
  uint32_t dim_x = alloc->dimension.get()->dim_1;
  uint32_t dim_y = alloc->dimension.get()->dim_2;
  uint32_t dim_z = alloc->dimension.get()->dim_3;

  // Our plan of jitting the last element address doesn't seem to work for
  // struct Allocations` Instead try to infer the size ourselves without any
  // inter element padding.
  if (alloc->element.children.size() > 0) {
    if (dim_x == 0)
      dim_x = 1;
    if (dim_y == 0)
      dim_y = 1;
    if (dim_z == 0)
      dim_z = 1;

    alloc->size = dim_x * dim_y * dim_z * *alloc->element.datum_size.get();

    LLDB_LOGF(log, "%s - inferred size of struct allocation %" PRIu32 ".",
              __FUNCTION__, *alloc->size.get());
    return true;
  }

  const char *fmt_str = JITTemplate(eExprGetOffsetPtr);
  char expr_buf[jit_max_expr_size];

  // Calculate last element
  dim_x = dim_x == 0 ? 0 : dim_x - 1;
  dim_y = dim_y == 0 ? 0 : dim_y - 1;
  dim_z = dim_z == 0 ? 0 : dim_z - 1;

  int written = snprintf(expr_buf, jit_max_expr_size, fmt_str,
                         *alloc->address.get(), dim_x, dim_y, dim_z);
  if (written < 0) {
    LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
    return false;
  } else if (written >= jit_max_expr_size) {
    LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
    return false;
  }

  uint64_t result = 0;
  if (!EvalRSExpression(expr_buf, frame_ptr, &result))
    return false;

  addr_t mem_ptr = static_cast<lldb::addr_t>(result);
  // Find pointer to last element and add on size of an element
  alloc->size = static_cast<uint32_t>(mem_ptr - *alloc->data_ptr.get()) +
                *alloc->element.datum_size.get();

  return true;
}

// JITs the RS runtime for information about the stride between rows in the
// allocation. This is done to detect padding, since allocated memory is
// 16-byte aligned. Returns true on success, false otherwise
bool RenderScriptRuntime::JITAllocationStride(AllocationDetails *alloc,
                                              StackFrame *frame_ptr) {
  Log *log = GetLog(LLDBLog::Language);

  if (!alloc->address.isValid() || !alloc->data_ptr.isValid()) {
    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
    return false;
  }

  const char *fmt_str = JITTemplate(eExprGetOffsetPtr);
  char expr_buf[jit_max_expr_size];

  int written = snprintf(expr_buf, jit_max_expr_size, fmt_str,
                         *alloc->address.get(), 0, 1, 0);
  if (written < 0) {
    LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
    return false;
  } else if (written >= jit_max_expr_size) {
    LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
    return false;
  }

  uint64_t result = 0;
  if (!EvalRSExpression(expr_buf, frame_ptr, &result))
    return false;

  addr_t mem_ptr = static_cast<lldb::addr_t>(result);
  alloc->stride = static_cast<uint32_t>(mem_ptr - *alloc->data_ptr.get());

  return true;
}

// JIT all the current runtime info regarding an allocation
bool RenderScriptRuntime::RefreshAllocation(AllocationDetails *alloc,
                                            StackFrame *frame_ptr) {
  // GetOffsetPointer()
  if (!JITDataPointer(alloc, frame_ptr))
    return false;

  // rsaAllocationGetType()
  if (!JITTypePointer(alloc, frame_ptr))
    return false;

  // rsaTypeGetNativeData()
  if (!JITTypePacked(alloc, frame_ptr))
    return false;

  // rsaElementGetNativeData()
  if (!JITElementPacked(alloc->element, *alloc->context.get(), frame_ptr))
    return false;

  // Sets the datum_size member in Element
  SetElementSize(alloc->element);

  // Use GetOffsetPointer() to infer size of the allocation
  return JITAllocationSize(alloc, frame_ptr);
}

// Function attempts to set the type_name member of the parameterised Element
// object. This string should be the name of the struct type the Element
// represents. We need this string for pretty printing the Element to users.
void RenderScriptRuntime::FindStructTypeName(Element &elem,
                                             StackFrame *frame_ptr) {
  Log *log = GetLog(LLDBLog::Language);

  if (!elem.type_name.IsEmpty()) // Name already set
    return;
  else
    elem.type_name = Element::GetFallbackStructName(); // Default type name if
                                                       // we don't succeed

  // Find all the global variables from the script rs modules
  VariableList var_list;
  for (auto module_sp : m_rsmodules)
    module_sp->m_module->FindGlobalVariables(
        RegularExpression(llvm::StringRef(".")), UINT32_MAX, var_list);

  // Iterate over all the global variables looking for one with a matching type
  // to the Element. We make the assumption a match exists since there needs to
  // be a global variable to reflect the struct type back into java host code.
  for (const VariableSP &var_sp : var_list) {
    if (!var_sp)
      continue;

    ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp);
    if (!valobj_sp)
      continue;

    // Find the number of variable fields.
    // If it has no fields, or more fields than our Element, then it can't be
    // the struct we're looking for. Don't check for equality since RS can add
    // extra struct members for padding.
    size_t num_children = valobj_sp->GetNumChildren();
    if (num_children > elem.children.size() || num_children == 0)
      continue;

    // Iterate over children looking for members with matching field names. If
    // all the field names match, this is likely the struct we want.
    //   TODO: This could be made more robust by also checking children data
    //   sizes, or array size
    bool found = true;
    for (size_t i = 0; i < num_children; ++i) {
      ValueObjectSP child = valobj_sp->GetChildAtIndex(i, true);
      if (!child || (child->GetName() != elem.children[i].type_name)) {
        found = false;
        break;
      }
    }

    // RS can add extra struct members for padding in the format
    // '#rs_padding_[0-9]+'
    if (found && num_children < elem.children.size()) {
      const uint32_t size_diff = elem.children.size() - num_children;
      LLDB_LOGF(log, "%s - %" PRIu32 " padding struct entries", __FUNCTION__,
                size_diff);

      for (uint32_t i = 0; i < size_diff; ++i) {
        ConstString name = elem.children[num_children + i].type_name;
        if (strcmp(name.AsCString(), "#rs_padding") < 0)
          found = false;
      }
    }

    // We've found a global variable with matching type
    if (found) {
      // Dereference since our Element type isn't a pointer.
      if (valobj_sp->IsPointerType()) {
        Status err;
        ValueObjectSP deref_valobj = valobj_sp->Dereference(err);
        if (!err.Fail())
          valobj_sp = deref_valobj;
      }

      // Save name of variable in Element.
      elem.type_name = valobj_sp->GetTypeName();
      LLDB_LOGF(log, "%s - element name set to %s", __FUNCTION__,
                elem.type_name.AsCString());

      return;
    }
  }
}

// Function sets the datum_size member of Element. Representing the size of a
// single instance including padding. Assumes the relevant allocation
// information has already been jitted.
void RenderScriptRuntime::SetElementSize(Element &elem) {
  Log *log = GetLog(LLDBLog::Language);
  const Element::DataType type = *elem.type.get();
  assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT &&
         "Invalid allocation type");

  const uint32_t vec_size = *elem.type_vec_size.get();
  uint32_t data_size = 0;
  uint32_t padding = 0;

  // Element is of a struct type, calculate size recursively.
  if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0)) {
    for (Element &child : elem.children) {
      SetElementSize(child);
      const uint32_t array_size =
          child.array_size.isValid() ? *child.array_size.get() : 1;
      data_size += *child.datum_size.get() * array_size;
    }
  }
  // These have been packed already
  else if (type == Element::RS_TYPE_UNSIGNED_5_6_5 ||
           type == Element::RS_TYPE_UNSIGNED_5_5_5_1 ||
           type == Element::RS_TYPE_UNSIGNED_4_4_4_4) {
    data_size = AllocationDetails::RSTypeToFormat[type][eElementSize];
  } else if (type < Element::RS_TYPE_ELEMENT) {
    data_size =
        vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
    if (vec_size == 3)
      padding = AllocationDetails::RSTypeToFormat[type][eElementSize];
  } else
    data_size =
        GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();

  elem.padding = padding;
  elem.datum_size = data_size + padding;
  LLDB_LOGF(log, "%s - element size set to %" PRIu32, __FUNCTION__,
            data_size + padding);
}

// Given an allocation, this function copies the allocation contents from
// device into a buffer on the heap. Returning a shared pointer to the buffer
// containing the data.
std::shared_ptr<uint8_t>
RenderScriptRuntime::GetAllocationData(AllocationDetails *alloc,
                                       StackFrame *frame_ptr) {
  Log *log = GetLog(LLDBLog::Language);

  // JIT all the allocation details
  if (alloc->ShouldRefresh()) {
    LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info",
              __FUNCTION__);

    if (!RefreshAllocation(alloc, frame_ptr)) {
      LLDB_LOGF(log, "%s - couldn't JIT allocation details", __FUNCTION__);
      return nullptr;
    }
  }

  assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() &&
         alloc->element.type_vec_size.isValid() && alloc->size.isValid() &&
         "Allocation information not available");

  // Allocate a buffer to copy data into
  const uint32_t size = *alloc->size.get();
  std::shared_ptr<uint8_t> buffer(new uint8_t[size]);
  if (!buffer) {
    LLDB_LOGF(log, "%s - couldn't allocate a %" PRIu32 " byte buffer",
              __FUNCTION__, size);
    return nullptr;
  }

  // Read the inferior memory
  Status err;
  lldb::addr_t data_ptr = *alloc->data_ptr.get();
  GetProcess()->ReadMemory(data_ptr, buffer.get(), size, err);
  if (err.Fail()) {
    LLDB_LOGF(log,
              "%s - '%s' Couldn't read %" PRIu32
              " bytes of allocation data from 0x%" PRIx64,
              __FUNCTION__, err.AsCString(), size, data_ptr);
    return nullptr;
  }

  return buffer;
}

// Function copies data from a binary file into an allocation. There is a
// header at the start of the file, FileHeader, before the data content itself.
// Information from this header is used to display warnings to the user about
// incompatibilities
bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
                                         const char *path,
                                         StackFrame *frame_ptr) {
  Log *log = GetLog(LLDBLog::Language);

  // Find allocation with the given id
  AllocationDetails *alloc = FindAllocByID(strm, alloc_id);
  if (!alloc)
    return false;

  LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64, __FUNCTION__,
            *alloc->address.get());

  // JIT all the allocation details
  if (alloc->ShouldRefresh()) {
    LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.",
              __FUNCTION__);

    if (!RefreshAllocation(alloc, frame_ptr)) {
      LLDB_LOGF(log, "%s - couldn't JIT allocation details", __FUNCTION__);
      return false;
    }
  }

  assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() &&
         alloc->element.type_vec_size.isValid() && alloc->size.isValid() &&
         alloc->element.datum_size.isValid() &&
         "Allocation information not available");

  // Check we can read from file
  FileSpec file(path);
  FileSystem::Instance().Resolve(file);
  if (!FileSystem::Instance().Exists(file)) {
    strm.Printf("Error: File %s does not exist", path);
    strm.EOL();
    return false;
  }

  if (!FileSystem::Instance().Readable(file)) {
    strm.Printf("Error: File %s does not have readable permissions", path);
    strm.EOL();
    return false;
  }

  // Read file into data buffer
  auto data_sp = FileSystem::Instance().CreateDataBuffer(file.GetPath());

  // Cast start of buffer to FileHeader and use pointer to read metadata
  const void *file_buf = data_sp->GetBytes();
  if (file_buf == nullptr ||
      data_sp->GetByteSize() < (sizeof(AllocationDetails::FileHeader) +
                                sizeof(AllocationDetails::ElementHeader))) {
    strm.Printf("Error: File %s does not contain enough data for header", path);
    strm.EOL();
    return false;
  }
  const AllocationDetails::FileHeader *file_header =
      static_cast<const AllocationDetails::FileHeader *>(file_buf);

  // Check file starts with ascii characters "RSAD"
  if (memcmp(file_header->ident, "RSAD", 4)) {
    strm.Printf("Error: File doesn't contain identifier for an RS allocation "
                "dump. Are you sure this is the correct file?");
    strm.EOL();
    return false;
  }

  // Look at the type of the root element in the header
  AllocationDetails::ElementHeader root_el_hdr;
  memcpy(&root_el_hdr,
         static_cast<const uint8_t *>(file_buf) +
             sizeof(AllocationDetails::FileHeader),
         sizeof(AllocationDetails::ElementHeader));

  LLDB_LOGF(log, "%s - header type %" PRIu32 ", element size %" PRIu32,
            __FUNCTION__, root_el_hdr.type, root_el_hdr.element_size);

  // Check if the target allocation and file both have the same number of bytes
  // for an Element
  if (*alloc->element.datum_size.get() != root_el_hdr.element_size) {
    strm.Printf("Warning: Mismatched Element sizes - file %" PRIu32
                " bytes, allocation %" PRIu32 " bytes",
                root_el_hdr.element_size, *alloc->element.datum_size.get());
    strm.EOL();
  }

  // Check if the target allocation and file both have the same type
  const uint32_t alloc_type = static_cast<uint32_t>(*alloc->element.type.get());
  const uint32_t file_type = root_el_hdr.type;

  if (file_type > Element::RS_TYPE_FONT) {
    strm.Printf("Warning: File has unknown allocation type");
    strm.EOL();
  } else if (alloc_type != file_type) {
    // Enum value isn't monotonous, so doesn't always index RsDataTypeToString
    // array
    uint32_t target_type_name_idx = alloc_type;
    uint32_t head_type_name_idx = file_type;
    if (alloc_type >= Element::RS_TYPE_ELEMENT &&
        alloc_type <= Element::RS_TYPE_FONT)
      target_type_name_idx = static_cast<Element::DataType>(
          (alloc_type - Element::RS_TYPE_ELEMENT) +
          Element::RS_TYPE_MATRIX_2X2 + 1);

    if (file_type >= Element::RS_TYPE_ELEMENT &&
        file_type <= Element::RS_TYPE_FONT)
      head_type_name_idx = static_cast<Element::DataType>(
          (file_type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 +
          1);

    const char *head_type_name =
        AllocationDetails::RsDataTypeToString[head_type_name_idx][0];
    const char *target_type_name =
        AllocationDetails::RsDataTypeToString[target_type_name_idx][0];

    strm.Printf(
        "Warning: Mismatched Types - file '%s' type, allocation '%s' type",
        head_type_name, target_type_name);
    strm.EOL();
  }

  // Advance buffer past header
  file_buf = static_cast<const uint8_t *>(file_buf) + file_header->hdr_size;

  // Calculate size of allocation data in file
  size_t size = data_sp->GetByteSize() - file_header->hdr_size;

  // Check if the target allocation and file both have the same total data
  // size.
  const uint32_t alloc_size = *alloc->size.get();
  if (alloc_size != size) {
    strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64
                " bytes, allocation 0x%" PRIx32 " bytes",
                (uint64_t)size, alloc_size);
    strm.EOL();
    // Set length to copy to minimum
    size = alloc_size < size ? alloc_size : size;
  }

  // Copy file data from our buffer into the target allocation.
  lldb::addr_t alloc_data = *alloc->data_ptr.get();
  Status err;
  size_t written = GetProcess()->WriteMemory(alloc_data, file_buf, size, err);
  if (!err.Success() || written != size) {
    strm.Printf("Error: Couldn't write data to allocation %s", err.AsCString());
    strm.EOL();
    return false;
  }

  strm.Printf("Contents of file '%s' read into allocation %" PRIu32, path,
              alloc->id);
  strm.EOL();

  return true;
}

// Function takes as parameters a byte buffer, which will eventually be written
// to file as the element header, an offset into that buffer, and an Element
// that will be saved into the buffer at the parametrised offset. Return value
// is the new offset after writing the element into the buffer. Elements are
// saved to the file as the ElementHeader struct followed by offsets to the
// structs of all the element's children.
size_t RenderScriptRuntime::PopulateElementHeaders(
    const std::shared_ptr<uint8_t> header_buffer, size_t offset,
    const Element &elem) {
  // File struct for an element header with all the relevant details copied
  // from elem. We assume members are valid already.
  AllocationDetails::ElementHeader elem_header;
  elem_header.type = *elem.type.get();
  elem_header.kind = *elem.type_kind.get();
  elem_header.element_size = *elem.datum_size.get();
  elem_header.vector_size = *elem.type_vec_size.get();
  elem_header.array_size =
      elem.array_size.isValid() ? *elem.array_size.get() : 0;
  const size_t elem_header_size = sizeof(AllocationDetails::ElementHeader);

  // Copy struct into buffer and advance offset We assume that header_buffer
  // has been checked for nullptr before this method is called
  memcpy(header_buffer.get() + offset, &elem_header, elem_header_size);
  offset += elem_header_size;

  // Starting offset of child ElementHeader struct
  size_t child_offset =
      offset + ((elem.children.size() + 1) * sizeof(uint32_t));
  for (const RenderScriptRuntime::Element &child : elem.children) {
    // Recursively populate the buffer with the element header structs of
    // children. Then save the offsets where they were set after the parent
    // element header.
    memcpy(header_buffer.get() + offset, &child_offset, sizeof(uint32_t));
    offset += sizeof(uint32_t);

    child_offset = PopulateElementHeaders(header_buffer, child_offset, child);
  }

  // Zero indicates no more children
  memset(header_buffer.get() + offset, 0, sizeof(uint32_t));

  return child_offset;
}

// Given an Element object this function returns the total size needed in the
// file header to store the element's details. Taking into account the size of
// the element header struct, plus the offsets to all the element's children.
// Function is recursive so that the size of all ancestors is taken into
// account.
size_t RenderScriptRuntime::CalculateElementHeaderSize(const Element &elem) {
  // Offsets to children plus zero terminator
  size_t size = (elem.children.size() + 1) * sizeof(uint32_t);
  // Size of header struct with type details
  size += sizeof(AllocationDetails::ElementHeader);

  // Calculate recursively for all descendants
  for (const Element &child : elem.children)
    size += CalculateElementHeaderSize(child);

  return size;
}

// Function copies allocation contents into a binary file. This file can then
// be loaded later into a different allocation. There is a header, FileHeader,
// before the allocation data containing meta-data.
bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id,
                                         const char *path,
                                         StackFrame *frame_ptr) {
  Log *log = GetLog(LLDBLog::Language);

  // Find allocation with the given id
  AllocationDetails *alloc = FindAllocByID(strm, alloc_id);
  if (!alloc)
    return false;

  LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64 ".", __FUNCTION__,
            *alloc->address.get());

  // JIT all the allocation details
  if (alloc->ShouldRefresh()) {
    LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.",
              __FUNCTION__);

    if (!RefreshAllocation(alloc, frame_ptr)) {
      LLDB_LOGF(log, "%s - couldn't JIT allocation details.", __FUNCTION__);
      return false;
    }
  }

  assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() &&
         alloc->element.type_vec_size.isValid() &&
         alloc->element.datum_size.get() &&
         alloc->element.type_kind.isValid() && alloc->dimension.isValid() &&
         "Allocation information not available");

  // Check we can create writable file
  FileSpec file_spec(path);
  FileSystem::Instance().Resolve(file_spec);
  auto file = FileSystem::Instance().Open(
      file_spec, File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate |
                     File::eOpenOptionTruncate);

  if (!file) {
    std::string error = llvm::toString(file.takeError());
    strm.Printf("Error: Failed to open '%s' for writing: %s", path,
                error.c_str());
    strm.EOL();
    return false;
  }

  // Read allocation into buffer of heap memory
  const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
  if (!buffer) {
    strm.Printf("Error: Couldn't read allocation data into buffer");
    strm.EOL();
    return false;
  }

  // Create the file header
  AllocationDetails::FileHeader head;
  memcpy(head.ident, "RSAD", 4);
  head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);
  head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);
  head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);

  const size_t element_header_size = CalculateElementHeaderSize(alloc->element);
  assert((sizeof(AllocationDetails::FileHeader) + element_header_size) <
             UINT16_MAX &&
         "Element header too large");
  head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader) +
                                        element_header_size);

  // Write the file header
  size_t num_bytes = sizeof(AllocationDetails::FileHeader);
  LLDB_LOGF(log, "%s - writing File Header, 0x%" PRIx64 " bytes", __FUNCTION__,
            (uint64_t)num_bytes);

  Status err = file.get()->Write(&head, num_bytes);
  if (!err.Success()) {
    strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path);
    strm.EOL();
    return false;
  }

  // Create the headers describing the element type of the allocation.
  std::shared_ptr<uint8_t> element_header_buffer(
      new uint8_t[element_header_size]);
  if (element_header_buffer == nullptr) {
    strm.Printf("Internal Error: Couldn't allocate %" PRIu64
                " bytes on the heap",
                (uint64_t)element_header_size);
    strm.EOL();
    return false;
  }

  PopulateElementHeaders(element_header_buffer, 0, alloc->element);

  // Write headers for allocation element type to file
  num_bytes = element_header_size;
  LLDB_LOGF(log, "%s - writing element headers, 0x%" PRIx64 " bytes.",
            __FUNCTION__, (uint64_t)num_bytes);

  err = file.get()->Write(element_header_buffer.get(), num_bytes);
  if (!err.Success()) {
    strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path);
    strm.EOL();
    return false;
  }

  // Write allocation data to file
  num_bytes = static_cast<size_t>(*alloc->size.get());
  LLDB_LOGF(log, "%s - writing 0x%" PRIx64 " bytes", __FUNCTION__,
            (uint64_t)num_bytes);

  err = file.get()->Write(buffer.get(), num_bytes);
  if (!err.Success()) {
    strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path);
    strm.EOL();
    return false;
  }

  strm.Printf("Allocation written to file '%s'", path);
  strm.EOL();
  return true;
}

bool RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) {
  Log *log = GetLog(LLDBLog::Language);

  if (module_sp) {
    for (const auto &rs_module : m_rsmodules) {
      if (rs_module->m_module == module_sp) {
        // Check if the user has enabled automatically breaking on all RS
        // kernels.
        if (m_breakAllKernels)
          BreakOnModuleKernels(rs_module);

        return false;
      }
    }
    bool module_loaded = false;
    switch (GetModuleKind(module_sp)) {
    case eModuleKindKernelObj: {
      RSModuleDescriptorSP module_desc;
      module_desc = std::make_shared<RSModuleDescriptor>(module_sp);
      if (module_desc->ParseRSInfo()) {
        m_rsmodules.push_back(module_desc);
        module_desc->WarnIfVersionMismatch(GetProcess()
                                               ->GetTarget()
                                               .GetDebugger()
                                               .GetAsyncOutputStream()
                                               .get());
        module_loaded = true;
      }
      if (module_loaded) {
        FixupScriptDetails(module_desc);
      }
      break;
    }
    case eModuleKindDriver: {
      if (!m_libRSDriver) {
        m_libRSDriver = module_sp;
        LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver);
      }
      break;
    }
    case eModuleKindImpl: {
      if (!m_libRSCpuRef) {
        m_libRSCpuRef = module_sp;
        LoadRuntimeHooks(m_libRSCpuRef, RenderScriptRuntime::eModuleKindImpl);
      }
      break;
    }
    case eModuleKindLibRS: {
      if (!m_libRS) {
        m_libRS = module_sp;
        static ConstString gDbgPresentStr("gDebuggerPresent");
        const Symbol *debug_present = m_libRS->FindFirstSymbolWithNameAndType(
            gDbgPresentStr, eSymbolTypeData);
        if (debug_present) {
          Status err;
          uint32_t flag = 0x00000001U;
          Target &target = GetProcess()->GetTarget();
          addr_t addr = debug_present->GetLoadAddress(&target);
          GetProcess()->WriteMemory(addr, &flag, sizeof(flag), err);
          if (err.Success()) {
            LLDB_LOGF(log, "%s - debugger present flag set on debugee.",
                      __FUNCTION__);

            m_debuggerPresentFlagged = true;
          } else if (log) {
            LLDB_LOGF(log, "%s - error writing debugger present flags '%s' ",
                      __FUNCTION__, err.AsCString());
          }
        } else if (log) {
          LLDB_LOGF(
              log,
              "%s - error writing debugger present flags - symbol not found",
              __FUNCTION__);
        }
      }
      break;
    }
    default:
      break;
    }
    if (module_loaded)
      Update();
    return module_loaded;
  }
  return false;
}

void RenderScriptRuntime::Update() {
  if (m_rsmodules.size() > 0) {
    if (!m_initiated) {
      Initiate();
    }
  }
}

void RSModuleDescriptor::WarnIfVersionMismatch(lldb_private::Stream *s) const {
  if (!s)
    return;

  if (m_slang_version.empty() || m_bcc_version.empty()) {
    s->PutCString("WARNING: Unknown bcc or slang (llvm-rs-cc) version; debug "
                  "experience may be unreliable");
    s->EOL();
  } else if (m_slang_version != m_bcc_version) {
    s->Printf("WARNING: The debug info emitted by the slang frontend "
              "(llvm-rs-cc) used to build this module (%s) does not match the "
              "version of bcc used to generate the debug information (%s). "
              "This is an unsupported configuration and may result in a poor "
              "debugging experience; proceed with caution",
              m_slang_version.c_str(), m_bcc_version.c_str());
    s->EOL();
  }
}

bool RSModuleDescriptor::ParsePragmaCount(llvm::StringRef *lines,
                                          size_t n_lines) {
  // Skip the pragma prototype line
  ++lines;
  for (; n_lines--; ++lines) {
    const auto kv_pair = lines->split(" - ");
    m_pragmas[kv_pair.first.trim().str()] = kv_pair.second.trim().str();
  }
  return true;
}

bool RSModuleDescriptor::ParseExportReduceCount(llvm::StringRef *lines,
                                                size_t n_lines) {
  // The list of reduction kernels in the `.rs.info` symbol is of the form
  // "signature - accumulatordatasize - reduction_name - initializer_name -
  // accumulator_name - combiner_name - outconverter_name - halter_name" Where
  // a function is not explicitly named by the user, or is not generated by the
  // compiler, it is named "." so the dash separated list should always be 8
  // items long
  Log *log = GetLog(LLDBLog::Language);
  // Skip the exportReduceCount line
  ++lines;
  for (; n_lines--; ++lines) {
    llvm::SmallVector<llvm::StringRef, 8> spec;
    lines->split(spec, " - ");
    if (spec.size() != 8) {
      if (spec.size() < 8) {
        if (log)
          log->Error("Error parsing RenderScript reduction spec. wrong number "
                     "of fields");
        return false;
      } else if (log)
        log->Warning("Extraneous members in reduction spec: '%s'",
                     lines->str().c_str());
    }

    const auto sig_s = spec[0];
    uint32_t sig;
    if (sig_s.getAsInteger(10, sig)) {
      if (log)
        log->Error("Error parsing Renderscript reduction spec: invalid kernel "
                   "signature: '%s'",
                   sig_s.str().c_str());
      return false;
    }

    const auto accum_data_size_s = spec[1];
    uint32_t accum_data_size;
    if (accum_data_size_s.getAsInteger(10, accum_data_size)) {
      if (log)
        log->Error("Error parsing Renderscript reduction spec: invalid "
                   "accumulator data size %s",
                   accum_data_size_s.str().c_str());
      return false;
    }

    LLDB_LOGF(log, "Found RenderScript reduction '%s'", spec[2].str().c_str());

    m_reductions.push_back(RSReductionDescriptor(this, sig, accum_data_size,
                                                 spec[2], spec[3], spec[4],
                                                 spec[5], spec[6], spec[7]));
  }
  return true;
}

bool RSModuleDescriptor::ParseVersionInfo(llvm::StringRef *lines,
                                          size_t n_lines) {
  // Skip the versionInfo line
  ++lines;
  for (; n_lines--; ++lines) {
    // We're only interested in bcc and slang versions, and ignore all other
    // versionInfo lines
    const auto kv_pair = lines->split(" - ");
    if (kv_pair.first == "slang")
      m_slang_version = kv_pair.second.str();
    else if (kv_pair.first == "bcc")
      m_bcc_version = kv_pair.second.str();
  }
  return true;
}

bool RSModuleDescriptor::ParseExportForeachCount(llvm::StringRef *lines,
                                                 size_t n_lines) {
  // Skip the exportForeachCount line
  ++lines;
  for (; n_lines--; ++lines) {
    uint32_t slot;
    // `forEach` kernels are listed in the `.rs.info` packet as a "slot - name"
    // pair per line
    const auto kv_pair = lines->split(" - ");
    if (kv_pair.first.getAsInteger(10, slot))
      return false;
    m_kernels.push_back(RSKernelDescriptor(this, kv_pair.second, slot));
  }
  return true;
}

bool RSModuleDescriptor::ParseExportVarCount(llvm::StringRef *lines,
                                             size_t n_lines) {
  // Skip the ExportVarCount line
  ++lines;
  for (; n_lines--; ++lines)
    m_globals.push_back(RSGlobalDescriptor(this, *lines));
  return true;
}

// The .rs.info symbol in renderscript modules contains a string which needs to
// be parsed. The string is basic and is parsed on a line by line basis.
bool RSModuleDescriptor::ParseRSInfo() {
  assert(m_module);
  Log *log = GetLog(LLDBLog::Language);
  const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(
      ConstString(".rs.info"), eSymbolTypeData);
  if (!info_sym)
    return false;

  const addr_t addr = info_sym->GetAddressRef().GetFileAddress();
  if (addr == LLDB_INVALID_ADDRESS)
    return false;

  const addr_t size = info_sym->GetByteSize();
  const FileSpec fs = m_module->GetFileSpec();

  auto buffer =
      FileSystem::Instance().CreateDataBuffer(fs.GetPath(), size, addr);
  if (!buffer)
    return false;

  // split rs.info. contents into lines
  llvm::SmallVector<llvm::StringRef, 128> info_lines;
  {
    const llvm::StringRef raw_rs_info((const char *)buffer->GetBytes());
    raw_rs_info.split(info_lines, '\n');
    LLDB_LOGF(log, "'.rs.info symbol for '%s':\n%s",
              m_module->GetFileSpec().GetCString(), raw_rs_info.str().c_str());
  }

  enum {
    eExportVar,
    eExportForEach,
    eExportReduce,
    ePragma,
    eBuildChecksum,
    eObjectSlot,
    eVersionInfo,
  };

  const auto rs_info_handler = [](llvm::StringRef name) -> int {
    return llvm::StringSwitch<int>(name)
        // The number of visible global variables in the script
        .Case("exportVarCount", eExportVar)
        // The number of RenderScrip `forEach` kernels __attribute__((kernel))
        .Case("exportForEachCount", eExportForEach)
        // The number of generalreductions: This marked in the script by
        // `#pragma reduce()`
        .Case("exportReduceCount", eExportReduce)
        // Total count of all RenderScript specific `#pragmas` used in the
        // script
        .Case("pragmaCount", ePragma)
        .Case("objectSlotCount", eObjectSlot)
        .Case("versionInfo", eVersionInfo)
        .Default(-1);
  };

  // parse all text lines of .rs.info
  for (auto line = info_lines.begin(); line != info_lines.end(); ++line) {
    const auto kv_pair = line->split(": ");
    const auto key = kv_pair.first;
    const auto val = kv_pair.second.trim();

    const auto handler = rs_info_handler(key);
    if (handler == -1)
      continue;
    // getAsInteger returns `true` on an error condition - we're only
    // interested in numeric fields at the moment
    uint64_t n_lines;
    if (val.getAsInteger(10, n_lines)) {
      LLDB_LOGV(log, "Failed to parse non-numeric '.rs.info' section {0}",
                line->str());
      continue;
    }
    if (info_lines.end() - (line + 1) < (ptrdiff_t)n_lines)
      return false;

    bool success = false;
    switch (handler) {
    case eExportVar:
      success = ParseExportVarCount(line, n_lines);
      break;
    case eExportForEach:
      success = ParseExportForeachCount(line, n_lines);
      break;
    case eExportReduce:
      success = ParseExportReduceCount(line, n_lines);
      break;
    case ePragma:
      success = ParsePragmaCount(line, n_lines);
      break;
    case eVersionInfo:
      success = ParseVersionInfo(line, n_lines);
      break;
    default: {
      LLDB_LOGF(log, "%s - skipping .rs.info field '%s'", __FUNCTION__,
                line->str().c_str());
      continue;
    }
    }
    if (!success)
      return false;
    line += n_lines;
  }
  return info_lines.size() > 0;
}

void RenderScriptRuntime::DumpStatus(Stream &strm) const {
  if (m_libRS) {
    strm.Printf("Runtime Library discovered.");
    strm.EOL();
  }
  if (m_libRSDriver) {
    strm.Printf("Runtime Driver discovered.");
    strm.EOL();
  }
  if (m_libRSCpuRef) {
    strm.Printf("CPU Reference Implementation discovered.");
    strm.EOL();
  }

  if (m_runtimeHooks.size()) {
    strm.Printf("Runtime functions hooked:");
    strm.EOL();
    for (auto b : m_runtimeHooks) {
      strm.Indent(b.second->defn->name);
      strm.EOL();
    }
  } else {
    strm.Printf("Runtime is not hooked.");
    strm.EOL();
  }
}

void RenderScriptRuntime::DumpContexts(Stream &strm) const {
  strm.Printf("Inferred RenderScript Contexts:");
  strm.EOL();
  strm.IndentMore();

  std::map<addr_t, uint64_t> contextReferences;

  // Iterate over all of the currently discovered scripts. Note: We cant push
  // or pop from m_scripts inside this loop or it may invalidate script.
  for (const auto &script : m_scripts) {
    if (!script->context.isValid())
      continue;
    lldb::addr_t context = *script->context;

    if (contextReferences.find(context) != contextReferences.end()) {
      contextReferences[context]++;
    } else {
      contextReferences[context] = 1;
    }
  }

  for (const auto &cRef : contextReferences) {
    strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances",
                cRef.first, cRef.second);
    strm.EOL();
  }
  strm.IndentLess();
}

void RenderScriptRuntime::DumpKernels(Stream &strm) const {
  strm.Printf("RenderScript Kernels:");
  strm.EOL();
  strm.IndentMore();
  for (const auto &module : m_rsmodules) {
    strm.Printf("Resource '%s':", module->m_resname.c_str());
    strm.EOL();
    for (const auto &kernel : module->m_kernels) {
      strm.Indent(kernel.m_name.GetStringRef());
      strm.EOL();
    }
  }
  strm.IndentLess();
}

RenderScriptRuntime::AllocationDetails *
RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id) {
  AllocationDetails *alloc = nullptr;

  // See if we can find allocation using id as an index;
  if (alloc_id <= m_allocations.size() && alloc_id != 0 &&
      m_allocations[alloc_id - 1]->id == alloc_id) {
    alloc = m_allocations[alloc_id - 1].get();
    return alloc;
  }

  // Fallback to searching
  for (const auto &a : m_allocations) {
    if (a->id == alloc_id) {
      alloc = a.get();
      break;
    }
  }

  if (alloc == nullptr) {
    strm.Printf("Error: Couldn't find allocation with id matching %" PRIu32,
                alloc_id);
    strm.EOL();
  }

  return alloc;
}

// Prints the contents of an allocation to the output stream, which may be a
// file
bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr,
                                         const uint32_t id) {
  Log *log = GetLog(LLDBLog::Language);

  // Check we can find the desired allocation
  AllocationDetails *alloc = FindAllocByID(strm, id);
  if (!alloc)
    return false; // FindAllocByID() will print error message for us here

  LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64, __FUNCTION__,
            *alloc->address.get());

  // Check we have information about the allocation, if not calculate it
  if (alloc->ShouldRefresh()) {
    LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.",
              __FUNCTION__);

    // JIT all the allocation information
    if (!RefreshAllocation(alloc, frame_ptr)) {
      strm.Printf("Error: Couldn't JIT allocation details");
      strm.EOL();
      return false;
    }
  }

  // Establish format and size of each data element
  const uint32_t vec_size = *alloc->element.type_vec_size.get();
  const Element::DataType type = *alloc->element.type.get();

  assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT &&
         "Invalid allocation type");

  lldb::Format format;
  if (type >= Element::RS_TYPE_ELEMENT)
    format = eFormatHex;
  else
    format = vec_size == 1
                 ? static_cast<lldb::Format>(
                       AllocationDetails::RSTypeToFormat[type][eFormatSingle])
                 : static_cast<lldb::Format>(
                       AllocationDetails::RSTypeToFormat[type][eFormatVector]);

  const uint32_t data_size = *alloc->element.datum_size.get();

  LLDB_LOGF(log, "%s - element size %" PRIu32 " bytes, including padding",
            __FUNCTION__, data_size);

  // Allocate a buffer to copy data into
  std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
  if (!buffer) {
    strm.Printf("Error: Couldn't read allocation data");
    strm.EOL();
    return false;
  }

  // Calculate stride between rows as there may be padding at end of rows since
  // allocated memory is 16-byte aligned
  if (!alloc->stride.isValid()) {
    if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension
      alloc->stride = 0;
    else if (!JITAllocationStride(alloc, frame_ptr)) {
      strm.Printf("Error: Couldn't calculate allocation row stride");
      strm.EOL();
      return false;
    }
  }
  const uint32_t stride = *alloc->stride.get();
  const uint32_t size = *alloc->size.get(); // Size of whole allocation
  const uint32_t padding =
      alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0;
  LLDB_LOGF(log,
            "%s - stride %" PRIu32 " bytes, size %" PRIu32
            " bytes, padding %" PRIu32,
            __FUNCTION__, stride, size, padding);

  // Find dimensions used to index loops, so need to be non-zero
  uint32_t dim_x = alloc->dimension.get()->dim_1;
  dim_x = dim_x == 0 ? 1 : dim_x;

  uint32_t dim_y = alloc->dimension.get()->dim_2;
  dim_y = dim_y == 0 ? 1 : dim_y;

  uint32_t dim_z = alloc->dimension.get()->dim_3;
  dim_z = dim_z == 0 ? 1 : dim_z;

  // Use data extractor to format output
  const uint32_t target_ptr_size =
      GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
  DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(),
                           target_ptr_size);

  uint32_t offset = 0;   // Offset in buffer to next element to be printed
  uint32_t prev_row = 0; // Offset to the start of the previous row

  // Iterate over allocation dimensions, printing results to user
  strm.Printf("Data (X, Y, Z):");
  for (uint32_t z = 0; z < dim_z; ++z) {
    for (uint32_t y = 0; y < dim_y; ++y) {
      // Use stride to index start of next row.
      if (!(y == 0 && z == 0))
        offset = prev_row + stride;
      prev_row = offset;

      // Print each element in the row individually
      for (uint32_t x = 0; x < dim_x; ++x) {
        strm.Printf("\n(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ") = ", x, y, z);
        if ((type == Element::RS_TYPE_NONE) &&
            (alloc->element.children.size() > 0) &&
            (alloc->element.type_name != Element::GetFallbackStructName())) {
          // Here we are dumping an Element of struct type. This is done using
          // expression evaluation with the name of the struct type and pointer
          // to element. Don't print the name of the resulting expression,
          // since this will be '$[0-9]+'
          DumpValueObjectOptions expr_options;
          expr_options.SetHideName(true);

          // Setup expression as dereferencing a pointer cast to element
          // address.
          char expr_char_buffer[jit_max_expr_size];
          int written =
              snprintf(expr_char_buffer, jit_max_expr_size, "*(%s*) 0x%" PRIx64,
                       alloc->element.type_name.AsCString(),
                       *alloc->data_ptr.get() + offset);

          if (written < 0 || written >= jit_max_expr_size) {
            LLDB_LOGF(log, "%s - error in snprintf().", __FUNCTION__);
            continue;
          }

          // Evaluate expression
          ValueObjectSP expr_result;
          GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer,
                                                       frame_ptr, expr_result);

          // Print the results to our stream.
          expr_result->Dump(strm, expr_options);
        } else {
          DumpDataExtractor(alloc_data, &strm, offset, format,
                            data_size - padding, 1, 1, LLDB_INVALID_ADDRESS, 0,
                            0);
        }
        offset += data_size;
      }
    }
  }
  strm.EOL();

  return true;
}

// Function recalculates all our cached information about allocations by
// jitting the RS runtime regarding each allocation we know about. Returns true
// if all allocations could be recomputed, false otherwise.
bool RenderScriptRuntime::RecomputeAllAllocations(Stream &strm,
                                                  StackFrame *frame_ptr) {
  bool success = true;
  for (auto &alloc : m_allocations) {
    // JIT current allocation information
    if (!RefreshAllocation(alloc.get(), frame_ptr)) {
      strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32
                  "\n",
                  alloc->id);
      success = false;
    }
  }

  if (success)
    strm.Printf("All allocations successfully recomputed");
  strm.EOL();

  return success;
}

// Prints information regarding currently loaded allocations. These details are
// gathered by jitting the runtime, which has as latency. Index parameter
// specifies a single allocation ID to print, or a zero value to print them all
void RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame *frame_ptr,
                                          const uint32_t index) {
  strm.Printf("RenderScript Allocations:");
  strm.EOL();
  strm.IndentMore();

  for (auto &alloc : m_allocations) {
    // index will only be zero if we want to print all allocations
    if (index != 0 && index != alloc->id)
      continue;

    // JIT current allocation information
    if (alloc->ShouldRefresh() && !RefreshAllocation(alloc.get(), frame_ptr)) {
      strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32,
                  alloc->id);
      strm.EOL();
      continue;
    }

    strm.Printf("%" PRIu32 ":", alloc->id);
    strm.EOL();
    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("(%" PRId32 ", %" PRId32 ", %" PRId32 ")\n",
                  alloc->dimension.get()->dim_1, alloc->dimension.get()->dim_2,
                  alloc->dimension.get()->dim_3);

    strm.Indent("Data Type: ");
    if (!alloc->element.type.isValid() ||
        !alloc->element.type_vec_size.isValid())
      strm.Printf("unknown\n");
    else {
      const int vector_size = *alloc->element.type_vec_size.get();
      Element::DataType type = *alloc->element.type.get();

      if (!alloc->element.type_name.IsEmpty())
        strm.Printf("%s\n", alloc->element.type_name.AsCString());
      else {
        // Enum value isn't monotonous, so doesn't always index
        // RsDataTypeToString array
        if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT)
          type =
              static_cast<Element::DataType>((type - Element::RS_TYPE_ELEMENT) +
                                             Element::RS_TYPE_MATRIX_2X2 + 1);

        if (type >= (sizeof(AllocationDetails::RsDataTypeToString) /
                     sizeof(AllocationDetails::RsDataTypeToString[0])) ||
            vector_size > 4 || vector_size < 1)
          strm.Printf("invalid type\n");
        else
          strm.Printf(
              "%s\n",
              AllocationDetails::RsDataTypeToString[static_cast<uint32_t>(type)]
                                                   [vector_size - 1]);
      }
    }

    strm.Indent("Data Kind: ");
    if (!alloc->element.type_kind.isValid())
      strm.Printf("unknown\n");
    else {
      const Element::DataKind kind = *alloc->element.type_kind.get();
      if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV)
        strm.Printf("invalid kind\n");
      else
        strm.Printf(
            "%s\n",
            AllocationDetails::RsDataKindToString[static_cast<uint32_t>(kind)]);
    }

    strm.EOL();
    strm.IndentLess();
  }
  strm.IndentLess();
}

// Set breakpoints on every kernel found in RS module
void RenderScriptRuntime::BreakOnModuleKernels(
    const RSModuleDescriptorSP rsmodule_sp) {
  for (const auto &kernel : rsmodule_sp->m_kernels) {
    // Don't set breakpoint on 'root' kernel
    if (strcmp(kernel.m_name.AsCString(), "root") == 0)
      continue;

    CreateKernelBreakpoint(kernel.m_name);
  }
}

// Method is internally called by the 'kernel breakpoint all' command to enable
// or disable breaking on all kernels. When do_break is true we want to enable
// this functionality. When do_break is false we want to disable it.
void RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) {
  Log *log = GetLog(LLDBLog::Language | LLDBLog::Breakpoints);

  InitSearchFilter(target);

  // Set breakpoints on all the kernels
  if (do_break && !m_breakAllKernels) {
    m_breakAllKernels = true;

    for (const auto &module : m_rsmodules)
      BreakOnModuleKernels(module);

    LLDB_LOGF(log,
              "%s(True) - breakpoints set on all currently loaded kernels.",
              __FUNCTION__);
  } else if (!do_break &&
             m_breakAllKernels) // Breakpoints won't be set on any new kernels.
  {
    m_breakAllKernels = false;

    LLDB_LOGF(log, "%s(False) - breakpoints no longer automatically set.",
              __FUNCTION__);
  }
}

// Given the name of a kernel this function creates a breakpoint using our own
// breakpoint resolver, and returns the Breakpoint shared pointer.
BreakpointSP
RenderScriptRuntime::CreateKernelBreakpoint(ConstString name) {
  Log *log = GetLog(LLDBLog::Language | LLDBLog::Breakpoints);

  if (!m_filtersp) {
    LLDB_LOGF(log, "%s - error, no breakpoint search filter set.",
              __FUNCTION__);
    return nullptr;
  }

  BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
  Target &target = GetProcess()->GetTarget();
  BreakpointSP bp = target.CreateBreakpoint(
      m_filtersp, resolver_sp, false, false, false);

  // Give RS breakpoints a specific name, so the user can manipulate them as a
  // group.
  Status err;
  target.AddNameToBreakpoint(bp, "RenderScriptKernel", err);
  if (err.Fail() && log)
    LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__,
              err.AsCString());

  return bp;
}

BreakpointSP
RenderScriptRuntime::CreateReductionBreakpoint(ConstString name,
                                               int kernel_types) {
  Log *log = GetLog(LLDBLog::Language | LLDBLog::Breakpoints);

  if (!m_filtersp) {
    LLDB_LOGF(log, "%s - error, no breakpoint search filter set.",
              __FUNCTION__);
    return nullptr;
  }

  BreakpointResolverSP resolver_sp(new RSReduceBreakpointResolver(
      nullptr, name, &m_rsmodules, kernel_types));
  Target &target = GetProcess()->GetTarget();
  BreakpointSP bp = target.CreateBreakpoint(
      m_filtersp, resolver_sp, false, false, false);

  // Give RS breakpoints a specific name, so the user can manipulate them as a
  // group.
  Status err;
  target.AddNameToBreakpoint(bp, "RenderScriptReduction", err);
  if (err.Fail() && log)
    LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__,
              err.AsCString());

  return bp;
}

// Given an expression for a variable this function tries to calculate the
// variable's value. If this is possible it returns true and sets the uint64_t
// parameter to the variables unsigned value. Otherwise function returns false.
bool RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp,
                                                const char *var_name,
                                                uint64_t &val) {
  Log *log = GetLog(LLDBLog::Language);
  Status err;
  VariableSP var_sp;

  // Find variable in stack frame
  ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath(
      var_name, eNoDynamicValues,
      StackFrame::eExpressionPathOptionCheckPtrVsMember |
          StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
      var_sp, err));
  if (!err.Success()) {
    LLDB_LOGF(log, "%s - error, couldn't find '%s' in frame", __FUNCTION__,
              var_name);
    return false;
  }

  // Find the uint32_t value for the variable
  bool success = false;
  val = value_sp->GetValueAsUnsigned(0, &success);
  if (!success) {
    LLDB_LOGF(log, "%s - error, couldn't parse '%s' as an uint32_t.",
              __FUNCTION__, var_name);
    return false;
  }

  return true;
}

// Function attempts to find the current coordinate of a kernel invocation by
// investigating the values of frame variables in the .expand function. These
// coordinates are returned via the coord array reference parameter. Returns
// true if the coordinates could be found, and false otherwise.
bool RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord,
                                              Thread *thread_ptr) {
  static const char *const x_expr = "rsIndex";
  static const char *const y_expr = "p->current.y";
  static const char *const z_expr = "p->current.z";

  Log *log = GetLog(LLDBLog::Language);

  if (!thread_ptr) {
    LLDB_LOGF(log, "%s - Error, No thread pointer", __FUNCTION__);

    return false;
  }

  // Walk the call stack looking for a function whose name has the suffix
  // '.expand' and contains the variables we're looking for.
  for (uint32_t i = 0; i < thread_ptr->GetStackFrameCount(); ++i) {
    if (!thread_ptr->SetSelectedFrameByIndex(i))
      continue;

    StackFrameSP frame_sp = thread_ptr->GetSelectedFrame();
    if (!frame_sp)
      continue;

    // Find the function name
    const SymbolContext sym_ctx =
        frame_sp->GetSymbolContext(eSymbolContextFunction);
    const ConstString func_name = sym_ctx.GetFunctionName();
    if (!func_name)
      continue;

    LLDB_LOGF(log, "%s - Inspecting function '%s'", __FUNCTION__,
              func_name.GetCString());

    // Check if function name has .expand suffix
    if (!func_name.GetStringRef().endswith(".expand"))
      continue;

    LLDB_LOGF(log, "%s - Found .expand function '%s'", __FUNCTION__,
              func_name.GetCString());

    // Get values for variables in .expand frame that tell us the current
    // kernel invocation
    uint64_t x, y, z;
    bool found = GetFrameVarAsUnsigned(frame_sp, x_expr, x) &&
                 GetFrameVarAsUnsigned(frame_sp, y_expr, y) &&
                 GetFrameVarAsUnsigned(frame_sp, z_expr, z);

    if (found) {
      // The RenderScript runtime uses uint32_t for these vars. If they're not
      // within bounds, our frame parsing is garbage
      assert(x <= UINT32_MAX && y <= UINT32_MAX && z <= UINT32_MAX);
      coord.x = (uint32_t)x;
      coord.y = (uint32_t)y;
      coord.z = (uint32_t)z;
      return true;
    }
  }
  return false;
}

// Callback when a kernel breakpoint hits and we're looking for a specific
// coordinate. Baton parameter contains a pointer to the target coordinate we
// want to break on. Function then checks the .expand frame for the current
// coordinate and breaks to user if it matches. Parameter 'break_id' is the id
// of the Breakpoint which made the callback. Parameter 'break_loc_id' is the
// id for the BreakpointLocation which was hit, a single logical breakpoint can
// have multiple addresses.
bool RenderScriptRuntime::KernelBreakpointHit(void *baton,
                                              StoppointCallbackContext *ctx,
                                              user_id_t break_id,
                                              user_id_t break_loc_id) {
  Log *log = GetLog(LLDBLog::Language | LLDBLog::Breakpoints);

  assert(baton &&
         "Error: null baton in conditional kernel breakpoint callback");

  // Coordinate we want to stop on
  RSCoordinate target_coord = *static_cast<RSCoordinate *>(baton);

  LLDB_LOGF(log, "%s - Break ID %" PRIu64 ", " FMT_COORD, __FUNCTION__,
            break_id, target_coord.x, target_coord.y, target_coord.z);

  // Select current thread
  ExecutionContext context(ctx->exe_ctx_ref);
  Thread *thread_ptr = context.GetThreadPtr();
  assert(thread_ptr && "Null thread pointer");

  // Find current kernel invocation from .expand frame variables
  RSCoordinate current_coord{};
  if (!GetKernelCoordinate(current_coord, thread_ptr)) {
    LLDB_LOGF(log, "%s - Error, couldn't select .expand stack frame",
              __FUNCTION__);
    return false;
  }

  LLDB_LOGF(log, "%s - " FMT_COORD, __FUNCTION__, current_coord.x,
            current_coord.y, current_coord.z);

  // Check if the current kernel invocation coordinate matches our target
  // coordinate
  if (target_coord == current_coord) {
    LLDB_LOGF(log, "%s, BREAKING " FMT_COORD, __FUNCTION__, current_coord.x,
              current_coord.y, current_coord.z);

    BreakpointSP breakpoint_sp =
        context.GetTargetPtr()->GetBreakpointByID(break_id);
    assert(breakpoint_sp != nullptr &&
           "Error: Couldn't find breakpoint matching break id for callback");
    breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint
                                      // should only be hit once.
    return true;
  }

  // No match on coordinate
  return false;
}

void RenderScriptRuntime::SetConditional(BreakpointSP bp, Stream &messages,
                                         const RSCoordinate &coord) {
  messages.Printf("Conditional kernel breakpoint on coordinate " FMT_COORD,
                  coord.x, coord.y, coord.z);
  messages.EOL();

  // Allocate memory for the baton, and copy over coordinate
  RSCoordinate *baton = new RSCoordinate(coord);

  // Create a callback that will be invoked every time the breakpoint is hit.
  // The baton object passed to the handler is the target coordinate we want to
  // break on.
  bp->SetCallback(KernelBreakpointHit, baton, true);

  // Store a shared pointer to the baton, so the memory will eventually be
  // cleaned up after destruction
  m_conditional_breaks[bp->GetID()] = std::unique_ptr<RSCoordinate>(baton);
}

// Tries to set a breakpoint on the start of a kernel, resolved using the
// kernel name. Argument 'coords', represents a three dimensional coordinate
// which can be used to specify a single kernel instance to break on. If this
// is set then we add a callback to the breakpoint.
bool RenderScriptRuntime::PlaceBreakpointOnKernel(TargetSP target,
                                                  Stream &messages,
                                                  const char *name,
                                                  const RSCoordinate *coord) {
  if (!name)
    return false;

  InitSearchFilter(target);

  ConstString kernel_name(name);
  BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
  if (!bp)
    return false;

  // We have a conditional breakpoint on a specific coordinate
  if (coord)
    SetConditional(bp, messages, *coord);

  bp->GetDescription(&messages, lldb::eDescriptionLevelInitial, false);

  return true;
}

BreakpointSP
RenderScriptRuntime::CreateScriptGroupBreakpoint(ConstString name,
                                                 bool stop_on_all) {
  Log *log = GetLog(LLDBLog::Language | LLDBLog::Breakpoints);

  if (!m_filtersp) {
    LLDB_LOGF(log, "%s - error, no breakpoint search filter set.",
              __FUNCTION__);
    return nullptr;
  }

  BreakpointResolverSP resolver_sp(new RSScriptGroupBreakpointResolver(
      nullptr, name, m_scriptGroups, stop_on_all));
  Target &target = GetProcess()->GetTarget();
  BreakpointSP bp = target.CreateBreakpoint(
      m_filtersp, resolver_sp, false, false, false);
  // Give RS breakpoints a specific name, so the user can manipulate them as a
  // group.
  Status err;
  target.AddNameToBreakpoint(bp, name.GetCString(), err);
  if (err.Fail() && log)
    LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__,
              err.AsCString());
  // ask the breakpoint to resolve itself
  bp->ResolveBreakpoint();
  return bp;
}

bool RenderScriptRuntime::PlaceBreakpointOnScriptGroup(TargetSP target,
                                                       Stream &strm,
                                                       ConstString name,
                                                       bool multi) {
  InitSearchFilter(target);
  BreakpointSP bp = CreateScriptGroupBreakpoint(name, multi);
  if (bp)
    bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
  return bool(bp);
}

bool RenderScriptRuntime::PlaceBreakpointOnReduction(TargetSP target,
                                                     Stream &messages,
                                                     const char *reduce_name,
                                                     const RSCoordinate *coord,
                                                     int kernel_types) {
  if (!reduce_name)
    return false;

  InitSearchFilter(target);
  BreakpointSP bp =
      CreateReductionBreakpoint(ConstString(reduce_name), kernel_types);
  if (!bp)
    return false;

  if (coord)
    SetConditional(bp, messages, *coord);

  bp->GetDescription(&messages, lldb::eDescriptionLevelInitial, false);

  return true;
}

void RenderScriptRuntime::DumpModules(Stream &strm) const {
  strm.Printf("RenderScript Modules:");
  strm.EOL();
  strm.IndentMore();
  for (const auto &module : m_rsmodules) {
    module->Dump(strm);
  }
  strm.IndentLess();
}

RenderScriptRuntime::ScriptDetails *
RenderScriptRuntime::LookUpScript(addr_t address, bool create) {
  for (const auto &s : m_scripts) {
    if (s->script.isValid())
      if (*s->script == address)
        return s.get();
  }
  if (create) {
    std::unique_ptr<ScriptDetails> s(new ScriptDetails);
    s->script = address;
    m_scripts.push_back(std::move(s));
    return m_scripts.back().get();
  }
  return nullptr;
}

RenderScriptRuntime::AllocationDetails *
RenderScriptRuntime::LookUpAllocation(addr_t address) {
  for (const auto &a : m_allocations) {
    if (a->address.isValid())
      if (*a->address == address)
        return a.get();
  }
  return nullptr;
}

RenderScriptRuntime::AllocationDetails *
RenderScriptRuntime::CreateAllocation(addr_t address) {
  Log *log = GetLog(LLDBLog::Language);

  // Remove any previous allocation which contains the same address
  auto it = m_allocations.begin();
  while (it != m_allocations.end()) {
    if (*((*it)->address) == address) {
      LLDB_LOGF(log, "%s - Removing allocation id: %d, address: 0x%" PRIx64,
                __FUNCTION__, (*it)->id, address);

      it = m_allocations.erase(it);
    } else {
      it++;
    }
  }

  std::unique_ptr<AllocationDetails> a(new AllocationDetails);
  a->address = address;
  m_allocations.push_back(std::move(a));
  return m_allocations.back().get();
}

bool RenderScriptRuntime::ResolveKernelName(lldb::addr_t kernel_addr,
                                            ConstString &name) {
  Log *log = GetLog(LLDBLog::Symbols);

  Target &target = GetProcess()->GetTarget();
  Address resolved;
  // RenderScript module
  if (!target.GetSectionLoadList().ResolveLoadAddress(kernel_addr, resolved)) {
    LLDB_LOGF(log, "%s: unable to resolve 0x%" PRIx64 " to a loaded symbol",
              __FUNCTION__, kernel_addr);
    return false;
  }

  Symbol *sym = resolved.CalculateSymbolContextSymbol();
  if (!sym)
    return false;

  name = sym->GetName();
  assert(IsRenderScriptModule(resolved.CalculateSymbolContextModule()));
  LLDB_LOGF(log, "%s: 0x%" PRIx64 " resolved to the symbol '%s'", __FUNCTION__,
            kernel_addr, name.GetCString());
  return true;
}

void RSModuleDescriptor::Dump(Stream &strm) const {
  int indent = strm.GetIndentLevel();

  strm.Indent();
  m_module->GetFileSpec().Dump(strm.AsRawOstream());
  strm.Indent(m_module->GetNumCompileUnits() ? "Debug info loaded."
                                             : "Debug info does not exist.");
  strm.EOL();
  strm.IndentMore();

  strm.Indent();
  strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
  strm.EOL();
  strm.IndentMore();
  for (const auto &global : m_globals) {
    global.Dump(strm);
  }
  strm.IndentLess();

  strm.Indent();
  strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
  strm.EOL();
  strm.IndentMore();
  for (const auto &kernel : m_kernels) {
    kernel.Dump(strm);
  }
  strm.IndentLess();

  strm.Indent();
  strm.Printf("Pragmas: %" PRIu64, static_cast<uint64_t>(m_pragmas.size()));
  strm.EOL();
  strm.IndentMore();
  for (const auto &key_val : m_pragmas) {
    strm.Indent();
    strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
    strm.EOL();
  }
  strm.IndentLess();

  strm.Indent();
  strm.Printf("Reductions: %" PRIu64,
              static_cast<uint64_t>(m_reductions.size()));
  strm.EOL();
  strm.IndentMore();
  for (const auto &reduction : m_reductions) {
    reduction.Dump(strm);
  }

  strm.SetIndentLevel(indent);
}

void RSGlobalDescriptor::Dump(Stream &strm) const {
  strm.Indent(m_name.GetStringRef());
  VariableList var_list;
  m_module->m_module->FindGlobalVariables(m_name, CompilerDeclContext(), 1U,
                                          var_list);
  if (var_list.GetSize() == 1) {
    auto var = var_list.GetVariableAtIndex(0);
    auto type = var->GetType();
    if (type) {
      strm.Printf(" - ");
      type->DumpTypeName(&strm);
    } else {
      strm.Printf(" - Unknown Type");
    }
  } else {
    strm.Printf(" - variable identified, but not found in binary");
    const Symbol *s = m_module->m_module->FindFirstSymbolWithNameAndType(
        m_name, eSymbolTypeData);
    if (s) {
      strm.Printf(" (symbol exists) ");
    }
  }

  strm.EOL();
}

void RSKernelDescriptor::Dump(Stream &strm) const {
  strm.Indent(m_name.GetStringRef());
  strm.EOL();
}

void RSReductionDescriptor::Dump(lldb_private::Stream &stream) const {
  stream.Indent(m_reduce_name.GetStringRef());
  stream.IndentMore();
  stream.EOL();
  stream.Indent();
  stream.Printf("accumulator: %s", m_accum_name.AsCString());
  stream.EOL();
  stream.Indent();
  stream.Printf("initializer: %s", m_init_name.AsCString());
  stream.EOL();
  stream.Indent();
  stream.Printf("combiner: %s", m_comb_name.AsCString());
  stream.EOL();
  stream.Indent();
  stream.Printf("outconverter: %s", m_outc_name.AsCString());
  stream.EOL();
  // XXX This is currently unspecified by RenderScript, and unused
  // stream.Indent();
  // stream.Printf("halter: '%s'", m_init_name.AsCString());
  // stream.EOL();
  stream.IndentLess();
}

class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "renderscript module dump",
            "Dumps renderscript specific information for all modules.",
            "renderscript module dump",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}

  ~CommandObjectRenderScriptRuntimeModuleDump() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));
    runtime->DumpModules(result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }
};

class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "renderscript module",
                               "Commands that deal with RenderScript modules.",
                               nullptr) {
    LoadSubCommand(
        "dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(
                    interpreter)));
  }

  ~CommandObjectRenderScriptRuntimeModule() override = default;
};

class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "renderscript kernel list",
            "Lists renderscript kernel names and associated script resources.",
            "renderscript kernel list",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}

  ~CommandObjectRenderScriptRuntimeKernelList() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));
    runtime->DumpKernels(result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }
};

static constexpr OptionDefinition g_renderscript_reduction_bp_set_options[] = {
    {LLDB_OPT_SET_1, false, "function-role", 't',
     OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner,
     "Break on a comma separated set of reduction kernel types "
     "(accumulator,outcoverter,combiner,initializer"},
    {LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument,
     nullptr, {}, 0, eArgTypeValue,
     "Set a breakpoint on a single invocation of the kernel with specified "
     "coordinate.\n"
     "Coordinate takes the form 'x[,y][,z] where x,y,z are positive "
     "integers representing kernel dimensions. "
     "Any unset dimensions will be defaulted to zero."}};

class CommandObjectRenderScriptRuntimeReductionBreakpointSet
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeReductionBreakpointSet(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "renderscript reduction breakpoint set",
            "Set a breakpoint on named RenderScript general reductions",
            "renderscript reduction breakpoint set  <kernel_name> [-t "
            "<reduction_kernel_type,...>]",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched |
                eCommandProcessMustBePaused),
        m_options() {
    CommandArgumentData name_arg{eArgTypeName, eArgRepeatPlain};
    m_arguments.push_back({name_arg});
  };

  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *exe_ctx) override {
      Status err;
      StreamString err_str;
      const int short_option = m_getopt_table[option_idx].val;
      switch (short_option) {
      case 't':
        if (!ParseReductionTypes(option_arg, err_str))
          err.SetErrorStringWithFormat(
              "Unable to deduce reduction types for %s: %s",
              option_arg.str().c_str(), err_str.GetData());
        break;
      case 'c': {
        auto coord = RSCoordinate{};
        if (!ParseCoordinate(option_arg, coord))
          err.SetErrorStringWithFormat("unable to parse coordinate for %s",
                                       option_arg.str().c_str());
        else {
          m_have_coord = true;
          m_coord = coord;
        }
        break;
      }
      default:
        err.SetErrorStringWithFormat("Invalid option '-%c'", short_option);
      }
      return err;
    }

    void OptionParsingStarting(ExecutionContext *exe_ctx) override {
      m_have_coord = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_renderscript_reduction_bp_set_options);
    }

    bool ParseReductionTypes(llvm::StringRef option_val,
                             StreamString &err_str) {
      m_kernel_types = RSReduceBreakpointResolver::eKernelTypeNone;
      const auto reduce_name_to_type = [](llvm::StringRef name) -> int {
        return llvm::StringSwitch<int>(name)
            .Case("accumulator", RSReduceBreakpointResolver::eKernelTypeAccum)
            .Case("initializer", RSReduceBreakpointResolver::eKernelTypeInit)
            .Case("outconverter", RSReduceBreakpointResolver::eKernelTypeOutC)
            .Case("combiner", RSReduceBreakpointResolver::eKernelTypeComb)
            .Case("all", RSReduceBreakpointResolver::eKernelTypeAll)
            // Currently not exposed by the runtime
            // .Case("halter", RSReduceBreakpointResolver::eKernelTypeHalter)
            .Default(0);
      };

      // Matching a comma separated list of known words is fairly
      // straightforward with PCRE, but we're using ERE, so we end up with a
      // little ugliness...
      RegularExpression match_type_list(
          llvm::StringRef("^([[:alpha:]]+)(,[[:alpha:]]+){0,4}$"));

      assert(match_type_list.IsValid());

      if (!match_type_list.Execute(option_val)) {
        err_str.PutCString(
            "a comma-separated list of kernel types is required");
        return false;
      }

      // splitting on commas is much easier with llvm::StringRef than regex
      llvm::SmallVector<llvm::StringRef, 5> type_names;
      llvm::StringRef(option_val).split(type_names, ',');

      for (const auto &name : type_names) {
        const int type = reduce_name_to_type(name);
        if (!type) {
          err_str.Printf("unknown kernel type name %s", name.str().c_str());
          return false;
        }
        m_kernel_types |= type;
      }

      return true;
    }

    int m_kernel_types = RSReduceBreakpointResolver::eKernelTypeAll;
    llvm::StringRef m_reduce_name;
    RSCoordinate m_coord;
    bool m_have_coord = false;
  };

  Options *GetOptions() override { return &m_options; }

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc < 1) {
      result.AppendErrorWithFormat("'%s' takes 1 argument of reduction name, "
                                   "and an optional kernel type list",
                                   m_cmd_name.c_str());
      return false;
    }

    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));

    auto &outstream = result.GetOutputStream();
    auto name = command.GetArgumentAtIndex(0);
    auto &target = m_exe_ctx.GetTargetSP();
    auto coord = m_options.m_have_coord ? &m_options.m_coord : nullptr;
    if (!runtime->PlaceBreakpointOnReduction(target, outstream, name, coord,
                                             m_options.m_kernel_types)) {
      result.AppendError("Error: unable to place breakpoint on reduction");
      return false;
    }
    result.AppendMessage("Breakpoint(s) created");
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }

private:
  CommandOptions m_options;
};

static constexpr OptionDefinition g_renderscript_kernel_bp_set_options[] = {
    {LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument,
     nullptr, {}, 0, eArgTypeValue,
     "Set a breakpoint on a single invocation of the kernel with specified "
     "coordinate.\n"
     "Coordinate takes the form 'x[,y][,z] where x,y,z are positive "
     "integers representing kernel dimensions. "
     "Any unset dimensions will be defaulted to zero."}};

class CommandObjectRenderScriptRuntimeKernelBreakpointSet
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeKernelBreakpointSet(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "renderscript kernel breakpoint set",
            "Sets a breakpoint on a renderscript kernel.",
            "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched |
                eCommandProcessMustBePaused),
        m_options() {
    CommandArgumentData name_arg{eArgTypeName, eArgRepeatPlain};
    m_arguments.push_back({name_arg});
  }

  ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default;

  Options *GetOptions() override { return &m_options; }

  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *exe_ctx) override {
      Status err;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'c': {
        auto coord = RSCoordinate{};
        if (!ParseCoordinate(option_arg, coord))
          err.SetErrorStringWithFormat(
              "Couldn't parse coordinate '%s', should be in format 'x,y,z'.",
              option_arg.str().c_str());
        else {
          m_have_coord = true;
          m_coord = coord;
        }
        break;
      }
      default:
        err.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
        break;
      }
      return err;
    }

    void OptionParsingStarting(ExecutionContext *exe_ctx) override {
      m_have_coord = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_renderscript_kernel_bp_set_options);
    }

    RSCoordinate m_coord;
    bool m_have_coord = false;
  };

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc < 1) {
      result.AppendErrorWithFormat(
          "'%s' takes 1 argument of kernel name, and an optional coordinate.",
          m_cmd_name.c_str());
      return false;
    }

    RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));

    auto &outstream = result.GetOutputStream();
    auto &target = m_exe_ctx.GetTargetSP();
    auto name = command.GetArgumentAtIndex(0);
    auto coord = m_options.m_have_coord ? &m_options.m_coord : nullptr;
    if (!runtime->PlaceBreakpointOnKernel(target, outstream, name, coord)) {
      result.AppendErrorWithFormat(
          "Error: unable to set breakpoint on kernel '%s'", name);
      return false;
    }

    result.AppendMessage("Breakpoint(s) created");
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }

private:
  CommandOptions m_options;
};

class CommandObjectRenderScriptRuntimeKernelBreakpointAll
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeKernelBreakpointAll(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "renderscript kernel breakpoint all",
            "Automatically sets a breakpoint on all renderscript kernels that "
            "are or will be loaded.\n"
            "Disabling option means breakpoints will no longer be set on any "
            "kernels loaded in the future, "
            "but does not remove currently set breakpoints.",
            "renderscript kernel breakpoint all <enable/disable>",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched |
                eCommandProcessMustBePaused) {
    CommandArgumentData enable_arg{eArgTypeNone, eArgRepeatPlain};
    m_arguments.push_back({enable_arg});
  }

  ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc != 1) {
      result.AppendErrorWithFormat(
          "'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
      return false;
    }

    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));

    bool do_break = false;
    const char *argument = command.GetArgumentAtIndex(0);
    if (strcmp(argument, "enable") == 0) {
      do_break = true;
      result.AppendMessage("Breakpoints will be set on all kernels.");
    } else if (strcmp(argument, "disable") == 0) {
      do_break = false;
      result.AppendMessage("Breakpoints will not be set on any new kernels.");
    } else {
      result.AppendErrorWithFormat(
          "Argument must be either 'enable' or 'disable'");
      return false;
    }

    runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());

    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }
};

class CommandObjectRenderScriptRuntimeReductionBreakpoint
    : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntimeReductionBreakpoint(
      CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "renderscript reduction breakpoint",
                               "Commands that manipulate breakpoints on "
                               "renderscript general reductions.",
                               nullptr) {
    LoadSubCommand(
        "set", CommandObjectSP(
                   new CommandObjectRenderScriptRuntimeReductionBreakpointSet(
                       interpreter)));
  }

  ~CommandObjectRenderScriptRuntimeReductionBreakpoint() override = default;
};

class CommandObjectRenderScriptRuntimeKernelCoordinate
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeKernelCoordinate(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "renderscript kernel coordinate",
            "Shows the (x,y,z) coordinate of the current kernel invocation.",
            "renderscript kernel coordinate",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched |
                eCommandProcessMustBePaused) {}

  ~CommandObjectRenderScriptRuntimeKernelCoordinate() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    RSCoordinate coord{};
    bool success = RenderScriptRuntime::GetKernelCoordinate(
        coord, m_exe_ctx.GetThreadPtr());
    Stream &stream = result.GetOutputStream();

    if (success) {
      stream.Printf("Coordinate: " FMT_COORD, coord.x, coord.y, coord.z);
      stream.EOL();
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      stream.Printf("Error: Coordinate could not be found.");
      stream.EOL();
      result.SetStatus(eReturnStatusFailed);
    }
    return true;
  }
};

class CommandObjectRenderScriptRuntimeKernelBreakpoint
    : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntimeKernelBreakpoint(
      CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "renderscript kernel",
            "Commands that generate breakpoints on renderscript kernels.",
            nullptr) {
    LoadSubCommand(
        "set",
        CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(
            interpreter)));
    LoadSubCommand(
        "all",
        CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(
            interpreter)));
  }

  ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default;
};

class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "renderscript kernel",
                               "Commands that deal with RenderScript kernels.",
                               nullptr) {
    LoadSubCommand(
        "list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(
                    interpreter)));
    LoadSubCommand(
        "coordinate",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeKernelCoordinate(interpreter)));
    LoadSubCommand(
        "breakpoint",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
  }

  ~CommandObjectRenderScriptRuntimeKernel() override = default;
};

class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "renderscript context dump",
                            "Dumps renderscript context information.",
                            "renderscript context dump",
                            eCommandRequiresProcess |
                                eCommandProcessMustBeLaunched) {}

  ~CommandObjectRenderScriptRuntimeContextDump() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));
    runtime->DumpContexts(result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }
};

static constexpr OptionDefinition g_renderscript_runtime_alloc_dump_options[] = {
    {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument,
     nullptr, {}, 0, eArgTypeFilename,
     "Print results to specified file instead of command line."}};

class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "renderscript context",
                               "Commands that deal with RenderScript contexts.",
                               nullptr) {
    LoadSubCommand(
        "dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(
                    interpreter)));
  }

  ~CommandObjectRenderScriptRuntimeContext() override = default;
};

class CommandObjectRenderScriptRuntimeAllocationDump
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeAllocationDump(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "renderscript allocation dump",
                            "Displays the contents of a particular allocation",
                            "renderscript allocation dump <ID>",
                            eCommandRequiresProcess |
                                eCommandProcessMustBeLaunched),
        m_options() {
    CommandArgumentData id_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
    m_arguments.push_back({id_arg});
  }

  ~CommandObjectRenderScriptRuntimeAllocationDump() override = default;

  Options *GetOptions() override { return &m_options; }

  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *exe_ctx) override {
      Status err;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'f':
        m_outfile.SetFile(option_arg, FileSpec::Style::native);
        FileSystem::Instance().Resolve(m_outfile);
        if (FileSystem::Instance().Exists(m_outfile)) {
          m_outfile.Clear();
          err.SetErrorStringWithFormat("file already exists: '%s'",
                                       option_arg.str().c_str());
        }
        break;
      default:
        err.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
        break;
      }
      return err;
    }

    void OptionParsingStarting(ExecutionContext *exe_ctx) override {
      m_outfile.Clear();
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_renderscript_runtime_alloc_dump_options);
    }

    FileSpec m_outfile;
  };

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc < 1) {
      result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. "
                                   "As well as an optional -f argument",
                                   m_cmd_name.c_str());
      return false;
    }

    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));

    const char *id_cstr = command.GetArgumentAtIndex(0);
    uint32_t id;
    if (!llvm::to_integer(id_cstr, id)) {
      result.AppendErrorWithFormat("invalid allocation id argument '%s'",
                                   id_cstr);
      return false;
    }

    Stream *output_stream_p = nullptr;
    std::unique_ptr<Stream> output_stream_storage;

    const FileSpec &outfile_spec =
        m_options.m_outfile; // Dump allocation to file instead
    if (outfile_spec) {
      // Open output file
      std::string path = outfile_spec.GetPath();
      auto file = FileSystem::Instance().Open(outfile_spec,
                                              File::eOpenOptionWriteOnly |
                                                  File::eOpenOptionCanCreate);
      if (file) {
        output_stream_storage =
            std::make_unique<StreamFile>(std::move(file.get()));
        output_stream_p = output_stream_storage.get();
        result.GetOutputStream().Printf("Results written to '%s'",
                                        path.c_str());
        result.GetOutputStream().EOL();
      } else {
        std::string error = llvm::toString(file.takeError());
        result.AppendErrorWithFormat("Couldn't open file '%s': %s",
                                     path.c_str(), error.c_str());
        return false;
      }
    } else
      output_stream_p = &result.GetOutputStream();

    assert(output_stream_p != nullptr);
    bool dumped =
        runtime->DumpAllocation(*output_stream_p, m_exe_ctx.GetFramePtr(), id);

    if (dumped)
      result.SetStatus(eReturnStatusSuccessFinishResult);
    else
      result.SetStatus(eReturnStatusFailed);

    return true;
  }

private:
  CommandOptions m_options;
};

static constexpr OptionDefinition g_renderscript_runtime_alloc_list_options[] = {
    {LLDB_OPT_SET_1, false, "id", 'i', OptionParser::eRequiredArgument, nullptr,
     {}, 0, eArgTypeIndex,
     "Only show details of a single allocation with specified id."}};

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() {}

  ~CommandObjectRenderScriptRuntimeAllocationList() override = default;

  Options *GetOptions() override { return &m_options; }

  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *exe_ctx) override {
      Status err;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'i':
        if (option_arg.getAsInteger(0, m_id))
          err.SetErrorStringWithFormat("invalid integer value for option '%c'",
                                       short_option);
        break;
      default:
        err.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
        break;
      }
      return err;
    }

    void OptionParsingStarting(ExecutionContext *exe_ctx) override { m_id = 0; }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_renderscript_runtime_alloc_list_options);
    }

    uint32_t m_id = 0;
  };

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));
    runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(),
                             m_options.m_id);
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }

private:
  CommandOptions m_options;
};

class CommandObjectRenderScriptRuntimeAllocationLoad
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeAllocationLoad(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "renderscript allocation load",
            "Loads renderscript allocation contents from a file.",
            "renderscript allocation load <ID> <filename>",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched) {
    CommandArgumentData id_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
    CommandArgumentData name_arg{eArgTypeFilename, eArgRepeatPlain};
    m_arguments.push_back({id_arg});
    m_arguments.push_back({name_arg});
  }

  ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc != 2) {
      result.AppendErrorWithFormat(
          "'%s' takes 2 arguments, an allocation ID and filename to read from.",
          m_cmd_name.c_str());
      return false;
    }

    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));

    const char *id_cstr = command.GetArgumentAtIndex(0);
    uint32_t id;
    if (!llvm::to_integer(id_cstr, id)) {
      result.AppendErrorWithFormat("invalid allocation id argument '%s'",
                                   id_cstr);
      return false;
    }

    const char *path = command.GetArgumentAtIndex(1);
    bool loaded = runtime->LoadAllocation(result.GetOutputStream(), id, path,
                                          m_exe_ctx.GetFramePtr());

    if (loaded)
      result.SetStatus(eReturnStatusSuccessFinishResult);
    else
      result.SetStatus(eReturnStatusFailed);

    return true;
  }
};

class CommandObjectRenderScriptRuntimeAllocationSave
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeAllocationSave(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "renderscript allocation save",
                            "Write renderscript allocation contents to a file.",
                            "renderscript allocation save <ID> <filename>",
                            eCommandRequiresProcess |
                                eCommandProcessMustBeLaunched) {
    CommandArgumentData id_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
    CommandArgumentData name_arg{eArgTypeFilename, eArgRepeatPlain};
    m_arguments.push_back({id_arg});
    m_arguments.push_back({name_arg});
  }

  ~CommandObjectRenderScriptRuntimeAllocationSave() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc != 2) {
      result.AppendErrorWithFormat(
          "'%s' takes 2 arguments, an allocation ID and filename to read from.",
          m_cmd_name.c_str());
      return false;
    }

    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));

    const char *id_cstr = command.GetArgumentAtIndex(0);
    uint32_t id;
    if (!llvm::to_integer(id_cstr, id)) {
      result.AppendErrorWithFormat("invalid allocation id argument '%s'",
                                   id_cstr);
      return false;
    }

    const char *path = command.GetArgumentAtIndex(1);
    bool saved = runtime->SaveAllocation(result.GetOutputStream(), id, path,
                                         m_exe_ctx.GetFramePtr());

    if (saved)
      result.SetStatus(eReturnStatusSuccessFinishResult);
    else
      result.SetStatus(eReturnStatusFailed);

    return true;
  }
};

class CommandObjectRenderScriptRuntimeAllocationRefresh
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeAllocationRefresh(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "renderscript allocation refresh",
                            "Recomputes the details of all allocations.",
                            "renderscript allocation refresh",
                            eCommandRequiresProcess |
                                eCommandProcessMustBeLaunched) {}

  ~CommandObjectRenderScriptRuntimeAllocationRefresh() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));

    bool success = runtime->RecomputeAllAllocations(result.GetOutputStream(),
                                                    m_exe_ctx.GetFramePtr());

    if (success) {
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return true;
    } else {
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
  }
};

class CommandObjectRenderScriptRuntimeAllocation
    : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "renderscript allocation",
            "Commands that deal with RenderScript allocations.", nullptr) {
    LoadSubCommand(
        "list",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeAllocationList(interpreter)));
    LoadSubCommand(
        "dump",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeAllocationDump(interpreter)));
    LoadSubCommand(
        "save",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeAllocationSave(interpreter)));
    LoadSubCommand(
        "load",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter)));
    LoadSubCommand(
        "refresh",
        CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationRefresh(
            interpreter)));
  }

  ~CommandObjectRenderScriptRuntimeAllocation() override = default;
};

class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "renderscript status",
                            "Displays current RenderScript runtime status.",
                            "renderscript status",
                            eCommandRequiresProcess |
                                eCommandProcessMustBeLaunched) {}

  ~CommandObjectRenderScriptRuntimeStatus() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));
    runtime->DumpStatus(result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }
};

class CommandObjectRenderScriptRuntimeReduction
    : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntimeReduction(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "renderscript reduction",
                               "Commands that handle general reduction kernels",
                               nullptr) {
    LoadSubCommand(
        "breakpoint",
        CommandObjectSP(new CommandObjectRenderScriptRuntimeReductionBreakpoint(
            interpreter)));
  }
  ~CommandObjectRenderScriptRuntimeReduction() override = default;
};

class CommandObjectRenderScriptRuntime : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "renderscript",
            "Commands for operating on the RenderScript runtime.",
            "renderscript <subcommand> [<subcommand-options>]") {
    LoadSubCommand(
        "module", CommandObjectSP(
                      new CommandObjectRenderScriptRuntimeModule(interpreter)));
    LoadSubCommand(
        "status", CommandObjectSP(
                      new CommandObjectRenderScriptRuntimeStatus(interpreter)));
    LoadSubCommand(
        "kernel", CommandObjectSP(
                      new CommandObjectRenderScriptRuntimeKernel(interpreter)));
    LoadSubCommand("context",
                   CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(
                       interpreter)));
    LoadSubCommand(
        "allocation",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
    LoadSubCommand("scriptgroup",
                   NewCommandObjectRenderScriptScriptGroup(interpreter));
    LoadSubCommand(
        "reduction",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeReduction(interpreter)));
  }

  ~CommandObjectRenderScriptRuntime() override = default;
};

void RenderScriptRuntime::Initiate() { assert(!m_initiated); }

RenderScriptRuntime::RenderScriptRuntime(Process *process)
    : lldb_private::CPPLanguageRuntime(process), m_initiated(false),
      m_debuggerPresentFlagged(false), m_breakAllKernels(false),
      m_ir_passes(nullptr) {
  ModulesDidLoad(process->GetTarget().GetImages());
}

lldb::CommandObjectSP RenderScriptRuntime::GetCommandObject(
    lldb_private::CommandInterpreter &interpreter) {
  return CommandObjectSP(new CommandObjectRenderScriptRuntime(interpreter));
}

RenderScriptRuntime::~RenderScriptRuntime() = default;
