diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 000000000..4b4042400 Binary files /dev/null and b/.DS_Store differ diff --git a/.bazelrc b/.bazelrc deleted file mode 100644 index e56bae6ae..000000000 --- a/.bazelrc +++ /dev/null @@ -1,3 +0,0 @@ -# To support new bazelrc file list: -# https://github.com/bazelbuild/bazel/issues/4502 -import %workspace%/tools/bazel.rc diff --git a/.gitignore b/.gitignore index 649ee4f4f..207a62f0f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.gitignore bazel-* build/* cmake-build/ @@ -39,3 +40,17 @@ __pycache__ *.egg-info .mace_run .model +_fa_out +BuildProducts.txt +compileInfo.txt +opt_conformer.txt +opt_transformer.txt +opt_hifigan.txt +output.txt +outputs_fa_out +._qxx +log +log + +acc_conformer.txt +conformer_vaild.txt \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index fe0f17c6e..adb380c5a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,5 @@ # new CUDA support requires 3.8 for Linux/Mac, and 3.9 for Windows cmake_minimum_required(VERSION 3.2 FATAL_ERROR) -message("CMAKE_VERSION: ${CMAKE_VERSION}") project(mace C CXX) option(MACE_ENABLE_CPU "whether to enable CPU support" OFF) @@ -19,8 +18,31 @@ option(MACE_ENABLE_OPT_SIZE "whether to build with optimized binary size" ON) option(MACE_ENABLE_OBFUSCATE "whether to build with code obfuscation" ON) option(MACE_ENABLE_CCACHE "whether to build with ccache" ON) option(MACE_ENABLE_CODE_MODE "whether to use code mode" OFF) +option(MACE_ENABLE_RPCMEM "whether to use rpcmem" OFF) +message("CMAKE_VERSION: ${CMAKE_VERSION}") +message("CROSSTOOL_ROOT: ${CROSSTOOL_ROOT}") +message("CMAKE_TOOLCHAIN_FILE: ${CMAKE_TOOLCHAIN_FILE}") message("CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}") +message("MACE_ENABLE_CPU = ${MACE_ENABLE_CPU} ") +message("MACE_ENABLE_NEON = ${MACE_ENABLE_NEON} ") +message("MACE_ENABLE_QUANTIZE = ${MACE_ENABLE_QUANTIZE} ") +message("MACE_ENABLE_OPENCL = ${MACE_ENABLE_OPENCL} ") +message("MACE_ENABLE_CUDA = ${MACE_ENABLE_CUDA} ") +message("MACE_ENABLE_HEXAGON_DSP = ${MACE_ENABLE_HEXAGON_DSP} ") +message("MACE_ENABLE_HEXAGON_HTA = ${MACE_ENABLE_HEXAGON_HTA} ") +message("MACE_ENABLE_MTK_APU = ${MACE_ENABLE_MTK_APU} ") +message("MACE_ENABLE_BFLOAT16 = ${MACE_ENABLE_BFLOAT16} ") +message("MACE_ENABLE_FP16 = ${MACE_ENABLE_FP16} ") +message("MACE_ENABLE_QNN = ${MACE_ENABLE_QNN} ") +message("MACE_ENABLE_TESTS = ${MACE_ENABLE_TESTS} ") +message("MACE_ENABLE_BENCHMARKS = ${MACE_ENABLE_BENCHMARKS} ") +message("MACE_ENABLE_OPT_SIZE = ${MACE_ENABLE_OPT_SIZE} ") +message("MACE_ENABLE_OBFUSCATE = ${MACE_ENABLE_OBFUSCATE} ") +message("MACE_ENABLE_CCACHE = ${MACE_ENABLE_CCACHE} ") +message("MACE_ENABLE_CODE_MODE = ${MACE_ENABLE_CODE_MODE}") +message("MACE_ENABLE_RPCMEM = ${MACE_ENABLE_RPCMEM}") + string(TOLOWER ${CMAKE_SYSTEM_NAME} MACE_OS) string(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} MACE_TARGET) @@ -40,7 +62,10 @@ if(MACE_ENABLE_OPT_SIZE) if(APPLE) set(MACE_LINKER_FLAGS "${MACE_LINKER_FLAGS} -Wl,-dead_strip -Wl,-dead_strip_dylibs") else(APPLE) - set(MACE_LINKER_FLAGS "${MACE_LINKER_FLAGS} -Wl,--strip-all -Wl,--gc-sections") + set(MACE_LINKER_FLAGS "${MACE_LINKER_FLAGS} -Wl,--gc-sections") + if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug")) + set(MACE_LINKER_FLAGS "${MACE_LINKER_FLAGS} -Wl,--strip-all") + endif() set(MACE_CC_FLAGS "${MACE_CC_FLAGS} -ffunction-sections -fdata-sections") endif(APPLE) set(MACE_CC_FLAGS "${MACE_CC_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden") @@ -57,7 +82,7 @@ endif(MACE_ENABLE_CODE_MODE) if(ANDROID) set(MACE_CODE_CC_FLAGS "${MACE_CODE_CC_FLAGS} -Wall -Werror -Wno-error=unused-command-line-argument -Wno-error=unevaluated-expression -Wno-error=tautological-compare") else(ANDROID) - set(MACE_CODE_CC_FLAGS "${MACE_CODE_CC_FLAGS} -Wall -Werror") + set(MACE_CODE_CC_FLAGS "${MACE_CODE_CC_FLAGS} -Wall -Werror -Wno-strict-aliasing") endif(ANDROID) set(MACE_CODE_CC_FLAGS "${MACE_CODE_CC_FLAGS} -std=c++11 -D_GLIBCXX_USE_C99_MATH_TR1") @@ -102,28 +127,25 @@ if(MACE_ENABLE_RPCMEM) endif(MACE_ENABLE_RPCMEM) if(MACE_ENABLE_HEXAGON_DSP OR MACE_ENABLE_HEXAGON_HTA) - if(ANDROID_ABI STREQUAL "arm64-v8a") + set(MACE_ENABLE_HEXAGON ON) + if(ANDROID_ABI STREQUAL "arm64-v8a" OR QNX) # Use gold linker to avoid linking check of libcdsprpc.so set(MACE_LINKER_FLAGS "${MACE_LINKER_FLAGS} -fuse-ld=gold") - endif(ANDROID_ABI STREQUAL "arm64-v8a") + endif() endif(MACE_ENABLE_HEXAGON_DSP OR MACE_ENABLE_HEXAGON_HTA) if(MACE_ENABLE_HEXAGON_DSP) - if(NOT ANDROID) - message(FATAL_ERROR "Hexagon DSP is only supported on Android") - endif(NOT ANDROID) - # TODO => -DMACE_ENABLE_HEXAGON_DSP + if(NOT ANDROID AND NOT QNX) + message(FATAL_ERROR "Hexagon DSP is only supported on Android and Qnx") + endif() + add_definitions(-DMACE_ENABLE_RPCMEM) add_definitions(-DMACE_ENABLE_HEXAGON) endif(MACE_ENABLE_HEXAGON_DSP) -if(MACE_ENABLE_RPCMEM) - add_definitions(-DMACE_ENABLE_RPCMEM) -endif(MACE_ENABLE_RPCMEM) - if(MACE_ENABLE_HEXAGON_HTA) - if(NOT ANDROID) - message(FATAL_ERROR "Hexagon HTA is only supported on Android") - endif(NOT ANDROID) + if(NOT ANDROID AND NOT QNX) + message(FATAL_ERROR "Hexagon HTA is only supported on Android and Qnx") + endif() add_definitions(-DMACE_ENABLE_HEXAGON_HTA) add_definitions(-DMACE_ENABLE_HTA) endif(MACE_ENABLE_HEXAGON_HTA) diff --git a/WORKSPACE b/WORKSPACE deleted file mode 100644 index 27acc2514..000000000 --- a/WORKSPACE +++ /dev/null @@ -1,163 +0,0 @@ -workspace(name = "mace") - -# generate version and opencl kernel code. -load("//repository/git:git_configure.bzl", "git_version_repository") -load("//repository/opencl-kernel:opencl_kernel_configure.bzl", "encrypt_opencl_kernel_repository") - -git_version_repository(name = "local_version_config") - -encrypt_opencl_kernel_repository(name = "local_opencl_kernel_encrypt") - -# proto_library rules implicitly depend on @com_google_protobuf//:protoc, -# which is the proto-compiler. -# This statement defines the @com_google_protobuf repo. -http_archive( - name = "com_google_protobuf", - sha256 = "d7a221b3d4fb4f05b7473795ccea9e05dab3b8721f6286a95fffbffc2d926f8b", - strip_prefix = "protobuf-3.6.1", - urls = [ - "https://cnbj1.fds.api.xiaomi.com/mace/third-party/protobuf/protobuf-3.6.1.zip", - "https://github.com/google/protobuf/archive/v3.6.1.zip", - ], -) - -new_http_archive( - name = "gtest", - build_file = "third_party/googletest/googletest.BUILD", - sha256 = "f3ed3b58511efd272eb074a3a6d6fb79d7c2e6a0e374323d1e6bcbcc1ef141bf", - strip_prefix = "googletest-release-1.8.0", - urls = [ - "https://cnbj1.fds.api.xiaomi.com/mace/third-party/googletest/googletest-release-1.8.0.zip", - "https://github.com/google/googletest/archive/release-1.8.0.zip", - ], -) - -new_http_archive( - name = "opencl_headers", - build_file = "third_party/opencl-headers/opencl-headers.BUILD", - sha256 = "e08f3c77a76f0e3d9ef886c7a7245757a831fdf5bc2c554587f57adb9226f53a", - strip_prefix = "OpenCL-Headers-2021.06.30", - urls = [ - "https://cnbj1.fds.api.xiaomi.com/mace/third-party/OpenCL-Headers/OpenCL-Headers-2021.06.30.zip", - "https://github.com/KhronosGroup/OpenCL-Headers/archive/refs/tags/v2021.06.30.zip", - ], -) - -new_http_archive( - name = "opencl_clhpp", - build_file = "third_party/opencl-clhpp/opencl-clhpp.BUILD", - sha256 = "767c2e9589739cfca814cbb94c57bcbb3112d94f1a8cafffa8a5cc3a5de00d12", - strip_prefix = "OpenCL-CLHPP-2.0.15", - urls = [ - "https://cnbj1.fds.api.xiaomi.com/mace/third-party/OpenCL-CLHPP/OpenCL-CLHPP-2.0.15.zip", - "https://github.com/KhronosGroup/OpenCL-CLHPP/archive/refs/tags/v2.0.15.zip", - ], -) - -new_http_archive( - name = "half", - build_file = "third_party/half/half.BUILD", - sha256 = "0f514a1e877932b21dc5edc26a148ddc700b6af2facfed4c030ca72f74d0219e", - strip_prefix = "half-code-356-trunk", - urls = [ - "https://cnbj1.fds.api.xiaomi.com/mace/third-party/half/half-code-356-trunk.zip", - ], -) - -new_http_archive( - name = "eigen", - build_file = "third_party/eigen3/eigen.BUILD", - sha256 = "ca7beac153d4059c02c8fc59816c82d54ea47fe58365e8aded4082ded0b820c4", - strip_prefix = "eigen-eigen-f3a22f35b044", - urls = [ - "http://cnbj1.fds.api.xiaomi.com/mace/third-party/eigen/f3a22f35b044.tar.gz", - "http://mirror.bazel.build/bitbucket.org/eigen/eigen/get/f3a22f35b044.tar.gz", - "https://bitbucket.org/eigen/eigen/get/f3a22f35b044.tar.gz", - ], -) - -http_archive( - name = "gemmlowp", - sha256 = "d445e5a0ef6ae18dcb68adb3c38245708cb357c0e1e51cb752dd933b7c975314", - strip_prefix = "gemmlowp-76272a197495297154e97cdcb624a52581165497", - urls = [ - "http://cnbj1.fds.api.xiaomi.com/mace/third-party/gemmlowp/gemmlowp-76272a197495297154e97cdcb624a52581165497.zip", - ], -) - -http_archive( - name = "tflite", - sha256 = "6f2671a02fe635a82c289c8c40a6e5bc24670ff1d4c3c2ab4a7aa9b825256a18", - strip_prefix = "tensorflow-mace-d73e88fc830320d3818ac24e57cd441820a85cc9", - urls = [ - "http://cnbj1.fds.api.xiaomi.com/mace/third-party/tflite/tensorflow-mace-d73e88fc830320d3818ac24e57cd441820a85cc9.zip", - ], -) - -new_http_archive( - name = "six_archive", - build_file = "third_party/six/six.BUILD", - sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a", - strip_prefix = "six-1.10.0", - urls = [ - "https://cnbj1.fds.api.xiaomi.com/mace/third-party/six/six-1.10.0.tar.gz", - "http://mirror.bazel.build/pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz", - "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz", - ], -) - -bind( - name = "six", - actual = "@six_archive//:six", -) - -http_archive( - # v2.2.0 + fix of include path - name = "com_github_gflags_gflags", - sha256 = "16903f6bb63c00689eee3bf7fb4b8f242934f6c839ce3afc5690f71b712187f9", - strip_prefix = "gflags-30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26e", - urls = [ - "https://cnbj1.fds.api.xiaomi.com/mace/third-party/gflags/gflags-30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26e.zip", - "https://github.com/gflags/gflags/archive/30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26e.zip", - ], -) - -bind( - name = "gflags", - actual = "@com_github_gflags_gflags//:gflags", -) - -bind( - name = "gflags_nothreads", - actual = "@com_github_gflags_gflags//:gflags_nothreads", -) - -# Set up Android NDK -android_ndk_repository( - name = "androidndk", - # Android 5.0 - api_level = 21, -) - -# Set up default cross compilers for arm linux -new_http_archive( - name = "gcc_linaro_7_3_1_arm_linux_gnueabihf", - build_file = "third_party/compilers/arm_compiler.BUILD", - sha256 = "7248bf105d0d468887a9b8a7120bb281ac8ad0223d9cb3d00dc7c2d498485d91", - strip_prefix = "gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabihf", - urls = [ - "https://cnbj1.fds.api.xiaomi.com/mace/third-party/gcc-linaro/gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabihf.tar.xz", - "https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/arm-linux-gnueabihf/gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabihf.tar.xz", - ], -) - -new_http_archive( - name = "gcc_linaro_7_3_1_aarch64_linux_gnu", - build_file = "third_party/compilers/aarch64_compiler.BUILD", - sha256 = "73eed74e593e2267504efbcf3678918bb22409ab7afa3dc7c135d2c6790c2345", - strip_prefix = "gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu", - urls = [ - "https://cnbj1.fds.api.xiaomi.com/mace/third-party/gcc-linaro/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz", - "https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/aarch64-linux-gnu/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz", - ], -) diff --git a/cmake/toolchains/aarch64-linux-gnu.cmake b/cmake/toolchains/aarch64-linux-gnu.cmake index aff7afab1..92c9ba63e 100644 --- a/cmake/toolchains/aarch64-linux-gnu.cmake +++ b/cmake/toolchains/aarch64-linux-gnu.cmake @@ -4,12 +4,12 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) -set(CMAKE_C_COMPILER "${CROSSTOOL_ROOT}/bin/aarch64-linux-gnu-gcc") +set( "${CROSSTOOL_ROOT}/bin/aarch64-linux-gnu-gcc") set(CMAKE_CXX_COMPILER "${CROSSTOOL_ROOT}/bin/aarch64-linux-gnu-g++") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(CMAKE_FIND_ROOCMAKE_C_COMPILERT_PATH_MODE_PACKAGE ONLY) set(CMAKE_CXX_FLAGS "-march=armv8-a ${CMAKE_CXX_FLAGS}") diff --git a/cmake/toolchains/qnx.cmake b/cmake/toolchains/qnx.cmake new file mode 100644 index 000000000..665aecb10 --- /dev/null +++ b/cmake/toolchains/qnx.cmake @@ -0,0 +1,13 @@ +set(CMAKE_SYSTEM_NAME QNX) +set(CMAKE_SYSTEM_PROCESSOR aarch64) + +set(CMAKE_C_COMPILER "${CROSSTOOL_ROOT}/qnx700/host/linux/x86_64/usr/bin/ntoaarch64-gcc") +set(CMAKE_CXX_COMPILER "${CROSSTOOL_ROOT}/qnx700/host/linux/x86_64/usr/bin/ntoaarch64-g++") +set(CMAKE_FIND_ROOT_PATH "${CROSSTOOL_ROOT}/qnx700/target/qnx7") + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +set(CMAKE_CXX_FLAGS "-D_XOPEN_SOURCE=500 -D_QNX_SOURCE ${CMAKE_CXX_FLAGS} -Wno-unused-variable") +set(MACE_CC_FLAGS "-D_XOPEN_SOURCE=500 -D_QNX_SOURCE ${MACE_CC_FLAGS}") \ No newline at end of file diff --git a/include/mace/port/env.h b/include/mace/port/env.h index c0b711b3d..12c6938f2 100644 --- a/include/mace/port/env.h +++ b/include/mace/port/env.h @@ -22,10 +22,14 @@ #include #include -#ifdef _WIN32 +#if defined(_WIN32) #include #endif +#if defined(__QNX__) +void *memalign(size_t __alignment, size_t __size); +#endif + #include #include "mace/public/mace.h" @@ -101,7 +105,7 @@ inline MaceStatus Memalign(void **memptr, size_t alignment, size_t size) { return MaceStatus::MACE_SUCCESS; } #else -#if defined(__ANDROID__) || defined(__hexagon__) +#if defined(__ANDROID__) || defined(__hexagon__) || defined(__QNX__) *memptr = memalign(alignment, size); if (*memptr == nullptr) { return MaceStatus::MACE_OUT_OF_RESOURCES; diff --git a/include/mace/utils/dbg.h b/include/mace/utils/dbg.h new file mode 100644 index 000000000..c657fcd1a --- /dev/null +++ b/include/mace/utils/dbg.h @@ -0,0 +1,1007 @@ +/***************************************************************************** + + dbg(...) macro + +License (MIT): + + Copyright (c) 2019 David Peter + + 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. + +*****************************************************************************/ + +#ifndef DBG_MACRO_DBG_H +#define DBG_MACRO_DBG_H + +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#define DBG_MACRO_UNIX +#elif defined(_MSC_VER) +#define DBG_MACRO_WINDOWS +#endif + +#ifndef DBG_MACRO_NO_WARNING +#pragma message("WARNING: the 'dbg.h' header is included in your code base") +#endif // DBG_MACRO_NO_WARNING + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DBG_MACRO_UNIX +#include +#endif + +#if __cplusplus >= 201703L +#define DBG_MACRO_CXX_STANDARD 17 +#elif __cplusplus >= 201402L +#define DBG_MACRO_CXX_STANDARD 14 +#else +#define DBG_MACRO_CXX_STANDARD 11 +#endif + +#if DBG_MACRO_CXX_STANDARD >= 17 +#include +#include +#endif + +namespace dbg { + +inline bool isColorizedOutputEnabled() { +#if defined(DBG_MACRO_FORCE_COLOR) + return true; +#elif defined(DBG_MACRO_UNIX) + return isatty(fileno(stderr)); +#else + return true; +#endif +} + +struct time {}; + +namespace pretty_function { + +// Compiler-agnostic version of __PRETTY_FUNCTION__ and constants to +// extract the template argument in `type_name_impl` + +#if defined(__clang__) +#define DBG_MACRO_PRETTY_FUNCTION __PRETTY_FUNCTION__ +static constexpr size_t PREFIX_LENGTH = + sizeof("const char *dbg::type_name_impl() [T = ") - 1; +static constexpr size_t SUFFIX_LENGTH = sizeof("]") - 1; +#elif defined(__GNUC__) && !defined(__clang__) +#define DBG_MACRO_PRETTY_FUNCTION __PRETTY_FUNCTION__ +static constexpr size_t PREFIX_LENGTH = + sizeof("const char* dbg::type_name_impl() [with T = ") - 1; +static constexpr size_t SUFFIX_LENGTH = sizeof("]") - 1; +#elif defined(_MSC_VER) +#define DBG_MACRO_PRETTY_FUNCTION __FUNCSIG__ +static constexpr size_t PREFIX_LENGTH = + sizeof("const char *__cdecl dbg::type_name_impl<") - 1; +static constexpr size_t SUFFIX_LENGTH = sizeof(">(void)") - 1; +#else +#error "This compiler is currently not supported by dbg_macro." +#endif + +} // namespace pretty_function + +// Formatting helpers + +template +struct print_formatted { + static_assert(std::is_integral::value, + "Only integral types are supported."); + + print_formatted(T value, int numeric_base) + : inner(value), base(numeric_base) {} + + operator T() const { return inner; } + + const char* prefix() const { + switch (base) { + case 8: + return "0o"; + case 16: + return "0x"; + case 2: + return "0b"; + default: + return ""; + } + } + + T inner; + int base; +}; + +template +print_formatted hex(T value) { + return print_formatted{value, 16}; +} + +template +print_formatted oct(T value) { + return print_formatted{value, 8}; +} + +template +print_formatted bin(T value) { + return print_formatted{value, 2}; +} + +// Implementation of 'type_name()' + +template +const char* type_name_impl() { + return DBG_MACRO_PRETTY_FUNCTION; +} + +template +struct type_tag {}; + +template +typename std::enable_if<(std::rank::value == 0), std::string>::type +get_type_name(type_tag) { + namespace pf = pretty_function; + + std::string type = type_name_impl(); + return type.substr(pf::PREFIX_LENGTH, + type.size() - pf::PREFIX_LENGTH - pf::SUFFIX_LENGTH); +} + +template +std::string type_name() { + if (std::is_volatile::value) { + if (std::is_pointer::value) { + return type_name::type>() + " volatile"; + } else { + return "volatile " + type_name::type>(); + } + } + if (std::is_const::value) { + if (std::is_pointer::value) { + return type_name::type>() + " const"; + } else { + return "const " + type_name::type>(); + } + } + if (std::is_pointer::value) { + return type_name::type>() + "*"; + } + if (std::is_lvalue_reference::value) { + return type_name::type>() + "&"; + } + if (std::is_rvalue_reference::value) { + return type_name::type>() + "&&"; + } + return get_type_name(type_tag{}); +} + +// Prefer bitsize variant over standard integral types +#define DBG_MACRO_REGISTER_TYPE_ASSOC(t_std, t_bit) \ + inline constexpr const char* get_type_name(type_tag) { \ + return std::is_same::value ? #t_bit : #t_std; \ + } + +DBG_MACRO_REGISTER_TYPE_ASSOC(unsigned char, uint8_t) +DBG_MACRO_REGISTER_TYPE_ASSOC(unsigned short, uint16_t) +DBG_MACRO_REGISTER_TYPE_ASSOC(unsigned int, uint32_t) +DBG_MACRO_REGISTER_TYPE_ASSOC(unsigned long, uint64_t) +DBG_MACRO_REGISTER_TYPE_ASSOC(signed char, int8_t) +DBG_MACRO_REGISTER_TYPE_ASSOC(short, int16_t) +DBG_MACRO_REGISTER_TYPE_ASSOC(int, int32_t) +DBG_MACRO_REGISTER_TYPE_ASSOC(long, int64_t) + +inline std::string get_type_name(type_tag) { + return "std::string"; +} + +template +typename std::enable_if<(std::rank::value == 1), std::string>::type +get_array_dim() { + return "[" + std::to_string(std::extent::value) + "]"; +} + +template +typename std::enable_if<(std::rank::value > 1), std::string>::type +get_array_dim() { + return "[" + std::to_string(std::extent::value) + "]" + + get_array_dim::type>(); +} + +template +typename std::enable_if<(std::rank::value > 0), std::string>::type +get_type_name(type_tag) { + return type_name::type>() + get_array_dim(); +} + +template +std::string get_type_name(type_tag>) { + return "std::array<" + type_name() + ", " + std::to_string(N) + ">"; +} + +template +std::string get_type_name(type_tag>>) { + return "std::vector<" + type_name() + ">"; +} + +template +std::string get_type_name(type_tag>) { + return "std::pair<" + type_name() + ", " + type_name() + ">"; +} + +template +std::string type_list_to_string() { + std::string result; + auto unused = {(result += type_name() + ", ", 0)..., 0}; + static_cast(unused); + +#if DBG_MACRO_CXX_STANDARD >= 17 + if constexpr (sizeof...(T) > 0) { +#else + if (sizeof...(T) > 0) { +#endif + result.pop_back(); + result.pop_back(); + } + return result; +} + +template +std::string get_type_name(type_tag>) { + return "std::tuple<" + type_list_to_string() + ">"; +} + +template +inline std::string get_type_name(type_tag>) { + return type_name(); +} + +// Implementation of 'is_detected' to specialize for container-like types + +namespace detail_detector { + +struct nonesuch { + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + void operator=(nonesuch const&) = delete; +}; + +template +using void_t = void; + +template + class Op, + class... Args> +struct detector { + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> { + using value_t = std::true_type; + using type = Op; +}; + +} // namespace detail_detector + +template