/* * 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 TVMRuntime.mm */ #import #include #include #include "RPCArgs.h" // internal TVM header #include <../../../src/runtime/file_utils.h> #if defined(USE_CUSTOM_DSO_LOADER) && USE_CUSTOM_DSO_LOADER == 1 // internal TVM header to achieve Library class #include <../../../3rdparty/tvm-ffi/src/ffi/extra/library_module.h> #include #endif namespace tvm { namespace runtime { namespace detail { // Override logging mechanism [[noreturn]] void LogFatalImpl(const std::string& file, int lineno, const std::string& message) { throw tvm::runtime::InternalError(file, lineno, message); } void LogMessageImpl(const std::string& file, int lineno, int level, const std::string& message) { NSLog(@"%s:%d: %s", file.c_str(), lineno, message.c_str()); } } // namespace detail TVM_FFI_STATIC_INIT_BLOCK() { namespace refl = tvm::ffi::reflection; refl::GlobalDef() .def_packed("tvm.rpc.server.workpath", [](ffi::PackedArgs args, ffi::Any* rv) { static const std::string base_ = NSTemporaryDirectory().UTF8String; const auto path = args[0].cast(); *rv = base_ + "/" + path; }) .def_packed("tvm.rpc.server.load_module", [](ffi::PackedArgs args, ffi::Any* rv) { auto name = args[0].cast(); std::string fmt = GetFileFormat(name, ""); NSString* base; if (fmt == "dylib") { // only load dylib from frameworks. NSBundle* bundle = [NSBundle mainBundle]; base = [[bundle privateFrameworksPath] stringByAppendingPathComponent:@"tvm"]; if (tvm::ffi::Function::GetGlobal("ffi.Module.load_from_file.dylib_custom")) { // Custom dso loader is present. Will use it. base = NSTemporaryDirectory(); fmt = "dylib_custom"; } } else { // Load other modules in tempdir. base = NSTemporaryDirectory(); } NSString* path = [base stringByAppendingPathComponent:[NSString stringWithUTF8String:name.c_str()]]; name = [path UTF8String]; *rv = Module::LoadFromFile(name, fmt); LOG(INFO) << "Load module from " << name << " ..."; }); } #if defined(USE_CUSTOM_DSO_LOADER) && USE_CUSTOM_DSO_LOADER == 1 // Custom dynamic library loader. Supports unsigned binary class UnsignedDSOLoader final : public Library { public: ~UnsignedDSOLoader() { if (lib_handle_) { custom_dlclose(lib_handle_); lib_handle_ = nullptr; }; } void Init(const std::string& name) { lib_handle_ = custom_dlopen(name.c_str(), RTLD_NOW | RTLD_LOCAL); TVM_FFI_ICHECK(lib_handle_ != nullptr) << "Failed to load dynamic shared library " << name << " " << custom_dlerror(); } void* GetSymbol(const char* name) final { return custom_dlsym(lib_handle_, name); } private: // Library handle void* lib_handle_{nullptr}; }; // Add UnsignedDSOLoader plugin in global registry TVM_FFI_STATIC_INIT_BLOCK() { namespace refl = tvm::ffi::reflection; refl::GlobalDef().def_packed("ffi.Module.load_from_file.dylib_custom", [](ffi::PackedArgs args, ffi::Any* rv) { auto n = ffi::make_object(); n->Init(args[0]); *rv = tvm::ffi::CreateLibraryModule(n); }); } #endif } // namespace runtime } // namespace tvm