/*! * Copyright (c) 2017 by Contributors * \file codegen.cc * \brief Common utilities to generated C style code. */ #include <tvm/codegen.h> #include <tvm/ir_pass.h> #include <tvm/runtime/registry.h> #include <tvm/runtime/module.h> #include <dmlc/memory_io.h> #include <sstream> #include <iostream> namespace tvm { namespace codegen { runtime::Module Build(const Array<LoweredFunc>& funcs, const std::string& target) { std::string mode = target; size_t pos = mode.find(' '); if (pos != std::string::npos) { mode = mode.substr(0, pos); } std::string build_f_name = "codegen.build_" + mode; // the build function. const PackedFunc* bf = runtime::Registry::Get(build_f_name); CHECK(bf != nullptr) << "Target " << target << " is not enabled"; runtime::Module m = (*bf)(funcs, target); return m; } std::string PackImportsToC(const runtime::Module& mod, bool system_lib) { std::string bin; dmlc::MemoryStringStream ms(&bin); dmlc::Stream* stream = &ms; uint64_t sz = static_cast<uint64_t>(mod->imports().size()); stream->Write(sz); for (runtime::Module im : mod->imports()) { CHECK_EQ(im->imports().size(), 0U) << "Only support simply one-level hierarchy"; std::string tkey = im->type_key(); std::string bin; stream->Write(tkey); im->SaveToBinary(stream); } // translate to C program std::ostringstream os; os << "#ifdef _WIN32\n" << "#define TVM_EXPORT __declspec(dllexport)\n" << "#else\n" << "#define TVM_EXPORT\n" << "#endif\n"; os << "#ifdef __cplusplus\n" << "extern \"C\" {\n" << "#endif\n"; os << "TVM_EXPORT extern const char " << runtime::symbol::tvm_dev_mblob << "[];\n"; uint64_t nbytes = bin.length(); os << "const char " << runtime::symbol::tvm_dev_mblob << "[" << bin.length() + sizeof(nbytes) << "] = {\n "; os << std::hex; size_t nunit = 80 / 4; for (size_t i = 0; i < sizeof(nbytes); ++i) { // sperators if (i != 0) { os << ","; } os << "0x" << ((nbytes >> (i * 8)) & 0xffUL); } for (size_t i = 0; i < bin.length(); ++i) { // sperators if ((i + sizeof(nbytes)) % nunit == 0) { os << ",\n "; } else { os << ","; } int c = bin[i]; os << "0x" << (c & 0xff); } os << "\n};\n"; if (system_lib) { os << "extern int TVMBackendRegisterSystemLibSymbol(const char*, void*);\n"; os << "static int " << runtime::symbol::tvm_dev_mblob << "_reg_ = " << "TVMBackendRegisterSystemLibSymbol(\"" << runtime::symbol::tvm_dev_mblob << "\", (void*)" << runtime::symbol::tvm_dev_mblob << ");\n"; } os << "#ifdef __cplusplus\n" << "}\n" << "#endif\n"; return os.str(); } } // namespace codegen } // namespace tvm