0093f50fdcb8e175dfccdd2be0ce9c7a8f6a56fe
[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   {
74     const std::string backend_so = "libbackend_" + backend + SHARED_LIB_EXT;
75     void *handle = dlopen(backend_so.c_str(), RTLD_LAZY | RTLD_LOCAL);
76
77     if (handle == nullptr)
78     {
79       VERBOSE_F() << "Failed to load backend '" << backend << "' - " << dlerror() << std::endl;
80       return;
81     }
82
83     VERBOSE_F() << "Successfully loaded '" << backend << "' - " << backend_so << "\n";
84
85     {
86       // load object creator function
87       auto backend_create = (backend_create_t)dlsym(handle, "onert_backend_create");
88       if (backend_create == nullptr)
89       {
90         fprintf(stderr, "BackendManager: unable to open function onert_backend_create : %s\n",
91                 dlerror());
92         abort();
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         fprintf(stderr, "BackendManager: unable to open function onert_backend_destroy : %s\n",
100                 dlerror());
101         abort();
102       }
103
104       auto backend_object =
105           std::unique_ptr<backend::Backend, backend_destroy_t>(backend_create(), backend_destroy);
106       bool initialized = backend_object->config()->initialize(); // Call initialize here?
107       if (!initialized)
108       {
109         VERBOSE_F() << backend.c_str() << " backend initialization failed. Don't use this backend"
110                     << std::endl;
111         dlclose(handle);
112         return;
113       }
114       _gen_map.emplace(backend_object->config()->id(), std::move(backend_object));
115     }
116
117     // Save backend handle (avoid warning by handle lost without dlclose())
118     auto u_handle = std::unique_ptr<void, dlhandle_destroy_t>{handle, [](void *h) { dlclose(h); }};
119     _handle_map.emplace(backend, std::move(u_handle));
120   }
121 }
122
123 backend::Backend *BackendManager::get(const std::string &key)
124 {
125   if (_gen_map.find(key) != _gen_map.end())
126   {
127     return _gen_map.at(key).get();
128   }
129
130   return nullptr;
131 }
132
133 const backend::Backend *BackendManager::get(const std::string &key) const
134 {
135   if (_gen_map.find(key) != _gen_map.end())
136   {
137     return _gen_map.at(key).get();
138   }
139
140   return nullptr;
141 }
142
143 const backend::controlflow::Backend *BackendManager::getControlflow() const { return _controlflow; }
144
145 } // namespace compiler
146 } // namespace onert