<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Fri, Sep 16, 2016 at 4:36 AM Luke Drummond via lldb-commits <<a href="mailto:lldb-commits@lists.llvm.org">lldb-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: ldrumm<br class="gmail_msg">
Date: Fri Sep 16 06:28:12 2016<br class="gmail_msg">
New Revision: 281717<br class="gmail_msg">
<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=281717&view=rev" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project?rev=281717&view=rev</a><br class="gmail_msg">
Log:<br class="gmail_msg">
[RenderScript] Support tracking and dumping reduction kernels<br class="gmail_msg">
<br class="gmail_msg">
Initial implementation of support for tracking<br class="gmail_msg">
[RenderScript Reductions](<a href="https://developer.android.com/guide/topics/renderscript/compute.html#reduction-in-depth" rel="noreferrer" class="gmail_msg" target="_blank">https://developer.android.com/guide/topics/renderscript/compute.html#reduction-in-depth</a>)<br class="gmail_msg">
<br class="gmail_msg">
With this patch, `language renderscript module dump` properly lists reductions<br class="gmail_msg">
that are part of loaded RenderScript modules as well the the consituent<br class="gmail_msg">
functions and their roles, within the reduction.<br class="gmail_msg">
<br class="gmail_msg">
This support required new tracking mechanisms for the `#pragma(reduce)`<br class="gmail_msg">
mechanism, and extension of `RSModuleDescriptor::ParseRSInfo` to support<br class="gmail_msg">
the metadata output by `bcc`. This work was also an opportunity to<br class="gmail_msg">
refactor/improve parse code:<br class="gmail_msg">
<br class="gmail_msg">
- `RSModuleDescriptor::ParseExportReduceCount` now has a complete<br class="gmail_msg">
  implementation and the debugger can correctly track reductions on<br class="gmail_msg">
  receipt of a module hook.<br class="gmail_msg">
- `RSModuleDescriptor::Dump` now dumps Reductions as well as `ForEach`<br class="gmail_msg">
  kernels. Also, fixed indentation of the output, and made indentation<br class="gmail_msg">
  groupings in the source clearer.<br class="gmail_msg">
- `RSModuleDescriptor::ParseRSInfo` now returns true if the `".<a href="http://rs.info" rel="noreferrer" class="gmail_msg" target="_blank">rs.info</a>"`<br class="gmail_msg">
  packet has nonzero linecount, rather than rejecting RenderScripts that<br class="gmail_msg">
  don't contain kernels (an unlikely situation, but possibly valid). This<br class="gmail_msg">
  was changed because scripts that only contained reductions were not<br class="gmail_msg">
  being tracked in `RenderScriptRuntime::LoadModule`.<br class="gmail_msg">
- Refactor `RSModuleInfo::ParseRSInfo` and add reduction spec parser stub<br class="gmail_msg">
 - Prepared ParseRSInfo to more easily be able to add new parser types<br class="gmail_msg">
 - Use llvm::StringRef and llvm::StringMap helpers to make the parsing code cleaner<br class="gmail_msg">
 - factor out forEachCount, globalVarCount, and pragmaCount parsing block to their own methods<br class="gmail_msg">
 - Add ExportReduceCount Parser<br class="gmail_msg">
 - Use `llvm::StringRef` in `RSKernelDescriptor` constructor<br class="gmail_msg">
 - removed now superfluous `MAXLINE` macros as we've switched from `const<br class="gmail_msg">
   char *` to `llvm::StringRef`<br class="gmail_msg">
<br class="gmail_msg">
Modified:<br class="gmail_msg">
    lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp<br class="gmail_msg">
    lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h<br class="gmail_msg">
<br class="gmail_msg">
Modified: lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp?rev=281717&r1=281716&r2=281717&view=diff" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp?rev=281717&r1=281716&r2=281717&view=diff</a><br class="gmail_msg">
==============================================================================<br class="gmail_msg">
--- lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp (original)<br class="gmail_msg">
+++ lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp Fri Sep 16 06:28:12 2016<br class="gmail_msg">
@@ -10,6 +10,8 @@<br class="gmail_msg">
 // C Includes<br class="gmail_msg">
 // C++ Includes<br class="gmail_msg">
 // Other libraries and framework includes<br class="gmail_msg">
+#include "llvm/ADT/StringMap.h"<br class="gmail_msg">
+<br class="gmail_msg">
 // Project includes<br class="gmail_msg">
 #include "RenderScriptRuntime.h"<br class="gmail_msg">
<br class="gmail_msg">
@@ -2587,17 +2589,104 @@ void RenderScriptRuntime::Update() {<br class="gmail_msg">
   }<br class="gmail_msg">
 }<br class="gmail_msg">
<br class="gmail_msg">
-// The maximum line length of an .<a href="http://rs.info" rel="noreferrer" class="gmail_msg" target="_blank">rs.info</a> packet<br class="gmail_msg">
-#define MAXLINE 500<br class="gmail_msg">
-#define STRINGIFY(x) #x<br class="gmail_msg">
-#define MAXLINESTR_(x) "%" STRINGIFY(x) "s"<br class="gmail_msg">
-#define MAXLINESTR MAXLINESTR_(MAXLINE)<br class="gmail_msg">
+bool RSModuleDescriptor::ParsePragmaCount(llvm::StringRef *lines,<br class="gmail_msg">
+                                          size_t n_lines) {<br class="gmail_msg">
+  // Skip the pragma prototype line<br class="gmail_msg">
+  ++lines;<br class="gmail_msg">
+  for (; n_lines--; ++lines) {<br class="gmail_msg">
+    const auto kv_pair = lines->split(" - ");<br class="gmail_msg">
+    m_pragmas[kv_pair.first.trim().str()] = kv_pair.second.trim().str();<br class="gmail_msg">
+  }<br class="gmail_msg">
+  return true;<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+bool RSModuleDescriptor::ParseExportReduceCount(llvm::StringRef *lines,<br class="gmail_msg">
+                                                size_t n_lines) {<br class="gmail_msg"></blockquote><div>This should take an ArrayRef<StringRef>.  In general this is true any time you're passing an array to a function via (T* items, size_t length).  </div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+  // The list of reduction kernels in the `.<a href="http://rs.info" rel="noreferrer" class="gmail_msg" target="_blank">rs.info</a>` symbol is of the form<br class="gmail_msg">
+  // "signature - accumulatordatasize - reduction_name - initializer_name -<br class="gmail_msg">
+  // accumulator_name - combiner_name -<br class="gmail_msg">
+  // outconverter_name - halter_name"<br class="gmail_msg">
+  // Where a function is not explicitly named by the user, or is not generated<br class="gmail_msg">
+  // by the compiler, it is named "." so the<br class="gmail_msg">
+  // dash separated list should always be 8 items long<br class="gmail_msg">
+  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);<br class="gmail_msg">
+  // Skip the exportReduceCount line<br class="gmail_msg">
+  ++lines;<br class="gmail_msg">
+  for (; n_lines--; ++lines) {<br class="gmail_msg"></blockquote><div>With ArrayRef this would be written as:</div><div><br></div><div>for (StringRef line : lines.drop_front()) {</div><div>}</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+    llvm::SmallVector<llvm::StringRef, 8> spec;<br class="gmail_msg">
+    lines->split(spec, " - ");<br class="gmail_msg">
+    if (spec.size() != 8) {<br class="gmail_msg">
+      if (spec.size() < 8) {<br class="gmail_msg">
+        if (log)<br class="gmail_msg">
+          log->Error("Error parsing RenderScript reduction spec. wrong number "<br class="gmail_msg">
+                     "of fields");<br class="gmail_msg">
+        return false;<br class="gmail_msg">
+      } else if (log)<br class="gmail_msg">
+        log->Warning("Extraneous members in reduction spec: '%s'",<br class="gmail_msg">
+                     lines->str().c_str());<br class="gmail_msg">
+    }<br class="gmail_msg">
+<br class="gmail_msg">
+    const auto sig_s = spec[0];<br class="gmail_msg">
+    uint32_t sig;<br class="gmail_msg">
+    if (sig_s.getAsInteger(10, sig)) {<br class="gmail_msg">
+      if (log)<br class="gmail_msg">
+        log->Error("Error parsing Renderscript reduction spec: invalid kernel "<br class="gmail_msg">
+                   "signature: '%s'",<br class="gmail_msg">
+                   sig_s.str().c_str());<br class="gmail_msg">
+      return false;<br class="gmail_msg">
+    }<br class="gmail_msg">
+<br class="gmail_msg">
+    const auto accum_data_size_s = spec[1];<br class="gmail_msg">
+    uint32_t accum_data_size;<br class="gmail_msg">
+    if (accum_data_size_s.getAsInteger(10, accum_data_size)) {<br class="gmail_msg">
+      if (log)<br class="gmail_msg">
+        log->Error("Error parsing Renderscript reduction spec: invalid "<br class="gmail_msg">
+                   "accumulator data size %s",<br class="gmail_msg">
+                   accum_data_size_s.str().c_str());<br class="gmail_msg">
+      return false;<br class="gmail_msg">
+    }<br class="gmail_msg">
+<br class="gmail_msg">
+    if (log)<br class="gmail_msg">
+      log->Printf("Found RenderScript reduction '%s'", spec[2].str().c_str());<br class="gmail_msg">
+<br class="gmail_msg">
+    m_reductions.push_back(RSReductionDescriptor(this, sig, accum_data_size,<br class="gmail_msg">
+                                                 spec[2], spec[3], spec[4],<br class="gmail_msg">
+                                                 spec[5], spec[6], spec[7]));<br class="gmail_msg">
+  }<br class="gmail_msg">
+  return true;<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+bool RSModuleDescriptor::ParseExportForeachCount(llvm::StringRef *lines,<br class="gmail_msg">
+                                                 size_t n_lines) {<br class="gmail_msg"></blockquote><div>Same as above.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+  // Skip the exportForeachCount line<br class="gmail_msg">
+  ++lines;<br class="gmail_msg">
+  for (; n_lines--; ++lines) {<br class="gmail_msg">
+    uint32_t slot;<br class="gmail_msg">
+    // `forEach` kernels are listed in the `.<a href="http://rs.info" rel="noreferrer" class="gmail_msg" target="_blank">rs.info</a>` packet as a "slot - name"<br class="gmail_msg">
+    // pair per line<br class="gmail_msg">
+    const auto kv_pair = lines->split(" - ");<br class="gmail_msg">
+    if (kv_pair.first.getAsInteger(10, slot))<br class="gmail_msg">
+      return false;<br class="gmail_msg">
+    m_kernels.push_back(RSKernelDescriptor(this, kv_pair.second, slot));<br class="gmail_msg">
+  }<br class="gmail_msg">
+  return true;<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+bool RSModuleDescriptor::ParseExportVarCount(llvm::StringRef *lines,<br class="gmail_msg">
+                                             size_t n_lines) {<br class="gmail_msg"></blockquote><div>Same</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+  // Skip the ExportVarCount line<br class="gmail_msg">
+  ++lines;<br class="gmail_msg">
+  for (; n_lines--; ++lines)<br class="gmail_msg">
+    m_globals.push_back(RSGlobalDescriptor(this, *lines));<br class="gmail_msg">
+  return true;<br class="gmail_msg">
+}<br class="gmail_msg">
<br class="gmail_msg">
 // The .<a href="http://rs.info" rel="noreferrer" class="gmail_msg" target="_blank">rs.info</a> symbol in renderscript modules contains a string which needs to<br class="gmail_msg">
 // be parsed.<br class="gmail_msg">
 // The string is basic and is parsed on a line by line basis.<br class="gmail_msg">
 bool RSModuleDescriptor::ParseRSInfo() {<br class="gmail_msg">
   assert(m_module);<br class="gmail_msg">
+  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));<br class="gmail_msg">
   const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(<br class="gmail_msg">
       ConstString(".<a href="http://rs.info" rel="noreferrer" class="gmail_msg" target="_blank">rs.info</a>"), eSymbolTypeData);<br class="gmail_msg">
   if (!info_sym)<br class="gmail_msg">
@@ -2615,61 +2704,85 @@ bool RSModuleDescriptor::ParseRSInfo() {<br class="gmail_msg">
     return false;<br class="gmail_msg">
<br class="gmail_msg">
   // split <a href="http://rs.info" rel="noreferrer" class="gmail_msg" target="_blank">rs.info</a>. contents into lines<br class="gmail_msg">
-  std::vector<std::string> info_lines;<br class="gmail_msg">
+  llvm::SmallVector<llvm::StringRef, 128> info_lines;<br class="gmail_msg">
   {<br class="gmail_msg">
-    const std::string info((const char *)buffer->GetBytes());<br class="gmail_msg">
-    for (size_t tail = 0; tail < info.size();) {<br class="gmail_msg">
-      // find next new line or end of string<br class="gmail_msg">
-      size_t head = info.find('\n', tail);<br class="gmail_msg">
-      head = (head == std::string::npos) ? info.size() : head;<br class="gmail_msg">
-      std::string line = info.substr(tail, head - tail);<br class="gmail_msg">
-      // add to line list<br class="gmail_msg">
-      info_lines.push_back(line);<br class="gmail_msg">
-      tail = head + 1;<br class="gmail_msg">
-    }<br class="gmail_msg">
+    const llvm::StringRef raw_rs_info((const char *)buffer->GetBytes());<br class="gmail_msg">
+    raw_rs_info.split(info_lines, '\n');<br class="gmail_msg">
+    if (log)<br class="gmail_msg">
+      log->Printf("'.<a href="http://rs.info" rel="noreferrer" class="gmail_msg" target="_blank">rs.info</a> symbol for '%s':\n%s",<br class="gmail_msg">
+                  m_module->GetFileSpec().GetCString(),<br class="gmail_msg">
+                  raw_rs_info.str().c_str());<br class="gmail_msg">
   }<br class="gmail_msg">
<br class="gmail_msg">
-  std::array<char, MAXLINE> name{{'\0'}};<br class="gmail_msg">
-  std::array<char, MAXLINE> value{{'\0'}};<br class="gmail_msg">
+  enum {<br class="gmail_msg">
+    eExportVar,<br class="gmail_msg">
+    eExportForEach,<br class="gmail_msg">
+    eExportReduce,<br class="gmail_msg">
+    ePragma,<br class="gmail_msg">
+    eBuildChecksum,<br class="gmail_msg">
+    eObjectSlot<br class="gmail_msg">
+  };<br class="gmail_msg">
+<br class="gmail_msg">
+  static const llvm::StringMap<int> rs_info_handlers{<br class="gmail_msg">
+      {// The number of visible global variables in the script<br class="gmail_msg">
+       {"exportVarCount", eExportVar},<br class="gmail_msg">
+       // The number of RenderScrip `forEach` kernels __attribute__((kernel))<br class="gmail_msg">
+       {"exportForEachCount", eExportForEach},<br class="gmail_msg">
+       // The number of generalreductions: This marked in the script by `#pragma<br class="gmail_msg">
+       // reduce()`<br class="gmail_msg">
+       {"exportReduceCount", eExportReduce},<br class="gmail_msg">
+       // Total count of all RenderScript specific `#pragmas` used in the script<br class="gmail_msg">
+       {"pragmaCount", ePragma},<br class="gmail_msg">
+       {"objectSlotCount", eObjectSlot}}};<br class="gmail_msg">
<br class="gmail_msg">
   // parse all text lines of .<a href="http://rs.info" rel="noreferrer" class="gmail_msg" target="_blank">rs.info</a><br class="gmail_msg">
   for (auto line = info_lines.begin(); line != info_lines.end(); ++line) {<br class="gmail_msg"></blockquote><div>How about (for auto line : info_lines) {</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
-    uint32_t numDefns = 0;<br class="gmail_msg">
-    if (sscanf(line->c_str(), "exportVarCount: %" PRIu32 "", &numDefns) == 1) {<br class="gmail_msg">
-      while (numDefns--)<br class="gmail_msg">
-        m_globals.push_back(RSGlobalDescriptor(this, (++line)->c_str()));<br class="gmail_msg">
-    } else if (sscanf(line->c_str(), "exportForEachCount: %" PRIu32 "",<br class="gmail_msg">
-                      &numDefns) == 1) {<br class="gmail_msg">
-      while (numDefns--) {<br class="gmail_msg">
-        uint32_t slot = 0;<br class="gmail_msg">
-        name[0] = '\0';<br class="gmail_msg">
-        static const char *fmt_s = "%" PRIu32 " - " MAXLINESTR;<br class="gmail_msg">
-        if (sscanf((++line)->c_str(), fmt_s, &slot, name.data()) == 2) {<br class="gmail_msg">
-          if (name[0] != '\0')<br class="gmail_msg">
-            m_kernels.push_back(RSKernelDescriptor(this, name.data(), slot));<br class="gmail_msg">
-        }<br class="gmail_msg">
-      }<br class="gmail_msg">
-    } else if (sscanf(line->c_str(), "pragmaCount: %" PRIu32 "", &numDefns) ==<br class="gmail_msg">
-               1) {<br class="gmail_msg">
-      while (numDefns--) {<br class="gmail_msg">
-        name[0] = value[0] = '\0';<br class="gmail_msg">
-        static const char *fmt_s = MAXLINESTR " - " MAXLINESTR;<br class="gmail_msg">
-        if (sscanf((++line)->c_str(), fmt_s, name.data(), value.data()) != 0) {<br class="gmail_msg">
-          if (name[0] != '\0')<br class="gmail_msg">
-            m_pragmas[std::string(name.data())] = value.data();<br class="gmail_msg">
-        }<br class="gmail_msg">
-      }<br class="gmail_msg">
-    } else {<br class="gmail_msg">
-      Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));<br class="gmail_msg">
-      if (log) {<br class="gmail_msg">
+    const auto kv_pair = line->split(": ");<br class="gmail_msg">
+    const auto key = kv_pair.first;<br class="gmail_msg">
+    const auto val = kv_pair.second.trim();<br class="gmail_msg">
+<br class="gmail_msg">
+    const auto handler = rs_info_handlers.find(key);<br class="gmail_msg">
+    if (handler == rs_info_handlers.end())<br class="gmail_msg">
+      continue;<br class="gmail_msg"></blockquote><div>Instead of constructing this map, you could use llvm::StringSwitch, like this:</div><div>int handler = llvm::StringSwitch<int>(key)</div><div>                        .Case("exportVarCount", eExportVar)<br></div><div>                        .Case("exportForEachCount", eExportForEach)</div><div>                        .Case("exportReduceCount", eExportReduce)</div><div>                        .Case("pragmaCount", ePragma)</div><div>                        .Case("objectSlotCount", eObjectSlot)<br></div><div>                        .Default(-1);<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+    // getAsInteger returns `true` on an error condition - we're only interested<br class="gmail_msg">
+    // in<br class="gmail_msg">
+    // numeric fields at the moment<br class="gmail_msg">
+    uint64_t n_lines;<br class="gmail_msg">
+    if (val.getAsInteger(10, n_lines)) {<br class="gmail_msg">
+      if (log)<br class="gmail_msg">
+        log->Debug("Failed to parse non-numeric '.<a href="http://rs.info" rel="noreferrer" class="gmail_msg" target="_blank">rs.info</a>' section %s",<br class="gmail_msg">
+                   line->str().c_str());<br class="gmail_msg">
+      continue;<br class="gmail_msg">
+    }<br class="gmail_msg">
+    if (info_lines.end() - (line + 1) < (ptrdiff_t)n_lines)<br class="gmail_msg">
+      return false;<br class="gmail_msg">
+<br class="gmail_msg">
+    bool success = false;<br class="gmail_msg">
+    switch (handler->getValue()) {<br class="gmail_msg">
+    case eExportVar:<br class="gmail_msg">
+      success = ParseExportVarCount(line, n_lines);<br class="gmail_msg">
+      break;<br class="gmail_msg">
+    case eExportForEach:<br class="gmail_msg">
+      success = ParseExportForeachCount(line, n_lines);<br class="gmail_msg">
+      break;<br class="gmail_msg">
+    case eExportReduce:<br class="gmail_msg">
+      success = ParseExportReduceCount(line, n_lines);<br class="gmail_msg">
+      break;<br class="gmail_msg">
+    case ePragma:<br class="gmail_msg">
+      success = ParsePragmaCount(line, n_lines);<br class="gmail_msg">
+      break;<br class="gmail_msg">
+    default: {<br class="gmail_msg">
+      if (log)<br class="gmail_msg">
         log->Printf("%s - skipping .<a href="http://rs.info" rel="noreferrer" class="gmail_msg" target="_blank">rs.info</a> field '%s'", __FUNCTION__,<br class="gmail_msg">
-                    line->c_str());<br class="gmail_msg">
-      }<br class="gmail_msg">
+                    line->str().c_str());<br class="gmail_msg">
+      continue;<br class="gmail_msg">
+    }<br class="gmail_msg">
     }<br class="gmail_msg">
