diff options
Diffstat (limited to 'lldb/source/Plugins/LanguageRuntime/RenderScript')
2 files changed, 264 insertions, 59 deletions
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp index b2a63098c45..832f50dba88 100644 --- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -10,6 +10,8 @@ // C Includes // C++ Includes // Other libraries and framework includes +#include "llvm/ADT/StringMap.h" + // Project includes #include "RenderScriptRuntime.h" @@ -2587,17 +2589,104 @@ void RenderScriptRuntime::Update() { } } -// The maximum line length of an .rs.info packet -#define MAXLINE 500 -#define STRINGIFY(x) #x -#define MAXLINESTR_(x) "%" STRINGIFY(x) "s" -#define MAXLINESTR MAXLINESTR_(MAXLINE) +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 = GetLogIfAllCategoriesSet(LIBLLDB_LOG_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; + } + + if (log) + log->Printf("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::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(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType( ConstString(".rs.info"), eSymbolTypeData); if (!info_sym) @@ -2615,61 +2704,85 @@ bool RSModuleDescriptor::ParseRSInfo() { return false; // split rs.info. contents into lines - std::vector<std::string> info_lines; + llvm::SmallVector<llvm::StringRef, 128> info_lines; { - const std::string info((const char *)buffer->GetBytes()); - for (size_t tail = 0; tail < info.size();) { - // find next new line or end of string - size_t head = info.find('\n', tail); - head = (head == std::string::npos) ? info.size() : head; - std::string line = info.substr(tail, head - tail); - // add to line list - info_lines.push_back(line); - tail = head + 1; - } + const llvm::StringRef raw_rs_info((const char *)buffer->GetBytes()); + raw_rs_info.split(info_lines, '\n'); + if (log) + log->Printf("'.rs.info symbol for '%s':\n%s", + m_module->GetFileSpec().GetCString(), + raw_rs_info.str().c_str()); } - std::array<char, MAXLINE> name{{'\0'}}; - std::array<char, MAXLINE> value{{'\0'}}; + enum { + eExportVar, + eExportForEach, + eExportReduce, + ePragma, + eBuildChecksum, + eObjectSlot + }; + + static const llvm::StringMap<int> rs_info_handlers{ + {// The number of visible global variables in the script + {"exportVarCount", eExportVar}, + // The number of RenderScrip `forEach` kernels __attribute__((kernel)) + {"exportForEachCount", eExportForEach}, + // The number of generalreductions: This marked in the script by `#pragma + // reduce()` + {"exportReduceCount", eExportReduce}, + // Total count of all RenderScript specific `#pragmas` used in the script + {"pragmaCount", ePragma}, + {"objectSlotCount", eObjectSlot}}}; // parse all text lines of .rs.info for (auto line = info_lines.begin(); line != info_lines.end(); ++line) { - uint32_t numDefns = 0; - if (sscanf(line->c_str(), "exportVarCount: %" PRIu32 "", &numDefns) == 1) { - while (numDefns--) - m_globals.push_back(RSGlobalDescriptor(this, (++line)->c_str())); - } else if (sscanf(line->c_str(), "exportForEachCount: %" PRIu32 "", - &numDefns) == 1) { - while (numDefns--) { - uint32_t slot = 0; - name[0] = '\0'; - static const char *fmt_s = "%" PRIu32 " - " MAXLINESTR; - if (sscanf((++line)->c_str(), fmt_s, &slot, name.data()) == 2) { - if (name[0] != '\0') - m_kernels.push_back(RSKernelDescriptor(this, name.data(), slot)); - } - } - } else if (sscanf(line->c_str(), "pragmaCount: %" PRIu32 "", &numDefns) == - 1) { - while (numDefns--) { - name[0] = value[0] = '\0'; - static const char *fmt_s = MAXLINESTR " - " MAXLINESTR; - if (sscanf((++line)->c_str(), fmt_s, name.data(), value.data()) != 0) { - if (name[0] != '\0') - m_pragmas[std::string(name.data())] = value.data(); - } - } - } else { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); - if (log) { + const auto kv_pair = line->split(": "); + const auto key = kv_pair.first; + const auto val = kv_pair.second.trim(); + + const auto handler = rs_info_handlers.find(key); + if (handler == rs_info_handlers.end()) + 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)) { + if (log) + log->Debug("Failed to parse non-numeric '.rs.info' section %s", + line->str().c_str()); + continue; + } + if (info_lines.end() - (line + 1) < (ptrdiff_t)n_lines) + return false; + + bool success = false; + switch (handler->getValue()) { + 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; + default: { + if (log) log->Printf("%s - skipping .rs.info field '%s'", __FUNCTION__, - line->c_str()); - } + line->str().c_str()); + continue; + } } + if (!success) + return false; + line += n_lines; } - - // 'root' kernel should always be present - return m_kernels.size() > 0; + return info_lines.size() > 0; } void RenderScriptRuntime::Status(Stream &strm) const { @@ -3419,15 +3532,15 @@ RenderScriptRuntime::CreateAllocation(addr_t address) { } void RSModuleDescriptor::Dump(Stream &strm) const { + int indent = strm.GetIndentLevel(); + strm.Indent(); m_module->GetFileSpec().Dump(&strm); - if (m_module->GetNumCompileUnits()) { - strm.Indent("Debug info loaded."); - } else { - strm.Indent("Debug info does not exist."); - } + 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(); @@ -3436,6 +3549,7 @@ void RSModuleDescriptor::Dump(Stream &strm) const { global.Dump(strm); } strm.IndentLess(); + strm.Indent(); strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size())); strm.EOL(); @@ -3443,14 +3557,29 @@ void RSModuleDescriptor::Dump(Stream &strm) const { 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(4); + 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 { @@ -3483,6 +3612,29 @@ void RSKernelDescriptor::Dump(Stream &strm) const { strm.EOL(); } +void RSReductionDescriptor::Dump(lldb_private::Stream &stream) const { + stream.Indent(m_reduce_name.AsCString()); + 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) diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h index 7aad7058d86..c19835d6bfb 100644 --- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h @@ -19,6 +19,8 @@ #include <vector> // Other libraries and framework includes +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" // Project includes #include "lldb/Core/Module.h" #include "lldb/Expression/LLVMUserExpression.h" @@ -33,6 +35,7 @@ typedef uint32_t RSSlot; class RSModuleDescriptor; struct RSGlobalDescriptor; struct RSKernelDescriptor; +struct RSReductionDescriptor; typedef std::shared_ptr<RSModuleDescriptor> RSModuleDescriptorSP; typedef std::shared_ptr<RSGlobalDescriptor> RSGlobalDescriptorSP; @@ -75,7 +78,7 @@ protected: struct RSKernelDescriptor { public: - RSKernelDescriptor(const RSModuleDescriptor *module, const char *name, + RSKernelDescriptor(const RSModuleDescriptor *module, llvm::StringRef name, uint32_t slot) : m_module(module), m_name(name), m_slot(slot) {} @@ -88,7 +91,7 @@ public: struct RSGlobalDescriptor { public: - RSGlobalDescriptor(const RSModuleDescriptor *module, const char *name) + RSGlobalDescriptor(const RSModuleDescriptor *module, llvm::StringRef name) : m_module(module), m_name(name) {} void Dump(Stream &strm) const; @@ -97,7 +100,56 @@ public: ConstString m_name; }; +struct RSReductionDescriptor { + RSReductionDescriptor(const RSModuleDescriptor *module, uint32_t sig, + uint32_t accum_data_size, llvm::StringRef name, + llvm::StringRef init_name, llvm::StringRef accum_name, + llvm::StringRef comb_name, llvm::StringRef outc_name, + llvm::StringRef halter_name = ".") + : m_module(module), m_reduce_name(name), m_init_name(init_name), + m_accum_name(accum_name), m_comb_name(comb_name), + m_outc_name(outc_name), m_halter_name(halter_name) { + // TODO Check whether the combiner is an autogenerated name, and track + // this + } + + void Dump(Stream &strm) const; + + const RSModuleDescriptor *m_module; + ConstString m_reduce_name; // This is the name given to the general reduction + // as a group as passed to pragma + // reduce(m_reduce_name). There is no kernel function with this name + ConstString m_init_name; // The name of the initializer name. "." if no + // initializer given + ConstString m_accum_name; // The accumulator function name. "." if not given + ConstString m_comb_name; // The name of the combiner function. If this was not + // given, a name is generated by the + // compiler. TODO + ConstString m_outc_name; // The name of the outconverter + + ConstString m_halter_name; // The name of the halter function. XXX This is not + // yet specified by the RenderScript + // compiler or runtime, and its semantics and existence is still under + // discussion by the + // RenderScript Contributors + RSSlot m_accum_sig; // metatdata signature for this reduction (bitwise mask of + // type information (see + // libbcc/include/bcinfo/MetadataExtractor.h + uint32_t m_accum_data_size; // Data size of the accumulator function input + bool m_comb_name_generated; // Was the combiner name generated by the compiler +}; + class RSModuleDescriptor { + bool ParseExportForeachCount(llvm::StringRef *, size_t n_lines); + + bool ParseExportVarCount(llvm::StringRef *, size_t n_lines); + + bool ParseExportReduceCount(llvm::StringRef *, size_t n_lines); + + bool ParseBuildChecksum(llvm::StringRef *, size_t n_lines); + + bool ParsePragmaCount(llvm::StringRef *, size_t n_lines); + public: RSModuleDescriptor(const lldb::ModuleSP &module) : m_module(module) {} @@ -110,6 +162,7 @@ public: const lldb::ModuleSP m_module; std::vector<RSKernelDescriptor> m_kernels; std::vector<RSGlobalDescriptor> m_globals; + std::vector<RSReductionDescriptor> m_reductions; std::map<std::string, std::string> m_pragmas; std::string m_resname; }; |