Imported Upstream version 1.7.0
[platform/core/ml/nnfw.git] / runtime / onert / core / src / compiler / BackendManager.cc
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "compiler/BackendManager.h"
18
19 #include <memory>
20 #include <dlfcn.h>
21
22 #include "backend/Backend.h"
23 #include "backend/controlflow/Backend.h"
24 #include "backend/controlflow/Config.h"
25 #include "backend/IConfig.h"
26 #include "util/logging.h"
27 #include "util/ConfigSource.h"
28 #include "misc/string_helpers.h"
29
30 static const char *SHARED_LIB_EXT =
31 #if defined(__APPLE__) && defined(__MACH__)
32     ".dylib";
33 #else
34     ".so";
35 #endif
36
37 namespace onert
38 {
39 namespace compiler
40 {
41
42 BackendManager &BackendManager::get()
43 {
44   static BackendManager object;
45   return object;
46 }
47
48 BackendManager::BackendManager() { loadControlflowBackend(); }
49
50 void BackendManager::loadControlflowBackend()
51 {
52   auto backend_object = std::unique_ptr<backend::controlflow::Backend, backend_destroy_t>(
53       new backend::controlflow::Backend, [](backend::Backend *backend) { delete backend; });
54
55   bool initialized = backend_object->config()->initialize(); // Call initialize here?
56   if (!initialized)
57   {
58     throw std::runtime_error(backend::controlflow::Config::ID + " backend initialization failed");
59   }
60   _controlflow = backend_object.get(); // Save the controlflow backend implementation pointer
61   assert(_controlflow);
62   _gen_map.emplace(backend_object->config()->id(), std::move(backend_object));
63 }
64
65 void BackendManager::loadBackend(const std::string &backend)
66 {
67   if (get(backend) != nullptr)
68   {
69     return;
70   }
71
72   // TODO Remove indentation
73   // Workaround If backend have dynamic library with "-boost" suffix naming,
74   //            BackendManager load library with "-boost" suffix instead of library without suffix
75   //            This feature is used for custom backend extension to support additional operations
76   {
77     const std::string backend_boost_so = "libbackend_" + backend + "-boost" + SHARED_LIB_EXT;
78     const std::string backend_so = "libbackend_" + backend + SHARED_LIB_EXT;
79
80     void *handle = dlopen(backend_boost_so.c_str(), RTLD_LAZY | RTLD_LOCAL);
81     if (handle == nullptr)
82     {
83       handle = dlopen(backend_so.c_str(), RTLD_LAZY | RTLD_LOCAL);
84
85       if (handle == nullptr)
86       {
87         VERBOSE_F() << "Failed to load backend '" << backend << "' - " << dlerror() << std::endl;
88         return;
89       }
90
91       VERBOSE_F() << "Successfully loaded '" << backend << "' - " << backend_so << "\n";
92     }
93     else
94     {
95       VERBOSE_F() << "Successfully loaded '" << backend << "' - " << backend_boost_so << "\n";
96     }
97
98     {
99       // load object creator function
100       auto backend_create = (backend_create_t)dlsym(handle, "onert_backend_create");
101       if (backend_create == nullptr)
102       {
103         fprintf(stderr, "BackendManager: unable to open function onert_backend_create : %s\n",
104                 dlerror());
105         abort();
106       }
107
108       // load object creator function
109       auto backend_destroy = (backend_destroy_t)dlsym(handle, "onert_backend_destroy");
110       if (backend_destroy == nullptr)
111       {
112         fprintf(stderr, "BackendManager: unable to open function onert_backend_destroy : %s\n",
113                 dlerror());
114         abort();
115       }
116
117       auto backend_object =
118           std::unique_ptr<backend::Backend, backend_destroy_t>(backend_create(), backend_destroy);
119       bool initialized = backend_object->config()->initialize(); // Call initialize here?
120       if (!initialized)
121       {
122         VERBOSE_F() << backend.c_str() << " backend initialization failed. Don't use this backend"
123                     << std::endl;
124         dlclose(handle);
125         return;
126       }
127       _gen_map.emplace(backend_object->config()->id(), std::move(backend_object));
128     }
129
130     // Save backend handle (avoid warning by handle lost without dlclose())
131     auto u_handle = std::unique_ptr<void, dlhandle_destroy_t>{handle, [](void *h) { dlclose(h); }};
132     _handle_map.emplace(backend, std::move(u_handle));
133   }
134 }
135
136 backend::Backend *BackendManager::get(const std::string &key)
137 {
138   if (_gen_map.find(key) != _gen_map.end())
139   {
140     return _gen_map.at(key).get();
141   }
142
143   return nullptr;
144 }
145
146 const backend::Backend *BackendManager::get(const std::string &key) const
147 {
148   if (_gen_map.find(key) != _gen_map.end())
149   {
150     return _gen_map.at(key).get();
151   }
152
153   return nullptr;
154 }
155
156 const backend::controlflow::Backend *BackendManager::getControlflow() const { return _controlflow; }
157
158 } // namespace compiler
159 } // namespace onert