+    if (!success)<br class="gmail_msg">
+      return false;<br class="gmail_msg">
+    line += n_lines;<br class="gmail_msg">
   }<br class="gmail_msg">
-<br class="gmail_msg">
-  // 'root' kernel should always be present<br class="gmail_msg">
-  return m_kernels.size() > 0;<br class="gmail_msg">
+  return info_lines.size() > 0;<br class="gmail_msg">
 }<br class="gmail_msg">
<br class="gmail_msg">
 void RenderScriptRuntime::Status(Stream &strm) const {<br class="gmail_msg">
@@ -3419,15 +3532,15 @@ RenderScriptRuntime::CreateAllocation(ad<br class="gmail_msg">
 }<br class="gmail_msg">
<br class="gmail_msg">
 void RSModuleDescriptor::Dump(Stream &strm) const {<br class="gmail_msg">
+  int indent = strm.GetIndentLevel();<br class="gmail_msg">
+<br class="gmail_msg">
   strm.Indent();<br class="gmail_msg">
   m_module->GetFileSpec().Dump(&strm);<br class="gmail_msg">
-  if (m_module->GetNumCompileUnits()) {<br class="gmail_msg">
-    strm.Indent("Debug info loaded.");<br class="gmail_msg">
-  } else {<br class="gmail_msg">
-    strm.Indent("Debug info does not exist.");<br class="gmail_msg">
-  }<br class="gmail_msg">
+  strm.Indent(m_module->GetNumCompileUnits() ? "Debug info loaded."<br class="gmail_msg">
+                                             : "Debug info does not exist.");<br class="gmail_msg">
   strm.EOL();<br class="gmail_msg">
   strm.IndentMore();<br class="gmail_msg">
+<br class="gmail_msg">
   strm.Indent();<br class="gmail_msg">
   strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));<br class="gmail_msg">
   strm.EOL();<br class="gmail_msg">
