blob: bbcadd21b4273441d52f7dd1d6eaeb6ae4d4df08 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*!
* \file stackvm_module.cc
*/
#include "stackvm_module.h"
#include <dmlc/memory_io.h>
#include <tvm/runtime/module.h>
#include <tvm/runtime/registry.h>
#include <memory>
#include <unordered_map>
#include <utility>
#include "../file_utils.h"
namespace tvm {
namespace runtime {
class StackVMModuleNode : public runtime::ModuleNode {
public:
const char* type_key() const final { return "stackvm"; }
PackedFunc GetFunction(const std::string& name, const ObjectPtr<Object>& sptr_to_self) final {
if (name == runtime::symbol::tvm_module_main) {
return GetFunction(entry_func_, sptr_to_self);
}
auto it = fmap_.find(name);
if (it == fmap_.end()) return PackedFunc();
const StackVM& vm = it->second;
// capture sptr_to_self to keep module node alive.
return PackedFunc(
[vm, sptr_to_self, this](TVMArgs args, TVMRetValue* rv) { vm.Run(args, this); });
}
std::string GetSource(const std::string& format) final {
std::ostringstream os;
for (const auto& kv : fmap_) {
os << "Function: " << kv.first << '\n';
os << kv.second;
}
return os.str();
}
void SaveToFile(const std::string& file_name, const std::string& format) final {
std::string data, mblob;
dmlc::MemoryStringStream writer(&data);
dmlc::Stream* strm = &writer;
strm->Write(fmap_);
strm->Write(entry_func_);
// also save imports
uint64_t num_imports = static_cast<uint64_t>(imports_.size());
strm->Write(num_imports);
for (runtime::Module im : imports_) {
ICHECK_EQ(im->imports().size(), 0U) << "Only support simply one-level hierarchy";
std::string tkey = im->type_key();
strm->Write(tkey);
im->SaveToBinary(strm);
}
SaveBinaryToFile(file_name, data);
}
static Module Create(std::unordered_map<std::string, StackVM> fmap, std::string entry_func) {
auto n = make_object<StackVMModuleNode>();
n->fmap_ = std::move(fmap);
n->entry_func_ = std::move(entry_func);
return Module(n);
}
static Module Load(dmlc::Stream* strm) {
std::unordered_map<std::string, StackVM> fmap;
std::string entry_func, data;
strm->Read(&fmap);
strm->Read(&entry_func);
auto n = make_object<StackVMModuleNode>();
n->fmap_ = std::move(fmap);
n->entry_func_ = std::move(entry_func);
uint64_t num_imports;
strm->Read(&num_imports);
for (uint64_t i = 0; i < num_imports; ++i) {
std::string tkey;
ICHECK(strm->Read(&tkey));
std::string loadkey = "runtime.module.loadbinary_";
std::string fkey = loadkey + tkey;
const PackedFunc* f = Registry::Get(fkey);
if (f == nullptr) {
std::string loaders = "";
for (auto name : Registry::ListNames()) {
if (name.rfind(loadkey, 0) == 0) {
if (loaders.size() > 0) {
loaders += ", ";
}
loaders += name.substr(loadkey.size());
}
}
ICHECK(f != nullptr)
<< "Binary was created using " << tkey
<< " but a loader of that name is not registered. Available loaders are " << loaders
<< ". Perhaps you need to recompile with this runtime enabled.";
}
Module m = (*f)(static_cast<void*>(strm));
n->imports_.emplace_back(std::move(m));
}
return Module(n);
}
static Module LoadFromFile(std::string file_name, std::string format) {
std::string data;
LoadBinaryFromFile(file_name, &data);
dmlc::MemoryStringStream reader(&data);
return Load(&reader);
}
private:
// internal function map
std::unordered_map<std::string, StackVM> fmap_;
// entry function.
std::string entry_func_;
};
Module StackVMModuleCreate(std::unordered_map<std::string, StackVM> fmap, std::string entry_func) {
return StackVMModuleNode::Create(fmap, entry_func);
}
TVM_REGISTER_GLOBAL("runtime.module.loadfile_stackvm")
.set_body_typed(StackVMModuleNode::LoadFromFile);
} // namespace runtime
} // namespace tvm