From 3b118235a245649050e8e0114f458125a8b965f4 Mon Sep 17 00:00:00 2001 From: Artur Wojcik Date: Tue, 3 Oct 2023 23:26:44 +0200 Subject: [PATCH 1/5] port class 'dynamic_loader' to Windows --- src/CMakeLists.txt | 6 +- src/dynamic_loader_win32.cpp | 92 +++++++++++++++++++++++++ src/include/migraphx/dynamic_loader.hpp | 2 + 3 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/dynamic_loader_win32.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a00242f4de8..384057d1c33 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -43,7 +43,6 @@ add_library(migraphx cpp_generator.cpp dead_code_elimination.cpp dom_info.cpp - dynamic_loader.cpp eliminate_allocation.cpp eliminate_common_subexpression.cpp eliminate_concat.cpp @@ -104,6 +103,11 @@ add_library(migraphx value.cpp verify_args.cpp ) +if(WIN32) + target_sources(migraphx PRIVATE dynamic_loader_win32.cpp) +else() + target_sources(migraphx PRIVATE dynamic_loader.cpp) +endif() configure_file(version.h.in include/migraphx/version.h) rocm_set_soversion(migraphx ${MIGRAPHX_SO_VERSION}) function(register_migraphx_ops) diff --git a/src/dynamic_loader_win32.cpp b/src/dynamic_loader_win32.cpp new file mode 100644 index 00000000000..957b8c574a3 --- /dev/null +++ b/src/dynamic_loader_win32.cpp @@ -0,0 +1,92 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2022 Advanced Micro Devices, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include +#include +#include +#include + +// cppcheck-suppress definePrefix +#define WIN32_LEAN_AND_MEAN +#include + +namespace migraphx { +inline namespace MIGRAPHX_INLINE_NS { + +struct dynamic_loader_impl +{ + dynamic_loader_impl() = default; + dynamic_loader_impl(const fs::path& p, std::shared_ptr t = nullptr) + : handle(LoadLibrary(p.string().c_str())), temp(std::move(t)) + { + if(handle == nullptr) + { + MIGRAPHX_THROW("Error loading DLL: " + p.string() + " (" + + std::to_string(GetLastError()) + ")"); + } + } + + ~dynamic_loader_impl() + { + if(handle != nullptr) + { + FreeLibrary(handle); + } + } + static std::shared_ptr from_buffer(const char* image, std::size_t size) + { + auto t = std::make_shared("migx-dynload"); + auto f = t->path / "tmp.dll"; + write_buffer(f.string(), image, size); + return std::make_shared(f, t); + } + + HMODULE handle = nullptr; + std::shared_ptr temp = nullptr; +}; + +dynamic_loader::dynamic_loader(const fs::path& p) : impl(std::make_shared(p)) +{ +} + +dynamic_loader::dynamic_loader(const char* image, std::size_t size) + : impl(dynamic_loader_impl::from_buffer(image, size)) +{ +} + +dynamic_loader::dynamic_loader(const std::vector& buffer) + : impl(dynamic_loader_impl::from_buffer(buffer.data(), buffer.size())) +{ +} + +std::shared_ptr dynamic_loader::get_symbol(const std::string& name) const +{ + FARPROC addr = GetProcAddress(impl->handle, name.c_str()); + if(addr == nullptr) + MIGRAPHX_THROW("Symbol not found: " + name + " (" + std::to_string(GetLastError()) + ")"); + return {impl, reinterpret_cast(addr)}; +} + +} // namespace MIGRAPHX_INLINE_NS +} // namespace migraphx diff --git a/src/include/migraphx/dynamic_loader.hpp b/src/include/migraphx/dynamic_loader.hpp index 6b9feee2174..aa69bed73b2 100644 --- a/src/include/migraphx/dynamic_loader.hpp +++ b/src/include/migraphx/dynamic_loader.hpp @@ -38,6 +38,7 @@ struct dynamic_loader_impl; struct MIGRAPHX_EXPORT dynamic_loader { +#ifndef _WIN32 template static fs::path path(T* address) { @@ -46,6 +47,7 @@ struct MIGRAPHX_EXPORT dynamic_loader static fs::path path(void* address); static optional try_load(const fs::path& p); +#endif dynamic_loader() = default; From e267b3ffe2a076139a9f06480e476a82d83baba5 Mon Sep 17 00:00:00 2001 From: Artur Wojcik Date: Sun, 8 Oct 2023 20:42:06 +0200 Subject: [PATCH 2/5] dynamic_loader: incorporate review feedback --- src/CMakeLists.txt | 6 +- src/dynamic_loader.cpp | 52 ++++++++++++++ src/dynamic_loader_win32.cpp | 92 ------------------------- src/include/migraphx/dynamic_loader.hpp | 2 +- src/include/migraphx/tmp_dir.hpp | 1 + 5 files changed, 55 insertions(+), 98 deletions(-) delete mode 100644 src/dynamic_loader_win32.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 384057d1c33..a00242f4de8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -43,6 +43,7 @@ add_library(migraphx cpp_generator.cpp dead_code_elimination.cpp dom_info.cpp + dynamic_loader.cpp eliminate_allocation.cpp eliminate_common_subexpression.cpp eliminate_concat.cpp @@ -103,11 +104,6 @@ add_library(migraphx value.cpp verify_args.cpp ) -if(WIN32) - target_sources(migraphx PRIVATE dynamic_loader_win32.cpp) -else() - target_sources(migraphx PRIVATE dynamic_loader.cpp) -endif() configure_file(version.h.in include/migraphx/version.h) rocm_set_soversion(migraphx ${MIGRAPHX_SO_VERSION}) function(register_migraphx_ops) diff --git a/src/dynamic_loader.cpp b/src/dynamic_loader.cpp index 7c88df5f20a..6d12697648e 100644 --- a/src/dynamic_loader.cpp +++ b/src/dynamic_loader.cpp @@ -27,11 +27,20 @@ #include #include #include + +#ifdef _WIN32 +// cppcheck-suppress definePrefix +#define WIN32_LEAN_AND_MEAN +#include +#else #include +#endif namespace migraphx { inline namespace MIGRAPHX_INLINE_NS { +#ifndef _WIN32 + void check_load_error(bool flush = false) { char* error_msg = dlerror(); @@ -81,6 +90,42 @@ fs::path dynamic_loader::path(void* address) return p; } +#else + +struct dynamic_loader_impl +{ + dynamic_loader_impl() = default; + dynamic_loader_impl(const fs::path& p, tmp_dir t = {}) + : handle{LoadLibrary(p.string().c_str())}, temp{std::move(t)} + { + if(handle == nullptr) + { + MIGRAPHX_THROW("Error loading DLL: " + p.string() + " (" + + std::to_string(GetLastError()) + ")"); + } + } + + ~dynamic_loader_impl() + { + if(handle != nullptr) + { + FreeLibrary(handle); + } + } + static std::shared_ptr from_buffer(const char* image, std::size_t size) + { + auto t = tmp_dir{"migx-dynload"}; + auto f = t.path / "tmp.dll"; + write_buffer(f.string(), image, size); + return std::make_shared(f, std::move(t)); + } + + HMODULE handle = nullptr; + tmp_dir temp; +}; + +#endif + optional dynamic_loader::try_load(const fs::path& p) { try @@ -109,12 +154,19 @@ dynamic_loader::dynamic_loader(const std::vector& buffer) std::shared_ptr dynamic_loader::get_symbol(const std::string& name) const { +#ifndef _WIN32 // flush any previous error messages check_load_error(true); void* symbol = dlsym(impl->handle.get(), name.c_str()); if(symbol == nullptr) check_load_error(); return {impl, symbol}; +#else + FARPROC addr = GetProcAddress(impl->handle, name.c_str()); + if(addr == nullptr) + MIGRAPHX_THROW("Symbol not found: " + name + " (" + std::to_string(GetLastError()) + ")"); + return {impl, reinterpret_cast(addr)}; +#endif } } // namespace MIGRAPHX_INLINE_NS diff --git a/src/dynamic_loader_win32.cpp b/src/dynamic_loader_win32.cpp deleted file mode 100644 index 957b8c574a3..00000000000 --- a/src/dynamic_loader_win32.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015-2022 Advanced Micro Devices, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include -#include -#include -#include - -// cppcheck-suppress definePrefix -#define WIN32_LEAN_AND_MEAN -#include - -namespace migraphx { -inline namespace MIGRAPHX_INLINE_NS { - -struct dynamic_loader_impl -{ - dynamic_loader_impl() = default; - dynamic_loader_impl(const fs::path& p, std::shared_ptr t = nullptr) - : handle(LoadLibrary(p.string().c_str())), temp(std::move(t)) - { - if(handle == nullptr) - { - MIGRAPHX_THROW("Error loading DLL: " + p.string() + " (" + - std::to_string(GetLastError()) + ")"); - } - } - - ~dynamic_loader_impl() - { - if(handle != nullptr) - { - FreeLibrary(handle); - } - } - static std::shared_ptr from_buffer(const char* image, std::size_t size) - { - auto t = std::make_shared("migx-dynload"); - auto f = t->path / "tmp.dll"; - write_buffer(f.string(), image, size); - return std::make_shared(f, t); - } - - HMODULE handle = nullptr; - std::shared_ptr temp = nullptr; -}; - -dynamic_loader::dynamic_loader(const fs::path& p) : impl(std::make_shared(p)) -{ -} - -dynamic_loader::dynamic_loader(const char* image, std::size_t size) - : impl(dynamic_loader_impl::from_buffer(image, size)) -{ -} - -dynamic_loader::dynamic_loader(const std::vector& buffer) - : impl(dynamic_loader_impl::from_buffer(buffer.data(), buffer.size())) -{ -} - -std::shared_ptr dynamic_loader::get_symbol(const std::string& name) const -{ - FARPROC addr = GetProcAddress(impl->handle, name.c_str()); - if(addr == nullptr) - MIGRAPHX_THROW("Symbol not found: " + name + " (" + std::to_string(GetLastError()) + ")"); - return {impl, reinterpret_cast(addr)}; -} - -} // namespace MIGRAPHX_INLINE_NS -} // namespace migraphx diff --git a/src/include/migraphx/dynamic_loader.hpp b/src/include/migraphx/dynamic_loader.hpp index aa69bed73b2..4f2d55a38ef 100644 --- a/src/include/migraphx/dynamic_loader.hpp +++ b/src/include/migraphx/dynamic_loader.hpp @@ -45,9 +45,9 @@ struct MIGRAPHX_EXPORT dynamic_loader return path(reinterpret_cast(address)); } static fs::path path(void* address); +#endif static optional try_load(const fs::path& p); -#endif dynamic_loader() = default; diff --git a/src/include/migraphx/tmp_dir.hpp b/src/include/migraphx/tmp_dir.hpp index e176c0acff0..fa1547852ec 100644 --- a/src/include/migraphx/tmp_dir.hpp +++ b/src/include/migraphx/tmp_dir.hpp @@ -34,6 +34,7 @@ struct MIGRAPHX_EXPORT tmp_dir { fs::path path; tmp_dir(const std::string& prefix = ""); + tmp_dir(tmp_dir&&) = default; void execute(const std::string& exe, const std::string& args) const; From 1826c7a8725f3b2ec8f33ccac7f20385378caada Mon Sep 17 00:00:00 2001 From: Artur Wojcik Date: Mon, 9 Oct 2023 14:42:36 +0200 Subject: [PATCH 3/5] incorporate review feedback --- src/dynamic_loader.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/dynamic_loader.cpp b/src/dynamic_loader.cpp index 6d12697648e..e0b4bdba5ef 100644 --- a/src/dynamic_loader.cpp +++ b/src/dynamic_loader.cpp @@ -105,6 +105,11 @@ struct dynamic_loader_impl } } + dynamic_loader_impl(const dynamic_loader_impl&) = delete; + dynamic_loader_impl& operator=(const dynamic_loader_impl&) = delete; + + dynamic_loader_impl(dynamic_loader_impl&&) = default; + ~dynamic_loader_impl() { if(handle != nullptr) @@ -112,6 +117,7 @@ struct dynamic_loader_impl FreeLibrary(handle); } } + static std::shared_ptr from_buffer(const char* image, std::size_t size) { auto t = tmp_dir{"migx-dynload"}; From 86fd9a4902f2f2e871c8ee2ace2371d212388156 Mon Sep 17 00:00:00 2001 From: Artur Wojcik Date: Wed, 11 Oct 2023 19:14:29 +0200 Subject: [PATCH 4/5] fix cppcheck in instruction_ref.h --- src/include/migraphx/instruction_ref.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/migraphx/instruction_ref.hpp b/src/include/migraphx/instruction_ref.hpp index 706c082d0b3..cc62e53a746 100644 --- a/src/include/migraphx/instruction_ref.hpp +++ b/src/include/migraphx/instruction_ref.hpp @@ -57,7 +57,7 @@ struct instruction_ref : std::list::iterator std::is_same{})> friend bool operator!=(const T& x, const U& y) { - return !(x == y); + return not (x == y); } }; #else From e31ed7d49ddcc1f0a9a5fc4089c1208941e6da28 Mon Sep 17 00:00:00 2001 From: Artur Wojcik Date: Wed, 11 Oct 2023 19:39:41 +0200 Subject: [PATCH 5/5] fix cppcheck in instruction_ref.h (more) --- src/include/migraphx/instruction_ref.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/migraphx/instruction_ref.hpp b/src/include/migraphx/instruction_ref.hpp index cc62e53a746..eb183fb390b 100644 --- a/src/include/migraphx/instruction_ref.hpp +++ b/src/include/migraphx/instruction_ref.hpp @@ -57,7 +57,7 @@ struct instruction_ref : std::list::iterator std::is_same{})> friend bool operator!=(const T& x, const U& y) { - return not (x == y); + return not(x == y); } }; #else