@@ -3436,6 +3549,7 @@ void RSModuleDescriptor::Dump(Stream &st<br class="gmail_msg">
     global.Dump(strm);<br class="gmail_msg">
   }<br class="gmail_msg">
   strm.IndentLess();<br class="gmail_msg">
+<br class="gmail_msg">
   strm.Indent();<br class="gmail_msg">
   strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));<br class="gmail_msg">
   strm.EOL();<br class="gmail_msg">
@@ -3443,14 +3557,29 @@ void RSModuleDescriptor::Dump(Stream &st<br class="gmail_msg">
   for (const auto &kernel : m_kernels) {<br class="gmail_msg">
     kernel.Dump(strm);<br class="gmail_msg">
   }<br class="gmail_msg">
+  strm.IndentLess();<br class="gmail_msg">
+<br class="gmail_msg">
+  strm.Indent();<br class="gmail_msg">
   strm.Printf("Pragmas: %" PRIu64, static_cast<uint64_t>(m_pragmas.size()));<br class="gmail_msg">
   strm.EOL();<br class="gmail_msg">
   strm.IndentMore();<br class="gmail_msg">
   for (const auto &key_val : m_pragmas) {<br class="gmail_msg">
+    strm.Indent();<br class="gmail_msg">
     strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());<br class="gmail_msg">
     strm.EOL();<br class="gmail_msg">
   }<br class="gmail_msg">
