Imported Upstream version 1.12.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   const std::string backend_so = "libbackend_" + backend + SHARED_LIB_EXT;
73   void *handle = dlopen(backend_so.c_str(), RTLD_LAZY | RTLD_LOCAL);
74
75   if (handle == nullptr)
76   {
77     VERBOSE(BackendManager) << "Failed to load backend '" << backend << "' - " << dlerror() << "\n";
78     return;
79   }
80
81   VERBOSE(BackendManager) << "Successfully loaded '" << backend << "'(" << backend_so << ")\n";
82
83   {
84     // load object creator function
85     auto backend_create = (backend_create_t)dlsym(handle, "onert_backend_create");
86     if (backend_create == nullptr)
87     {
88       // TODO replace `fprintf` with `VERBOSE`
89       fprintf(stderr, "BackendManager: unable to find function `onert_backend_create` : %s\n",
90               dlerror());
91       dlclose(handle);
92       return;
93     }
94
95     // load object creator function
96     auto backend_destroy = (backend_destroy_t)dlsym(handle, "onert_backend_destroy");
97     if (backend_destroy == nullptr)
98     {
99       // TODO replace `fprintf` with `VERBOSE`
100       fprintf(stderr, "BackendManager: unable to find `function onert_backend_destroy` : %s\n",
101               dlerror());
102       dlclose(handle);
103       return;
104     }
105
106     auto backend_object =
107         std::unique_ptr<backend::Backend, backend_destroy_t>(backend_create(), backend_destroy);
108     bool initialized = backend_object->config()->initialize(); // Call initialize here?
109     if (!initialized)
110     {
111       VERBOSE(BackendManager) << backend.c_str()
112                               << " backend initialization failed. Don't use this backend"
113                               << std::endl;
114       dlclose(handle);
115       return;
116     }
117     _gen_map.emplace(backend_object->config()->id(), std::move(backend_object));
118   }
119
120   // Save backend handle (avoid warning by handle lost without dlclose())
121
122   // NOTE This is a workaround for clang-format3.9 (seems like it does not understand
123   //      "by-copy capture with an initializer"
124   // clang-format off
125   auto u_handle = std::unique_ptr<void, dlhandle_destroy_t>{
126       handle, [id = backend, filename = backend_so](void *h) {
127         if (dlclose(h) == 0)
128         {
129           VERBOSE(BackendManager) << "Successfully unloaded '" << id << "'(" << filename << ")\n";
130         }
131         else
132         {
133           VERBOSE(BackendManager)
134               << "Failed to unload backend '" << id << "'- " << dlerror() << "\n";
135         }
136       }};
137 // clang-format on
138 _handle_map.emplace(backend, std::move(u_handle));
139 }
140
141 backend::Backend *BackendManager::get(const std::string &key)
142 {
143   if (_gen_map.find(key) != _gen_map.end())
144   {
145     return _gen_map.at(key).get();
146   }
147
148   return nullptr;
149 }
150
151 const backend::Backend *BackendManager::get(const std::string &key) const
152 {
153   if (_gen_map.find(key) != _gen_map.end())
154   {
155     return _gen_map.at(key).get();
156   }
157
158   return nullptr;
159 }
160
161 const backend::controlflow::Backend *BackendManager::getControlflow() const { return _controlflow; }
162
163 } // namespace compiler
164 } // namespace onert