comaniac commented on a change in pull request #6218:
URL: https://github.com/apache/incubator-tvm/pull/6218#discussion_r468942491



##########
File path: src/target/target.cc
##########
@@ -30,20 +30,195 @@
 #include <algorithm>
 #include <stack>
 
+#include "../runtime/object_internal.h"
+
 namespace tvm {
 
 using runtime::PackedFunc;
 using runtime::TVMArgs;
 using runtime::TVMRetValue;
 
+TVM_REGISTER_NODE_TYPE(TargetNode);
+
+static inline size_t CountNumPrefixDashes(const std::string& s) {
+  size_t i = 0;
+  for (; i < s.length() && s[i] == '-'; ++i) {
+  }
+  return i;
+}
+
+static inline int FindUniqueSubstr(const std::string& str, const std::string& 
substr) {
+  size_t pos = str.find_first_of(substr);
+  if (pos == std::string::npos) {
+    return -1;
+  }
+  size_t next_pos = pos + substr.size();
+  CHECK(next_pos >= str.size() || str.find_first_of(substr, next_pos) == 
std::string::npos)
+      << "ValueError: At most one \"" << substr << "\" is allowed in "
+      << "the the given string \"" << str << "\"";
+  return pos;
+}
+
+static inline ObjectRef ParseAtomicType(uint32_t type_index, const 
std::string& str) {
+  std::istringstream is(str);
+  if (type_index == Integer::ContainerType::_GetOrAllocRuntimeTypeIndex()) {
+    int v;
+    is >> v;
+    return is.fail() ? ObjectRef(nullptr) : Integer(v);
+  } else if (type_index == 
String::ContainerType::_GetOrAllocRuntimeTypeIndex()) {
+    std::string v;
+    is >> v;
+    return is.fail() ? ObjectRef(nullptr) : String(v);
+  }
+  return ObjectRef(nullptr);
+}
+
+Map<String, ObjectRef> TargetNode::ParseAttrsFromRaw(
+    const std::vector<std::string>& options) const {
+  std::unordered_map<String, ObjectRef> attrs;
+  for (size_t iter = 0, end = options.size(); iter < end;) {
+    std::string s = options[iter++];
+    // remove the prefix dashes
+    size_t n_dashes = CountNumPrefixDashes(s);
+    CHECK(0 < n_dashes && n_dashes < s.size())
+        << "ValueError: Not an attribute key \"" << s << "\"";
+    s = s.substr(n_dashes);
+    // parse name-obj pair
+    std::string name;
+    std::string obj;
+    int pos;
+    if ((pos = FindUniqueSubstr(s, "=")) != -1) {
+      // case 1. --key=value
+      name = s.substr(0, pos);
+      obj = s.substr(pos + 1);
+      CHECK(!name.empty()) << "ValueError: Empty attribute key in \"" << 
options[iter - 1] << "\"";
+      CHECK(!obj.empty()) << "ValueError: Empty attribute in \"" << 
options[iter - 1] << "\"";
+    } else if (iter < end && options[iter][0] != '-') {
+      // case 2. --key value
+      name = s;
+      obj = options[iter++];
+    } else {
+      // case 3. --boolean-key
+      name = s;
+      obj = "1";
+    }
+    // check if `name` is invalid
+    auto it = this->kind->key2vtype_.find(name);
+    if (it == this->kind->key2vtype_.end()) {
+      std::ostringstream os;
+      os << "AttributeError: Invalid config option, cannot recognize \'" << 
name
+         << "\'. Candidates are:";
+      for (const auto& kv : this->kind->key2vtype_) {
+        os << "\n  " << kv.first;
+      }
+      LOG(FATAL) << os.str();
+    }
+    // check if `name` has been set once
+    CHECK(!attrs.count(name)) << "AttributeError: key \"" << name
+                              << "\" appears more than once in the target 
string";
+    // then `name` is valid, let's parse them
+    // only several types are supported when parsing raw string
+    const auto& info = it->second;
+    ObjectRef parsed_obj(nullptr);
+    if (info.type_index != ArrayNode::_type_index) {
+      parsed_obj = ParseAtomicType(info.type_index, obj);
+    } else {
+      Array<ObjectRef> array;
+      std::string item;
+      bool failed = false;
+      uint32_t type_index = info.key->type_index;
+      for (std::istringstream is(obj); std::getline(is, item, ',');) {
+        ObjectRef parsed_obj = ParseAtomicType(type_index, item);
+        if (parsed_obj.defined()) {
+          array.push_back(parsed_obj);
+        } else {
+          failed = true;
+          break;
+        }
+      }
+      if (!failed) {
+        parsed_obj = std::move(array);
+      }
+    }
+    if (!parsed_obj.defined()) {
+      LOG(FATAL) << "ValueError: Cannot parse type \"" << info.type_key << "\""
+                 << ", where attribute key is \"" << name << "\""
+                 << ", and attribute is \"" << obj << "\"";
+    }
+    attrs[name] = std::move(parsed_obj);
+  }
+  // set default attribute values if they do not exist
+  for (const auto& kv : this->kind->key2default_) {
+    if (!attrs.count(kv.first)) {
+      attrs[kv.first] = kv.second;
+    }
+  }
+  return attrs;
+}
+
+static inline Optional<String> StringifyAtomicType(const ObjectRef& obj) {
+  if (const auto* p = obj.as<IntImmNode>()) {
+    return String(std::to_string(p->value));
+  }
+  if (const auto* p = obj.as<StringObj>()) {
+    return GetRef<String>(p);
+  }
+  return NullOpt;
+}
+
+static inline Optional<String> JoinString(const std::vector<String>& array, 
char separator) {
+  if (array.empty()) {
+    return NullOpt;
+  }
+  std::ostringstream os;
+  os << array[0];
+  for (size_t i = 1; i < array.size(); ++i) {
+    os << separator << array[i];
+  }
+  return String(os.str());
+}
+
+Optional<String> TargetNode::StringifyAttrsToRaw(const Map<String, ObjectRef>& 
attrs) const {
+  std::ostringstream os;
+  std::vector<String> keys;
+  for (const auto& kv : attrs) {
+    keys.push_back(kv.first);
+  }
+  std::sort(keys.begin(), keys.end());
+  std::vector<String> result;
+  for (const auto& key : keys) {
+    const ObjectRef& obj = attrs[key];
+    Optional<String> value = NullOpt;
+    if (const auto* array = obj.as<ArrayNode>()) {
+      std::vector<String> items;
+      for (const ObjectRef& item : *array) {

Review comment:
       No we don't...




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to