-  strm.IndentLess(4);<br class="gmail_msg">
+  strm.IndentLess();<br class="gmail_msg">
+<br class="gmail_msg">
+  strm.Indent();<br class="gmail_msg">
+  strm.Printf("Reductions: %" PRIu64,<br class="gmail_msg">
+              static_cast<uint64_t>(m_reductions.size()));<br class="gmail_msg">
+  strm.EOL();<br class="gmail_msg">
+  strm.IndentMore();<br class="gmail_msg">
+  for (const auto &reduction : m_reductions) {<br class="gmail_msg">
+    reduction.Dump(strm);<br class="gmail_msg">
+  }<br class="gmail_msg">
+<br class="gmail_msg">
+  strm.SetIndentLevel(indent);<br class="gmail_msg">
 }<br class="gmail_msg">
<br class="gmail_msg">
 void RSGlobalDescriptor::Dump(Stream &strm) const {<br class="gmail_msg">
@@ -3483,6 +3612,29 @@ void RSKernelDescriptor::Dump(Stream &st<br class="gmail_msg">
   strm.EOL();<br class="gmail_msg">
 }<br class="gmail_msg">
<br class="gmail_msg">
+void RSReductionDescriptor::Dump(lldb_private::Stream &stream) const {<br class="gmail_msg">
+  stream.Indent(m_reduce_name.AsCString());<br class="gmail_msg">
+  stream.IndentMore();<br class="gmail_msg">
+  stream.EOL();<br class="gmail_msg">
+  stream.Indent();<br class="gmail_msg">
+  stream.Printf("accumulator: %s", m_accum_name.AsCString());<br class="gmail_msg">
+  stream.EOL();<br class="gmail_msg">
+  stream.Indent();<br class="gmail_msg">
+  stream.Printf("initializer: %s", m_init_name.AsCString());<br class="gmail_msg">
+  stream.EOL();<br class="gmail_msg">
+  stream.Indent();<br class="gmail_msg">
+  stream.Printf("combiner: %s", m_comb_name.AsCString());<br class="gmail_msg">
+  stream.EOL();<br class="gmail_msg">
+  stream.Indent();<br class="gmail_msg">
+  stream.Printf("outconverter: %s", m_outc_name.AsCString());<br class="gmail_msg">
+  stream.EOL();<br class="gmail_msg">
+  // XXX This is currently unspecified by RenderScript, and unused<br class="gmail_msg">
+  // stream.Indent();<br class="gmail_msg">
+  // stream.Printf("halter: '%s'", m_init_name.AsCString());<br class="gmail_msg">
+  // stream.EOL();<br class="gmail_msg">
+  stream.IndentLess();<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
 class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed {<br class="gmail_msg">
 public:<br class="gmail_msg">
   CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)<br class="gmail_msg">
<br class="gmail_msg">
Modified: lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h?rev=281717&r1=281716&r2=281717&view=diff" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h?rev=281717&r1=281716&r2=281717&view=diff</a><br class="gmail_msg">
==============================================================================<br class="gmail_msg">
--- lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h (original)<br class="gmail_msg">
+++ lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h Fri Sep 16 06:28:12 2016<br class="gmail_msg">
@@ -19,6 +19,8 @@<br class="gmail_msg">
 #include <vector><br class="gmail_msg">
<br class="gmail_msg">
 // Other libraries and framework includes<br class="gmail_msg">
+#include "llvm/ADT/SmallVector.h"<br class="gmail_msg">
+#include "llvm/ADT/StringRef.h"<br class="gmail_msg">
 // Project includes<br class="gmail_msg">
 #include "lldb/Core/Module.h"<br class="gmail_msg">
 #include "lldb/Expression/LLVMUserExpression.h"<br class="gmail_msg">
@@ -33,6 +35,7 @@ typedef uint32_t RSSlot;<br class="gmail_msg">
 class RSModuleDescriptor;<br class="gmail_msg">
 struct RSGlobalDescriptor;<br class="gmail_msg">
 struct RSKernelDescriptor;<br class="gmail_msg">
+struct RSReductionDescriptor;<br class="gmail_msg">
<br class="gmail_msg">
 typedef std::shared_ptr<RSModuleDescriptor> RSModuleDescriptorSP;<br class="gmail_msg">
 typedef std::shared_ptr<RSGlobalDescriptor> RSGlobalDescriptorSP;<br class="gmail_msg">
@@ -75,7 +78,7 @@ protected:<br class="gmail_msg">
<br class="gmail_msg">
 struct RSKernelDescriptor {<br class="gmail_msg">
 public:<br class="gmail_msg">
-  RSKernelDescriptor(const RSModuleDescriptor *module, const char *name,<br class="gmail_msg">
+  RSKernelDescriptor(const RSModuleDescriptor *module, llvm::StringRef name,<br class="gmail_msg">
                      uint32_t slot)<br class="gmail_msg">
       : m_module(module), m_name(name), m_slot(slot) {}<br class="gmail_msg">
<br class="gmail_msg">
@@ -88,7 +91,7 @@ public:<br class="gmail_msg">
<br class="gmail_msg">
 struct RSGlobalDescriptor {<br class="gmail_msg">
 public:<br class="gmail_msg">
-  RSGlobalDescriptor(const RSModuleDescriptor *module, const char *name)<br class="gmail_msg">
+  RSGlobalDescriptor(const RSModuleDescriptor *module, llvm::StringRef name)<br class="gmail_msg">
       : m_module(module), m_name(name) {}<br class="gmail_msg">
<br class="gmail_msg">
   void Dump(Stream &strm) const;<br class="gmail_msg">
@@ -97,7 +100,56 @@ public:<br class="gmail_msg">
   ConstString m_name;<br class="gmail_msg">
 };<br class="gmail_msg">
<br class="gmail_msg">
+struct RSReductionDescriptor {<br class="gmail_msg">
+  RSReductionDescriptor(const RSModuleDescriptor *module, uint32_t sig,<br class="gmail_msg">
+                        uint32_t accum_data_size, llvm::StringRef name,<br class="gmail_msg">
+                        llvm::StringRef init_name, llvm::StringRef accum_name,<br class="gmail_msg">
+                        llvm::StringRef comb_name, llvm::StringRef outc_name,<br class="gmail_msg">
+                        llvm::StringRef halter_name = ".")<br class="gmail_msg">
+      : m_module(module), m_reduce_name(name), m_init_name(init_name),<br class="gmail_msg">
+        m_accum_name(accum_name), m_comb_name(comb_name),<br class="gmail_msg">
+        m_outc_name(outc_name), m_halter_name(halter_name) {<br class="gmail_msg">
+    // TODO Check whether the combiner is an autogenerated name, and track<br class="gmail_msg">
+    // this<br class="gmail_msg">
+  }<br class="gmail_msg">
+<br class="gmail_msg">
+  void Dump(Stream &strm) const;<br class="gmail_msg">
+<br class="gmail_msg">
+  const RSModuleDescriptor *m_module;<br class="gmail_msg">
+  ConstString m_reduce_name; // This is the name given to the general reduction<br class="gmail_msg">
+                             // as a group as passed to pragma<br class="gmail_msg">
+  // reduce(m_reduce_name). There is no kernel function with this name<br class="gmail_msg">
+  ConstString m_init_name;  // The name of the initializer name. "." if no<br class="gmail_msg">
+                            // initializer given<br class="gmail_msg">
+  ConstString m_accum_name; // The accumulator function name. "." if not given<br class="gmail_msg">
+  ConstString m_comb_name; // The name of the combiner function. If this was not<br class="gmail_msg">
+                           // given, a name is generated by the<br class="gmail_msg">
+                           // compiler. TODO<br class="gmail_msg">
+  ConstString m_outc_name; // The name of the outconverter<br class="gmail_msg">
+<br class="gmail_msg">
+  ConstString m_halter_name; // The name of the halter function. XXX This is not<br class="gmail_msg">
+                             // yet specified by the RenderScript<br class="gmail_msg">
+  // compiler or runtime, and its semantics and existence is still under<br class="gmail_msg">
+  // discussion by the<br class="gmail_msg">
+  // RenderScript Contributors<br class="gmail_msg">
+  RSSlot m_accum_sig; // metatdata signature for this reduction (bitwise mask of<br class="gmail_msg">
+                      // type information (see<br class="gmail_msg">
+                      // libbcc/include/bcinfo/MetadataExtractor.h<br class="gmail_msg">
+  uint32_t m_accum_data_size; // Data size of the accumulator function input<br class="gmail_msg">
+  bool m_comb_name_generated; // Was the combiner name generated by the compiler<br class="gmail_msg">
+};<br class="gmail_msg">
+<br class="gmail_msg">
 class RSModuleDescriptor {<br class="gmail_msg">
+  bool ParseExportForeachCount(llvm::StringRef *, size_t n_lines);<br class="gmail_msg">
+<br class="gmail_msg">
+  bool ParseExportVarCount(llvm::StringRef *, size_t n_lines);<br class="gmail_msg">
+<br class="gmail_msg">
+  bool ParseExportReduceCount(llvm::StringRef *, size_t n_lines);<br class="gmail_msg">
+<br class="gmail_msg">
+  bool ParseBuildChecksum(llvm::StringRef *, size_t n_lines);<br class="gmail_msg">
+<br class="gmail_msg">
+  bool ParsePragmaCount(llvm::StringRef *, size_t n_lines);<br class="gmail_msg">
+<br class="gmail_msg">
 public:<br class="gmail_msg">
   RSModuleDescriptor(const lldb::ModuleSP &module) : m_module(module) {}<br class="gmail_msg">
<br class="gmail_msg">
@@ -110,6 +162,7 @@ public:<br class="gmail_msg">
   const lldb::ModuleSP m_module;<br class="gmail_msg">
   std::vector<RSKernelDescriptor> m_kernels;<br class="gmail_msg">
   std::vector<RSGlobalDescriptor> m_globals;<br class="gmail_msg">
+  std::vector<RSReductionDescriptor> m_reductions;<br class="gmail_msg">
   std::map<std::string, std::string> m_pragmas;<br class="gmail_msg"></blockquote><div>You should consider changing this to llvm::StringMap, which has better performance characteristics than std::map</div></div></div>