early-access version 1262
This commit is contained in:
parent
a5ba8b4937
commit
ac593731e0
@ -1,7 +1,7 @@
|
|||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 1261.
|
This is the source code for early-access 1262.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
657
externals/dynarmic/externals/catch/catch.hpp
vendored
657
externals/dynarmic/externals/catch/catch.hpp
vendored
File diff suppressed because it is too large
Load Diff
1
externals/dynarmic/externals/fmt/.gitignore
vendored
1
externals/dynarmic/externals/fmt/.gitignore
vendored
@ -15,6 +15,7 @@ bin/
|
|||||||
/CMakeScripts
|
/CMakeScripts
|
||||||
/doc/doxyxml
|
/doc/doxyxml
|
||||||
/doc/html
|
/doc/html
|
||||||
|
/doc/node_modules
|
||||||
virtualenv
|
virtualenv
|
||||||
/Testing
|
/Testing
|
||||||
/install_manifest.txt
|
/install_manifest.txt
|
||||||
|
75
externals/dynarmic/externals/fmt/CMakeLists.txt
vendored
75
externals/dynarmic/externals/fmt/CMakeLists.txt
vendored
@ -24,15 +24,23 @@ function(join result_var)
|
|||||||
set(${result_var} "${result}" PARENT_SCOPE)
|
set(${result_var} "${result}" PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
include(CMakeParseArguments)
|
||||||
|
|
||||||
# Sets a cache variable with a docstring joined from multiple arguments:
|
# Sets a cache variable with a docstring joined from multiple arguments:
|
||||||
# set(<variable> <value>... CACHE <type> <docstring>...)
|
# set(<variable> <value>... CACHE <type> <docstring>...)
|
||||||
# This allows splitting a long docstring for readability.
|
# This allows splitting a long docstring for readability.
|
||||||
function(set_verbose)
|
function(set_verbose)
|
||||||
cmake_parse_arguments(SET_VERBOSE "" "" "CACHE" ${ARGN})
|
# cmake_parse_arguments is broken in CMake 3.4 (cannot parse CACHE) so use
|
||||||
list(GET SET_VERBOSE_CACHE 0 type)
|
# list instead.
|
||||||
list(REMOVE_AT SET_VERBOSE_CACHE 0)
|
list(GET ARGN 0 var)
|
||||||
join(doc ${SET_VERBOSE_CACHE})
|
list(REMOVE_AT ARGN 0)
|
||||||
set(${SET_VERBOSE_UNPARSED_ARGUMENTS} CACHE ${type} ${doc})
|
list(GET ARGN 0 val)
|
||||||
|
list(REMOVE_AT ARGN 0)
|
||||||
|
list(REMOVE_AT ARGN 0)
|
||||||
|
list(GET ARGN 0 type)
|
||||||
|
list(REMOVE_AT ARGN 0)
|
||||||
|
join(doc ${ARGN})
|
||||||
|
set(${var} ${val} CACHE ${type} ${doc})
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
# Set the default CMAKE_BUILD_TYPE to Release.
|
# Set the default CMAKE_BUILD_TYPE to Release.
|
||||||
@ -44,6 +52,12 @@ if (MASTER_PROJECT AND NOT CMAKE_BUILD_TYPE)
|
|||||||
"CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
|
"CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
project(FMT CXX)
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
set_verbose(FMT_INC_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE STRING
|
||||||
|
"Installation directory for include files, a relative path "
|
||||||
|
"that will be joined to ${CMAKE_INSTALL_PREFIX}, or an arbitrary absolute path.")
|
||||||
|
|
||||||
option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF)
|
option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF)
|
||||||
option(FMT_WERROR "Halt the compilation with an error on compiler warnings."
|
option(FMT_WERROR "Halt the compilation with an error on compiler warnings."
|
||||||
OFF)
|
OFF)
|
||||||
@ -54,8 +68,7 @@ option(FMT_INSTALL "Generate the install target." ${MASTER_PROJECT})
|
|||||||
option(FMT_TEST "Generate the test target." ${MASTER_PROJECT})
|
option(FMT_TEST "Generate the test target." ${MASTER_PROJECT})
|
||||||
option(FMT_FUZZ "Generate the fuzz target." OFF)
|
option(FMT_FUZZ "Generate the fuzz target." OFF)
|
||||||
option(FMT_CUDA_TEST "Generate the cuda-test target." OFF)
|
option(FMT_CUDA_TEST "Generate the cuda-test target." OFF)
|
||||||
|
option(FMT_OS "Include core requiring OS (Windows/Posix) " ON)
|
||||||
project(FMT CXX)
|
|
||||||
|
|
||||||
# Get version from core.h
|
# Get version from core.h
|
||||||
file(READ include/fmt/core.h core_h)
|
file(READ include/fmt/core.h core_h)
|
||||||
@ -81,6 +94,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
|
|||||||
|
|
||||||
include(cxx14)
|
include(cxx14)
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
|
include(JoinPaths)
|
||||||
|
|
||||||
list(FIND CMAKE_CXX_COMPILE_FEATURES "cxx_variadic_templates" index)
|
list(FIND CMAKE_CXX_COMPILE_FEATURES "cxx_variadic_templates" index)
|
||||||
if (${index} GREATER -1)
|
if (${index} GREATER -1)
|
||||||
@ -173,7 +187,11 @@ endfunction()
|
|||||||
# Define the fmt library, its includes and the needed defines.
|
# Define the fmt library, its includes and the needed defines.
|
||||||
add_headers(FMT_HEADERS chrono.h color.h compile.h core.h format.h format-inl.h
|
add_headers(FMT_HEADERS chrono.h color.h compile.h core.h format.h format-inl.h
|
||||||
locale.h os.h ostream.h posix.h printf.h ranges.h)
|
locale.h os.h ostream.h posix.h printf.h ranges.h)
|
||||||
set(FMT_SOURCES src/format.cc src/os.cc)
|
if (FMT_OS)
|
||||||
|
set(FMT_SOURCES src/format.cc src/os.cc)
|
||||||
|
else()
|
||||||
|
set(FMT_SOURCES src/format.cc)
|
||||||
|
endif ()
|
||||||
|
|
||||||
add_library(fmt ${FMT_SOURCES} ${FMT_HEADERS} README.rst ChangeLog.rst)
|
add_library(fmt ${FMT_SOURCES} ${FMT_HEADERS} README.rst ChangeLog.rst)
|
||||||
add_library(fmt::fmt ALIAS fmt)
|
add_library(fmt::fmt ALIAS fmt)
|
||||||
@ -182,6 +200,10 @@ if (HAVE_STRTOD_L)
|
|||||||
target_compile_definitions(fmt PUBLIC FMT_LOCALE)
|
target_compile_definitions(fmt PUBLIC FMT_LOCALE)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if (MINGW)
|
||||||
|
target_compile_options(fmt PUBLIC "-Wa,-mbig-obj")
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (FMT_WERROR)
|
if (FMT_WERROR)
|
||||||
target_compile_options(fmt PRIVATE ${WERROR_FLAG})
|
target_compile_options(fmt PRIVATE ${WERROR_FLAG})
|
||||||
endif ()
|
endif ()
|
||||||
@ -193,7 +215,7 @@ target_compile_features(fmt INTERFACE ${FMT_REQUIRED_FEATURES})
|
|||||||
|
|
||||||
target_include_directories(fmt PUBLIC
|
target_include_directories(fmt PUBLIC
|
||||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||||
$<INSTALL_INTERFACE:include>)
|
$<INSTALL_INTERFACE:${FMT_INC_DIR}>)
|
||||||
|
|
||||||
set(FMT_DEBUG_POSTFIX d CACHE STRING "Debug library postfix.")
|
set(FMT_DEBUG_POSTFIX d CACHE STRING "Debug library postfix.")
|
||||||
|
|
||||||
@ -209,7 +231,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (BUILD_SHARED_LIBS)
|
if (BUILD_SHARED_LIBS)
|
||||||
if (UNIX AND NOT APPLE AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
if (UNIX AND NOT APPLE AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "SunOS" AND NOT EMSCRIPTEN)
|
||||||
# Fix rpmlint warning:
|
# Fix rpmlint warning:
|
||||||
# unused-direct-shlib-dependency /usr/lib/libformat.so.1.1.0 /lib/libm.so.6.
|
# unused-direct-shlib-dependency /usr/lib/libformat.so.1.1.0 /lib/libm.so.6.
|
||||||
target_link_libraries(fmt -Wl,--as-needed)
|
target_link_libraries(fmt -Wl,--as-needed)
|
||||||
@ -228,42 +250,36 @@ target_compile_features(fmt-header-only INTERFACE ${FMT_REQUIRED_FEATURES})
|
|||||||
|
|
||||||
target_include_directories(fmt-header-only INTERFACE
|
target_include_directories(fmt-header-only INTERFACE
|
||||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||||
$<INSTALL_INTERFACE:include>)
|
$<INSTALL_INTERFACE:${FMT_INC_DIR}>)
|
||||||
|
|
||||||
# Install targets.
|
# Install targets.
|
||||||
if (FMT_INSTALL)
|
if (FMT_INSTALL)
|
||||||
include(GNUInstallDirs)
|
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
set_verbose(FMT_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/fmt CACHE STRING
|
set_verbose(FMT_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/fmt CACHE STRING
|
||||||
"Installation directory for cmake files, relative to "
|
"Installation directory for cmake files, a relative path "
|
||||||
"${CMAKE_INSTALL_PREFIX}.")
|
"that will be joined to ${CMAKE_INSTALL_PREFIX}, or an arbitrary absolute path.")
|
||||||
set(version_config ${PROJECT_BINARY_DIR}/fmt-config-version.cmake)
|
set(version_config ${PROJECT_BINARY_DIR}/fmt-config-version.cmake)
|
||||||
set(project_config ${PROJECT_BINARY_DIR}/fmt-config.cmake)
|
set(project_config ${PROJECT_BINARY_DIR}/fmt-config.cmake)
|
||||||
set(pkgconfig ${PROJECT_BINARY_DIR}/fmt.pc)
|
set(pkgconfig ${PROJECT_BINARY_DIR}/fmt.pc)
|
||||||
set(targets_export_name fmt-targets)
|
set(targets_export_name fmt-targets)
|
||||||
|
|
||||||
set (INSTALL_TARGETS fmt)
|
|
||||||
if (TARGET fmt-header-only)
|
|
||||||
set(INSTALL_TARGETS ${INSTALL_TARGETS} fmt-header-only)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set_verbose(FMT_LIB_DIR ${CMAKE_INSTALL_LIBDIR} CACHE STRING
|
set_verbose(FMT_LIB_DIR ${CMAKE_INSTALL_LIBDIR} CACHE STRING
|
||||||
"Installation directory for libraries, relative to "
|
"Installation directory for libraries, a relative path "
|
||||||
"${CMAKE_INSTALL_PREFIX}.")
|
"that will be joined to ${CMAKE_INSTALL_PREFIX}, or an arbitrary absolute path.")
|
||||||
|
|
||||||
set_verbose(FMT_INC_DIR ${CMAKE_INSTALL_INCLUDEDIR}/fmt CACHE STRING
|
|
||||||
"Installation directory for include files, relative to "
|
|
||||||
"${CMAKE_INSTALL_PREFIX}.")
|
|
||||||
|
|
||||||
set_verbose(FMT_PKGCONFIG_DIR ${CMAKE_INSTALL_LIBDIR}/pkgconfig CACHE PATH
|
set_verbose(FMT_PKGCONFIG_DIR ${CMAKE_INSTALL_LIBDIR}/pkgconfig CACHE PATH
|
||||||
"Installation directory for pkgconfig (.pc) files, relative to "
|
"Installation directory for pkgconfig (.pc) files, a relative path "
|
||||||
"${CMAKE_INSTALL_PREFIX}.")
|
"that will be joined to ${CMAKE_INSTALL_PREFIX}, or an arbitrary absolute path.")
|
||||||
|
|
||||||
# Generate the version, config and target files into the build directory.
|
# Generate the version, config and target files into the build directory.
|
||||||
write_basic_package_version_file(
|
write_basic_package_version_file(
|
||||||
${version_config}
|
${version_config}
|
||||||
VERSION ${FMT_VERSION}
|
VERSION ${FMT_VERSION}
|
||||||
COMPATIBILITY AnyNewerVersion)
|
COMPATIBILITY AnyNewerVersion)
|
||||||
|
|
||||||
|
join_paths(libdir_for_pc_file "\${exec_prefix}" "${FMT_LIB_DIR}")
|
||||||
|
join_paths(includedir_for_pc_file "\${prefix}" "${FMT_INC_DIR}")
|
||||||
|
|
||||||
configure_file(
|
configure_file(
|
||||||
"${PROJECT_SOURCE_DIR}/support/cmake/fmt.pc.in"
|
"${PROJECT_SOURCE_DIR}/support/cmake/fmt.pc.in"
|
||||||
"${pkgconfig}"
|
"${pkgconfig}"
|
||||||
@ -272,6 +288,8 @@ if (FMT_INSTALL)
|
|||||||
${PROJECT_SOURCE_DIR}/support/cmake/fmt-config.cmake.in
|
${PROJECT_SOURCE_DIR}/support/cmake/fmt-config.cmake.in
|
||||||
${project_config}
|
${project_config}
|
||||||
INSTALL_DESTINATION ${FMT_CMAKE_DIR})
|
INSTALL_DESTINATION ${FMT_CMAKE_DIR})
|
||||||
|
|
||||||
|
set(INSTALL_TARGETS fmt fmt-header-only)
|
||||||
# Use a namespace because CMake provides better diagnostics for namespaced
|
# Use a namespace because CMake provides better diagnostics for namespaced
|
||||||
# imported targets.
|
# imported targets.
|
||||||
export(TARGETS ${INSTALL_TARGETS} NAMESPACE fmt::
|
export(TARGETS ${INSTALL_TARGETS} NAMESPACE fmt::
|
||||||
@ -292,7 +310,7 @@ if (FMT_INSTALL)
|
|||||||
|
|
||||||
install(FILES $<TARGET_PDB_FILE:${INSTALL_TARGETS}>
|
install(FILES $<TARGET_PDB_FILE:${INSTALL_TARGETS}>
|
||||||
DESTINATION ${FMT_LIB_DIR} OPTIONAL)
|
DESTINATION ${FMT_LIB_DIR} OPTIONAL)
|
||||||
install(FILES ${FMT_HEADERS} DESTINATION ${FMT_INC_DIR})
|
install(FILES ${FMT_HEADERS} DESTINATION "${FMT_INC_DIR}/fmt")
|
||||||
install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}")
|
install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
@ -308,6 +326,7 @@ endif ()
|
|||||||
# Control fuzzing independent of the unit tests.
|
# Control fuzzing independent of the unit tests.
|
||||||
if (FMT_FUZZ)
|
if (FMT_FUZZ)
|
||||||
add_subdirectory(test/fuzzing)
|
add_subdirectory(test/fuzzing)
|
||||||
|
target_compile_definitions(fmt PUBLIC FMT_FUZZ)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set(gitignore ${PROJECT_SOURCE_DIR}/.gitignore)
|
set(gitignore ${PROJECT_SOURCE_DIR}/.gitignore)
|
||||||
|
356
externals/dynarmic/externals/fmt/ChangeLog.rst
vendored
356
externals/dynarmic/externals/fmt/ChangeLog.rst
vendored
@ -1,3 +1,349 @@
|
|||||||
|
7.0.3 - 2020-08-06
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* Worked around broken ``numeric_limits`` for 128-bit integers
|
||||||
|
(`#1787 <https://github.com/fmtlib/fmt/issues/1787>`_).
|
||||||
|
|
||||||
|
* Added error reporting on missing named arguments
|
||||||
|
(`#1796 <https://github.com/fmtlib/fmt/issues/1796>`_).
|
||||||
|
|
||||||
|
* Stopped using 128-bit integers with clang-cl
|
||||||
|
(`#1800 <https://github.com/fmtlib/fmt/pull/1800>`_).
|
||||||
|
Thanks `@Kingcom <https://github.com/Kingcom>`_.
|
||||||
|
|
||||||
|
* Fixed issues in locale-specific integer formatting
|
||||||
|
(`#1782 <https://github.com/fmtlib/fmt/issues/1782>`_,
|
||||||
|
`#1801 <https://github.com/fmtlib/fmt/issues/1801>`_).
|
||||||
|
|
||||||
|
7.0.2 - 2020-07-29
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* Worked around broken ``numeric_limits`` for 128-bit integers
|
||||||
|
(`#1725 <https://github.com/fmtlib/fmt/issues/1725>`_).
|
||||||
|
|
||||||
|
* Fixed compatibility with CMake 3.4
|
||||||
|
(`#1779 <https://github.com/fmtlib/fmt/issues/1779>`_).
|
||||||
|
|
||||||
|
* Fixed handling of digit separators in locale-specific formatting
|
||||||
|
(`#1782 <https://github.com/fmtlib/fmt/issues/1782>`_).
|
||||||
|
|
||||||
|
7.0.1 - 2020-07-07
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* Updated the inline version namespace name.
|
||||||
|
|
||||||
|
* Worked around a gcc bug in mangling of alias templates
|
||||||
|
(`#1753 <https://github.com/fmtlib/fmt/issues/1753>`_).
|
||||||
|
|
||||||
|
* Fixed a linkage error on Windows
|
||||||
|
(`#1757 <https://github.com/fmtlib/fmt/issues/1757>`_).
|
||||||
|
Thanks `@Kurkin (Dmitry Kurkin) <https://github.com/Kurkin>`_.
|
||||||
|
|
||||||
|
* Fixed minor issues with the documentation.
|
||||||
|
|
||||||
|
7.0.0 - 2020-07-05
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* Reduced the library size. For example, on macOS a stripped test binary
|
||||||
|
statically linked with {fmt} `shrank from ~368k to less than 100k
|
||||||
|
<http://www.zverovich.net/2020/05/21/reducing-library-size.html>`_.
|
||||||
|
|
||||||
|
* Added a simpler and more efficient `format string compilation API
|
||||||
|
<https://fmt.dev/dev/api.html#compile-api>`_:
|
||||||
|
|
||||||
|
.. code:: c++
|
||||||
|
|
||||||
|
#include <fmt/compile.h>
|
||||||
|
|
||||||
|
// Converts 42 into std::string using the most efficient method and no
|
||||||
|
// runtime format string processing.
|
||||||
|
std::string s = fmt::format(FMT_COMPILE("{}"), 42);
|
||||||
|
|
||||||
|
The old ``fmt::compile`` API is now deprecated.
|
||||||
|
|
||||||
|
* Optimized integer formatting: ``format_to`` with format string compilation
|
||||||
|
and a stack-allocated buffer is now `faster than to_chars on both
|
||||||
|
libc++ and libstdc++
|
||||||
|
<http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_.
|
||||||
|
|
||||||
|
* Optimized handling of small format strings. For example,
|
||||||
|
|
||||||
|
.. code:: c++
|
||||||
|
|
||||||
|
fmt::format("Result: {}: ({},{},{},{})", str1, str2, str3, str4, str5)
|
||||||
|
|
||||||
|
is now ~40% faster (`#1685 <https://github.com/fmtlib/fmt/issues/1685>`_).
|
||||||
|
|
||||||
|
* Applied extern templates to improve compile times when using the core API
|
||||||
|
and ``fmt/format.h`` (`#1452 <https://github.com/fmtlib/fmt/issues/1452>`_).
|
||||||
|
For example, on macOS with clang the compile time of a test translation unit
|
||||||
|
dropped from 2.3s to 0.3s with ``-O2`` and from 0.6s to 0.3s with the default
|
||||||
|
settings (``-O0``).
|
||||||
|
|
||||||
|
Before (``-O2``)::
|
||||||
|
|
||||||
|
% time c++ -c test.cc -I include -std=c++17 -O2
|
||||||
|
c++ -c test.cc -I include -std=c++17 -O2 2.22s user 0.08s system 99% cpu 2.311 total
|
||||||
|
|
||||||
|
After (``-O2``)::
|
||||||
|
|
||||||
|
% time c++ -c test.cc -I include -std=c++17 -O2
|
||||||
|
c++ -c test.cc -I include -std=c++17 -O2 0.26s user 0.04s system 98% cpu 0.303 total
|
||||||
|
|
||||||
|
Before (default)::
|
||||||
|
|
||||||
|
% time c++ -c test.cc -I include -std=c++17
|
||||||
|
c++ -c test.cc -I include -std=c++17 0.53s user 0.06s system 98% cpu 0.601 total
|
||||||
|
|
||||||
|
After (default)::
|
||||||
|
|
||||||
|
% time c++ -c test.cc -I include -std=c++17
|
||||||
|
c++ -c test.cc -I include -std=c++17 0.24s user 0.06s system 98% cpu 0.301 total
|
||||||
|
|
||||||
|
It is still recommended to use ``fmt/core.h`` instead of ``fmt/format.h`` but
|
||||||
|
the compile time difference is now smaller. Thanks
|
||||||
|
`@alex3d <https://github.com/alex3d>`_ for the suggestion.
|
||||||
|
|
||||||
|
* Named arguments are now stored on stack (no dynamic memory allocations) and
|
||||||
|
the compiled code is more compact and efficient. For example
|
||||||
|
|
||||||
|
.. code:: c++
|
||||||
|
|
||||||
|
#include <fmt/core.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
fmt::print("The answer is {answer}\n", fmt::arg("answer", 42));
|
||||||
|
}
|
||||||
|
|
||||||
|
compiles to just (`godbolt <https://godbolt.org/z/NcfEp_>`__)
|
||||||
|
|
||||||
|
.. code:: asm
|
||||||
|
|
||||||
|
.LC0:
|
||||||
|
.string "answer"
|
||||||
|
.LC1:
|
||||||
|
.string "The answer is {answer}\n"
|
||||||
|
main:
|
||||||
|
sub rsp, 56
|
||||||
|
mov edi, OFFSET FLAT:.LC1
|
||||||
|
mov esi, 23
|
||||||
|
movabs rdx, 4611686018427387905
|
||||||
|
lea rax, [rsp+32]
|
||||||
|
lea rcx, [rsp+16]
|
||||||
|
mov QWORD PTR [rsp+8], 1
|
||||||
|
mov QWORD PTR [rsp], rax
|
||||||
|
mov DWORD PTR [rsp+16], 42
|
||||||
|
mov QWORD PTR [rsp+32], OFFSET FLAT:.LC0
|
||||||
|
mov DWORD PTR [rsp+40], 0
|
||||||
|
call fmt::v6::vprint(fmt::v6::basic_string_view<char>,
|
||||||
|
fmt::v6::format_args)
|
||||||
|
xor eax, eax
|
||||||
|
add rsp, 56
|
||||||
|
ret
|
||||||
|
|
||||||
|
.L.str.1:
|
||||||
|
.asciz "answer"
|
||||||
|
|
||||||
|
* Implemented compile-time checks for dynamic width and precision
|
||||||
|
(`#1614 <https://github.com/fmtlib/fmt/issues/1614>`_):
|
||||||
|
|
||||||
|
.. code:: c++
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
fmt::print(FMT_STRING("{0:{1}}"), 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
now gives a compilation error because argument 1 doesn't exist::
|
||||||
|
|
||||||
|
In file included from test.cc:1:
|
||||||
|
include/fmt/format.h:2726:27: error: constexpr variable 'invalid_format' must be
|
||||||
|
initialized by a constant expression
|
||||||
|
FMT_CONSTEXPR_DECL bool invalid_format =
|
||||||
|
^
|
||||||
|
...
|
||||||
|
include/fmt/core.h:569:26: note: in call to
|
||||||
|
'&checker(s, {}).context_->on_error(&"argument not found"[0])'
|
||||||
|
if (id >= num_args_) on_error("argument not found");
|
||||||
|
^
|
||||||
|
|
||||||
|
* Added sentinel support to ``fmt::join``
|
||||||
|
(`#1689 <https://github.com/fmtlib/fmt/pull/1689>`_)
|
||||||
|
|
||||||
|
.. code:: c++
|
||||||
|
|
||||||
|
struct zstring_sentinel {};
|
||||||
|
bool operator==(const char* p, zstring_sentinel) { return *p == '\0'; }
|
||||||
|
bool operator!=(const char* p, zstring_sentinel) { return *p != '\0'; }
|
||||||
|
|
||||||
|
struct zstring {
|
||||||
|
const char* p;
|
||||||
|
const char* begin() const { return p; }
|
||||||
|
zstring_sentinel end() const { return {}; }
|
||||||
|
};
|
||||||
|
|
||||||
|
auto s = fmt::format("{}", fmt::join(zstring{"hello"}, "_"));
|
||||||
|
// s == "h_e_l_l_o"
|
||||||
|
|
||||||
|
Thanks `@BRevzin (Barry Revzin) <https://github.com/BRevzin>`_.
|
||||||
|
|
||||||
|
* Added support for named args, ``clear`` and ``reserve`` to
|
||||||
|
``dynamic_format_arg_store``
|
||||||
|
(`#1655 <https://github.com/fmtlib/fmt/issues/1655>`_,
|
||||||
|
`#1663 <https://github.com/fmtlib/fmt/pull/1663>`_,
|
||||||
|
`#1674 <https://github.com/fmtlib/fmt/pull/1674>`_,
|
||||||
|
`#1677 <https://github.com/fmtlib/fmt/pull/1677>`_).
|
||||||
|
Thanks `@vsolontsov-ll (Vladimir Solontsov)
|
||||||
|
<https://github.com/vsolontsov-ll>`_.
|
||||||
|
|
||||||
|
* Added support for the ``'c'`` format specifier to integral types for
|
||||||
|
compatibility with ``std::format``
|
||||||
|
(`#1652 <https://github.com/fmtlib/fmt/issues/1652>`_).
|
||||||
|
|
||||||
|
* Replaced the ``'n'`` format specifier with ``'L'`` for compatibility with
|
||||||
|
``std::format`` (`#1624 <https://github.com/fmtlib/fmt/issues/1624>`_).
|
||||||
|
The ``'n'`` specifier can be enabled via the ``FMT_DEPRECATED_N_SPECIFIER``
|
||||||
|
macro.
|
||||||
|
|
||||||
|
* The ``'='`` format specifier is now disabled by default for compatibility with
|
||||||
|
``std::format``. It can be enabled via the ``FMT_DEPRECATED_NUMERIC_ALIGN``
|
||||||
|
macro.
|
||||||
|
|
||||||
|
* Removed the following deprecated APIs:
|
||||||
|
|
||||||
|
* ``FMT_STRING_ALIAS`` and ``fmt`` macros - replaced by ``FMT_STRING``
|
||||||
|
* ``fmt::basic_string_view::char_type`` - replaced by
|
||||||
|
``fmt::basic_string_view::value_type``
|
||||||
|
* ``convert_to_int``
|
||||||
|
* ``format_arg_store::types``
|
||||||
|
* ``*parse_context`` - replaced by ``*format_parse_context``
|
||||||
|
* ``FMT_DEPRECATED_INCLUDE_OS``
|
||||||
|
* ``FMT_DEPRECATED_PERCENT`` - incompatible with ``std::format``
|
||||||
|
* ``*writer`` - replaced by compiled format API
|
||||||
|
|
||||||
|
* Renamed the ``internal`` namespace to ``detail``
|
||||||
|
(`#1538 <https://github.com/fmtlib/fmt/issues/1538>`_). The former is still
|
||||||
|
provided as an alias if the ``FMT_USE_INTERNAL`` macro is defined.
|
||||||
|
|
||||||
|
* Improved compatibility between ``fmt::printf`` with the standard specs
|
||||||
|
(`#1595 <https://github.com/fmtlib/fmt/issues/1595>`_,
|
||||||
|
`#1682 <https://github.com/fmtlib/fmt/pull/1682>`_,
|
||||||
|
`#1683 <https://github.com/fmtlib/fmt/pull/1683>`_,
|
||||||
|
`#1687 <https://github.com/fmtlib/fmt/pull/1687>`_,
|
||||||
|
`#1699 <https://github.com/fmtlib/fmt/pull/1699>`_).
|
||||||
|
Thanks `@rimathia <https://github.com/rimathia>`_.
|
||||||
|
|
||||||
|
* Fixed handling of ``operator<<`` overloads that use ``copyfmt``
|
||||||
|
(`#1666 <https://github.com/fmtlib/fmt/issues/1666>`_).
|
||||||
|
|
||||||
|
* Added the ``FMT_OS`` CMake option to control inclusion of OS-specific APIs
|
||||||
|
in the fmt target. This can be useful for embedded platforms
|
||||||
|
(`#1654 <https://github.com/fmtlib/fmt/issues/1654>`_,
|
||||||
|
`#1656 <https://github.com/fmtlib/fmt/pull/1656>`_).
|
||||||
|
Thanks `@kwesolowski (Krzysztof Wesolowski)
|
||||||
|
<https://github.com/kwesolowski>`_.
|
||||||
|
|
||||||
|
* Replaced ``FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION`` with the ``FMT_FUZZ``
|
||||||
|
macro to prevent interferring with fuzzing of projects using {fmt}
|
||||||
|
(`#1650 <https://github.com/fmtlib/fmt/pull/1650>`_).
|
||||||
|
Thanks `@asraa (Asra Ali) <https://github.com/asraa>`_.
|
||||||
|
|
||||||
|
* Fixed compatibility with emscripten
|
||||||
|
(`#1636 <https://github.com/fmtlib/fmt/issues/1636>`_,
|
||||||
|
`#1637 <https://github.com/fmtlib/fmt/pull/1637>`_).
|
||||||
|
Thanks `@ArthurSonzogni (Arthur Sonzogni)
|
||||||
|
<https://github.com/ArthurSonzogni>`_.
|
||||||
|
|
||||||
|
* Improved documentation
|
||||||
|
(`#704 <https://github.com/fmtlib/fmt/issues/704>`_,
|
||||||
|
`#1643 <https://github.com/fmtlib/fmt/pull/1643>`_,
|
||||||
|
`#1660 <https://github.com/fmtlib/fmt/pull/1660>`_,
|
||||||
|
`#1681 <https://github.com/fmtlib/fmt/pull/1681>`_,
|
||||||
|
`#1691 <https://github.com/fmtlib/fmt/pull/1691>`_,
|
||||||
|
`#1706 <https://github.com/fmtlib/fmt/pull/1706>`_,
|
||||||
|
`#1714 <https://github.com/fmtlib/fmt/pull/1714>`_,
|
||||||
|
`#1721 <https://github.com/fmtlib/fmt/pull/1721>`_,
|
||||||
|
`#1739 <https://github.com/fmtlib/fmt/pull/1739>`_,
|
||||||
|
`#1740 <https://github.com/fmtlib/fmt/pull/1740>`_,
|
||||||
|
`#1741 <https://github.com/fmtlib/fmt/pull/1741>`_,
|
||||||
|
`#1751 <https://github.com/fmtlib/fmt/pull/1751>`_).
|
||||||
|
Thanks `@senior7515 (Alexander Gallego) <https://github.com/senior7515>`_,
|
||||||
|
`@lsr0 (Lindsay Roberts) <https://github.com/lsr0>`_,
|
||||||
|
`@puetzk (Kevin Puetz) <https://github.com/puetzk>`_,
|
||||||
|
`@fpelliccioni (Fernando Pelliccioni) <https://github.com/fpelliccioni>`_,
|
||||||
|
Alexey Kuzmenko, `@jelly (jelle van der Waa) <https://github.com/jelly>`_,
|
||||||
|
`@claremacrae (Clare Macrae) <https://github.com/claremacrae>`_,
|
||||||
|
`@jiapengwen (文佳鹏) <https://github.com/jiapengwen>`_,
|
||||||
|
`@gsjaardema (Greg Sjaardema) <https://github.com/gsjaardema>`_,
|
||||||
|
`@alexey-milovidov <https://github.com/alexey-milovidov>`_.
|
||||||
|
|
||||||
|
* Implemented various build configuration fixes and improvements
|
||||||
|
(`#1603 <https://github.com/fmtlib/fmt/pull/1603>`_,
|
||||||
|
`#1657 <https://github.com/fmtlib/fmt/pull/1657>`_,
|
||||||
|
`#1702 <https://github.com/fmtlib/fmt/pull/1702>`_,
|
||||||
|
`#1728 <https://github.com/fmtlib/fmt/pull/1728>`_).
|
||||||
|
Thanks `@scramsby (Scott Ramsby) <https://github.com/scramsby>`_,
|
||||||
|
`@jtojnar (Jan Tojnar) <https://github.com/jtojnar>`_,
|
||||||
|
`@orivej (Orivej Desh) <https://github.com/orivej>`_,
|
||||||
|
`@flagarde <https://github.com/flagarde>`_.
|
||||||
|
|
||||||
|
* Fixed various warnings and compilation issues
|
||||||
|
(`#1616 <https://github.com/fmtlib/fmt/pull/1616>`_,
|
||||||
|
`#1620 <https://github.com/fmtlib/fmt/issues/1620>`_,
|
||||||
|
`#1622 <https://github.com/fmtlib/fmt/issues/1622>`_,
|
||||||
|
`#1625 <https://github.com/fmtlib/fmt/issues/1625>`_,
|
||||||
|
`#1627 <https://github.com/fmtlib/fmt/pull/1627>`_,
|
||||||
|
`#1628 <https://github.com/fmtlib/fmt/issues/1628>`_,
|
||||||
|
`#1629 <https://github.com/fmtlib/fmt/pull/1629>`_,
|
||||||
|
`#1631 <https://github.com/fmtlib/fmt/issues/1631>`_,
|
||||||
|
`#1633 <https://github.com/fmtlib/fmt/pull/1633>`_,
|
||||||
|
`#1649 <https://github.com/fmtlib/fmt/pull/1649>`_,
|
||||||
|
`#1658 <https://github.com/fmtlib/fmt/issues/1658>`_,
|
||||||
|
`#1661 <https://github.com/fmtlib/fmt/pull/1661>`_,
|
||||||
|
`#1667 <https://github.com/fmtlib/fmt/pull/1667>`_,
|
||||||
|
`#1668 <https://github.com/fmtlib/fmt/issues/1668>`_,
|
||||||
|
`#1669 <https://github.com/fmtlib/fmt/pull/1669>`_,
|
||||||
|
`#1692 <https://github.com/fmtlib/fmt/issues/1692>`_,
|
||||||
|
`#1696 <https://github.com/fmtlib/fmt/pull/1696>`_,
|
||||||
|
`#1697 <https://github.com/fmtlib/fmt/pull/1697>`_,
|
||||||
|
`#1707 <https://github.com/fmtlib/fmt/issues/1707>`_,
|
||||||
|
`#1712 <https://github.com/fmtlib/fmt/pull/1712>`_,
|
||||||
|
`#1716 <https://github.com/fmtlib/fmt/pull/1716>`_,
|
||||||
|
`#1722 <https://github.com/fmtlib/fmt/pull/1722>`_,
|
||||||
|
`#1724 <https://github.com/fmtlib/fmt/issues/1724>`_,
|
||||||
|
`#1729 <https://github.com/fmtlib/fmt/pull/1729>`_,
|
||||||
|
`#1738 <https://github.com/fmtlib/fmt/pull/1738>`_,
|
||||||
|
`#1742 <https://github.com/fmtlib/fmt/issues/1742>`_,
|
||||||
|
`#1743 <https://github.com/fmtlib/fmt/issues/1743>`_,
|
||||||
|
`#1744 <https://github.com/fmtlib/fmt/pull/1744>`_,
|
||||||
|
`#1747 <https://github.com/fmtlib/fmt/issues/1747>`_,
|
||||||
|
`#1750 <https://github.com/fmtlib/fmt/pull/1750>`_).
|
||||||
|
Thanks `@gsjaardema (Greg Sjaardema) <https://github.com/gsjaardema>`_,
|
||||||
|
`@gabime (Gabi Melman) <https://github.com/gabime>`_,
|
||||||
|
`@johnor (Johan) <https://github.com/johnor>`_,
|
||||||
|
`@Kurkin (Dmitry Kurkin) <https://github.com/Kurkin>`_,
|
||||||
|
`@invexed (James Beach) <https://github.com/invexed>`_,
|
||||||
|
`@peterbell10 <https://github.com/peterbell10>`_,
|
||||||
|
`@daixtrose (Markus Werle) <https://github.com/daixtrose>`_,
|
||||||
|
`@petrutlucian94 (Lucian Petrut) <https://github.com/petrutlucian94>`_,
|
||||||
|
`@Neargye (Daniil Goncharov) <https://github.com/Neargye>`_,
|
||||||
|
`@ambitslix (Attila M. Szilagyi) <https://github.com/ambitslix>`_,
|
||||||
|
`@gabime (Gabi Melman) <https://github.com/gabime>`_,
|
||||||
|
`@erthink (Leonid Yuriev) <https://github.com/erthink>`_,
|
||||||
|
`@tohammer (Tobias Hammer) <https://github.com/tohammer>`_,
|
||||||
|
`@0x8000-0000 (Florin Iucha) <https://github.com/0x8000-0000>`_.
|
||||||
|
|
||||||
|
6.2.1 - 2020-05-09
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* Fixed ostream support in ``sprintf``
|
||||||
|
(`#1631 <https://github.com/fmtlib/fmt/issues/1631>`_).
|
||||||
|
|
||||||
|
* Fixed type detection when using implicit conversion to ``string_view`` and
|
||||||
|
ostream ``operator<<`` inconsistently
|
||||||
|
(`#1662 <https://github.com/fmtlib/fmt/issues/1662>`_).
|
||||||
|
|
||||||
6.2.0 - 2020-04-05
|
6.2.0 - 2020-04-05
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
@ -24,7 +370,7 @@
|
|||||||
|
|
||||||
if ``S`` is not formattable.
|
if ``S`` is not formattable.
|
||||||
|
|
||||||
* Reduced library size by ~10%.
|
* Reduced the library size by ~10%.
|
||||||
|
|
||||||
* Always print decimal point if ``#`` is specified
|
* Always print decimal point if ``#`` is specified
|
||||||
(`#1476 <https://github.com/fmtlib/fmt/issues/1476>`_,
|
(`#1476 <https://github.com/fmtlib/fmt/issues/1476>`_,
|
||||||
@ -587,16 +933,16 @@
|
|||||||
#include <fmt/compile.h>
|
#include <fmt/compile.h>
|
||||||
|
|
||||||
auto f = fmt::compile<int>("{}");
|
auto f = fmt::compile<int>("{}");
|
||||||
std::string s = fmt::format(f, 42); // can be called multiple times to format
|
std::string s = fmt::format(f, 42); // can be called multiple times to
|
||||||
// different values
|
// format different values
|
||||||
// s == "42"
|
// s == "42"
|
||||||
|
|
||||||
It moves the cost of parsing a format string outside of the format function
|
It moves the cost of parsing a format string outside of the format function
|
||||||
which can be beneficial when identically formatting many objects of the same
|
which can be beneficial when identically formatting many objects of the same
|
||||||
types. Thanks `@stryku (Mateusz Janek) <https://github.com/stryku>`_.
|
types. Thanks `@stryku (Mateusz Janek) <https://github.com/stryku>`_.
|
||||||
|
|
||||||
* Added the ``%`` format specifier that formats floating-point values as
|
* Added experimental ``%`` format specifier that formats floating-point values
|
||||||
percentages (`#1060 <https://github.com/fmtlib/fmt/pull/1060>`_,
|
as percentages (`#1060 <https://github.com/fmtlib/fmt/pull/1060>`_,
|
||||||
`#1069 <https://github.com/fmtlib/fmt/pull/1069>`_,
|
`#1069 <https://github.com/fmtlib/fmt/pull/1069>`_,
|
||||||
`#1071 <https://github.com/fmtlib/fmt/pull/1071>`_):
|
`#1071 <https://github.com/fmtlib/fmt/pull/1071>`_):
|
||||||
|
|
||||||
|
233
externals/dynarmic/externals/fmt/README.rst
vendored
233
externals/dynarmic/externals/fmt/README.rst
vendored
@ -9,7 +9,9 @@
|
|||||||
|
|
||||||
.. image:: https://oss-fuzz-build-logs.storage.googleapis.com/badges/libfmt.svg
|
.. image:: https://oss-fuzz-build-logs.storage.googleapis.com/badges/libfmt.svg
|
||||||
:alt: fmt is continuously fuzzed att oss-fuzz
|
:alt: fmt is continuously fuzzed att oss-fuzz
|
||||||
:target: https://bugs.chromium.org/p/oss-fuzz/issues/list?colspec=ID%20Type%20Component%20Status%20Proj%20Reported%20Owner%20Summary&q=proj%3Dlibfmt&can=1
|
:target: https://bugs.chromium.org/p/oss-fuzz/issues/list?\
|
||||||
|
colspec=ID%20Type%20Component%20Status%20Proj%20Reported%20Owner%20\
|
||||||
|
Summary&q=proj%3Dlibfmt&can=1
|
||||||
|
|
||||||
.. image:: https://img.shields.io/badge/stackoverflow-fmt-blue.svg
|
.. image:: https://img.shields.io/badge/stackoverflow-fmt-blue.svg
|
||||||
:alt: Ask questions at StackOverflow with the tag fmt
|
:alt: Ask questions at StackOverflow with the tag fmt
|
||||||
@ -20,42 +22,46 @@ It can be used as a safe and fast alternative to (s)printf and iostreams.
|
|||||||
|
|
||||||
`Documentation <https://fmt.dev/latest/>`__
|
`Documentation <https://fmt.dev/latest/>`__
|
||||||
|
|
||||||
Q&A: ask questions on `StackOverflow with the tag fmt <https://stackoverflow.com/questions/tagged/fmt>`_.
|
Q&A: ask questions on `StackOverflow with the tag fmt
|
||||||
|
<https://stackoverflow.com/questions/tagged/fmt>`_.
|
||||||
|
|
||||||
Features
|
Features
|
||||||
--------
|
--------
|
||||||
|
|
||||||
* Replacement-based `format API <https://fmt.dev/dev/api.html>`_ with
|
* Simple `format API <https://fmt.dev/dev/api.html>`_ with positional arguments
|
||||||
positional arguments for localization.
|
for localization
|
||||||
|
* Implementation of `C++20 std::format
|
||||||
|
<https://en.cppreference.com/w/cpp/utility/format>`__
|
||||||
* `Format string syntax <https://fmt.dev/dev/syntax.html>`_ similar to the one
|
* `Format string syntax <https://fmt.dev/dev/syntax.html>`_ similar to the one
|
||||||
of `str.format <https://docs.python.org/3/library/stdtypes.html#str.format>`_
|
of Python's
|
||||||
in Python.
|
`format <https://docs.python.org/3/library/stdtypes.html#str.format>`_
|
||||||
* Safe `printf implementation
|
* Safe `printf implementation
|
||||||
<https://fmt.dev/latest/api.html#printf-formatting>`_ including
|
<https://fmt.dev/latest/api.html#printf-formatting>`_ including
|
||||||
the POSIX extension for positional arguments.
|
the POSIX extension for positional arguments
|
||||||
* Implementation of `C++20 std::format <https://en.cppreference.com/w/cpp/utility/format>`__.
|
* Extensibility: support for user-defined types
|
||||||
* Support for user-defined types.
|
|
||||||
* High performance: faster than common standard library implementations of
|
* High performance: faster than common standard library implementations of
|
||||||
`printf <https://en.cppreference.com/w/cpp/io/c/fprintf>`_ and
|
`printf <https://en.cppreference.com/w/cpp/io/c/fprintf>`_,
|
||||||
iostreams. See `Speed tests`_ and `Fast integer to string conversion in C++
|
iostreams, ``to_string`` and ``to_chars``, see `Speed tests`_ and
|
||||||
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
|
`Converting a hundred million integers to strings per second
|
||||||
|
<http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_
|
||||||
* Small code size both in terms of source code (the minimum configuration
|
* Small code size both in terms of source code (the minimum configuration
|
||||||
consists of just three header files, ``core.h``, ``format.h`` and
|
consists of just three header files, ``core.h``, ``format.h`` and
|
||||||
``format-inl.h``) and compiled code. See `Compile time and code bloat`_.
|
``format-inl.h``) and compiled code. See `Compile time and code bloat`_
|
||||||
* Reliability: the library has an extensive set of `unit tests
|
* Reliability: the library has an extensive set of `unit tests
|
||||||
<https://github.com/fmtlib/fmt/tree/master/test>`_ and is continuously fuzzed.
|
<https://github.com/fmtlib/fmt/tree/master/test>`_ and is continuously fuzzed
|
||||||
* Safety: the library is fully type safe, errors in format strings can be
|
* Safety: the library is fully type safe, errors in format strings can be
|
||||||
reported at compile time, automatic memory management prevents buffer overflow
|
reported at compile time, automatic memory management prevents buffer overflow
|
||||||
errors.
|
errors
|
||||||
* Ease of use: small self-contained code base, no external dependencies,
|
* Ease of use: small self-contained code base, no external dependencies,
|
||||||
permissive MIT `license
|
permissive MIT `license
|
||||||
<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_
|
<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_
|
||||||
* `Portability <https://fmt.dev/latest/index.html#portability>`_ with
|
* `Portability <https://fmt.dev/latest/index.html#portability>`_ with
|
||||||
consistent output across platforms and support for older compilers.
|
consistent output across platforms and support for older compilers
|
||||||
* Clean warning-free codebase even on high warning levels
|
* Clean warning-free codebase even on high warning levels
|
||||||
(``-Wall -Wextra -pedantic``).
|
(``-Wall -Wextra -pedantic``)
|
||||||
* Support for wide strings.
|
* Locale-independence by default
|
||||||
* Optional header-only configuration enabled with the ``FMT_HEADER_ONLY`` macro.
|
* Support for wide strings
|
||||||
|
* Optional header-only configuration enabled with the ``FMT_HEADER_ONLY`` macro
|
||||||
|
|
||||||
See the `documentation <https://fmt.dev/latest/>`_ for more details.
|
See the `documentation <https://fmt.dev/latest/>`_ for more details.
|
||||||
|
|
||||||
@ -66,37 +72,49 @@ Print ``Hello, world!`` to ``stdout``:
|
|||||||
|
|
||||||
.. code:: c++
|
.. code:: c++
|
||||||
|
|
||||||
fmt::print("Hello, {}!", "world"); // Python-like format string syntax
|
#include <fmt/core.h>
|
||||||
fmt::printf("Hello, %s!", "world"); // printf format string syntax
|
|
||||||
|
int main() {
|
||||||
|
fmt::print("Hello, world!\n");
|
||||||
|
}
|
||||||
|
|
||||||
Format a string and use positional arguments:
|
Format a string:
|
||||||
|
|
||||||
|
.. code:: c++
|
||||||
|
|
||||||
|
std::string s = fmt::format("The answer is {}.", 42);
|
||||||
|
// s == "The answer is 42."
|
||||||
|
|
||||||
|
Format a string using positional arguments:
|
||||||
|
|
||||||
.. code:: c++
|
.. code:: c++
|
||||||
|
|
||||||
std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy");
|
std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy");
|
||||||
// s == "I'd rather be happy than right."
|
// s == "I'd rather be happy than right."
|
||||||
|
|
||||||
|
Print a chrono duration:
|
||||||
|
|
||||||
|
.. code:: c++
|
||||||
|
|
||||||
|
#include <fmt/chrono.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
fmt::print("Elapsed time: {}", 42ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
prints "Elapsed time: 42ms".
|
||||||
|
|
||||||
Check a format string at compile time:
|
Check a format string at compile time:
|
||||||
|
|
||||||
.. code:: c++
|
.. code:: c++
|
||||||
|
|
||||||
// test.cc
|
// test.cc
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
std::string s = format(FMT_STRING("{2}"), 42);
|
std::string s = format(FMT_STRING("{:d}"), "hello");
|
||||||
|
|
||||||
.. code::
|
gives a compile-time error because ``d`` is an invalid format specifier for a
|
||||||
|
string.
|
||||||
$ c++ -Iinclude -std=c++14 test.cc
|
|
||||||
...
|
|
||||||
test.cc:4:17: note: in instantiation of function template specialization 'fmt::v5::format<S, int>' requested here
|
|
||||||
std::string s = format(FMT_STRING("{2}"), 42);
|
|
||||||
^
|
|
||||||
include/fmt/core.h:778:19: note: non-constexpr function 'on_error' cannot be used in a constant expression
|
|
||||||
ErrorHandler::on_error(message);
|
|
||||||
^
|
|
||||||
include/fmt/format.h:2226:16: note: in call to '&checker.context_->on_error(&"argument index out of range"[0])'
|
|
||||||
context_.on_error("argument index out of range");
|
|
||||||
^
|
|
||||||
|
|
||||||
Use {fmt} as a safe portable replacement for ``itoa``
|
Use {fmt} as a safe portable replacement for ``itoa``
|
||||||
(`godbolt <https://godbolt.org/g/NXmpU4>`_):
|
(`godbolt <https://godbolt.org/g/NXmpU4>`_):
|
||||||
@ -113,7 +131,7 @@ Format objects of user-defined types via a simple `extension API
|
|||||||
|
|
||||||
.. code:: c++
|
.. code:: c++
|
||||||
|
|
||||||
#include "fmt/format.h"
|
#include <fmt/format.h>
|
||||||
|
|
||||||
struct date {
|
struct date {
|
||||||
int year, month, day;
|
int year, month, day;
|
||||||
@ -174,15 +192,15 @@ Folly Format folly::format 2.23
|
|||||||
{fmt} is the fastest of the benchmarked methods, ~35% faster than ``printf``.
|
{fmt} is the fastest of the benchmarked methods, ~35% faster than ``printf``.
|
||||||
|
|
||||||
The above results were generated by building ``tinyformat_test.cpp`` on macOS
|
The above results were generated by building ``tinyformat_test.cpp`` on macOS
|
||||||
10.14.6 with ``clang++ -O3 -DSPEED_TEST -DHAVE_FORMAT``, and taking the best of
|
10.14.6 with ``clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT``, and taking the
|
||||||
three runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"``
|
best of three runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"``
|
||||||
or equivalent is filled 2,000,000 times with output sent to ``/dev/null``; for
|
or equivalent is filled 2,000,000 times with output sent to ``/dev/null``; for
|
||||||
further details refer to the `source
|
further details refer to the `source
|
||||||
<https://github.com/fmtlib/format-benchmark/blob/master/tinyformat_test.cpp>`_.
|
<https://github.com/fmtlib/format-benchmark/blob/master/tinyformat_test.cpp>`_.
|
||||||
|
|
||||||
{fmt} is 10x faster than ``std::ostringstream`` and ``sprintf`` on floating-point
|
{fmt} is up to 10x faster than ``std::ostringstream`` and ``sprintf`` on
|
||||||
formatting (`dtoa-benchmark <https://github.com/fmtlib/dtoa-benchmark>`_)
|
floating-point formatting (`dtoa-benchmark <https://github.com/fmtlib/dtoa-benchmark>`_)
|
||||||
and as fast as `double-conversion <https://github.com/google/double-conversion>`_:
|
and faster than `double-conversion <https://github.com/google/double-conversion>`_:
|
||||||
|
|
||||||
.. image:: https://user-images.githubusercontent.com/576385/69767160-cdaca400-112f-11ea-9fc5-347c9f83caad.png
|
.. image:: https://user-images.githubusercontent.com/576385/69767160-cdaca400-112f-11ea-9fc5-347c9f83caad.png
|
||||||
:target: https://fmt.dev/unknown_mac64_clang10.0.html
|
:target: https://fmt.dev/unknown_mac64_clang10.0.html
|
||||||
@ -264,12 +282,15 @@ or the bloat test::
|
|||||||
Projects using this library
|
Projects using this library
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
* `0 A.D. <https://play0ad.com/>`_: A free, open-source, cross-platform real-time
|
* `0 A.D. <https://play0ad.com/>`_: A free, open-source, cross-platform
|
||||||
strategy game
|
real-time strategy game
|
||||||
|
|
||||||
* `AMPL/MP <https://github.com/ampl/mp>`_:
|
* `AMPL/MP <https://github.com/ampl/mp>`_:
|
||||||
An open-source library for mathematical programming
|
An open-source library for mathematical programming
|
||||||
|
|
||||||
|
* `Aseprite <https://github.com/aseprite/aseprite>`_:
|
||||||
|
Animated sprite editor & pixel art tool
|
||||||
|
|
||||||
* `AvioBook <https://www.aviobook.aero/en>`_: A comprehensive aircraft
|
* `AvioBook <https://www.aviobook.aero/en>`_: A comprehensive aircraft
|
||||||
operations suite
|
operations suite
|
||||||
|
|
||||||
@ -279,9 +300,21 @@ Projects using this library
|
|||||||
|
|
||||||
* `ccache <https://ccache.dev/>`_: A compiler cache
|
* `ccache <https://ccache.dev/>`_: A compiler cache
|
||||||
|
|
||||||
|
* `ClickHouse <https://github.com/ClickHouse/ClickHouse>`_: analytical database management system
|
||||||
|
|
||||||
* `CUAUV <http://cuauv.org/>`_: Cornell University's autonomous underwater
|
* `CUAUV <http://cuauv.org/>`_: Cornell University's autonomous underwater
|
||||||
vehicle
|
vehicle
|
||||||
|
|
||||||
|
* `Drake <https://drake.mit.edu/>`_: A planning, control, and analysis toolbox
|
||||||
|
for nonlinear dynamical systems (MIT)
|
||||||
|
|
||||||
|
* `Envoy <https://lyft.github.io/envoy/>`_: C++ L7 proxy and communication bus
|
||||||
|
(Lyft)
|
||||||
|
|
||||||
|
* `FiveM <https://fivem.net/>`_: a modification framework for GTA V
|
||||||
|
|
||||||
|
* `Folly <https://github.com/facebook/folly>`_: Facebook open-source library
|
||||||
|
|
||||||
* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
|
* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
|
||||||
Player vs Player Gaming Network with tweaks
|
Player vs Player Gaming Network with tweaks
|
||||||
|
|
||||||
@ -291,27 +324,25 @@ Projects using this library
|
|||||||
|
|
||||||
* `Kodi <https://kodi.tv/>`_ (formerly xbmc): Home theater software
|
* `Kodi <https://kodi.tv/>`_ (formerly xbmc): Home theater software
|
||||||
|
|
||||||
* `Lifeline <https://github.com/peter-clark/lifeline>`_: A 2D game
|
* `Knuth <https://kth.cash/>`_: High-performance Bitcoin full-node
|
||||||
|
|
||||||
* `Drake <https://drake.mit.edu/>`_: A planning, control, and analysis toolbox
|
* `Microsoft Verona <https://github.com/microsoft/verona>`_:
|
||||||
for nonlinear dynamical systems (MIT)
|
Research programming language for concurrent ownership
|
||||||
|
|
||||||
* `Envoy <https://lyft.github.io/envoy/>`_: C++ L7 proxy and communication bus
|
|
||||||
(Lyft)
|
|
||||||
|
|
||||||
* `FiveM <https://fivem.net/>`_: a modification framework for GTA V
|
|
||||||
|
|
||||||
* `MongoDB <https://mongodb.com/>`_: Distributed document database
|
* `MongoDB <https://mongodb.com/>`_: Distributed document database
|
||||||
|
|
||||||
* `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: A small tool to
|
* `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: A small tool to
|
||||||
generate randomized datasets
|
generate randomized datasets
|
||||||
|
|
||||||
* `OpenSpace <https://openspaceproject.com/>`_: An open-source astrovisualization
|
* `OpenSpace <https://openspaceproject.com/>`_: An open-source
|
||||||
framework
|
astrovisualization framework
|
||||||
|
|
||||||
* `PenUltima Online (POL) <https://www.polserver.com/>`_:
|
* `PenUltima Online (POL) <https://www.polserver.com/>`_:
|
||||||
An MMO server, compatible with most Ultima Online clients
|
An MMO server, compatible with most Ultima Online clients
|
||||||
|
|
||||||
|
* `PyTorch <https://github.com/pytorch/pytorch>`_: An open-source machine
|
||||||
|
learning library
|
||||||
|
|
||||||
* `quasardb <https://www.quasardb.net/>`_: A distributed, high-performance,
|
* `quasardb <https://www.quasardb.net/>`_: A distributed, high-performance,
|
||||||
associative database
|
associative database
|
||||||
|
|
||||||
@ -320,13 +351,14 @@ Projects using this library
|
|||||||
* `redis-cerberus <https://github.com/HunanTV/redis-cerberus>`_: A Redis cluster
|
* `redis-cerberus <https://github.com/HunanTV/redis-cerberus>`_: A Redis cluster
|
||||||
proxy
|
proxy
|
||||||
|
|
||||||
|
* `redpanda <https://vectorized.io/redpanda>`_: A 10x faster Kafka® replacement
|
||||||
|
for mission critical systems written in C++
|
||||||
|
|
||||||
* `rpclib <http://rpclib.net/>`_: A modern C++ msgpack-RPC server and client
|
* `rpclib <http://rpclib.net/>`_: A modern C++ msgpack-RPC server and client
|
||||||
library
|
library
|
||||||
|
|
||||||
* `Saddy <https://github.com/mamontov-cpp/saddy-graphics-engine-2d>`_:
|
* `Salesforce Analytics Cloud
|
||||||
Small crossplatform 2D graphic engine
|
<https://www.salesforce.com/analytics-cloud/overview/>`_:
|
||||||
|
|
||||||
* `Salesforce Analytics Cloud <https://www.salesforce.com/analytics-cloud/overview/>`_:
|
|
||||||
Business intelligence software
|
Business intelligence software
|
||||||
|
|
||||||
* `Scylla <https://www.scylladb.com/>`_: A Cassandra-compatible NoSQL data store
|
* `Scylla <https://www.scylladb.com/>`_: A Cassandra-compatible NoSQL data store
|
||||||
@ -344,6 +376,9 @@ Projects using this library
|
|||||||
* `TrinityCore <https://github.com/TrinityCore/TrinityCore>`_: Open-source
|
* `TrinityCore <https://github.com/TrinityCore/TrinityCore>`_: Open-source
|
||||||
MMORPG framework
|
MMORPG framework
|
||||||
|
|
||||||
|
* `Windows Terminal <https://github.com/microsoft/terminal>`_: The new Windows
|
||||||
|
Terminal
|
||||||
|
|
||||||
`More... <https://github.com/search?q=fmtlib&type=Code>`_
|
`More... <https://github.com/search?q=fmtlib&type=Code>`_
|
||||||
|
|
||||||
If you are aware of other projects using this library, please let me know
|
If you are aware of other projects using this library, please let me know
|
||||||
@ -407,8 +442,8 @@ Format also has excessive build times and severe code bloat issues (see
|
|||||||
FastFormat
|
FastFormat
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
This is an interesting library which is fast, safe and has positional
|
This is an interesting library which is fast, safe and has positional arguments.
|
||||||
arguments. However it has significant limitations, citing its author:
|
However, it has significant limitations, citing its author:
|
||||||
|
|
||||||
Three features that have no hope of being accommodated within the
|
Three features that have no hope of being accommodated within the
|
||||||
current design are:
|
current design are:
|
||||||
@ -417,8 +452,8 @@ arguments. However it has significant limitations, citing its author:
|
|||||||
* Octal/hexadecimal encoding
|
* Octal/hexadecimal encoding
|
||||||
* Runtime width/alignment specification
|
* Runtime width/alignment specification
|
||||||
|
|
||||||
It is also quite big and has a heavy dependency, STLSoft, which might be
|
It is also quite big and has a heavy dependency, STLSoft, which might be too
|
||||||
too restrictive for using it in some projects.
|
restrictive for using it in some projects.
|
||||||
|
|
||||||
Boost Spirit.Karma
|
Boost Spirit.Karma
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
@ -426,32 +461,9 @@ Boost Spirit.Karma
|
|||||||
This is not really a formatting library but I decided to include it here for
|
This is not really a formatting library but I decided to include it here for
|
||||||
completeness. As iostreams, it suffers from the problem of mixing verbatim text
|
completeness. As iostreams, it suffers from the problem of mixing verbatim text
|
||||||
with arguments. The library is pretty fast, but slower on integer formatting
|
with arguments. The library is pretty fast, but slower on integer formatting
|
||||||
than ``fmt::format_int`` on Karma's own benchmark,
|
than ``fmt::format_to`` with format string compilation on Karma's own benchmark,
|
||||||
see `Fast integer to string conversion in C++
|
see `Converting a hundred million integers to strings per second
|
||||||
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
|
<http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_.
|
||||||
|
|
||||||
FAQ
|
|
||||||
---
|
|
||||||
|
|
||||||
Q: how can I capture formatting arguments and format them later?
|
|
||||||
|
|
||||||
A: use ``std::tuple``:
|
|
||||||
|
|
||||||
.. code:: c++
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
auto capture(const Args&... args) {
|
|
||||||
return std::make_tuple(args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto print_message = [](const auto&... args) {
|
|
||||||
fmt::print(args...);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Capture and store arguments:
|
|
||||||
auto args = capture("{} {}", 42, "foo");
|
|
||||||
// Do formatting:
|
|
||||||
std::apply(print_message, args);
|
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
@ -459,18 +471,19 @@ License
|
|||||||
{fmt} is distributed under the MIT `license
|
{fmt} is distributed under the MIT `license
|
||||||
<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_.
|
<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_.
|
||||||
|
|
||||||
The `Format String Syntax
|
Documentation License
|
||||||
<https://fmt.dev/latest/syntax.html>`_
|
---------------------
|
||||||
section in the documentation is based on the one from Python `string module
|
|
||||||
documentation <https://docs.python.org/3/library/string.html#module-string>`_
|
|
||||||
adapted for the current library. For this reason the documentation is
|
|
||||||
distributed under the Python Software Foundation license available in
|
|
||||||
`doc/python-license.txt
|
|
||||||
<https://raw.github.com/fmtlib/fmt/master/doc/python-license.txt>`_.
|
|
||||||
It only applies if you distribute the documentation of fmt.
|
|
||||||
|
|
||||||
Acknowledgments
|
The `Format String Syntax <https://fmt.dev/latest/syntax.html>`_
|
||||||
---------------
|
section in the documentation is based on the one from Python `string module
|
||||||
|
documentation <https://docs.python.org/3/library/string.html#module-string>`_.
|
||||||
|
For this reason the documentation is distributed under the Python Software
|
||||||
|
Foundation license available in `doc/python-license.txt
|
||||||
|
<https://raw.github.com/fmtlib/fmt/master/doc/python-license.txt>`_.
|
||||||
|
It only applies if you distribute the documentation of {fmt}.
|
||||||
|
|
||||||
|
Maintainers
|
||||||
|
-----------
|
||||||
|
|
||||||
The {fmt} library is maintained by Victor Zverovich (`vitaut
|
The {fmt} library is maintained by Victor Zverovich (`vitaut
|
||||||
<https://github.com/vitaut>`_) and Jonathan Müller (`foonathan
|
<https://github.com/vitaut>`_) and Jonathan Müller (`foonathan
|
||||||
@ -479,23 +492,3 @@ See `Contributors <https://github.com/fmtlib/fmt/graphs/contributors>`_ and
|
|||||||
`Releases <https://github.com/fmtlib/fmt/releases>`_ for some of the names.
|
`Releases <https://github.com/fmtlib/fmt/releases>`_ for some of the names.
|
||||||
Let us know if your contribution is not listed or mentioned incorrectly and
|
Let us know if your contribution is not listed or mentioned incorrectly and
|
||||||
we'll make it right.
|
we'll make it right.
|
||||||
|
|
||||||
The benchmark section of this readme file and the performance tests are taken
|
|
||||||
from the excellent `tinyformat <https://github.com/c42f/tinyformat>`_ library
|
|
||||||
written by Chris Foster. Boost Format library is acknowledged transitively
|
|
||||||
since it had some influence on tinyformat.
|
|
||||||
Some ideas used in the implementation are borrowed from `Loki
|
|
||||||
<http://loki-lib.sourceforge.net/>`_ SafeFormat and `Diagnostic API
|
|
||||||
<https://clang.llvm.org/doxygen/classclang_1_1Diagnostic.html>`_ in
|
|
||||||
`Clang <https://clang.llvm.org/>`_.
|
|
||||||
Format string syntax and the documentation are based on Python's `str.format
|
|
||||||
<https://docs.python.org/3/library/stdtypes.html#str.format>`_.
|
|
||||||
Thanks `Doug Turnbull <https://github.com/softwaredoug>`_ for his valuable
|
|
||||||
comments and contribution to the design of the type-safe API and
|
|
||||||
`Gregory Czajkowski <https://github.com/gcflymoto>`_ for implementing binary
|
|
||||||
formatting. Thanks `Ruslan Baratov <https://github.com/ruslo>`_ for comprehensive
|
|
||||||
`comparison of integer formatting algorithms <https://github.com/ruslo/int-dec-format-tests>`_
|
|
||||||
and useful comments regarding performance, `Boris Kaul <https://github.com/localvoid>`_ for
|
|
||||||
`C++ counting digits benchmark <https://github.com/localvoid/cxx-benchmark-count-digits>`_.
|
|
||||||
Thanks to `CarterLi <https://github.com/CarterLi>`_ for contributing various
|
|
||||||
improvements to the code.
|
|
||||||
|
@ -9,4 +9,5 @@ add_custom_target(doc
|
|||||||
SOURCES api.rst syntax.rst usage.rst build.py conf.py _templates/layout.html)
|
SOURCES api.rst syntax.rst usage.rst build.py conf.py _templates/layout.html)
|
||||||
|
|
||||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/
|
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/
|
||||||
DESTINATION share/doc/fmt OPTIONAL)
|
DESTINATION share/doc/fmt OPTIONAL
|
||||||
|
PATTERN ".doctrees" EXCLUDE)
|
||||||
|
@ -6,14 +6,13 @@
|
|||||||
<meta name="author" content="Victor Zverovich">
|
<meta name="author" content="Victor Zverovich">
|
||||||
<link rel="stylesheet" href="_static/fmt.css">
|
<link rel="stylesheet" href="_static/fmt.css">
|
||||||
{# Google Analytics #}
|
{# Google Analytics #}
|
||||||
|
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-20116650-4"></script>
|
||||||
<script>
|
<script>
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
window.dataLayer = window.dataLayer || [];
|
||||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
|
function gtag(){dataLayer.push(arguments);}
|
||||||
a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;
|
gtag('js', new Date());
|
||||||
a.src=g;m.parentNode.insertBefore(a,m)
|
|
||||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
gtag('config', 'UA-20116650-4');
|
||||||
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
|
||||||
ga('send', 'pageview');
|
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
115
externals/dynarmic/externals/fmt/doc/api.rst
vendored
115
externals/dynarmic/externals/fmt/doc/api.rst
vendored
@ -9,10 +9,12 @@ The {fmt} library API consists of the following parts:
|
|||||||
* :ref:`fmt/core.h <core-api>`: the core API providing argument handling
|
* :ref:`fmt/core.h <core-api>`: the core API providing argument handling
|
||||||
facilities and a lightweight subset of formatting functions
|
facilities and a lightweight subset of formatting functions
|
||||||
* :ref:`fmt/format.h <format-api>`: the full format API providing compile-time
|
* :ref:`fmt/format.h <format-api>`: the full format API providing compile-time
|
||||||
format string checks, output iterator and user-defined type support
|
format string checks, wide string, output iterator and user-defined type
|
||||||
|
support
|
||||||
* :ref:`fmt/ranges.h <ranges-api>`: additional formatting support for ranges
|
* :ref:`fmt/ranges.h <ranges-api>`: additional formatting support for ranges
|
||||||
and tuples
|
and tuples
|
||||||
* :ref:`fmt/chrono.h <chrono-api>`: date and time formatting
|
* :ref:`fmt/chrono.h <chrono-api>`: date and time formatting
|
||||||
|
* :ref:`fmt/compile.h <compile-api>`: format string compilation
|
||||||
* :ref:`fmt/ostream.h <ostream-api>`: ``std::ostream`` support
|
* :ref:`fmt/ostream.h <ostream-api>`: ``std::ostream`` support
|
||||||
* :ref:`fmt/printf.h <printf-api>`: ``printf`` formatting
|
* :ref:`fmt/printf.h <printf-api>`: ``printf`` formatting
|
||||||
|
|
||||||
@ -43,7 +45,7 @@ participate in an overload resolution if the latter is not a string.
|
|||||||
.. _format:
|
.. _format:
|
||||||
|
|
||||||
.. doxygenfunction:: format(const S&, Args&&...)
|
.. doxygenfunction:: format(const S&, Args&&...)
|
||||||
.. doxygenfunction:: vformat(const S&, basic_format_args<buffer_context<Char>>)
|
.. doxygenfunction:: vformat(const S&, basic_format_args<buffer_context<type_identity_t<Char>>>)
|
||||||
|
|
||||||
.. _print:
|
.. _print:
|
||||||
|
|
||||||
@ -68,6 +70,9 @@ Argument Lists
|
|||||||
.. doxygenclass:: fmt::format_arg_store
|
.. doxygenclass:: fmt::format_arg_store
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. doxygenclass:: fmt::dynamic_format_arg_store
|
||||||
|
:members:
|
||||||
|
|
||||||
.. doxygenclass:: fmt::basic_format_args
|
.. doxygenclass:: fmt::basic_format_args
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
@ -96,7 +101,7 @@ locale::
|
|||||||
#include <locale>
|
#include <locale>
|
||||||
|
|
||||||
std::locale::global(std::locale("en_US.UTF-8"));
|
std::locale::global(std::locale("en_US.UTF-8"));
|
||||||
auto s = fmt::format("{:n}", 1000000); // s == "1,000,000"
|
auto s = fmt::format("{:L}", 1000000); // s == "1,000,000"
|
||||||
|
|
||||||
.. _format-api:
|
.. _format-api:
|
||||||
|
|
||||||
@ -104,7 +109,7 @@ Format API
|
|||||||
==========
|
==========
|
||||||
|
|
||||||
``fmt/format.h`` defines the full format API providing compile-time format
|
``fmt/format.h`` defines the full format API providing compile-time format
|
||||||
string checks, output iterator and user-defined type support.
|
string checks, wide string, output iterator and user-defined type support.
|
||||||
|
|
||||||
Compile-time Format String Checks
|
Compile-time Format String Checks
|
||||||
---------------------------------
|
---------------------------------
|
||||||
@ -132,6 +137,7 @@ template and implement ``parse`` and ``format`` methods::
|
|||||||
|
|
||||||
// Parses format specifications of the form ['f' | 'e'].
|
// Parses format specifications of the form ['f' | 'e'].
|
||||||
constexpr auto parse(format_parse_context& ctx) {
|
constexpr auto parse(format_parse_context& ctx) {
|
||||||
|
// auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) // c++11
|
||||||
// [ctx.begin(), ctx.end()) is a character range that contains a part of
|
// [ctx.begin(), ctx.end()) is a character range that contains a part of
|
||||||
// the format string starting from the format specifications to be parsed,
|
// the format string starting from the format specifications to be parsed,
|
||||||
// e.g. in
|
// e.g. in
|
||||||
@ -159,6 +165,7 @@ template and implement ``parse`` and ``format`` methods::
|
|||||||
// stored in this formatter.
|
// stored in this formatter.
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const point& p, FormatContext& ctx) {
|
auto format(const point& p, FormatContext& ctx) {
|
||||||
|
// auto format(const point &p, FormatContext &ctx) -> decltype(ctx.out()) // c++11
|
||||||
// ctx.out() is an output iterator to write to.
|
// ctx.out() is an output iterator to write to.
|
||||||
return format_to(
|
return format_to(
|
||||||
ctx.out(),
|
ctx.out(),
|
||||||
@ -178,8 +185,7 @@ example::
|
|||||||
|
|
||||||
enum class color {red, green, blue};
|
enum class color {red, green, blue};
|
||||||
|
|
||||||
template <>
|
template <> struct fmt::formatter<color>: formatter<string_view> {
|
||||||
struct fmt::formatter<color>: formatter<string_view> {
|
|
||||||
// parse is inherited from formatter<string_view>.
|
// parse is inherited from formatter<string_view>.
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(color c, FormatContext& ctx) {
|
auto format(color c, FormatContext& ctx) {
|
||||||
@ -193,6 +199,15 @@ example::
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Since ``parse`` is inherited from ``formatter<string_view>`` it will recognize
|
||||||
|
all string format specifications, for example
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
fmt::format("{:>10}", color::blue)
|
||||||
|
|
||||||
|
will return ``" blue"``.
|
||||||
|
|
||||||
You can also write a formatter for a hierarchy of classes::
|
You can also write a formatter for a hierarchy of classes::
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@ -229,7 +244,7 @@ Output Iterator Support
|
|||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
.. doxygenfunction:: fmt::format_to(OutputIt, const S&, Args&&...)
|
.. doxygenfunction:: fmt::format_to(OutputIt, const S&, Args&&...)
|
||||||
.. doxygenfunction:: fmt::format_to_n(OutputIt, std::size_t, string_view, Args&&...)
|
.. doxygenfunction:: fmt::format_to_n(OutputIt, size_t, const S&, const Args&...)
|
||||||
.. doxygenstruct:: fmt::format_to_n_result
|
.. doxygenstruct:: fmt::format_to_n_result
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
@ -238,9 +253,9 @@ Literal-based API
|
|||||||
|
|
||||||
The following user-defined literals are defined in ``fmt/format.h``.
|
The following user-defined literals are defined in ``fmt/format.h``.
|
||||||
|
|
||||||
.. doxygenfunction:: operator""_format(const char *, std::size_t)
|
.. doxygenfunction:: operator""_format(const char *, size_t)
|
||||||
|
|
||||||
.. doxygenfunction:: operator""_a(const char *, std::size_t)
|
.. doxygenfunction:: operator""_a(const char *, size_t)
|
||||||
|
|
||||||
Utilities
|
Utilities
|
||||||
---------
|
---------
|
||||||
@ -259,7 +274,10 @@ Utilities
|
|||||||
|
|
||||||
.. doxygenfunction:: fmt::join(const Range&, string_view)
|
.. doxygenfunction:: fmt::join(const Range&, string_view)
|
||||||
|
|
||||||
.. doxygenfunction:: fmt::join(It, It, string_view)
|
.. doxygenfunction:: fmt::join(It, Sentinel, string_view)
|
||||||
|
|
||||||
|
.. doxygenclass:: fmt::detail::buffer
|
||||||
|
:members:
|
||||||
|
|
||||||
.. doxygenclass:: fmt::basic_memory_buffer
|
.. doxygenclass:: fmt::basic_memory_buffer
|
||||||
:protected-members:
|
:protected-members:
|
||||||
@ -317,50 +335,6 @@ arguments, the container that stores pointers to them will be allocated using
|
|||||||
the default allocator. Also floating-point formatting falls back on ``sprintf``
|
the default allocator. Also floating-point formatting falls back on ``sprintf``
|
||||||
which may do allocations.
|
which may do allocations.
|
||||||
|
|
||||||
Custom Formatting of Built-in Types
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
It is possible to change the way arguments are formatted by providing a
|
|
||||||
custom argument formatter class::
|
|
||||||
|
|
||||||
using arg_formatter = fmt::arg_formatter<fmt::buffer_range<char>>;
|
|
||||||
|
|
||||||
// A custom argument formatter that formats negative integers as unsigned
|
|
||||||
// with the ``x`` format specifier.
|
|
||||||
class custom_arg_formatter : public arg_formatter {
|
|
||||||
public:
|
|
||||||
custom_arg_formatter(fmt::format_context& ctx,
|
|
||||||
fmt::format_parse_context* parse_ctx = nullptr,
|
|
||||||
fmt::format_specs* spec = nullptr)
|
|
||||||
: arg_formatter(ctx, parse_ctx, spec) {}
|
|
||||||
|
|
||||||
using arg_formatter::operator();
|
|
||||||
|
|
||||||
auto operator()(int value) {
|
|
||||||
if (specs() && specs()->type == 'x')
|
|
||||||
return (*this)(static_cast<unsigned>(value)); // convert to unsigned and format
|
|
||||||
return arg_formatter::operator()(value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
|
||||||
fmt::memory_buffer buffer;
|
|
||||||
// Pass custom argument formatter as a template arg to vformat_to.
|
|
||||||
fmt::vformat_to<custom_arg_formatter>(buffer, format_str, args);
|
|
||||||
return fmt::to_string(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ...Args>
|
|
||||||
inline std::string custom_format(
|
|
||||||
fmt::string_view format_str, const Args&... args) {
|
|
||||||
return custom_vformat(format_str, fmt::make_format_args(args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string s = custom_format("{:x}", -42); // s == "ffffffd6"
|
|
||||||
|
|
||||||
.. doxygenclass:: fmt::arg_formatter
|
|
||||||
:members:
|
|
||||||
|
|
||||||
.. _ranges-api:
|
.. _ranges-api:
|
||||||
|
|
||||||
Ranges and Tuple Formatting
|
Ranges and Tuple Formatting
|
||||||
@ -399,11 +373,26 @@ formatting::
|
|||||||
|
|
||||||
std::time_t t = std::time(nullptr);
|
std::time_t t = std::time(nullptr);
|
||||||
// Prints "The date is 2016-04-29." (with the current date)
|
// Prints "The date is 2016-04-29." (with the current date)
|
||||||
fmt::print("The date is {:%Y-%m-%d}.", *std::localtime(&t));
|
fmt::print("The date is {:%Y-%m-%d}.", fmt::localtime(t));
|
||||||
|
|
||||||
The format string syntax is described in the documentation of
|
The format string syntax is described in the documentation of
|
||||||
`strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_.
|
`strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_.
|
||||||
|
|
||||||
|
.. _compile-api:
|
||||||
|
|
||||||
|
Format string compilation
|
||||||
|
=========================
|
||||||
|
|
||||||
|
``fmt/compile.h`` provides format string compilation support. Format strings
|
||||||
|
are parsed at compile time and converted into efficient formatting code. This
|
||||||
|
supports arguments of built-in and string types as well as user-defined types
|
||||||
|
with ``constexpr`` ``parse`` functions in their ``formatter`` specializations.
|
||||||
|
Format string compilation can generate more binary code compared to the default
|
||||||
|
API and is only recommended in places where formatting is a performance
|
||||||
|
bottleneck.
|
||||||
|
|
||||||
|
.. doxygendefine:: FMT_COMPILE
|
||||||
|
|
||||||
.. _ostream-api:
|
.. _ostream-api:
|
||||||
|
|
||||||
``std::ostream`` Support
|
``std::ostream`` Support
|
||||||
@ -448,3 +437,19 @@ argument type doesn't match its format specification.
|
|||||||
.. doxygenfunction:: fprintf(std::basic_ostream<Char>&, const S&, const Args&...)
|
.. doxygenfunction:: fprintf(std::basic_ostream<Char>&, const S&, const Args&...)
|
||||||
|
|
||||||
.. doxygenfunction:: sprintf(const S&, const Args&...)
|
.. doxygenfunction:: sprintf(const S&, const Args&...)
|
||||||
|
|
||||||
|
Compatibility with C++20 ``std::format``
|
||||||
|
========================================
|
||||||
|
|
||||||
|
{fmt} implements nearly all of the `C++20 formatting library
|
||||||
|
<https://en.cppreference.com/w/cpp/utility/format>`_ with the following
|
||||||
|
differences:
|
||||||
|
|
||||||
|
* Names are defined in the ``fmt`` namespace instead of ``std`` to avoid
|
||||||
|
collisions with standard library implementations.
|
||||||
|
* The ``'L'`` format specifier cannot be combined with presentation specifiers
|
||||||
|
yet.
|
||||||
|
* Width calculation doesn't use grapheme clusterization. The latter has been
|
||||||
|
implemented in a separate branch but hasn't been integrated yet.
|
||||||
|
* Chrono formatting doesn't support C++20 date types since they are not provided
|
||||||
|
by standard library implementations.
|
||||||
|
@ -6,7 +6,7 @@ import errno, os, shutil, sys, tempfile
|
|||||||
from subprocess import check_call, check_output, CalledProcessError, Popen, PIPE
|
from subprocess import check_call, check_output, CalledProcessError, Popen, PIPE
|
||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
|
|
||||||
versions = ['1.0.0', '1.1.0', '2.0.0', '3.0.2', '4.0.0', '4.1.0', '5.0.0', '5.1.0', '5.2.0', '5.2.1', '5.3.0', '6.0.0', '6.1.0', '6.1.1', '6.1.2', '6.2.0']
|
versions = ['1.0.0', '1.1.0', '2.0.0', '3.0.2', '4.0.0', '4.1.0', '5.0.0', '5.1.0', '5.2.0', '5.2.1', '5.3.0', '6.0.0', '6.1.0', '6.1.1', '6.1.2', '6.2.0', '6.2.1', '7.0.0', '7.0.1', '7.0.2', '7.0.3']
|
||||||
|
|
||||||
def pip_install(package, commit=None, **kwargs):
|
def pip_install(package, commit=None, **kwargs):
|
||||||
"Install package using pip."
|
"Install package using pip."
|
||||||
@ -74,8 +74,8 @@ def build_docs(version='dev', **kwargs):
|
|||||||
GENERATE_MAN = NO
|
GENERATE_MAN = NO
|
||||||
GENERATE_RTF = NO
|
GENERATE_RTF = NO
|
||||||
CASE_SENSE_NAMES = NO
|
CASE_SENSE_NAMES = NO
|
||||||
INPUT = {0}/core.h {0}/format.h {0}/os.h {0}/ostream.h \
|
INPUT = {0}/core.h {0}/compile.h {0}/format.h {0}/os.h \
|
||||||
{0}/printf.h {0}/time.h
|
{0}/ostream.h {0}/printf.h {0}/time.h
|
||||||
QUIET = YES
|
QUIET = YES
|
||||||
JAVADOC_AUTOBRIEF = YES
|
JAVADOC_AUTOBRIEF = YES
|
||||||
AUTOLINK_SUPPORT = NO
|
AUTOLINK_SUPPORT = NO
|
||||||
|
@ -22,7 +22,7 @@ Format API
|
|||||||
----------
|
----------
|
||||||
|
|
||||||
The format API is similar in spirit to the C ``printf`` family of function but
|
The format API is similar in spirit to the C ``printf`` family of function but
|
||||||
is safer, simpler and serveral times `faster
|
is safer, simpler and several times `faster
|
||||||
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_
|
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_
|
||||||
than common standard library implementations.
|
than common standard library implementations.
|
||||||
The `format string syntax <syntax.html>`_ is similar to the one used by
|
The `format string syntax <syntax.html>`_ is similar to the one used by
|
||||||
|
@ -79,8 +79,8 @@ The general form of a *standard format specifier* is:
|
|||||||
fill: <a character other than '{' or '}'>
|
fill: <a character other than '{' or '}'>
|
||||||
align: "<" | ">" | "^"
|
align: "<" | ">" | "^"
|
||||||
sign: "+" | "-" | " "
|
sign: "+" | "-" | " "
|
||||||
width: `integer` | "{" `arg_id` "}"
|
width: `integer` | "{" [`arg_id`] "}"
|
||||||
precision: `integer` | "{" `arg_id` "}"
|
precision: `integer` | "{" [`arg_id`] "}"
|
||||||
type: `int_type` | "a" | "A" | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "L" | "p" | "s"
|
type: `int_type` | "a" | "A" | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "L" | "p" | "s"
|
||||||
int_type: "b" | "B" | "d" | "o" | "x" | "X"
|
int_type: "b" | "B" | "d" | "o" | "x" | "X"
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
|
|||||||
// From fits in To without any problem.
|
// From fits in To without any problem.
|
||||||
} else {
|
} else {
|
||||||
// From does not always fit in To, resort to a dynamic check.
|
// From does not always fit in To, resort to a dynamic check.
|
||||||
if (from < T::min() || from > T::max()) {
|
if (from < (T::min)() || from > (T::max)()) {
|
||||||
// outside range.
|
// outside range.
|
||||||
ec = 1;
|
ec = 1;
|
||||||
return {};
|
return {};
|
||||||
@ -74,7 +74,7 @@ FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
|
|||||||
|
|
||||||
if (F::is_signed && !T::is_signed) {
|
if (F::is_signed && !T::is_signed) {
|
||||||
// From may be negative, not allowed!
|
// From may be negative, not allowed!
|
||||||
if (fmt::internal::is_negative(from)) {
|
if (fmt::detail::is_negative(from)) {
|
||||||
ec = 1;
|
ec = 1;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -84,7 +84,7 @@ FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
|
|||||||
// yes, From always fits in To.
|
// yes, From always fits in To.
|
||||||
} else {
|
} else {
|
||||||
// from may not fit in To, we have to do a dynamic check
|
// from may not fit in To, we have to do a dynamic check
|
||||||
if (from > static_cast<From>(T::max())) {
|
if (from > static_cast<From>((T::max)())) {
|
||||||
ec = 1;
|
ec = 1;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
|
|||||||
// yes, From always fits in To.
|
// yes, From always fits in To.
|
||||||
} else {
|
} else {
|
||||||
// from may not fit in To, we have to do a dynamic check
|
// from may not fit in To, we have to do a dynamic check
|
||||||
if (from > static_cast<From>(T::max())) {
|
if (from > static_cast<From>((T::max)())) {
|
||||||
// outside range.
|
// outside range.
|
||||||
ec = 1;
|
ec = 1;
|
||||||
return {};
|
return {};
|
||||||
@ -141,7 +141,7 @@ FMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) {
|
|||||||
|
|
||||||
// catch the only happy case
|
// catch the only happy case
|
||||||
if (std::isfinite(from)) {
|
if (std::isfinite(from)) {
|
||||||
if (from >= T::lowest() && from <= T::max()) {
|
if (from >= T::lowest() && from <= (T::max)()) {
|
||||||
return static_cast<To>(from);
|
return static_cast<To>(from);
|
||||||
}
|
}
|
||||||
// not within range.
|
// not within range.
|
||||||
@ -195,12 +195,13 @@ To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
|
|||||||
}
|
}
|
||||||
// multiply with Factor::num without overflow or underflow
|
// multiply with Factor::num without overflow or underflow
|
||||||
if (Factor::num != 1) {
|
if (Factor::num != 1) {
|
||||||
const auto max1 = internal::max_value<IntermediateRep>() / Factor::num;
|
const auto max1 = detail::max_value<IntermediateRep>() / Factor::num;
|
||||||
if (count > max1) {
|
if (count > max1) {
|
||||||
ec = 1;
|
ec = 1;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const auto min1 = std::numeric_limits<IntermediateRep>::min() / Factor::num;
|
const auto min1 =
|
||||||
|
(std::numeric_limits<IntermediateRep>::min)() / Factor::num;
|
||||||
if (count < min1) {
|
if (count < min1) {
|
||||||
ec = 1;
|
ec = 1;
|
||||||
return {};
|
return {};
|
||||||
@ -269,7 +270,7 @@ To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
|
|||||||
|
|
||||||
// multiply with Factor::num without overflow or underflow
|
// multiply with Factor::num without overflow or underflow
|
||||||
if (Factor::num != 1) {
|
if (Factor::num != 1) {
|
||||||
constexpr auto max1 = internal::max_value<IntermediateRep>() /
|
constexpr auto max1 = detail::max_value<IntermediateRep>() /
|
||||||
static_cast<IntermediateRep>(Factor::num);
|
static_cast<IntermediateRep>(Factor::num);
|
||||||
if (count > max1) {
|
if (count > max1) {
|
||||||
ec = 1;
|
ec = 1;
|
||||||
@ -306,12 +307,12 @@ To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
|
|||||||
// Usage: f FMT_NOMACRO()
|
// Usage: f FMT_NOMACRO()
|
||||||
#define FMT_NOMACRO
|
#define FMT_NOMACRO
|
||||||
|
|
||||||
namespace internal {
|
namespace detail {
|
||||||
inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); }
|
inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); }
|
||||||
inline null<> localtime_s(...) { return null<>(); }
|
inline null<> localtime_s(...) { return null<>(); }
|
||||||
inline null<> gmtime_r(...) { return null<>(); }
|
inline null<> gmtime_r(...) { return null<>(); }
|
||||||
inline null<> gmtime_s(...) { return null<>(); }
|
inline null<> gmtime_s(...) { return null<>(); }
|
||||||
} // namespace internal
|
} // namespace detail
|
||||||
|
|
||||||
// Thread-safe replacement for std::localtime
|
// Thread-safe replacement for std::localtime
|
||||||
inline std::tm localtime(std::time_t time) {
|
inline std::tm localtime(std::time_t time) {
|
||||||
@ -322,22 +323,22 @@ inline std::tm localtime(std::time_t time) {
|
|||||||
dispatcher(std::time_t t) : time_(t) {}
|
dispatcher(std::time_t t) : time_(t) {}
|
||||||
|
|
||||||
bool run() {
|
bool run() {
|
||||||
using namespace fmt::internal;
|
using namespace fmt::detail;
|
||||||
return handle(localtime_r(&time_, &tm_));
|
return handle(localtime_r(&time_, &tm_));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool handle(std::tm* tm) { return tm != nullptr; }
|
bool handle(std::tm* tm) { return tm != nullptr; }
|
||||||
|
|
||||||
bool handle(internal::null<>) {
|
bool handle(detail::null<>) {
|
||||||
using namespace fmt::internal;
|
using namespace fmt::detail;
|
||||||
return fallback(localtime_s(&tm_, &time_));
|
return fallback(localtime_s(&tm_, &time_));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fallback(int res) { return res == 0; }
|
bool fallback(int res) { return res == 0; }
|
||||||
|
|
||||||
#if !FMT_MSC_VER
|
#if !FMT_MSC_VER
|
||||||
bool fallback(internal::null<>) {
|
bool fallback(detail::null<>) {
|
||||||
using namespace fmt::internal;
|
using namespace fmt::detail;
|
||||||
std::tm* tm = std::localtime(&time_);
|
std::tm* tm = std::localtime(&time_);
|
||||||
if (tm) tm_ = *tm;
|
if (tm) tm_ = *tm;
|
||||||
return tm != nullptr;
|
return tm != nullptr;
|
||||||
@ -359,21 +360,21 @@ inline std::tm gmtime(std::time_t time) {
|
|||||||
dispatcher(std::time_t t) : time_(t) {}
|
dispatcher(std::time_t t) : time_(t) {}
|
||||||
|
|
||||||
bool run() {
|
bool run() {
|
||||||
using namespace fmt::internal;
|
using namespace fmt::detail;
|
||||||
return handle(gmtime_r(&time_, &tm_));
|
return handle(gmtime_r(&time_, &tm_));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool handle(std::tm* tm) { return tm != nullptr; }
|
bool handle(std::tm* tm) { return tm != nullptr; }
|
||||||
|
|
||||||
bool handle(internal::null<>) {
|
bool handle(detail::null<>) {
|
||||||
using namespace fmt::internal;
|
using namespace fmt::detail;
|
||||||
return fallback(gmtime_s(&tm_, &time_));
|
return fallback(gmtime_s(&tm_, &time_));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fallback(int res) { return res == 0; }
|
bool fallback(int res) { return res == 0; }
|
||||||
|
|
||||||
#if !FMT_MSC_VER
|
#if !FMT_MSC_VER
|
||||||
bool fallback(internal::null<>) {
|
bool fallback(detail::null<>) {
|
||||||
std::tm* tm = std::gmtime(&time_);
|
std::tm* tm = std::gmtime(&time_);
|
||||||
if (tm) tm_ = *tm;
|
if (tm) tm_ = *tm;
|
||||||
return tm != nullptr;
|
return tm != nullptr;
|
||||||
@ -386,17 +387,17 @@ inline std::tm gmtime(std::time_t time) {
|
|||||||
return gt.tm_;
|
return gt.tm_;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace internal {
|
namespace detail {
|
||||||
inline std::size_t strftime(char* str, std::size_t count, const char* format,
|
inline size_t strftime(char* str, size_t count, const char* format,
|
||||||
const std::tm* time) {
|
const std::tm* time) {
|
||||||
return std::strftime(str, count, format, time);
|
return std::strftime(str, count, format, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::size_t strftime(wchar_t* str, std::size_t count,
|
inline size_t strftime(wchar_t* str, size_t count, const wchar_t* format,
|
||||||
const wchar_t* format, const std::tm* time) {
|
const std::tm* time) {
|
||||||
return std::wcsftime(str, count, format, time);
|
return std::wcsftime(str, count, format, time);
|
||||||
}
|
}
|
||||||
} // namespace internal
|
} // namespace detail
|
||||||
|
|
||||||
template <typename Char> struct formatter<std::tm, Char> {
|
template <typename Char> struct formatter<std::tm, Char> {
|
||||||
template <typename ParseContext>
|
template <typename ParseContext>
|
||||||
@ -405,7 +406,7 @@ template <typename Char> struct formatter<std::tm, Char> {
|
|||||||
if (it != ctx.end() && *it == ':') ++it;
|
if (it != ctx.end() && *it == ':') ++it;
|
||||||
auto end = it;
|
auto end = it;
|
||||||
while (end != ctx.end() && *end != '}') ++end;
|
while (end != ctx.end() && *end != '}') ++end;
|
||||||
tm_format.reserve(internal::to_unsigned(end - it + 1));
|
tm_format.reserve(detail::to_unsigned(end - it + 1));
|
||||||
tm_format.append(it, end);
|
tm_format.append(it, end);
|
||||||
tm_format.push_back('\0');
|
tm_format.push_back('\0');
|
||||||
return end;
|
return end;
|
||||||
@ -414,11 +415,10 @@ template <typename Char> struct formatter<std::tm, Char> {
|
|||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const std::tm& tm, FormatContext& ctx) -> decltype(ctx.out()) {
|
auto format(const std::tm& tm, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||||
basic_memory_buffer<Char> buf;
|
basic_memory_buffer<Char> buf;
|
||||||
std::size_t start = buf.size();
|
size_t start = buf.size();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
std::size_t size = buf.capacity() - start;
|
size_t size = buf.capacity() - start;
|
||||||
std::size_t count =
|
size_t count = detail::strftime(&buf[start], size, &tm_format[0], &tm);
|
||||||
internal::strftime(&buf[start], size, &tm_format[0], &tm);
|
|
||||||
if (count != 0) {
|
if (count != 0) {
|
||||||
buf.resize(start + count);
|
buf.resize(start + count);
|
||||||
break;
|
break;
|
||||||
@ -430,7 +430,7 @@ template <typename Char> struct formatter<std::tm, Char> {
|
|||||||
// https://github.com/fmtlib/fmt/issues/367
|
// https://github.com/fmtlib/fmt/issues/367
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const std::size_t MIN_GROWTH = 10;
|
const size_t MIN_GROWTH = 10;
|
||||||
buf.reserve(buf.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
|
buf.reserve(buf.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
|
||||||
}
|
}
|
||||||
return std::copy(buf.begin(), buf.end(), ctx.out());
|
return std::copy(buf.begin(), buf.end(), ctx.out());
|
||||||
@ -439,7 +439,7 @@ template <typename Char> struct formatter<std::tm, Char> {
|
|||||||
basic_memory_buffer<Char> tm_format;
|
basic_memory_buffer<Char> tm_format;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace internal {
|
namespace detail {
|
||||||
template <typename Period> FMT_CONSTEXPR const char* get_units() {
|
template <typename Period> FMT_CONSTEXPR const char* get_units() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -768,19 +768,25 @@ OutputIt format_duration_value(OutputIt out, Rep val, int precision) {
|
|||||||
return format_to(out, std::is_floating_point<Rep>::value ? fp_f : format,
|
return format_to(out, std::is_floating_point<Rep>::value ? fp_f : format,
|
||||||
val);
|
val);
|
||||||
}
|
}
|
||||||
|
template <typename Char, typename OutputIt>
|
||||||
|
OutputIt copy_unit(string_view unit, OutputIt out, Char) {
|
||||||
|
return std::copy(unit.begin(), unit.end(), out);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputIt>
|
||||||
|
OutputIt copy_unit(string_view unit, OutputIt out, wchar_t) {
|
||||||
|
// This works when wchar_t is UTF-32 because units only contain characters
|
||||||
|
// that have the same representation in UTF-16 and UTF-32.
|
||||||
|
utf8_to_utf16 u(unit);
|
||||||
|
return std::copy(u.c_str(), u.c_str() + u.size(), out);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Char, typename Period, typename OutputIt>
|
template <typename Char, typename Period, typename OutputIt>
|
||||||
OutputIt format_duration_unit(OutputIt out) {
|
OutputIt format_duration_unit(OutputIt out) {
|
||||||
if (const char* unit = get_units<Period>()) {
|
if (const char* unit = get_units<Period>())
|
||||||
string_view s(unit);
|
return copy_unit(string_view(unit), out, Char());
|
||||||
if (const_check(std::is_same<Char, wchar_t>())) {
|
|
||||||
utf8_to_utf16 u(s);
|
|
||||||
return std::copy(u.c_str(), u.c_str() + u.size(), out);
|
|
||||||
}
|
|
||||||
return std::copy(s.begin(), s.end(), out);
|
|
||||||
}
|
|
||||||
const Char num_f[] = {'[', '{', '}', ']', 's', 0};
|
const Char num_f[] = {'[', '{', '}', ']', 's', 0};
|
||||||
if (Period::den == 1) return format_to(out, num_f, Period::num);
|
if (const_check(Period::den == 1)) return format_to(out, num_f, Period::num);
|
||||||
const Char num_def_f[] = {'[', '{', '}', '/', '{', '}', ']', 's', 0};
|
const Char num_def_f[] = {'[', '{', '}', '/', '{', '}', ']', 's', 0};
|
||||||
return format_to(out, num_def_f, Period::num, Period::den);
|
return format_to(out, num_def_f, Period::num, Period::den);
|
||||||
}
|
}
|
||||||
@ -874,9 +880,9 @@ struct chrono_formatter {
|
|||||||
if (isnan(value)) return write_nan();
|
if (isnan(value)) return write_nan();
|
||||||
uint32_or_64_or_128_t<int> n =
|
uint32_or_64_or_128_t<int> n =
|
||||||
to_unsigned(to_nonnegative_int(value, max_value<int>()));
|
to_unsigned(to_nonnegative_int(value, max_value<int>()));
|
||||||
int num_digits = internal::count_digits(n);
|
int num_digits = detail::count_digits(n);
|
||||||
if (width > num_digits) out = std::fill_n(out, width - num_digits, '0');
|
if (width > num_digits) out = std::fill_n(out, width - num_digits, '0');
|
||||||
out = format_decimal<char_type>(out, n, num_digits);
|
out = format_decimal<char_type>(out, n, num_digits).end;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_nan() { std::copy_n("nan", 3, out); }
|
void write_nan() { std::copy_n("nan", 3, out); }
|
||||||
@ -1004,14 +1010,14 @@ struct chrono_formatter {
|
|||||||
out = format_duration_unit<char_type, Period>(out);
|
out = format_duration_unit<char_type, Period>(out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace internal
|
} // namespace detail
|
||||||
|
|
||||||
template <typename Rep, typename Period, typename Char>
|
template <typename Rep, typename Period, typename Char>
|
||||||
struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||||
private:
|
private:
|
||||||
basic_format_specs<Char> specs;
|
basic_format_specs<Char> specs;
|
||||||
int precision;
|
int precision;
|
||||||
using arg_ref_type = internal::arg_ref<Char>;
|
using arg_ref_type = detail::arg_ref<Char>;
|
||||||
arg_ref_type width_ref;
|
arg_ref_type width_ref;
|
||||||
arg_ref_type precision_ref;
|
arg_ref_type precision_ref;
|
||||||
mutable basic_string_view<Char> format_str;
|
mutable basic_string_view<Char> format_str;
|
||||||
@ -1032,7 +1038,7 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
|||||||
return arg_ref_type(arg_id);
|
return arg_ref_type(arg_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR arg_ref_type make_arg_ref(internal::auto_id) {
|
FMT_CONSTEXPR arg_ref_type make_arg_ref(detail::auto_id) {
|
||||||
return arg_ref_type(context.next_arg_id());
|
return arg_ref_type(context.next_arg_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1062,17 +1068,17 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
|||||||
auto begin = ctx.begin(), end = ctx.end();
|
auto begin = ctx.begin(), end = ctx.end();
|
||||||
if (begin == end || *begin == '}') return {begin, begin};
|
if (begin == end || *begin == '}') return {begin, begin};
|
||||||
spec_handler handler{*this, ctx, format_str};
|
spec_handler handler{*this, ctx, format_str};
|
||||||
begin = internal::parse_align(begin, end, handler);
|
begin = detail::parse_align(begin, end, handler);
|
||||||
if (begin == end) return {begin, begin};
|
if (begin == end) return {begin, begin};
|
||||||
begin = internal::parse_width(begin, end, handler);
|
begin = detail::parse_width(begin, end, handler);
|
||||||
if (begin == end) return {begin, begin};
|
if (begin == end) return {begin, begin};
|
||||||
if (*begin == '.') {
|
if (*begin == '.') {
|
||||||
if (std::is_floating_point<Rep>::value)
|
if (std::is_floating_point<Rep>::value)
|
||||||
begin = internal::parse_precision(begin, end, handler);
|
begin = detail::parse_precision(begin, end, handler);
|
||||||
else
|
else
|
||||||
handler.on_error("precision not allowed for this argument type");
|
handler.on_error("precision not allowed for this argument type");
|
||||||
}
|
}
|
||||||
end = parse_chrono_format(begin, end, internal::chrono_format_checker());
|
end = parse_chrono_format(begin, end, detail::chrono_format_checker());
|
||||||
return {begin, end};
|
return {begin, end};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1083,7 +1089,7 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
|||||||
-> decltype(ctx.begin()) {
|
-> decltype(ctx.begin()) {
|
||||||
auto range = do_parse(ctx);
|
auto range = do_parse(ctx);
|
||||||
format_str = basic_string_view<Char>(
|
format_str = basic_string_view<Char>(
|
||||||
&*range.begin, internal::to_unsigned(range.end - range.begin));
|
&*range.begin, detail::to_unsigned(range.end - range.begin));
|
||||||
return range.end;
|
return range.end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1094,23 +1100,21 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
|||||||
// is not specified.
|
// is not specified.
|
||||||
basic_memory_buffer<Char> buf;
|
basic_memory_buffer<Char> buf;
|
||||||
auto out = std::back_inserter(buf);
|
auto out = std::back_inserter(buf);
|
||||||
using range = internal::output_range<decltype(ctx.out()), Char>;
|
detail::handle_dynamic_spec<detail::width_checker>(specs.width, width_ref,
|
||||||
internal::basic_writer<range> w(range(ctx.out()));
|
ctx);
|
||||||
internal::handle_dynamic_spec<internal::width_checker>(specs.width,
|
detail::handle_dynamic_spec<detail::precision_checker>(precision,
|
||||||
width_ref, ctx);
|
precision_ref, ctx);
|
||||||
internal::handle_dynamic_spec<internal::precision_checker>(
|
|
||||||
precision, precision_ref, ctx);
|
|
||||||
if (begin == end || *begin == '}') {
|
if (begin == end || *begin == '}') {
|
||||||
out = internal::format_duration_value<Char>(out, d.count(), precision);
|
out = detail::format_duration_value<Char>(out, d.count(), precision);
|
||||||
internal::format_duration_unit<Char, Period>(out);
|
detail::format_duration_unit<Char, Period>(out);
|
||||||
} else {
|
} else {
|
||||||
internal::chrono_formatter<FormatContext, decltype(out), Rep, Period> f(
|
detail::chrono_formatter<FormatContext, decltype(out), Rep, Period> f(
|
||||||
ctx, out, d);
|
ctx, out, d);
|
||||||
f.precision = precision;
|
f.precision = precision;
|
||||||
parse_chrono_format(begin, end, f);
|
parse_chrono_format(begin, end, f);
|
||||||
}
|
}
|
||||||
w.write(buf.data(), buf.size(), specs);
|
return detail::write(
|
||||||
return w.out();
|
ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ struct rgb {
|
|||||||
uint8_t b;
|
uint8_t b;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace internal {
|
namespace detail {
|
||||||
|
|
||||||
// color is a struct of either a rgb color or a terminal color.
|
// color is a struct of either a rgb color or a terminal color.
|
||||||
struct color_type {
|
struct color_type {
|
||||||
@ -221,7 +221,7 @@ struct color_type {
|
|||||||
uint32_t rgb_color;
|
uint32_t rgb_color;
|
||||||
} value;
|
} value;
|
||||||
};
|
};
|
||||||
} // namespace internal
|
} // namespace detail
|
||||||
|
|
||||||
// Experimental text formatting support.
|
// Experimental text formatting support.
|
||||||
class text_style {
|
class text_style {
|
||||||
@ -298,11 +298,11 @@ class text_style {
|
|||||||
FMT_CONSTEXPR bool has_emphasis() const FMT_NOEXCEPT {
|
FMT_CONSTEXPR bool has_emphasis() const FMT_NOEXCEPT {
|
||||||
return static_cast<uint8_t>(ems) != 0;
|
return static_cast<uint8_t>(ems) != 0;
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR internal::color_type get_foreground() const FMT_NOEXCEPT {
|
FMT_CONSTEXPR detail::color_type get_foreground() const FMT_NOEXCEPT {
|
||||||
FMT_ASSERT(has_foreground(), "no foreground specified for this style");
|
FMT_ASSERT(has_foreground(), "no foreground specified for this style");
|
||||||
return foreground_color;
|
return foreground_color;
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR internal::color_type get_background() const FMT_NOEXCEPT {
|
FMT_CONSTEXPR detail::color_type get_background() const FMT_NOEXCEPT {
|
||||||
FMT_ASSERT(has_background(), "no background specified for this style");
|
FMT_ASSERT(has_background(), "no background specified for this style");
|
||||||
return background_color;
|
return background_color;
|
||||||
}
|
}
|
||||||
@ -313,7 +313,7 @@ class text_style {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
FMT_CONSTEXPR text_style(bool is_foreground,
|
FMT_CONSTEXPR text_style(bool is_foreground,
|
||||||
internal::color_type text_color) FMT_NOEXCEPT
|
detail::color_type text_color) FMT_NOEXCEPT
|
||||||
: set_foreground_color(),
|
: set_foreground_color(),
|
||||||
set_background_color(),
|
set_background_color(),
|
||||||
ems() {
|
ems() {
|
||||||
@ -326,23 +326,23 @@ class text_style {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
friend FMT_CONSTEXPR_DECL text_style fg(internal::color_type foreground)
|
friend FMT_CONSTEXPR_DECL text_style fg(detail::color_type foreground)
|
||||||
FMT_NOEXCEPT;
|
FMT_NOEXCEPT;
|
||||||
friend FMT_CONSTEXPR_DECL text_style bg(internal::color_type background)
|
friend FMT_CONSTEXPR_DECL text_style bg(detail::color_type background)
|
||||||
FMT_NOEXCEPT;
|
FMT_NOEXCEPT;
|
||||||
|
|
||||||
internal::color_type foreground_color;
|
detail::color_type foreground_color;
|
||||||
internal::color_type background_color;
|
detail::color_type background_color;
|
||||||
bool set_foreground_color;
|
bool set_foreground_color;
|
||||||
bool set_background_color;
|
bool set_background_color;
|
||||||
emphasis ems;
|
emphasis ems;
|
||||||
};
|
};
|
||||||
|
|
||||||
FMT_CONSTEXPR text_style fg(internal::color_type foreground) FMT_NOEXCEPT {
|
FMT_CONSTEXPR text_style fg(detail::color_type foreground) FMT_NOEXCEPT {
|
||||||
return text_style(/*is_foreground=*/true, foreground);
|
return text_style(/*is_foreground=*/true, foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR text_style bg(internal::color_type background) FMT_NOEXCEPT {
|
FMT_CONSTEXPR text_style bg(detail::color_type background) FMT_NOEXCEPT {
|
||||||
return text_style(/*is_foreground=*/false, background);
|
return text_style(/*is_foreground=*/false, background);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,21 +350,21 @@ FMT_CONSTEXPR text_style operator|(emphasis lhs, emphasis rhs) FMT_NOEXCEPT {
|
|||||||
return text_style(lhs) | rhs;
|
return text_style(lhs) | rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace internal {
|
namespace detail {
|
||||||
|
|
||||||
template <typename Char> struct ansi_color_escape {
|
template <typename Char> struct ansi_color_escape {
|
||||||
FMT_CONSTEXPR ansi_color_escape(internal::color_type text_color,
|
FMT_CONSTEXPR ansi_color_escape(detail::color_type text_color,
|
||||||
const char* esc) FMT_NOEXCEPT {
|
const char* esc) FMT_NOEXCEPT {
|
||||||
// If we have a terminal color, we need to output another escape code
|
// If we have a terminal color, we need to output another escape code
|
||||||
// sequence.
|
// sequence.
|
||||||
if (!text_color.is_rgb) {
|
if (!text_color.is_rgb) {
|
||||||
bool is_background = esc == internal::data::background_color;
|
bool is_background = esc == detail::data::background_color;
|
||||||
uint32_t value = text_color.value.term_color;
|
uint32_t value = text_color.value.term_color;
|
||||||
// Background ASCII codes are the same as the foreground ones but with
|
// Background ASCII codes are the same as the foreground ones but with
|
||||||
// 10 more.
|
// 10 more.
|
||||||
if (is_background) value += 10u;
|
if (is_background) value += 10u;
|
||||||
|
|
||||||
std::size_t index = 0;
|
size_t index = 0;
|
||||||
buffer[index++] = static_cast<Char>('\x1b');
|
buffer[index++] = static_cast<Char>('\x1b');
|
||||||
buffer[index++] = static_cast<Char>('[');
|
buffer[index++] = static_cast<Char>('[');
|
||||||
|
|
||||||
@ -398,7 +398,7 @@ template <typename Char> struct ansi_color_escape {
|
|||||||
if (em_bits & static_cast<uint8_t>(emphasis::strikethrough))
|
if (em_bits & static_cast<uint8_t>(emphasis::strikethrough))
|
||||||
em_codes[3] = 9;
|
em_codes[3] = 9;
|
||||||
|
|
||||||
std::size_t index = 0;
|
size_t index = 0;
|
||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
if (!em_codes[i]) continue;
|
if (!em_codes[i]) continue;
|
||||||
buffer[index++] = static_cast<Char>('\x1b');
|
buffer[index++] = static_cast<Char>('\x1b');
|
||||||
@ -429,14 +429,14 @@ template <typename Char> struct ansi_color_escape {
|
|||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
FMT_CONSTEXPR ansi_color_escape<Char> make_foreground_color(
|
FMT_CONSTEXPR ansi_color_escape<Char> make_foreground_color(
|
||||||
internal::color_type foreground) FMT_NOEXCEPT {
|
detail::color_type foreground) FMT_NOEXCEPT {
|
||||||
return ansi_color_escape<Char>(foreground, internal::data::foreground_color);
|
return ansi_color_escape<Char>(foreground, detail::data::foreground_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
FMT_CONSTEXPR ansi_color_escape<Char> make_background_color(
|
FMT_CONSTEXPR ansi_color_escape<Char> make_background_color(
|
||||||
internal::color_type background) FMT_NOEXCEPT {
|
detail::color_type background) FMT_NOEXCEPT {
|
||||||
return ansi_color_escape<Char>(background, internal::data::background_color);
|
return ansi_color_escape<Char>(background, detail::data::background_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
@ -455,11 +455,11 @@ inline void fputs<wchar_t>(const wchar_t* chars, FILE* stream) FMT_NOEXCEPT {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char> inline void reset_color(FILE* stream) FMT_NOEXCEPT {
|
template <typename Char> inline void reset_color(FILE* stream) FMT_NOEXCEPT {
|
||||||
fputs(internal::data::reset_color, stream);
|
fputs(detail::data::reset_color, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> inline void reset_color<wchar_t>(FILE* stream) FMT_NOEXCEPT {
|
template <> inline void reset_color<wchar_t>(FILE* stream) FMT_NOEXCEPT {
|
||||||
fputs(internal::data::wreset_color, stream);
|
fputs(detail::data::wreset_color, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
@ -476,33 +476,31 @@ void vformat_to(basic_memory_buffer<Char>& buf, const text_style& ts,
|
|||||||
bool has_style = false;
|
bool has_style = false;
|
||||||
if (ts.has_emphasis()) {
|
if (ts.has_emphasis()) {
|
||||||
has_style = true;
|
has_style = true;
|
||||||
auto emphasis = internal::make_emphasis<Char>(ts.get_emphasis());
|
auto emphasis = detail::make_emphasis<Char>(ts.get_emphasis());
|
||||||
buf.append(emphasis.begin(), emphasis.end());
|
buf.append(emphasis.begin(), emphasis.end());
|
||||||
}
|
}
|
||||||
if (ts.has_foreground()) {
|
if (ts.has_foreground()) {
|
||||||
has_style = true;
|
has_style = true;
|
||||||
auto foreground =
|
auto foreground = detail::make_foreground_color<Char>(ts.get_foreground());
|
||||||
internal::make_foreground_color<Char>(ts.get_foreground());
|
|
||||||
buf.append(foreground.begin(), foreground.end());
|
buf.append(foreground.begin(), foreground.end());
|
||||||
}
|
}
|
||||||
if (ts.has_background()) {
|
if (ts.has_background()) {
|
||||||
has_style = true;
|
has_style = true;
|
||||||
auto background =
|
auto background = detail::make_background_color<Char>(ts.get_background());
|
||||||
internal::make_background_color<Char>(ts.get_background());
|
|
||||||
buf.append(background.begin(), background.end());
|
buf.append(background.begin(), background.end());
|
||||||
}
|
}
|
||||||
internal::vformat_to(buf, format_str, args);
|
detail::vformat_to(buf, format_str, args);
|
||||||
if (has_style) internal::reset_color<Char>(buf);
|
if (has_style) detail::reset_color<Char>(buf);
|
||||||
}
|
}
|
||||||
} // namespace internal
|
} // namespace detail
|
||||||
|
|
||||||
template <typename S, typename Char = char_t<S>>
|
template <typename S, typename Char = char_t<S>>
|
||||||
void vprint(std::FILE* f, const text_style& ts, const S& format,
|
void vprint(std::FILE* f, const text_style& ts, const S& format,
|
||||||
basic_format_args<buffer_context<Char>> args) {
|
basic_format_args<buffer_context<Char>> args) {
|
||||||
basic_memory_buffer<Char> buf;
|
basic_memory_buffer<Char> buf;
|
||||||
internal::vformat_to(buf, ts, to_string_view(format), args);
|
detail::vformat_to(buf, ts, to_string_view(format), args);
|
||||||
buf.push_back(Char(0));
|
buf.push_back(Char(0));
|
||||||
internal::fputs(buf.data(), f);
|
detail::fputs(buf.data(), f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -513,10 +511,10 @@ void vprint(std::FILE* f, const text_style& ts, const S& format,
|
|||||||
"Elapsed time: {0:.2f} seconds", 1.23);
|
"Elapsed time: {0:.2f} seconds", 1.23);
|
||||||
*/
|
*/
|
||||||
template <typename S, typename... Args,
|
template <typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(internal::is_string<S>::value)>
|
FMT_ENABLE_IF(detail::is_string<S>::value)>
|
||||||
void print(std::FILE* f, const text_style& ts, const S& format_str,
|
void print(std::FILE* f, const text_style& ts, const S& format_str,
|
||||||
const Args&... args) {
|
const Args&... args) {
|
||||||
internal::check_format_string<Args...>(format_str);
|
detail::check_format_string<Args...>(format_str);
|
||||||
using context = buffer_context<char_t<S>>;
|
using context = buffer_context<char_t<S>>;
|
||||||
format_arg_store<context, Args...> as{args...};
|
format_arg_store<context, Args...> as{args...};
|
||||||
vprint(f, ts, format_str, basic_format_args<context>(as));
|
vprint(f, ts, format_str, basic_format_args<context>(as));
|
||||||
@ -530,7 +528,7 @@ void print(std::FILE* f, const text_style& ts, const S& format_str,
|
|||||||
"Elapsed time: {0:.2f} seconds", 1.23);
|
"Elapsed time: {0:.2f} seconds", 1.23);
|
||||||
*/
|
*/
|
||||||
template <typename S, typename... Args,
|
template <typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(internal::is_string<S>::value)>
|
FMT_ENABLE_IF(detail::is_string<S>::value)>
|
||||||
void print(const text_style& ts, const S& format_str, const Args&... args) {
|
void print(const text_style& ts, const S& format_str, const Args&... args) {
|
||||||
return print(stdout, ts, format_str, args...);
|
return print(stdout, ts, format_str, args...);
|
||||||
}
|
}
|
||||||
@ -540,7 +538,7 @@ inline std::basic_string<Char> vformat(
|
|||||||
const text_style& ts, const S& format_str,
|
const text_style& ts, const S& format_str,
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||||
basic_memory_buffer<Char> buf;
|
basic_memory_buffer<Char> buf;
|
||||||
internal::vformat_to(buf, ts, to_string_view(format_str), args);
|
detail::vformat_to(buf, ts, to_string_view(format_str), args);
|
||||||
return fmt::to_string(buf);
|
return fmt::to_string(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,7 +558,7 @@ template <typename S, typename... Args, typename Char = char_t<S>>
|
|||||||
inline std::basic_string<Char> format(const text_style& ts, const S& format_str,
|
inline std::basic_string<Char> format(const text_style& ts, const S& format_str,
|
||||||
const Args&... args) {
|
const Args&... args) {
|
||||||
return vformat(ts, to_string_view(format_str),
|
return vformat(ts, to_string_view(format_str),
|
||||||
internal::make_args_checked<Args...>(format_str, args...));
|
detail::make_args_checked<Args...>(format_str, args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_END_NAMESPACE
|
FMT_END_NAMESPACE
|
||||||
|
@ -13,7 +13,33 @@
|
|||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
namespace internal {
|
namespace detail {
|
||||||
|
|
||||||
|
// A compile-time string which is compiled into fast formatting code.
|
||||||
|
class compiled_string {};
|
||||||
|
|
||||||
|
template <typename S>
|
||||||
|
struct is_compiled_string : std::is_base_of<compiled_string, S> {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Converts a string literal *s* into a format string that will be parsed at
|
||||||
|
compile time and converted into efficient formatting code. Requires C++17
|
||||||
|
``constexpr if`` compiler support.
|
||||||
|
|
||||||
|
**Example**::
|
||||||
|
|
||||||
|
// Converts 42 into std::string using the most efficient method and no
|
||||||
|
// runtime format string processing.
|
||||||
|
std::string s = fmt::format(FMT_COMPILE("{}"), 42);
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
#define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::detail::compiled_string)
|
||||||
|
|
||||||
|
template <typename T, typename... Tail>
|
||||||
|
const T& first(const T& value, const Tail&...) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
// Part of a compiled format string. It can be either literal text or a
|
// Part of a compiled format string. It can be either literal text or a
|
||||||
// replacement field.
|
// replacement field.
|
||||||
@ -62,13 +88,15 @@ template <typename Char> struct part_counter {
|
|||||||
if (begin != end) ++num_parts;
|
if (begin != end) ++num_parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_arg_id() { ++num_parts; }
|
FMT_CONSTEXPR int on_arg_id() { return ++num_parts, 0; }
|
||||||
FMT_CONSTEXPR void on_arg_id(int) { ++num_parts; }
|
FMT_CONSTEXPR int on_arg_id(int) { return ++num_parts, 0; }
|
||||||
FMT_CONSTEXPR void on_arg_id(basic_string_view<Char>) { ++num_parts; }
|
FMT_CONSTEXPR int on_arg_id(basic_string_view<Char>) {
|
||||||
|
return ++num_parts, 0;
|
||||||
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_replacement_field(const Char*) {}
|
FMT_CONSTEXPR void on_replacement_field(int, const Char*) {}
|
||||||
|
|
||||||
FMT_CONSTEXPR const Char* on_format_specs(const Char* begin,
|
FMT_CONSTEXPR const Char* on_format_specs(int, const Char* begin,
|
||||||
const Char* end) {
|
const Char* end) {
|
||||||
// Find the matching brace.
|
// Find the matching brace.
|
||||||
unsigned brace_counter = 0;
|
unsigned brace_counter = 0;
|
||||||
@ -116,25 +144,28 @@ class format_string_compiler : public error_handler {
|
|||||||
handler_(part::make_text({begin, to_unsigned(end - begin)}));
|
handler_(part::make_text({begin, to_unsigned(end - begin)}));
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_arg_id() {
|
FMT_CONSTEXPR int on_arg_id() {
|
||||||
part_ = part::make_arg_index(parse_context_.next_arg_id());
|
part_ = part::make_arg_index(parse_context_.next_arg_id());
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_arg_id(int id) {
|
FMT_CONSTEXPR int on_arg_id(int id) {
|
||||||
parse_context_.check_arg_id(id);
|
parse_context_.check_arg_id(id);
|
||||||
part_ = part::make_arg_index(id);
|
part_ = part::make_arg_index(id);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_arg_id(basic_string_view<Char> id) {
|
FMT_CONSTEXPR int on_arg_id(basic_string_view<Char> id) {
|
||||||
part_ = part::make_arg_name(id);
|
part_ = part::make_arg_name(id);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_replacement_field(const Char* ptr) {
|
FMT_CONSTEXPR void on_replacement_field(int, const Char* ptr) {
|
||||||
part_.arg_id_end = ptr;
|
part_.arg_id_end = ptr;
|
||||||
handler_(part_);
|
handler_(part_);
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR const Char* on_format_specs(const Char* begin,
|
FMT_CONSTEXPR const Char* on_format_specs(int, const Char* begin,
|
||||||
const Char* end) {
|
const Char* end) {
|
||||||
auto repl = typename part::replacement();
|
auto repl = typename part::replacement();
|
||||||
dynamic_specs_handler<basic_format_parse_context<Char>> handler(
|
dynamic_specs_handler<basic_format_parse_context<Char>> handler(
|
||||||
@ -160,23 +191,24 @@ FMT_CONSTEXPR void compile_format_string(basic_string_view<Char> format_str,
|
|||||||
format_string_compiler<Char, PartHandler>(format_str, handler));
|
format_string_compiler<Char, PartHandler>(format_str, handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Range, typename Context, typename Id>
|
template <typename OutputIt, typename Context, typename Id>
|
||||||
void format_arg(
|
void format_arg(
|
||||||
basic_format_parse_context<typename Range::value_type>& parse_ctx,
|
basic_format_parse_context<typename Context::char_type>& parse_ctx,
|
||||||
Context& ctx, Id arg_id) {
|
Context& ctx, Id arg_id) {
|
||||||
ctx.advance_to(
|
ctx.advance_to(visit_format_arg(
|
||||||
visit_format_arg(arg_formatter<Range>(ctx, &parse_ctx), ctx.arg(arg_id)));
|
arg_formatter<OutputIt, typename Context::char_type>(ctx, &parse_ctx),
|
||||||
|
ctx.arg(arg_id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// vformat_to is defined in a subnamespace to prevent ADL.
|
// vformat_to is defined in a subnamespace to prevent ADL.
|
||||||
namespace cf {
|
namespace cf {
|
||||||
template <typename Context, typename Range, typename CompiledFormat>
|
template <typename Context, typename OutputIt, typename CompiledFormat>
|
||||||
auto vformat_to(Range out, CompiledFormat& cf, basic_format_args<Context> args)
|
auto vformat_to(OutputIt out, CompiledFormat& cf,
|
||||||
-> typename Context::iterator {
|
basic_format_args<Context> args) -> typename Context::iterator {
|
||||||
using char_type = typename Context::char_type;
|
using char_type = typename Context::char_type;
|
||||||
basic_format_parse_context<char_type> parse_ctx(
|
basic_format_parse_context<char_type> parse_ctx(
|
||||||
to_string_view(cf.format_str_));
|
to_string_view(cf.format_str_));
|
||||||
Context ctx(out.begin(), args);
|
Context ctx(out, args);
|
||||||
|
|
||||||
const auto& parts = cf.parts();
|
const auto& parts = cf.parts();
|
||||||
for (auto part_it = std::begin(parts); part_it != std::end(parts);
|
for (auto part_it = std::begin(parts); part_it != std::end(parts);
|
||||||
@ -197,12 +229,12 @@ auto vformat_to(Range out, CompiledFormat& cf, basic_format_args<Context> args)
|
|||||||
|
|
||||||
case format_part_t::kind::arg_index:
|
case format_part_t::kind::arg_index:
|
||||||
advance_to(parse_ctx, part.arg_id_end);
|
advance_to(parse_ctx, part.arg_id_end);
|
||||||
internal::format_arg<Range>(parse_ctx, ctx, value.arg_index);
|
detail::format_arg<OutputIt>(parse_ctx, ctx, value.arg_index);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case format_part_t::kind::arg_name:
|
case format_part_t::kind::arg_name:
|
||||||
advance_to(parse_ctx, part.arg_id_end);
|
advance_to(parse_ctx, part.arg_id_end);
|
||||||
internal::format_arg<Range>(parse_ctx, ctx, value.str);
|
detail::format_arg<OutputIt>(parse_ctx, ctx, value.str);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case format_part_t::kind::replacement: {
|
case format_part_t::kind::replacement: {
|
||||||
@ -226,7 +258,9 @@ auto vformat_to(Range out, CompiledFormat& cf, basic_format_args<Context> args)
|
|||||||
|
|
||||||
advance_to(parse_ctx, part.arg_id_end);
|
advance_to(parse_ctx, part.arg_id_end);
|
||||||
ctx.advance_to(
|
ctx.advance_to(
|
||||||
visit_format_arg(arg_formatter<Range>(ctx, nullptr, &specs), arg));
|
visit_format_arg(arg_formatter<OutputIt, typename Context::char_type>(
|
||||||
|
ctx, nullptr, &specs),
|
||||||
|
arg));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,7 +274,7 @@ struct basic_compiled_format {};
|
|||||||
template <typename S, typename = void>
|
template <typename S, typename = void>
|
||||||
struct compiled_format_base : basic_compiled_format {
|
struct compiled_format_base : basic_compiled_format {
|
||||||
using char_type = char_t<S>;
|
using char_type = char_t<S>;
|
||||||
using parts_container = std::vector<internal::format_part<char_type>>;
|
using parts_container = std::vector<detail::format_part<char_type>>;
|
||||||
|
|
||||||
parts_container compiled_parts;
|
parts_container compiled_parts;
|
||||||
|
|
||||||
@ -305,7 +339,7 @@ struct compiled_format_base<S, enable_if_t<is_compile_string<S>::value>>
|
|||||||
const parts_container& parts() const {
|
const parts_container& parts() const {
|
||||||
static FMT_CONSTEXPR_DECL const auto compiled_parts =
|
static FMT_CONSTEXPR_DECL const auto compiled_parts =
|
||||||
compile_to_parts<char_type, num_format_parts>(
|
compile_to_parts<char_type, num_format_parts>(
|
||||||
internal::to_string_view(S()));
|
detail::to_string_view(S()));
|
||||||
return compiled_parts.data;
|
return compiled_parts.data;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -318,8 +352,8 @@ class compiled_format : private compiled_format_base<S> {
|
|||||||
private:
|
private:
|
||||||
basic_string_view<char_type> format_str_;
|
basic_string_view<char_type> format_str_;
|
||||||
|
|
||||||
template <typename Context, typename Range, typename CompiledFormat>
|
template <typename Context, typename OutputIt, typename CompiledFormat>
|
||||||
friend auto cf::vformat_to(Range out, CompiledFormat& cf,
|
friend auto cf::vformat_to(OutputIt out, CompiledFormat& cf,
|
||||||
basic_format_args<Context> args) ->
|
basic_format_args<Context> args) ->
|
||||||
typename Context::iterator;
|
typename Context::iterator;
|
||||||
|
|
||||||
@ -359,8 +393,7 @@ template <typename Char> struct text {
|
|||||||
|
|
||||||
template <typename OutputIt, typename... Args>
|
template <typename OutputIt, typename... Args>
|
||||||
OutputIt format(OutputIt out, const Args&...) const {
|
OutputIt format(OutputIt out, const Args&...) const {
|
||||||
// TODO: reserve
|
return write<Char>(out, data);
|
||||||
return copy_str<Char>(data.begin(), data.end(), out);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -373,33 +406,6 @@ constexpr text<Char> make_text(basic_string_view<Char> s, size_t pos,
|
|||||||
return {{&s[pos], size}};
|
return {{&s[pos], size}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char, typename OutputIt, typename T,
|
|
||||||
std::enable_if_t<std::is_integral_v<T>, int> = 0>
|
|
||||||
OutputIt format_default(OutputIt out, T value) {
|
|
||||||
// TODO: reserve
|
|
||||||
format_int fi(value);
|
|
||||||
return std::copy(fi.data(), fi.data() + fi.size(), out);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char, typename OutputIt>
|
|
||||||
OutputIt format_default(OutputIt out, double value) {
|
|
||||||
writer w(out);
|
|
||||||
w.write(value);
|
|
||||||
return w.out();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char, typename OutputIt>
|
|
||||||
OutputIt format_default(OutputIt out, Char value) {
|
|
||||||
*out++ = value;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char, typename OutputIt>
|
|
||||||
OutputIt format_default(OutputIt out, const Char* value) {
|
|
||||||
auto length = std::char_traits<Char>::length(value);
|
|
||||||
return copy_str<Char>(value, value + length, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
// A replacement field that refers to argument N.
|
// A replacement field that refers to argument N.
|
||||||
template <typename Char, typename T, int N> struct field {
|
template <typename Char, typename T, int N> struct field {
|
||||||
using char_type = Char;
|
using char_type = Char;
|
||||||
@ -408,13 +414,30 @@ template <typename Char, typename T, int N> struct field {
|
|||||||
OutputIt format(OutputIt out, const Args&... args) const {
|
OutputIt format(OutputIt out, const Args&... args) const {
|
||||||
// This ensures that the argument type is convertile to `const T&`.
|
// This ensures that the argument type is convertile to `const T&`.
|
||||||
const T& arg = get<N>(args...);
|
const T& arg = get<N>(args...);
|
||||||
return format_default<Char>(out, arg);
|
return write<Char>(out, arg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Char, typename T, int N>
|
template <typename Char, typename T, int N>
|
||||||
struct is_compiled_format<field<Char, T, N>> : std::true_type {};
|
struct is_compiled_format<field<Char, T, N>> : std::true_type {};
|
||||||
|
|
||||||
|
// A replacement field that refers to argument N and has format specifiers.
|
||||||
|
template <typename Char, typename T, int N> struct spec_field {
|
||||||
|
using char_type = Char;
|
||||||
|
mutable formatter<T, Char> fmt;
|
||||||
|
|
||||||
|
template <typename OutputIt, typename... Args>
|
||||||
|
OutputIt format(OutputIt out, const Args&... args) const {
|
||||||
|
// This ensures that the argument type is convertile to `const T&`.
|
||||||
|
const T& arg = get<N>(args...);
|
||||||
|
basic_format_context<OutputIt, Char> ctx(out, {});
|
||||||
|
return fmt.format(arg, ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Char, typename T, int N>
|
||||||
|
struct is_compiled_format<spec_field<Char, T, N>> : std::true_type {};
|
||||||
|
|
||||||
template <typename L, typename R> struct concat {
|
template <typename L, typename R> struct concat {
|
||||||
L lhs;
|
L lhs;
|
||||||
R rhs;
|
R rhs;
|
||||||
@ -450,7 +473,8 @@ constexpr auto compile_format_string(S format_str);
|
|||||||
|
|
||||||
template <typename Args, size_t POS, int ID, typename T, typename S>
|
template <typename Args, size_t POS, int ID, typename T, typename S>
|
||||||
constexpr auto parse_tail(T head, S format_str) {
|
constexpr auto parse_tail(T head, S format_str) {
|
||||||
if constexpr (POS != to_string_view(format_str).size()) {
|
if constexpr (POS !=
|
||||||
|
basic_string_view<typename S::char_type>(format_str).size()) {
|
||||||
constexpr auto tail = compile_format_string<Args, POS, ID>(format_str);
|
constexpr auto tail = compile_format_string<Args, POS, ID>(format_str);
|
||||||
if constexpr (std::is_same<remove_cvref_t<decltype(tail)>,
|
if constexpr (std::is_same<remove_cvref_t<decltype(tail)>,
|
||||||
unknown_format>())
|
unknown_format>())
|
||||||
@ -462,6 +486,21 @@ constexpr auto parse_tail(T head, S format_str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Char> struct parse_specs_result {
|
||||||
|
formatter<T, Char> fmt;
|
||||||
|
size_t end;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename Char>
|
||||||
|
constexpr parse_specs_result<T, Char> parse_specs(basic_string_view<Char> str,
|
||||||
|
size_t pos) {
|
||||||
|
str.remove_prefix(pos);
|
||||||
|
auto ctx = basic_format_parse_context<Char>(str);
|
||||||
|
auto f = formatter<T, Char>();
|
||||||
|
auto end = f.parse(ctx);
|
||||||
|
return {f, pos + (end - str.data()) + 1};
|
||||||
|
}
|
||||||
|
|
||||||
// Compiles a non-empty format string and returns the compiled representation
|
// Compiles a non-empty format string and returns the compiled representation
|
||||||
// or unknown_format() on unrecognized input.
|
// or unknown_format() on unrecognized input.
|
||||||
template <typename Args, size_t POS, int ID, typename S>
|
template <typename Args, size_t POS, int ID, typename S>
|
||||||
@ -475,12 +514,13 @@ constexpr auto compile_format_string(S format_str) {
|
|||||||
return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);
|
return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);
|
||||||
} else if constexpr (str[POS + 1] == '}') {
|
} else if constexpr (str[POS + 1] == '}') {
|
||||||
using type = get_type<ID, Args>;
|
using type = get_type<ID, Args>;
|
||||||
if constexpr (std::is_same<type, int>::value) {
|
return parse_tail<Args, POS + 2, ID + 1>(field<char_type, type, ID>(),
|
||||||
return parse_tail<Args, POS + 2, ID + 1>(field<char_type, type, ID>(),
|
format_str);
|
||||||
format_str);
|
} else if constexpr (str[POS + 1] == ':') {
|
||||||
} else {
|
using type = get_type<ID, Args>;
|
||||||
return unknown_format();
|
constexpr auto result = parse_specs<type>(str, POS + 2);
|
||||||
}
|
return parse_tail<Args, result.end, ID + 1>(
|
||||||
|
spec_field<char_type, type, ID>{result.fmt}, format_str);
|
||||||
} else {
|
} else {
|
||||||
return unknown_format();
|
return unknown_format();
|
||||||
}
|
}
|
||||||
@ -494,100 +534,130 @@ constexpr auto compile_format_string(S format_str) {
|
|||||||
format_str);
|
format_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // __cpp_if_constexpr
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
#if FMT_USE_CONSTEXPR
|
|
||||||
# ifdef __cpp_if_constexpr
|
|
||||||
template <typename... Args, typename S,
|
template <typename... Args, typename S,
|
||||||
FMT_ENABLE_IF(is_compile_string<S>::value)>
|
FMT_ENABLE_IF(is_compile_string<S>::value ||
|
||||||
|
detail::is_compiled_string<S>::value)>
|
||||||
constexpr auto compile(S format_str) {
|
constexpr auto compile(S format_str) {
|
||||||
constexpr basic_string_view<typename S::char_type> str = format_str;
|
constexpr basic_string_view<typename S::char_type> str = format_str;
|
||||||
if constexpr (str.size() == 0) {
|
if constexpr (str.size() == 0) {
|
||||||
return internal::make_text(str, 0, 0);
|
return detail::make_text(str, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
constexpr auto result =
|
constexpr auto result =
|
||||||
internal::compile_format_string<internal::type_list<Args...>, 0, 0>(
|
detail::compile_format_string<detail::type_list<Args...>, 0, 0>(
|
||||||
format_str);
|
format_str);
|
||||||
if constexpr (std::is_same<remove_cvref_t<decltype(result)>,
|
if constexpr (std::is_same<remove_cvref_t<decltype(result)>,
|
||||||
internal::unknown_format>()) {
|
detail::unknown_format>()) {
|
||||||
return internal::compiled_format<S, Args...>(to_string_view(format_str));
|
return detail::compiled_format<S, Args...>(to_string_view(format_str));
|
||||||
} else {
|
} else {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
template <typename CompiledFormat, typename... Args,
|
|
||||||
typename Char = typename CompiledFormat::char_type,
|
|
||||||
FMT_ENABLE_IF(internal::is_compiled_format<CompiledFormat>::value)>
|
|
||||||
std::basic_string<Char> format(const CompiledFormat& cf, const Args&... args) {
|
|
||||||
basic_memory_buffer<Char> buffer;
|
|
||||||
cf.format(std::back_inserter(buffer), args...);
|
|
||||||
return to_string(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OutputIt, typename CompiledFormat, typename... Args,
|
|
||||||
FMT_ENABLE_IF(internal::is_compiled_format<CompiledFormat>::value)>
|
|
||||||
OutputIt format_to(OutputIt out, const CompiledFormat& cf,
|
|
||||||
const Args&... args) {
|
|
||||||
return cf.format(out, args...);
|
|
||||||
}
|
|
||||||
# else
|
|
||||||
template <typename... Args, typename S,
|
template <typename... Args, typename S,
|
||||||
FMT_ENABLE_IF(is_compile_string<S>::value)>
|
FMT_ENABLE_IF(is_compile_string<S>::value)>
|
||||||
constexpr auto compile(S format_str) -> internal::compiled_format<S, Args...> {
|
constexpr auto compile(S format_str) -> detail::compiled_format<S, Args...> {
|
||||||
return internal::compiled_format<S, Args...>(to_string_view(format_str));
|
return detail::compiled_format<S, Args...>(to_string_view(format_str));
|
||||||
}
|
}
|
||||||
# endif // __cpp_if_constexpr
|
#endif // __cpp_if_constexpr
|
||||||
#endif // FMT_USE_CONSTEXPR
|
|
||||||
|
|
||||||
// Compiles the format string which must be a string literal.
|
// Compiles the format string which must be a string literal.
|
||||||
template <typename... Args, typename Char, size_t N>
|
template <typename... Args, typename Char, size_t N>
|
||||||
auto compile(const Char (&format_str)[N])
|
auto compile(const Char (&format_str)[N])
|
||||||
-> internal::compiled_format<const Char*, Args...> {
|
-> detail::compiled_format<const Char*, Args...> {
|
||||||
return internal::compiled_format<const Char*, Args...>(
|
return detail::compiled_format<const Char*, Args...>(
|
||||||
basic_string_view<Char>(format_str, N - 1));
|
basic_string_view<Char>(format_str, N - 1));
|
||||||
}
|
}
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
// DEPRECATED! use FMT_COMPILE instead.
|
||||||
|
template <typename... Args>
|
||||||
|
FMT_DEPRECATED auto compile(const Args&... args)
|
||||||
|
-> decltype(detail::compile(args...)) {
|
||||||
|
return detail::compile(args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if FMT_USE_CONSTEXPR
|
||||||
|
# ifdef __cpp_if_constexpr
|
||||||
|
|
||||||
template <typename CompiledFormat, typename... Args,
|
template <typename CompiledFormat, typename... Args,
|
||||||
typename Char = typename CompiledFormat::char_type,
|
typename Char = typename CompiledFormat::char_type,
|
||||||
FMT_ENABLE_IF(std::is_base_of<internal::basic_compiled_format,
|
FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
|
||||||
CompiledFormat>::value)>
|
FMT_INLINE std::basic_string<Char> format(const CompiledFormat& cf,
|
||||||
std::basic_string<Char> format(const CompiledFormat& cf, const Args&... args) {
|
const Args&... args) {
|
||||||
basic_memory_buffer<Char> buffer;
|
basic_memory_buffer<Char> buffer;
|
||||||
using range = buffer_range<Char>;
|
detail::buffer<Char>& base = buffer;
|
||||||
using context = buffer_context<Char>;
|
cf.format(std::back_inserter(base), args...);
|
||||||
internal::cf::vformat_to<context>(range(buffer), cf,
|
|
||||||
make_format_args<context>(args...));
|
|
||||||
return to_string(buffer);
|
return to_string(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename CompiledFormat, typename... Args,
|
template <typename OutputIt, typename CompiledFormat, typename... Args,
|
||||||
FMT_ENABLE_IF(std::is_base_of<internal::basic_compiled_format,
|
FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
|
||||||
|
OutputIt format_to(OutputIt out, const CompiledFormat& cf,
|
||||||
|
const Args&... args) {
|
||||||
|
return cf.format(out, args...);
|
||||||
|
}
|
||||||
|
# endif // __cpp_if_constexpr
|
||||||
|
#endif // FMT_USE_CONSTEXPR
|
||||||
|
|
||||||
|
template <typename CompiledFormat, typename... Args,
|
||||||
|
typename Char = typename CompiledFormat::char_type,
|
||||||
|
FMT_ENABLE_IF(std::is_base_of<detail::basic_compiled_format,
|
||||||
|
CompiledFormat>::value)>
|
||||||
|
std::basic_string<Char> format(const CompiledFormat& cf, const Args&... args) {
|
||||||
|
basic_memory_buffer<Char> buffer;
|
||||||
|
using context = buffer_context<Char>;
|
||||||
|
detail::buffer<Char>& base = buffer;
|
||||||
|
detail::cf::vformat_to<context>(std::back_inserter(base), cf,
|
||||||
|
make_format_args<context>(args...));
|
||||||
|
return to_string(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename S, typename... Args,
|
||||||
|
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||||
|
FMT_INLINE std::basic_string<typename S::char_type> format(const S&,
|
||||||
|
Args&&... args) {
|
||||||
|
constexpr basic_string_view<typename S::char_type> str = S();
|
||||||
|
if (str.size() == 2 && str[0] == '{' && str[1] == '}')
|
||||||
|
return fmt::to_string(detail::first(args...));
|
||||||
|
constexpr auto compiled = detail::compile<Args...>(S());
|
||||||
|
return format(compiled, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputIt, typename CompiledFormat, typename... Args,
|
||||||
|
FMT_ENABLE_IF(std::is_base_of<detail::basic_compiled_format,
|
||||||
CompiledFormat>::value)>
|
CompiledFormat>::value)>
|
||||||
OutputIt format_to(OutputIt out, const CompiledFormat& cf,
|
OutputIt format_to(OutputIt out, const CompiledFormat& cf,
|
||||||
const Args&... args) {
|
const Args&... args) {
|
||||||
using char_type = typename CompiledFormat::char_type;
|
using char_type = typename CompiledFormat::char_type;
|
||||||
using range = internal::output_range<OutputIt, char_type>;
|
|
||||||
using context = format_context_t<OutputIt, char_type>;
|
using context = format_context_t<OutputIt, char_type>;
|
||||||
return internal::cf::vformat_to<context>(range(out), cf,
|
return detail::cf::vformat_to<context>(out, cf,
|
||||||
make_format_args<context>(args...));
|
make_format_args<context>(args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename CompiledFormat, typename... Args,
|
template <typename OutputIt, typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value)>
|
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||||
|
OutputIt format_to(OutputIt out, const S&, const Args&... args) {
|
||||||
|
constexpr auto compiled = detail::compile<Args...>(S());
|
||||||
|
return format_to(out, compiled, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename OutputIt, typename CompiledFormat, typename... Args,
|
||||||
|
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value&& std::is_base_of<
|
||||||
|
detail::basic_compiled_format, CompiledFormat>::value)>
|
||||||
format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
||||||
const CompiledFormat& cf,
|
const CompiledFormat& cf,
|
||||||
const Args&... args) {
|
const Args&... args) {
|
||||||
auto it =
|
auto it =
|
||||||
format_to(internal::truncating_iterator<OutputIt>(out, n), cf, args...);
|
format_to(detail::truncating_iterator<OutputIt>(out, n), cf, args...);
|
||||||
return {it.base(), it.count()};
|
return {it.base(), it.count()};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename CompiledFormat, typename... Args>
|
template <typename CompiledFormat, typename... Args>
|
||||||
std::size_t formatted_size(const CompiledFormat& cf, const Args&... args) {
|
size_t formatted_size(const CompiledFormat& cf, const Args&... args) {
|
||||||
return format_to(internal::counting_iterator(), cf, args...).count();
|
return format_to(detail::counting_iterator(), cf, args...).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_END_NAMESPACE
|
FMT_END_NAMESPACE
|
||||||
|
995
externals/dynarmic/externals/fmt/include/fmt/core.h
vendored
995
externals/dynarmic/externals/fmt/include/fmt/core.h
vendored
File diff suppressed because it is too large
Load Diff
@ -15,6 +15,7 @@
|
|||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstring> // for std::memmove
|
#include <cstring> // for std::memmove
|
||||||
#include <cwchar>
|
#include <cwchar>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
||||||
@ -22,8 +23,16 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
# if !defined(NOMINMAX) && !defined(WIN32_LEAN_AND_MEAN)
|
||||||
|
# define NOMINMAX
|
||||||
|
# define WIN32_LEAN_AND_MEAN
|
||||||
|
# include <windows.h>
|
||||||
|
# undef WIN32_LEAN_AND_MEAN
|
||||||
|
# undef NOMINMAX
|
||||||
|
# else
|
||||||
|
# include <windows.h>
|
||||||
|
# endif
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
# include <windows.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@ -33,15 +42,19 @@
|
|||||||
|
|
||||||
// Dummy implementations of strerror_r and strerror_s called if corresponding
|
// Dummy implementations of strerror_r and strerror_s called if corresponding
|
||||||
// system functions are not available.
|
// system functions are not available.
|
||||||
inline fmt::internal::null<> strerror_r(int, char*, ...) { return {}; }
|
inline fmt::detail::null<> strerror_r(int, char*, ...) { return {}; }
|
||||||
inline fmt::internal::null<> strerror_s(char*, std::size_t, ...) { return {}; }
|
inline fmt::detail::null<> strerror_s(char*, size_t, ...) { return {}; }
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
namespace internal {
|
namespace detail {
|
||||||
|
|
||||||
FMT_FUNC void assert_fail(const char* file, int line, const char* message) {
|
FMT_FUNC void assert_fail(const char* file, int line, const char* message) {
|
||||||
print(stderr, "{}:{}: assertion failed: {}", file, line, message);
|
// Use unchecked std::fprintf to avoid triggering another assertion when
|
||||||
std::abort();
|
// writing to stderr fails
|
||||||
|
std::fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message);
|
||||||
|
// Chosen instead of std::abort to satisfy Clang in CUDA mode during device
|
||||||
|
// code pass.
|
||||||
|
std::terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
@ -67,14 +80,14 @@ inline int fmt_snprintf(char* buffer, size_t size, const char* format, ...) {
|
|||||||
// other - failure
|
// other - failure
|
||||||
// Buffer should be at least of size 1.
|
// Buffer should be at least of size 1.
|
||||||
FMT_FUNC int safe_strerror(int error_code, char*& buffer,
|
FMT_FUNC int safe_strerror(int error_code, char*& buffer,
|
||||||
std::size_t buffer_size) FMT_NOEXCEPT {
|
size_t buffer_size) FMT_NOEXCEPT {
|
||||||
FMT_ASSERT(buffer != nullptr && buffer_size != 0, "invalid buffer");
|
FMT_ASSERT(buffer != nullptr && buffer_size != 0, "invalid buffer");
|
||||||
|
|
||||||
class dispatcher {
|
class dispatcher {
|
||||||
private:
|
private:
|
||||||
int error_code_;
|
int error_code_;
|
||||||
char*& buffer_;
|
char*& buffer_;
|
||||||
std::size_t buffer_size_;
|
size_t buffer_size_;
|
||||||
|
|
||||||
// A noop assignment operator to avoid bogus warnings.
|
// A noop assignment operator to avoid bogus warnings.
|
||||||
void operator=(const dispatcher&) {}
|
void operator=(const dispatcher&) {}
|
||||||
@ -97,7 +110,7 @@ FMT_FUNC int safe_strerror(int error_code, char*& buffer,
|
|||||||
|
|
||||||
// Handle the case when strerror_r is not available.
|
// Handle the case when strerror_r is not available.
|
||||||
FMT_MAYBE_UNUSED
|
FMT_MAYBE_UNUSED
|
||||||
int handle(internal::null<>) {
|
int handle(detail::null<>) {
|
||||||
return fallback(strerror_s(buffer_, buffer_size_, error_code_));
|
return fallback(strerror_s(buffer_, buffer_size_, error_code_));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +124,7 @@ FMT_FUNC int safe_strerror(int error_code, char*& buffer,
|
|||||||
|
|
||||||
#if !FMT_MSC_VER
|
#if !FMT_MSC_VER
|
||||||
// Fallback to strerror if strerror_r and strerror_s are not available.
|
// Fallback to strerror if strerror_r and strerror_s are not available.
|
||||||
int fallback(internal::null<>) {
|
int fallback(detail::null<>) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
buffer_ = strerror(error_code_);
|
buffer_ = strerror(error_code_);
|
||||||
return errno;
|
return errno;
|
||||||
@ -119,7 +132,7 @@ FMT_FUNC int safe_strerror(int error_code, char*& buffer,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
dispatcher(int err_code, char*& buf, std::size_t buf_size)
|
dispatcher(int err_code, char*& buf, size_t buf_size)
|
||||||
: error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
|
: error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
|
||||||
|
|
||||||
int run() { return handle(strerror_r(error_code_, buffer_, buffer_size_)); }
|
int run() { return handle(strerror_r(error_code_, buffer_, buffer_size_)); }
|
||||||
@ -127,7 +140,7 @@ FMT_FUNC int safe_strerror(int error_code, char*& buffer,
|
|||||||
return dispatcher(error_code, buffer, buffer_size).run();
|
return dispatcher(error_code, buffer, buffer_size).run();
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_FUNC void format_error_code(internal::buffer<char>& out, int error_code,
|
FMT_FUNC void format_error_code(detail::buffer<char>& out, int error_code,
|
||||||
string_view message) FMT_NOEXCEPT {
|
string_view message) FMT_NOEXCEPT {
|
||||||
// Report error code making sure that the output fits into
|
// Report error code making sure that the output fits into
|
||||||
// inline_buffer_size to avoid dynamic memory allocation and potential
|
// inline_buffer_size to avoid dynamic memory allocation and potential
|
||||||
@ -136,20 +149,17 @@ FMT_FUNC void format_error_code(internal::buffer<char>& out, int error_code,
|
|||||||
static const char SEP[] = ": ";
|
static const char SEP[] = ": ";
|
||||||
static const char ERROR_STR[] = "error ";
|
static const char ERROR_STR[] = "error ";
|
||||||
// Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
|
// Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
|
||||||
std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
|
size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
|
||||||
auto abs_value = static_cast<uint32_or_64_or_128_t<int>>(error_code);
|
auto abs_value = static_cast<uint32_or_64_or_128_t<int>>(error_code);
|
||||||
if (internal::is_negative(error_code)) {
|
if (detail::is_negative(error_code)) {
|
||||||
abs_value = 0 - abs_value;
|
abs_value = 0 - abs_value;
|
||||||
++error_code_size;
|
++error_code_size;
|
||||||
}
|
}
|
||||||
error_code_size += internal::to_unsigned(internal::count_digits(abs_value));
|
error_code_size += detail::to_unsigned(detail::count_digits(abs_value));
|
||||||
internal::writer w(out);
|
auto it = std::back_inserter(out);
|
||||||
if (message.size() <= inline_buffer_size - error_code_size) {
|
if (message.size() <= inline_buffer_size - error_code_size)
|
||||||
w.write(message);
|
format_to(it, "{}{}", message, SEP);
|
||||||
w.write(SEP);
|
format_to(it, "{}{}", ERROR_STR, error_code);
|
||||||
}
|
|
||||||
w.write(ERROR_STR);
|
|
||||||
w.write(error_code);
|
|
||||||
assert(out.size() <= inline_buffer_size);
|
assert(out.size() <= inline_buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,10 +178,10 @@ FMT_FUNC void fwrite_fully(const void* ptr, size_t size, size_t count,
|
|||||||
size_t written = std::fwrite(ptr, size, count, stream);
|
size_t written = std::fwrite(ptr, size, count, stream);
|
||||||
if (written < count) FMT_THROW(system_error(errno, "cannot write to file"));
|
if (written < count) FMT_THROW(system_error(errno, "cannot write to file"));
|
||||||
}
|
}
|
||||||
} // namespace internal
|
} // namespace detail
|
||||||
|
|
||||||
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
||||||
namespace internal {
|
namespace detail {
|
||||||
|
|
||||||
template <typename Locale>
|
template <typename Locale>
|
||||||
locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
|
locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
|
||||||
@ -194,18 +204,16 @@ template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref loc) {
|
|||||||
return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
|
return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
|
||||||
.decimal_point();
|
.decimal_point();
|
||||||
}
|
}
|
||||||
} // namespace internal
|
} // namespace detail
|
||||||
#else
|
#else
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
FMT_FUNC std::string internal::grouping_impl(locale_ref) {
|
FMT_FUNC std::string detail::grouping_impl(locale_ref) {
|
||||||
return "\03";
|
return "\03";
|
||||||
}
|
}
|
||||||
template <typename Char>
|
template <typename Char> FMT_FUNC Char detail::thousands_sep_impl(locale_ref) {
|
||||||
FMT_FUNC Char internal::thousands_sep_impl(locale_ref) {
|
|
||||||
return FMT_STATIC_THOUSANDS_SEPARATOR;
|
return FMT_STATIC_THOUSANDS_SEPARATOR;
|
||||||
}
|
}
|
||||||
template <typename Char>
|
template <typename Char> FMT_FUNC Char detail::decimal_point_impl(locale_ref) {
|
||||||
FMT_FUNC Char internal::decimal_point_impl(locale_ref) {
|
|
||||||
return '.';
|
return '.';
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -222,9 +230,9 @@ FMT_FUNC void system_error::init(int err_code, string_view format_str,
|
|||||||
base = std::runtime_error(to_string(buffer));
|
base = std::runtime_error(to_string(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace internal {
|
namespace detail {
|
||||||
|
|
||||||
template <> FMT_FUNC int count_digits<4>(internal::fallback_uintptr n) {
|
template <> FMT_FUNC int count_digits<4>(detail::fallback_uintptr n) {
|
||||||
// fallback_uintptr is always stored in little endian.
|
// fallback_uintptr is always stored in little endian.
|
||||||
int i = static_cast<int>(sizeof(void*)) - 1;
|
int i = static_cast<int>(sizeof(void*)) - 1;
|
||||||
while (i > 0 && n.value[i] == 0) --i;
|
while (i > 0 && n.value[i] == 0) --i;
|
||||||
@ -233,12 +241,27 @@ template <> FMT_FUNC int count_digits<4>(internal::fallback_uintptr n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const char basic_data<T>::digits[] =
|
const typename basic_data<T>::digit_pair basic_data<T>::digits[] = {
|
||||||
"0001020304050607080910111213141516171819"
|
{'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'},
|
||||||
"2021222324252627282930313233343536373839"
|
{'0', '5'}, {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'},
|
||||||
"4041424344454647484950515253545556575859"
|
{'1', '0'}, {'1', '1'}, {'1', '2'}, {'1', '3'}, {'1', '4'},
|
||||||
"6061626364656667686970717273747576777879"
|
{'1', '5'}, {'1', '6'}, {'1', '7'}, {'1', '8'}, {'1', '9'},
|
||||||
"8081828384858687888990919293949596979899";
|
{'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'}, {'2', '4'},
|
||||||
|
{'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
|
||||||
|
{'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'},
|
||||||
|
{'3', '5'}, {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'},
|
||||||
|
{'4', '0'}, {'4', '1'}, {'4', '2'}, {'4', '3'}, {'4', '4'},
|
||||||
|
{'4', '5'}, {'4', '6'}, {'4', '7'}, {'4', '8'}, {'4', '9'},
|
||||||
|
{'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'}, {'5', '4'},
|
||||||
|
{'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
|
||||||
|
{'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'},
|
||||||
|
{'6', '5'}, {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'},
|
||||||
|
{'7', '0'}, {'7', '1'}, {'7', '2'}, {'7', '3'}, {'7', '4'},
|
||||||
|
{'7', '5'}, {'7', '6'}, {'7', '7'}, {'7', '8'}, {'7', '9'},
|
||||||
|
{'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'}, {'8', '4'},
|
||||||
|
{'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
|
||||||
|
{'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'},
|
||||||
|
{'9', '5'}, {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const char basic_data<T>::hex_digits[] = "0123456789abcdef";
|
const char basic_data<T>::hex_digits[] = "0123456789abcdef";
|
||||||
@ -317,6 +340,10 @@ const char basic_data<T>::background_color[] = "\x1b[48;2;";
|
|||||||
template <typename T> const char basic_data<T>::reset_color[] = "\x1b[0m";
|
template <typename T> const char basic_data<T>::reset_color[] = "\x1b[0m";
|
||||||
template <typename T> const wchar_t basic_data<T>::wreset_color[] = L"\x1b[0m";
|
template <typename T> const wchar_t basic_data<T>::wreset_color[] = L"\x1b[0m";
|
||||||
template <typename T> const char basic_data<T>::signs[] = {0, '-', '+', ' '};
|
template <typename T> const char basic_data<T>::signs[] = {0, '-', '+', ' '};
|
||||||
|
template <typename T>
|
||||||
|
const char basic_data<T>::left_padding_shifts[] = {31, 31, 0, 1, 0};
|
||||||
|
template <typename T>
|
||||||
|
const char basic_data<T>::right_padding_shifts[] = {0, 31, 0, 1, 0};
|
||||||
|
|
||||||
template <typename T> struct bits {
|
template <typename T> struct bits {
|
||||||
static FMT_CONSTEXPR_DECL const int value =
|
static FMT_CONSTEXPR_DECL const int value =
|
||||||
@ -576,9 +603,10 @@ class bigint {
|
|||||||
void operator=(const bigint&) = delete;
|
void operator=(const bigint&) = delete;
|
||||||
|
|
||||||
void assign(const bigint& other) {
|
void assign(const bigint& other) {
|
||||||
bigits_.resize(other.bigits_.size());
|
auto size = other.bigits_.size();
|
||||||
|
bigits_.resize(size);
|
||||||
auto data = other.bigits_.data();
|
auto data = other.bigits_.data();
|
||||||
std::copy(data, data + other.bigits_.size(), bigits_.data());
|
std::copy(data, data + size, make_checked(bigits_.data(), size));
|
||||||
exp_ = other.exp_;
|
exp_ = other.exp_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,7 +622,7 @@ class bigint {
|
|||||||
|
|
||||||
int num_bigits() const { return static_cast<int>(bigits_.size()) + exp_; }
|
int num_bigits() const { return static_cast<int>(bigits_.size()) + exp_; }
|
||||||
|
|
||||||
bigint& operator<<=(int shift) {
|
FMT_NOINLINE bigint& operator<<=(int shift) {
|
||||||
assert(shift >= 0);
|
assert(shift >= 0);
|
||||||
exp_ += shift / bigit_bits;
|
exp_ += shift / bigit_bits;
|
||||||
shift %= bigit_bits;
|
shift %= bigit_bits;
|
||||||
@ -1125,7 +1153,7 @@ int snprintf_float(T value, int precision, float_specs specs,
|
|||||||
precision = (precision >= 0 ? precision : 6) - 1;
|
precision = (precision >= 0 ? precision : 6) - 1;
|
||||||
|
|
||||||
// Build the format string.
|
// Build the format string.
|
||||||
enum { max_format_size = 7 }; // Ths longest format is "%#.*Le".
|
enum { max_format_size = 7 }; // The longest format is "%#.*Le".
|
||||||
char format[max_format_size];
|
char format[max_format_size];
|
||||||
char* format_ptr = format;
|
char* format_ptr = format;
|
||||||
*format_ptr++ = '%';
|
*format_ptr++ = '%';
|
||||||
@ -1145,13 +1173,13 @@ int snprintf_float(T value, int precision, float_specs specs,
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
auto begin = buf.data() + offset;
|
auto begin = buf.data() + offset;
|
||||||
auto capacity = buf.capacity() - offset;
|
auto capacity = buf.capacity() - offset;
|
||||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
#ifdef FMT_FUZZ
|
||||||
if (precision > 100000)
|
if (precision > 100000)
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"fuzz mode - avoid large allocation inside snprintf");
|
"fuzz mode - avoid large allocation inside snprintf");
|
||||||
#endif
|
#endif
|
||||||
// Suppress the warning about a nonliteral format string.
|
// Suppress the warning about a nonliteral format string.
|
||||||
// Cannot use auto becase of a bug in MinGW (#1532).
|
// Cannot use auto because of a bug in MinGW (#1532).
|
||||||
int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF;
|
int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF;
|
||||||
int result = precision >= 0
|
int result = precision >= 0
|
||||||
? snprintf_ptr(begin, capacity, format, precision, value)
|
? snprintf_ptr(begin, capacity, format, precision, value)
|
||||||
@ -1268,14 +1296,14 @@ FMT_FUNC const char* utf8_decode(const char* buf, uint32_t* c, int* e) {
|
|||||||
|
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
} // namespace internal
|
} // namespace detail
|
||||||
|
|
||||||
template <> struct formatter<internal::bigint> {
|
template <> struct formatter<detail::bigint> {
|
||||||
format_parse_context::iterator parse(format_parse_context& ctx) {
|
format_parse_context::iterator parse(format_parse_context& ctx) {
|
||||||
return ctx.begin();
|
return ctx.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
format_context::iterator format(const internal::bigint& n,
|
format_context::iterator format(const detail::bigint& n,
|
||||||
format_context& ctx) {
|
format_context& ctx) {
|
||||||
auto out = ctx.out();
|
auto out = ctx.out();
|
||||||
bool first = true;
|
bool first = true;
|
||||||
@ -1289,12 +1317,12 @@ template <> struct formatter<internal::bigint> {
|
|||||||
out = format_to(out, "{:08x}", value);
|
out = format_to(out, "{:08x}", value);
|
||||||
}
|
}
|
||||||
if (n.exp_ > 0)
|
if (n.exp_ > 0)
|
||||||
out = format_to(out, "p{}", n.exp_ * internal::bigint::bigit_bits);
|
out = format_to(out, "p{}", n.exp_ * detail::bigint::bigit_bits);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
|
FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) {
|
||||||
auto transcode = [this](const char* p) {
|
auto transcode = [this](const char* p) {
|
||||||
auto cp = uint32_t();
|
auto cp = uint32_t();
|
||||||
auto error = 0;
|
auto error = 0;
|
||||||
@ -1325,7 +1353,7 @@ FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
|
|||||||
buffer_.push_back(0);
|
buffer_.push_back(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_FUNC void format_system_error(internal::buffer<char>& out, int error_code,
|
FMT_FUNC void format_system_error(detail::buffer<char>& out, int error_code,
|
||||||
string_view message) FMT_NOEXCEPT {
|
string_view message) FMT_NOEXCEPT {
|
||||||
FMT_TRY {
|
FMT_TRY {
|
||||||
memory_buffer buf;
|
memory_buffer buf;
|
||||||
@ -1333,12 +1361,9 @@ FMT_FUNC void format_system_error(internal::buffer<char>& out, int error_code,
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
char* system_message = &buf[0];
|
char* system_message = &buf[0];
|
||||||
int result =
|
int result =
|
||||||
internal::safe_strerror(error_code, system_message, buf.size());
|
detail::safe_strerror(error_code, system_message, buf.size());
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
internal::writer w(out);
|
format_to(std::back_inserter(out), "{}: {}", message, system_message);
|
||||||
w.write(message);
|
|
||||||
w.write(": ");
|
|
||||||
w.write(system_message);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result != ERANGE)
|
if (result != ERANGE)
|
||||||
@ -1350,7 +1375,7 @@ FMT_FUNC void format_system_error(internal::buffer<char>& out, int error_code,
|
|||||||
format_error_code(out, error_code, message);
|
format_error_code(out, error_code, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_FUNC void internal::error_handler::on_error(const char* message) {
|
FMT_FUNC void detail::error_handler::on_error(const char* message) {
|
||||||
FMT_THROW(format_error(message));
|
FMT_THROW(format_error(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1359,14 +1384,39 @@ FMT_FUNC void report_system_error(int error_code,
|
|||||||
report_error(format_system_error, error_code, message);
|
report_error(format_system_error, error_code, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct stringifier {
|
||||||
|
template <typename T> FMT_INLINE std::string operator()(T value) const {
|
||||||
|
return to_string(value);
|
||||||
|
}
|
||||||
|
std::string operator()(basic_format_arg<format_context>::handle h) const {
|
||||||
|
memory_buffer buf;
|
||||||
|
detail::buffer<char>& base = buf;
|
||||||
|
format_parse_context parse_ctx({});
|
||||||
|
format_context format_ctx(std::back_inserter(base), {}, {});
|
||||||
|
h.format(parse_ctx, format_ctx);
|
||||||
|
return to_string(buf);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FMT_FUNC std::string detail::vformat(string_view format_str, format_args args) {
|
||||||
|
if (format_str.size() == 2 && equal2(format_str.data(), "{}")) {
|
||||||
|
auto arg = args.get(0);
|
||||||
|
if (!arg) error_handler().on_error("argument not found");
|
||||||
|
return visit_format_arg(stringifier(), arg);
|
||||||
|
}
|
||||||
|
memory_buffer buffer;
|
||||||
|
detail::vformat_to(buffer, format_str, args);
|
||||||
|
return to_string(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) {
|
FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) {
|
||||||
memory_buffer buffer;
|
memory_buffer buffer;
|
||||||
internal::vformat_to(buffer, format_str,
|
detail::vformat_to(buffer, format_str,
|
||||||
basic_format_args<buffer_context<char>>(args));
|
basic_format_args<buffer_context<char>>(args));
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
auto fd = _fileno(f);
|
auto fd = _fileno(f);
|
||||||
if (_isatty(fd)) {
|
if (_isatty(fd)) {
|
||||||
internal::utf8_to_utf16 u16(string_view(buffer.data(), buffer.size()));
|
detail::utf8_to_utf16 u16(string_view(buffer.data(), buffer.size()));
|
||||||
auto written = DWORD();
|
auto written = DWORD();
|
||||||
if (!WriteConsoleW(reinterpret_cast<HANDLE>(_get_osfhandle(fd)),
|
if (!WriteConsoleW(reinterpret_cast<HANDLE>(_get_osfhandle(fd)),
|
||||||
u16.c_str(), static_cast<DWORD>(u16.size()), &written,
|
u16.c_str(), static_cast<DWORD>(u16.size()), &written,
|
||||||
@ -1376,16 +1426,16 @@ FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
internal::fwrite_fully(buffer.data(), 1, buffer.size(), f);
|
detail::fwrite_fully(buffer.data(), 1, buffer.size(), f);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Print assuming legacy (non-Unicode) encoding.
|
// Print assuming legacy (non-Unicode) encoding.
|
||||||
FMT_FUNC void internal::vprint_mojibake(std::FILE* f, string_view format_str,
|
FMT_FUNC void detail::vprint_mojibake(std::FILE* f, string_view format_str,
|
||||||
format_args args) {
|
format_args args) {
|
||||||
memory_buffer buffer;
|
memory_buffer buffer;
|
||||||
internal::vformat_to(buffer, format_str,
|
detail::vformat_to(buffer, format_str,
|
||||||
basic_format_args<buffer_context<char>>(args));
|
basic_format_args<buffer_context<char>>(args));
|
||||||
fwrite_fully(buffer.data(), 1, buffer.size(), f);
|
fwrite_fully(buffer.data(), 1, buffer.size(), f);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
2289
externals/dynarmic/externals/fmt/include/fmt/format.h
vendored
2289
externals/dynarmic/externals/fmt/include/fmt/format.h
vendored
File diff suppressed because it is too large
Load Diff
@ -14,15 +14,15 @@
|
|||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
namespace internal {
|
namespace detail {
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
typename buffer_context<Char>::iterator vformat_to(
|
typename buffer_context<Char>::iterator vformat_to(
|
||||||
const std::locale& loc, buffer<Char>& buf,
|
const std::locale& loc, buffer<Char>& buf,
|
||||||
basic_string_view<Char> format_str,
|
basic_string_view<Char> format_str,
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||||
using range = buffer_range<Char>;
|
using af = arg_formatter<typename buffer_context<Char>::iterator, Char>;
|
||||||
return vformat_to<arg_formatter<range>>(buf, to_string_view(format_str), args,
|
return vformat_to<af>(std::back_inserter(buf), to_string_view(format_str),
|
||||||
internal::locale_ref(loc));
|
args, detail::locale_ref(loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
@ -30,43 +30,43 @@ std::basic_string<Char> vformat(
|
|||||||
const std::locale& loc, basic_string_view<Char> format_str,
|
const std::locale& loc, basic_string_view<Char> format_str,
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||||
basic_memory_buffer<Char> buffer;
|
basic_memory_buffer<Char> buffer;
|
||||||
internal::vformat_to(loc, buffer, format_str, args);
|
detail::vformat_to(loc, buffer, format_str, args);
|
||||||
return fmt::to_string(buffer);
|
return fmt::to_string(buffer);
|
||||||
}
|
}
|
||||||
} // namespace internal
|
} // namespace detail
|
||||||
|
|
||||||
template <typename S, typename Char = char_t<S>>
|
template <typename S, typename Char = char_t<S>>
|
||||||
inline std::basic_string<Char> vformat(
|
inline std::basic_string<Char> vformat(
|
||||||
const std::locale& loc, const S& format_str,
|
const std::locale& loc, const S& format_str,
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||||
return internal::vformat(loc, to_string_view(format_str), args);
|
return detail::vformat(loc, to_string_view(format_str), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||||
inline std::basic_string<Char> format(const std::locale& loc,
|
inline std::basic_string<Char> format(const std::locale& loc,
|
||||||
const S& format_str, Args&&... args) {
|
const S& format_str, Args&&... args) {
|
||||||
return internal::vformat(
|
return detail::vformat(
|
||||||
loc, to_string_view(format_str),
|
loc, to_string_view(format_str),
|
||||||
internal::make_args_checked<Args...>(format_str, args...));
|
detail::make_args_checked<Args...>(format_str, args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename OutputIt, typename... Args,
|
template <typename S, typename OutputIt, typename... Args,
|
||||||
typename Char = enable_if_t<
|
typename Char = enable_if_t<
|
||||||
internal::is_output_iterator<OutputIt>::value, char_t<S>>>
|
detail::is_output_iterator<OutputIt>::value, char_t<S>>>
|
||||||
inline OutputIt vformat_to(
|
inline OutputIt vformat_to(
|
||||||
OutputIt out, const std::locale& loc, const S& format_str,
|
OutputIt out, const std::locale& loc, const S& format_str,
|
||||||
format_args_t<type_identity_t<OutputIt>, Char> args) {
|
format_args_t<type_identity_t<OutputIt>, Char> args) {
|
||||||
using range = internal::output_range<OutputIt, Char>;
|
using af = detail::arg_formatter<OutputIt, Char>;
|
||||||
return vformat_to<arg_formatter<range>>(
|
return vformat_to<af>(out, to_string_view(format_str), args,
|
||||||
range(out), to_string_view(format_str), args, internal::locale_ref(loc));
|
detail::locale_ref(loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename S, typename... Args,
|
template <typename OutputIt, typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value&&
|
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value&&
|
||||||
internal::is_string<S>::value)>
|
detail::is_string<S>::value)>
|
||||||
inline OutputIt format_to(OutputIt out, const std::locale& loc,
|
inline OutputIt format_to(OutputIt out, const std::locale& loc,
|
||||||
const S& format_str, Args&&... args) {
|
const S& format_str, Args&&... args) {
|
||||||
internal::check_format_string<Args...>(format_str);
|
detail::check_format_string<Args...>(format_str);
|
||||||
using context = format_context_t<OutputIt, char_t<S>>;
|
using context = format_context_t<OutputIt, char_t<S>>;
|
||||||
format_arg_store<context, Args...> as{args...};
|
format_arg_store<context, Args...> as{args...};
|
||||||
return vformat_to(out, loc, to_string_view(format_str),
|
return vformat_to(out, loc, to_string_view(format_str),
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
#ifdef FMT_SYSTEM
|
#ifdef FMT_SYSTEM
|
||||||
# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
|
# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
|
||||||
#else
|
#else
|
||||||
# define FMT_SYSTEM(call) call
|
# define FMT_SYSTEM(call) ::call
|
||||||
# ifdef _WIN32
|
# ifdef _WIN32
|
||||||
// Fix warnings about deprecated symbols.
|
// Fix warnings about deprecated symbols.
|
||||||
# define FMT_POSIX_CALL(call) ::_##call
|
# define FMT_POSIX_CALL(call) ::_##call
|
||||||
@ -133,7 +133,7 @@ class error_code {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
namespace internal {
|
namespace detail {
|
||||||
// A converter from UTF-16 to UTF-8.
|
// A converter from UTF-16 to UTF-8.
|
||||||
// It is only provided for Windows since other systems support UTF-8 natively.
|
// It is only provided for Windows since other systems support UTF-8 natively.
|
||||||
class utf16_to_utf8 {
|
class utf16_to_utf8 {
|
||||||
@ -156,7 +156,7 @@ class utf16_to_utf8 {
|
|||||||
|
|
||||||
FMT_API void format_windows_error(buffer<char>& out, int error_code,
|
FMT_API void format_windows_error(buffer<char>& out, int error_code,
|
||||||
string_view message) FMT_NOEXCEPT;
|
string_view message) FMT_NOEXCEPT;
|
||||||
} // namespace internal
|
} // namespace detail
|
||||||
|
|
||||||
/** A Windows error. */
|
/** A Windows error. */
|
||||||
class windows_error : public system_error {
|
class windows_error : public system_error {
|
||||||
@ -277,7 +277,8 @@ class file {
|
|||||||
enum {
|
enum {
|
||||||
RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
|
RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
|
||||||
WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
|
WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
|
||||||
RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing.
|
RDWR = FMT_POSIX(O_RDWR), // Open for reading and writing.
|
||||||
|
CREATE = FMT_POSIX(O_CREAT) // Create if the file doesn't exist.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constructs a file object which doesn't represent any file.
|
// Constructs a file object which doesn't represent any file.
|
||||||
@ -313,10 +314,10 @@ class file {
|
|||||||
FMT_API long long size() const;
|
FMT_API long long size() const;
|
||||||
|
|
||||||
// Attempts to read count bytes from the file into the specified buffer.
|
// Attempts to read count bytes from the file into the specified buffer.
|
||||||
FMT_API std::size_t read(void* buffer, std::size_t count);
|
FMT_API size_t read(void* buffer, size_t count);
|
||||||
|
|
||||||
// Attempts to write count bytes from the specified buffer to the file.
|
// Attempts to write count bytes from the specified buffer to the file.
|
||||||
FMT_API std::size_t write(const void* buffer, std::size_t count);
|
FMT_API size_t write(const void* buffer, size_t count);
|
||||||
|
|
||||||
// Duplicates a file descriptor with the dup function and returns
|
// Duplicates a file descriptor with the dup function and returns
|
||||||
// the duplicate as a file object.
|
// the duplicate as a file object.
|
||||||
@ -341,6 +342,63 @@ class file {
|
|||||||
|
|
||||||
// Returns the memory page size.
|
// Returns the memory page size.
|
||||||
long getpagesize();
|
long getpagesize();
|
||||||
|
|
||||||
|
class direct_buffered_file;
|
||||||
|
|
||||||
|
template <typename S, typename... Args>
|
||||||
|
void print(direct_buffered_file& f, const S& format_str,
|
||||||
|
const Args&... args);
|
||||||
|
|
||||||
|
// A buffered file with a direct buffer access and no synchronization.
|
||||||
|
class direct_buffered_file {
|
||||||
|
private:
|
||||||
|
file file_;
|
||||||
|
|
||||||
|
enum { buffer_size = 4096 };
|
||||||
|
char buffer_[buffer_size];
|
||||||
|
int pos_;
|
||||||
|
|
||||||
|
void flush() {
|
||||||
|
if (pos_ == 0) return;
|
||||||
|
file_.write(buffer_, pos_);
|
||||||
|
pos_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int free_capacity() const { return buffer_size - pos_; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
direct_buffered_file(cstring_view path, int oflag)
|
||||||
|
: file_(path, oflag), pos_(0) {}
|
||||||
|
|
||||||
|
~direct_buffered_file() {
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() {
|
||||||
|
flush();
|
||||||
|
file_.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename S, typename... Args>
|
||||||
|
friend void print(direct_buffered_file& f, const S& format_str,
|
||||||
|
const Args&... args) {
|
||||||
|
// We could avoid double buffering.
|
||||||
|
auto buf = fmt::memory_buffer();
|
||||||
|
fmt::format_to(std::back_inserter(buf), format_str, args...);
|
||||||
|
auto remaining_pos = 0;
|
||||||
|
auto remaining_size = buf.size();
|
||||||
|
while (remaining_size > detail::to_unsigned(f.free_capacity())) {
|
||||||
|
auto size = f.free_capacity();
|
||||||
|
memcpy(f.buffer_ + f.pos_, buf.data() + remaining_pos, size);
|
||||||
|
f.pos_ += size;
|
||||||
|
f.flush();
|
||||||
|
remaining_pos += size;
|
||||||
|
remaining_size -= size;
|
||||||
|
}
|
||||||
|
memcpy(f.buffer_ + f.pos_, buf.data() + remaining_pos, remaining_size);
|
||||||
|
f.pos_ += static_cast<int>(remaining_size);
|
||||||
|
}
|
||||||
|
};
|
||||||
#endif // FMT_USE_FCNTL
|
#endif // FMT_USE_FCNTL
|
||||||
|
|
||||||
#ifdef FMT_LOCALE
|
#ifdef FMT_LOCALE
|
||||||
|
@ -9,10 +9,15 @@
|
|||||||
#define FMT_OSTREAM_H_
|
#define FMT_OSTREAM_H_
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
namespace internal {
|
|
||||||
|
template <typename Char> class basic_printf_parse_context;
|
||||||
|
template <typename OutputIt, typename Char> class basic_printf_context;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
template <class Char> class formatbuf : public std::basic_streambuf<Char> {
|
template <class Char> class formatbuf : public std::basic_streambuf<Char> {
|
||||||
private:
|
private:
|
||||||
@ -75,7 +80,7 @@ template <typename T, typename Char> class is_streamable {
|
|||||||
|
|
||||||
// Write the content of buf to os.
|
// Write the content of buf to os.
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
void write(std::basic_ostream<Char>& os, buffer<Char>& buf) {
|
void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
|
||||||
const Char* buf_data = buf.data();
|
const Char* buf_data = buf.data();
|
||||||
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
|
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
|
||||||
unsigned_streamsize size = buf.size();
|
unsigned_streamsize size = buf.size();
|
||||||
@ -93,34 +98,53 @@ void format_value(buffer<Char>& buf, const T& value,
|
|||||||
locale_ref loc = locale_ref()) {
|
locale_ref loc = locale_ref()) {
|
||||||
formatbuf<Char> format_buf(buf);
|
formatbuf<Char> format_buf(buf);
|
||||||
std::basic_ostream<Char> output(&format_buf);
|
std::basic_ostream<Char> output(&format_buf);
|
||||||
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
||||||
if (loc) output.imbue(loc.get<std::locale>());
|
if (loc) output.imbue(loc.get<std::locale>());
|
||||||
#endif
|
#endif
|
||||||
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
|
||||||
output << value;
|
output << value;
|
||||||
|
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
||||||
buf.resize(buf.size());
|
buf.resize(buf.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Formats an object of type T that has an overloaded ostream operator<<.
|
// Formats an object of type T that has an overloaded ostream operator<<.
|
||||||
template <typename T, typename Char>
|
template <typename T, typename Char>
|
||||||
struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
|
struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
|
||||||
: formatter<basic_string_view<Char>, Char> {
|
: private formatter<basic_string_view<Char>, Char> {
|
||||||
template <typename Context>
|
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
||||||
auto format(const T& value, Context& ctx) -> decltype(ctx.out()) {
|
-> decltype(ctx.begin()) {
|
||||||
|
return formatter<basic_string_view<Char>, Char>::parse(ctx);
|
||||||
|
}
|
||||||
|
template <typename ParseCtx,
|
||||||
|
FMT_ENABLE_IF(std::is_same<
|
||||||
|
ParseCtx, basic_printf_parse_context<Char>>::value)>
|
||||||
|
auto parse(ParseCtx& ctx) -> decltype(ctx.begin()) {
|
||||||
|
return ctx.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputIt>
|
||||||
|
auto format(const T& value, basic_format_context<OutputIt, Char>& ctx)
|
||||||
|
-> OutputIt {
|
||||||
basic_memory_buffer<Char> buffer;
|
basic_memory_buffer<Char> buffer;
|
||||||
format_value(buffer, value, ctx.locale());
|
format_value(buffer, value, ctx.locale());
|
||||||
basic_string_view<Char> str(buffer.data(), buffer.size());
|
basic_string_view<Char> str(buffer.data(), buffer.size());
|
||||||
return formatter<basic_string_view<Char>, Char>::format(str, ctx);
|
return formatter<basic_string_view<Char>, Char>::format(str, ctx);
|
||||||
}
|
}
|
||||||
|
template <typename OutputIt>
|
||||||
|
auto format(const T& value, basic_printf_context<OutputIt, Char>& ctx)
|
||||||
|
-> OutputIt {
|
||||||
|
basic_memory_buffer<Char> buffer;
|
||||||
|
format_value(buffer, value, ctx.locale());
|
||||||
|
return std::copy(buffer.begin(), buffer.end(), ctx.out());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace internal
|
} // namespace detail
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str,
|
void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str,
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||||
basic_memory_buffer<Char> buffer;
|
basic_memory_buffer<Char> buffer;
|
||||||
internal::vformat_to(buffer, format_str, args);
|
detail::vformat_to(buffer, format_str, args);
|
||||||
internal::write(os, buffer);
|
detail::write_buffer(os, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,10 +157,10 @@ void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str,
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename S, typename... Args,
|
template <typename S, typename... Args,
|
||||||
typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>>
|
typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
|
||||||
void print(std::basic_ostream<Char>& os, const S& format_str, Args&&... args) {
|
void print(std::basic_ostream<Char>& os, const S& format_str, Args&&... args) {
|
||||||
vprint(os, to_string_view(format_str),
|
vprint(os, to_string_view(format_str),
|
||||||
internal::make_args_checked<Args...>(format_str, args...));
|
detail::make_args_checked<Args...>(format_str, args...));
|
||||||
}
|
}
|
||||||
FMT_END_NAMESPACE
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
#include "os.h"
|
#include "os.h"
|
||||||
#warning "fmt/posix.h is deprecated; use fmt/os.h instead"
|
#warning "fmt/posix.h is deprecated; use fmt/os.h instead"
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#include "ostream.h"
|
#include "ostream.h"
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
namespace internal {
|
namespace detail {
|
||||||
|
|
||||||
// Checks if a value fits in int - used to avoid warnings about comparing
|
// Checks if a value fits in int - used to avoid warnings about comparing
|
||||||
// signed and unsigned integers.
|
// signed and unsigned integers.
|
||||||
@ -90,11 +90,11 @@ template <typename T, typename Context> class arg_converter {
|
|||||||
if (const_check(sizeof(target_type) <= sizeof(int))) {
|
if (const_check(sizeof(target_type) <= sizeof(int))) {
|
||||||
// Extra casts are used to silence warnings.
|
// Extra casts are used to silence warnings.
|
||||||
if (is_signed) {
|
if (is_signed) {
|
||||||
arg_ = internal::make_arg<Context>(
|
arg_ = detail::make_arg<Context>(
|
||||||
static_cast<int>(static_cast<target_type>(value)));
|
static_cast<int>(static_cast<target_type>(value)));
|
||||||
} else {
|
} else {
|
||||||
using unsigned_type = typename make_unsigned_or_bool<target_type>::type;
|
using unsigned_type = typename make_unsigned_or_bool<target_type>::type;
|
||||||
arg_ = internal::make_arg<Context>(
|
arg_ = detail::make_arg<Context>(
|
||||||
static_cast<unsigned>(static_cast<unsigned_type>(value)));
|
static_cast<unsigned>(static_cast<unsigned_type>(value)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -102,9 +102,9 @@ template <typename T, typename Context> class arg_converter {
|
|||||||
// glibc's printf doesn't sign extend arguments of smaller types:
|
// glibc's printf doesn't sign extend arguments of smaller types:
|
||||||
// std::printf("%lld", -42); // prints "4294967254"
|
// std::printf("%lld", -42); // prints "4294967254"
|
||||||
// but we don't have to do the same because it's a UB.
|
// but we don't have to do the same because it's a UB.
|
||||||
arg_ = internal::make_arg<Context>(static_cast<long long>(value));
|
arg_ = detail::make_arg<Context>(static_cast<long long>(value));
|
||||||
} else {
|
} else {
|
||||||
arg_ = internal::make_arg<Context>(
|
arg_ = detail::make_arg<Context>(
|
||||||
static_cast<typename make_unsigned_or_bool<U>::type>(value));
|
static_cast<typename make_unsigned_or_bool<U>::type>(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ template <typename Context> class char_converter {
|
|||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||||
void operator()(T value) {
|
void operator()(T value) {
|
||||||
arg_ = internal::make_arg<Context>(
|
arg_ = detail::make_arg<Context>(
|
||||||
static_cast<typename Context::char_type>(value));
|
static_cast<typename Context::char_type>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,6 +141,13 @@ template <typename Context> class char_converter {
|
|||||||
void operator()(T) {} // No conversion needed for non-integral types.
|
void operator()(T) {} // No conversion needed for non-integral types.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// An argument visitor that return a pointer to a C string if argument is a
|
||||||
|
// string or null otherwise.
|
||||||
|
template <typename Char> struct get_cstring {
|
||||||
|
template <typename T> const Char* operator()(T) { return nullptr; }
|
||||||
|
const Char* operator()(const Char* s) { return s; }
|
||||||
|
};
|
||||||
|
|
||||||
// Checks if an argument is a valid printf width specifier and sets
|
// Checks if an argument is a valid printf width specifier and sets
|
||||||
// left alignment if it is negative.
|
// left alignment if it is negative.
|
||||||
template <typename Char> class printf_width_handler {
|
template <typename Char> class printf_width_handler {
|
||||||
@ -155,7 +162,7 @@ template <typename Char> class printf_width_handler {
|
|||||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||||
unsigned operator()(T value) {
|
unsigned operator()(T value) {
|
||||||
auto width = static_cast<uint32_or_64_or_128_t<T>>(value);
|
auto width = static_cast<uint32_or_64_or_128_t<T>>(value);
|
||||||
if (internal::is_negative(value)) {
|
if (detail::is_negative(value)) {
|
||||||
specs_.align = align::left;
|
specs_.align = align::left;
|
||||||
width = 0 - width;
|
width = 0 - width;
|
||||||
}
|
}
|
||||||
@ -172,23 +179,25 @@ template <typename Char> class printf_width_handler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Char, typename Context>
|
template <typename Char, typename Context>
|
||||||
void printf(buffer<Char>& buf, basic_string_view<Char> format,
|
void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
|
||||||
basic_format_args<Context> args) {
|
basic_format_args<Context> args) {
|
||||||
Context(std::back_inserter(buf), format, args).format();
|
Context(std::back_inserter(buf), format, args).format();
|
||||||
}
|
}
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
template <typename OutputIt, typename Char, typename Context>
|
// For printing into memory_buffer.
|
||||||
internal::truncating_iterator<OutputIt> printf(
|
template <typename Char, typename Context>
|
||||||
internal::truncating_iterator<OutputIt> it, basic_string_view<Char> format,
|
FMT_DEPRECATED void printf(detail::buffer<Char>& buf,
|
||||||
basic_format_args<Context> args) {
|
basic_string_view<Char> format,
|
||||||
return Context(it, format, args).format();
|
basic_format_args<Context> args) {
|
||||||
|
return detail::vprintf(buf, format, args);
|
||||||
}
|
}
|
||||||
} // namespace internal
|
using detail::vprintf;
|
||||||
|
|
||||||
using internal::printf; // For printing into memory_buffer.
|
|
||||||
|
|
||||||
template <typename Range> class printf_arg_formatter;
|
|
||||||
|
|
||||||
|
template <typename Char>
|
||||||
|
class basic_printf_parse_context : public basic_format_parse_context<Char> {
|
||||||
|
using basic_format_parse_context<Char>::basic_format_parse_context;
|
||||||
|
};
|
||||||
template <typename OutputIt, typename Char> class basic_printf_context;
|
template <typename OutputIt, typename Char> class basic_printf_context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -196,15 +205,15 @@ template <typename OutputIt, typename Char> class basic_printf_context;
|
|||||||
The ``printf`` argument formatter.
|
The ``printf`` argument formatter.
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename Range>
|
template <typename OutputIt, typename Char>
|
||||||
class printf_arg_formatter : public internal::arg_formatter_base<Range> {
|
class printf_arg_formatter : public detail::arg_formatter_base<OutputIt, Char> {
|
||||||
public:
|
public:
|
||||||
using iterator = typename Range::iterator;
|
using iterator = OutputIt;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using char_type = typename Range::value_type;
|
using char_type = Char;
|
||||||
using base = internal::arg_formatter_base<Range>;
|
using base = detail::arg_formatter_base<OutputIt, Char>;
|
||||||
using context_type = basic_printf_context<iterator, char_type>;
|
using context_type = basic_printf_context<OutputIt, Char>;
|
||||||
|
|
||||||
context_type& context_;
|
context_type& context_;
|
||||||
|
|
||||||
@ -229,9 +238,9 @@ class printf_arg_formatter : public internal::arg_formatter_base<Range> {
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
printf_arg_formatter(iterator iter, format_specs& specs, context_type& ctx)
|
printf_arg_formatter(iterator iter, format_specs& specs, context_type& ctx)
|
||||||
: base(Range(iter), &specs, internal::locale_ref()), context_(ctx) {}
|
: base(iter, &specs, detail::locale_ref()), context_(ctx) {}
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(fmt::internal::is_integral<T>::value)>
|
template <typename T, FMT_ENABLE_IF(fmt::detail::is_integral<T>::value)>
|
||||||
iterator operator()(T value) {
|
iterator operator()(T value) {
|
||||||
// MSVC2013 fails to compile separate overloads for bool and char_type so
|
// MSVC2013 fails to compile separate overloads for bool and char_type so
|
||||||
// use std::is_same instead.
|
// use std::is_same instead.
|
||||||
@ -246,7 +255,11 @@ class printf_arg_formatter : public internal::arg_formatter_base<Range> {
|
|||||||
return (*this)(static_cast<int>(value));
|
return (*this)(static_cast<int>(value));
|
||||||
fmt_specs.sign = sign::none;
|
fmt_specs.sign = sign::none;
|
||||||
fmt_specs.alt = false;
|
fmt_specs.alt = false;
|
||||||
fmt_specs.align = align::right;
|
fmt_specs.fill[0] = ' '; // Ignore '0' flag for char types.
|
||||||
|
// align::numeric needs to be overwritten here since the '0' flag is
|
||||||
|
// ignored for non-numeric types
|
||||||
|
if (fmt_specs.align == align::none || fmt_specs.align == align::numeric)
|
||||||
|
fmt_specs.align = align::right;
|
||||||
return base::operator()(value);
|
return base::operator()(value);
|
||||||
} else {
|
} else {
|
||||||
return base::operator()(value);
|
return base::operator()(value);
|
||||||
@ -312,18 +325,21 @@ template <typename T> struct printf_formatter {
|
|||||||
|
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const T& value, FormatContext& ctx) -> decltype(ctx.out()) {
|
auto format(const T& value, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||||
internal::format_value(internal::get_container(ctx.out()), value);
|
detail::format_value(detail::get_container(ctx.out()), value);
|
||||||
return ctx.out();
|
return ctx.out();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** This template formats data and writes the output to a writer. */
|
/**
|
||||||
|
This template formats data and writes the output through an output iterator.
|
||||||
|
*/
|
||||||
template <typename OutputIt, typename Char> class basic_printf_context {
|
template <typename OutputIt, typename Char> class basic_printf_context {
|
||||||
public:
|
public:
|
||||||
/** The character type for the output. */
|
/** The character type for the output. */
|
||||||
using char_type = Char;
|
using char_type = Char;
|
||||||
using iterator = OutputIt;
|
using iterator = OutputIt;
|
||||||
using format_arg = basic_format_arg<basic_printf_context>;
|
using format_arg = basic_format_arg<basic_printf_context>;
|
||||||
|
using parse_context_type = basic_printf_parse_context<Char>;
|
||||||
template <typename T> using formatter_type = printf_formatter<T>;
|
template <typename T> using formatter_type = printf_formatter<T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -331,7 +347,7 @@ template <typename OutputIt, typename Char> class basic_printf_context {
|
|||||||
|
|
||||||
OutputIt out_;
|
OutputIt out_;
|
||||||
basic_format_args<basic_printf_context> args_;
|
basic_format_args<basic_printf_context> args_;
|
||||||
basic_format_parse_context<Char> parse_ctx_;
|
parse_context_type parse_ctx_;
|
||||||
|
|
||||||
static void parse_flags(format_specs& specs, const Char*& it,
|
static void parse_flags(format_specs& specs, const Char*& it,
|
||||||
const Char* end);
|
const Char* end);
|
||||||
@ -346,9 +362,8 @@ template <typename OutputIt, typename Char> class basic_printf_context {
|
|||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
Constructs a ``printf_context`` object. References to the arguments and
|
Constructs a ``printf_context`` object. References to the arguments are
|
||||||
the writer are stored in the context object so make sure they have
|
stored in the context object so make sure they have appropriate lifetimes.
|
||||||
appropriate lifetimes.
|
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
basic_printf_context(OutputIt out, basic_string_view<char_type> format_str,
|
basic_printf_context(OutputIt out, basic_string_view<char_type> format_str,
|
||||||
@ -358,18 +373,18 @@ template <typename OutputIt, typename Char> class basic_printf_context {
|
|||||||
OutputIt out() { return out_; }
|
OutputIt out() { return out_; }
|
||||||
void advance_to(OutputIt it) { out_ = it; }
|
void advance_to(OutputIt it) { out_ = it; }
|
||||||
|
|
||||||
internal::locale_ref locale() { return {}; }
|
detail::locale_ref locale() { return {}; }
|
||||||
|
|
||||||
format_arg arg(int id) const { return args_.get(id); }
|
format_arg arg(int id) const { return args_.get(id); }
|
||||||
|
|
||||||
basic_format_parse_context<Char>& parse_context() { return parse_ctx_; }
|
parse_context_type& parse_context() { return parse_ctx_; }
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_error(const char* message) {
|
FMT_CONSTEXPR void on_error(const char* message) {
|
||||||
parse_ctx_.on_error(message);
|
parse_ctx_.on_error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Formats stored arguments and writes the output to the range. */
|
/** Formats stored arguments and writes the output to the range. */
|
||||||
template <typename ArgFormatter = printf_arg_formatter<buffer_range<Char>>>
|
template <typename ArgFormatter = printf_arg_formatter<OutputIt, Char>>
|
||||||
OutputIt format();
|
OutputIt format();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -389,7 +404,9 @@ void basic_printf_context<OutputIt, Char>::parse_flags(format_specs& specs,
|
|||||||
specs.fill[0] = '0';
|
specs.fill[0] = '0';
|
||||||
break;
|
break;
|
||||||
case ' ':
|
case ' ':
|
||||||
specs.sign = sign::space;
|
if (specs.sign != sign::plus) {
|
||||||
|
specs.sign = sign::space;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case '#':
|
case '#':
|
||||||
specs.alt = true;
|
specs.alt = true;
|
||||||
@ -407,7 +424,7 @@ basic_printf_context<OutputIt, Char>::get_arg(int arg_index) {
|
|||||||
arg_index = parse_ctx_.next_arg_id();
|
arg_index = parse_ctx_.next_arg_id();
|
||||||
else
|
else
|
||||||
parse_ctx_.check_arg_id(--arg_index);
|
parse_ctx_.check_arg_id(--arg_index);
|
||||||
return internal::get_arg(*this, arg_index);
|
return detail::get_arg(*this, arg_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename Char>
|
template <typename OutputIt, typename Char>
|
||||||
@ -419,7 +436,7 @@ int basic_printf_context<OutputIt, Char>::parse_header(const Char*& it,
|
|||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
// Parse an argument index (if followed by '$') or a width possibly
|
// Parse an argument index (if followed by '$') or a width possibly
|
||||||
// preceded with '0' flag(s).
|
// preceded with '0' flag(s).
|
||||||
internal::error_handler eh;
|
detail::error_handler eh;
|
||||||
int value = parse_nonnegative_int(it, end, eh);
|
int value = parse_nonnegative_int(it, end, eh);
|
||||||
if (it != end && *it == '$') { // value is an argument index
|
if (it != end && *it == '$') { // value is an argument index
|
||||||
++it;
|
++it;
|
||||||
@ -438,12 +455,12 @@ int basic_printf_context<OutputIt, Char>::parse_header(const Char*& it,
|
|||||||
// Parse width.
|
// Parse width.
|
||||||
if (it != end) {
|
if (it != end) {
|
||||||
if (*it >= '0' && *it <= '9') {
|
if (*it >= '0' && *it <= '9') {
|
||||||
internal::error_handler eh;
|
detail::error_handler eh;
|
||||||
specs.width = parse_nonnegative_int(it, end, eh);
|
specs.width = parse_nonnegative_int(it, end, eh);
|
||||||
} else if (*it == '*') {
|
} else if (*it == '*') {
|
||||||
++it;
|
++it;
|
||||||
specs.width = static_cast<int>(visit_format_arg(
|
specs.width = static_cast<int>(visit_format_arg(
|
||||||
internal::printf_width_handler<char_type>(specs), get_arg()));
|
detail::printf_width_handler<char_type>(specs), get_arg()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return arg_index;
|
return arg_index;
|
||||||
@ -471,38 +488,52 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
|||||||
|
|
||||||
// Parse argument index, flags and width.
|
// Parse argument index, flags and width.
|
||||||
int arg_index = parse_header(it, end, specs);
|
int arg_index = parse_header(it, end, specs);
|
||||||
if (arg_index == 0) on_error("argument index out of range");
|
if (arg_index == 0) on_error("argument not found");
|
||||||
|
|
||||||
// Parse precision.
|
// Parse precision.
|
||||||
if (it != end && *it == '.') {
|
if (it != end && *it == '.') {
|
||||||
++it;
|
++it;
|
||||||
c = it != end ? *it : 0;
|
c = it != end ? *it : 0;
|
||||||
if ('0' <= c && c <= '9') {
|
if ('0' <= c && c <= '9') {
|
||||||
internal::error_handler eh;
|
detail::error_handler eh;
|
||||||
specs.precision = parse_nonnegative_int(it, end, eh);
|
specs.precision = parse_nonnegative_int(it, end, eh);
|
||||||
} else if (c == '*') {
|
} else if (c == '*') {
|
||||||
++it;
|
++it;
|
||||||
specs.precision = static_cast<int>(
|
specs.precision = static_cast<int>(
|
||||||
visit_format_arg(internal::printf_precision_handler(), get_arg()));
|
visit_format_arg(detail::printf_precision_handler(), get_arg()));
|
||||||
} else {
|
} else {
|
||||||
specs.precision = 0;
|
specs.precision = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
format_arg arg = get_arg(arg_index);
|
format_arg arg = get_arg(arg_index);
|
||||||
if (specs.alt && visit_format_arg(internal::is_zero_int(), arg))
|
// For d, i, o, u, x, and X conversion specifiers, if a precision is
|
||||||
|
// specified, the '0' flag is ignored
|
||||||
|
if (specs.precision >= 0 && arg.is_integral())
|
||||||
|
specs.fill[0] =
|
||||||
|
' '; // Ignore '0' flag for non-numeric types or if '-' present.
|
||||||
|
if (specs.precision >= 0 && arg.type() == detail::type::cstring_type) {
|
||||||
|
auto str = visit_format_arg(detail::get_cstring<Char>(), arg);
|
||||||
|
auto str_end = str + specs.precision;
|
||||||
|
auto nul = std::find(str, str_end, Char());
|
||||||
|
arg = detail::make_arg<basic_printf_context>(basic_string_view<Char>(
|
||||||
|
str,
|
||||||
|
detail::to_unsigned(nul != str_end ? nul - str : specs.precision)));
|
||||||
|
}
|
||||||
|
if (specs.alt && visit_format_arg(detail::is_zero_int(), arg))
|
||||||
specs.alt = false;
|
specs.alt = false;
|
||||||
if (specs.fill[0] == '0') {
|
if (specs.fill[0] == '0') {
|
||||||
if (arg.is_arithmetic())
|
if (arg.is_arithmetic() && specs.align != align::left)
|
||||||
specs.align = align::numeric;
|
specs.align = align::numeric;
|
||||||
else
|
else
|
||||||
specs.fill[0] = ' '; // Ignore '0' flag for non-numeric types.
|
specs.fill[0] = ' '; // Ignore '0' flag for non-numeric types or if '-'
|
||||||
|
// flag is also present.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse length and convert the argument to the required type.
|
// Parse length and convert the argument to the required type.
|
||||||
c = it != end ? *it++ : 0;
|
c = it != end ? *it++ : 0;
|
||||||
char_type t = it != end ? *it : 0;
|
char_type t = it != end ? *it : 0;
|
||||||
using internal::convert_arg;
|
using detail::convert_arg;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
if (t == 'h') {
|
if (t == 'h') {
|
||||||
@ -526,7 +557,7 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
|||||||
convert_arg<intmax_t>(arg, t);
|
convert_arg<intmax_t>(arg, t);
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
convert_arg<std::size_t>(arg, t);
|
convert_arg<size_t>(arg, t);
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
convert_arg<std::ptrdiff_t>(arg, t);
|
convert_arg<std::ptrdiff_t>(arg, t);
|
||||||
@ -551,7 +582,7 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
|||||||
specs.type = 'd';
|
specs.type = 'd';
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
visit_format_arg(internal::char_converter<basic_printf_context>(arg),
|
visit_format_arg(detail::char_converter<basic_printf_context>(arg),
|
||||||
arg);
|
arg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -560,15 +591,14 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
|||||||
start = it;
|
start = it;
|
||||||
|
|
||||||
// Format argument.
|
// Format argument.
|
||||||
visit_format_arg(ArgFormatter(out, specs, *this), arg);
|
out = visit_format_arg(ArgFormatter(out, specs, *this), arg);
|
||||||
}
|
}
|
||||||
return std::copy(start, it, out);
|
return std::copy(start, it, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
using basic_printf_context_t =
|
using basic_printf_context_t =
|
||||||
basic_printf_context<std::back_insert_iterator<internal::buffer<Char>>,
|
basic_printf_context<std::back_insert_iterator<detail::buffer<Char>>, Char>;
|
||||||
Char>;
|
|
||||||
|
|
||||||
using printf_context = basic_printf_context_t<char>;
|
using printf_context = basic_printf_context_t<char>;
|
||||||
using wprintf_context = basic_printf_context_t<wchar_t>;
|
using wprintf_context = basic_printf_context_t<wchar_t>;
|
||||||
@ -605,7 +635,7 @@ inline std::basic_string<Char> vsprintf(
|
|||||||
const S& format,
|
const S& format,
|
||||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
|
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
|
||||||
basic_memory_buffer<Char> buffer;
|
basic_memory_buffer<Char> buffer;
|
||||||
printf(buffer, to_string_view(format), args);
|
vprintf(buffer, to_string_view(format), args);
|
||||||
return to_string(buffer);
|
return to_string(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -619,7 +649,7 @@ inline std::basic_string<Char> vsprintf(
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename S, typename... Args,
|
template <typename S, typename... Args,
|
||||||
typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>>
|
typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
|
||||||
inline std::basic_string<Char> sprintf(const S& format, const Args&... args) {
|
inline std::basic_string<Char> sprintf(const S& format, const Args&... args) {
|
||||||
using context = basic_printf_context_t<Char>;
|
using context = basic_printf_context_t<Char>;
|
||||||
return vsprintf(to_string_view(format), make_format_args<context>(args...));
|
return vsprintf(to_string_view(format), make_format_args<context>(args...));
|
||||||
@ -630,8 +660,8 @@ inline int vfprintf(
|
|||||||
std::FILE* f, const S& format,
|
std::FILE* f, const S& format,
|
||||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
|
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
|
||||||
basic_memory_buffer<Char> buffer;
|
basic_memory_buffer<Char> buffer;
|
||||||
printf(buffer, to_string_view(format), args);
|
vprintf(buffer, to_string_view(format), args);
|
||||||
std::size_t size = buffer.size();
|
size_t size = buffer.size();
|
||||||
return std::fwrite(buffer.data(), sizeof(Char), size, f) < size
|
return std::fwrite(buffer.data(), sizeof(Char), size, f) < size
|
||||||
? -1
|
? -1
|
||||||
: static_cast<int>(size);
|
: static_cast<int>(size);
|
||||||
@ -647,7 +677,7 @@ inline int vfprintf(
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename S, typename... Args,
|
template <typename S, typename... Args,
|
||||||
typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>>
|
typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
|
||||||
inline int fprintf(std::FILE* f, const S& format, const Args&... args) {
|
inline int fprintf(std::FILE* f, const S& format, const Args&... args) {
|
||||||
using context = basic_printf_context_t<Char>;
|
using context = basic_printf_context_t<Char>;
|
||||||
return vfprintf(f, to_string_view(format),
|
return vfprintf(f, to_string_view(format),
|
||||||
@ -671,7 +701,7 @@ inline int vprintf(
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename S, typename... Args,
|
template <typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(internal::is_string<S>::value)>
|
FMT_ENABLE_IF(detail::is_string<S>::value)>
|
||||||
inline int printf(const S& format_str, const Args&... args) {
|
inline int printf(const S& format_str, const Args&... args) {
|
||||||
using context = basic_printf_context_t<char_t<S>>;
|
using context = basic_printf_context_t<char_t<S>>;
|
||||||
return vprintf(to_string_view(format_str),
|
return vprintf(to_string_view(format_str),
|
||||||
@ -683,8 +713,8 @@ inline int vfprintf(
|
|||||||
std::basic_ostream<Char>& os, const S& format,
|
std::basic_ostream<Char>& os, const S& format,
|
||||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
|
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
|
||||||
basic_memory_buffer<Char> buffer;
|
basic_memory_buffer<Char> buffer;
|
||||||
printf(buffer, to_string_view(format), args);
|
vprintf(buffer, to_string_view(format), args);
|
||||||
internal::write(os, buffer);
|
detail::write_buffer(os, buffer);
|
||||||
return static_cast<int>(buffer.size());
|
return static_cast<int>(buffer.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -693,7 +723,7 @@ template <typename ArgFormatter, typename Char,
|
|||||||
typename Context =
|
typename Context =
|
||||||
basic_printf_context<typename ArgFormatter::iterator, Char>>
|
basic_printf_context<typename ArgFormatter::iterator, Char>>
|
||||||
typename ArgFormatter::iterator vprintf(
|
typename ArgFormatter::iterator vprintf(
|
||||||
internal::buffer<Char>& out, basic_string_view<Char> format_str,
|
detail::buffer<Char>& out, basic_string_view<Char> format_str,
|
||||||
basic_format_args<type_identity_t<Context>> args) {
|
basic_format_args<type_identity_t<Context>> args) {
|
||||||
typename ArgFormatter::iterator iter(out);
|
typename ArgFormatter::iterator iter(out);
|
||||||
Context(iter, format_str, args).template format<ArgFormatter>();
|
Context(iter, format_str, args).template format<ArgFormatter>();
|
||||||
|
@ -33,7 +33,7 @@ template <typename Char> struct formatting_base {
|
|||||||
|
|
||||||
template <typename Char, typename Enable = void>
|
template <typename Char, typename Enable = void>
|
||||||
struct formatting_range : formatting_base<Char> {
|
struct formatting_range : formatting_base<Char> {
|
||||||
static FMT_CONSTEXPR_DECL const std::size_t range_length_limit =
|
static FMT_CONSTEXPR_DECL const size_t range_length_limit =
|
||||||
FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the
|
FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the
|
||||||
// range.
|
// range.
|
||||||
Char prefix;
|
Char prefix;
|
||||||
@ -54,7 +54,7 @@ struct formatting_tuple : formatting_base<Char> {
|
|||||||
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
|
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace internal {
|
namespace detail {
|
||||||
|
|
||||||
template <typename RangeT, typename OutputIterator>
|
template <typename RangeT, typename OutputIterator>
|
||||||
OutputIterator copy(const RangeT& range, OutputIterator out) {
|
OutputIterator copy(const RangeT& range, OutputIterator out) {
|
||||||
@ -118,26 +118,24 @@ template <typename T> class is_tuple_like_ {
|
|||||||
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
|
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
|
||||||
template <typename T, T... N>
|
template <typename T, T... N>
|
||||||
using integer_sequence = std::integer_sequence<T, N...>;
|
using integer_sequence = std::integer_sequence<T, N...>;
|
||||||
template <std::size_t... N> using index_sequence = std::index_sequence<N...>;
|
template <size_t... N> using index_sequence = std::index_sequence<N...>;
|
||||||
template <std::size_t N>
|
template <size_t N> using make_index_sequence = std::make_index_sequence<N>;
|
||||||
using make_index_sequence = std::make_index_sequence<N>;
|
|
||||||
#else
|
#else
|
||||||
template <typename T, T... N> struct integer_sequence {
|
template <typename T, T... N> struct integer_sequence {
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
|
|
||||||
static FMT_CONSTEXPR std::size_t size() { return sizeof...(N); }
|
static FMT_CONSTEXPR size_t size() { return sizeof...(N); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t... N>
|
template <size_t... N> using index_sequence = integer_sequence<size_t, N...>;
|
||||||
using index_sequence = integer_sequence<std::size_t, N...>;
|
|
||||||
|
|
||||||
template <typename T, std::size_t N, T... Ns>
|
template <typename T, size_t N, T... Ns>
|
||||||
struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
|
struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
|
||||||
template <typename T, T... Ns>
|
template <typename T, T... Ns>
|
||||||
struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
|
struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
|
||||||
|
|
||||||
template <std::size_t N>
|
template <size_t N>
|
||||||
using make_index_sequence = make_integer_sequence<std::size_t, N>;
|
using make_index_sequence = make_integer_sequence<size_t, N>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <class Tuple, class F, size_t... Is>
|
template <class Tuple, class F, size_t... Is>
|
||||||
@ -185,11 +183,11 @@ FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t) {
|
|||||||
return add_space ? L" '{}'" : L"'{}'";
|
return add_space ? L" '{}'" : L"'{}'";
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace detail
|
||||||
|
|
||||||
template <typename T> struct is_tuple_like {
|
template <typename T> struct is_tuple_like {
|
||||||
static FMT_CONSTEXPR_DECL const bool value =
|
static FMT_CONSTEXPR_DECL const bool value =
|
||||||
internal::is_tuple_like_<T>::value && !internal::is_range_<T>::value;
|
detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TupleT, typename Char>
|
template <typename TupleT, typename Char>
|
||||||
@ -202,17 +200,17 @@ struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
|
|||||||
if (formatting.add_prepostfix_space) {
|
if (formatting.add_prepostfix_space) {
|
||||||
*out++ = ' ';
|
*out++ = ' ';
|
||||||
}
|
}
|
||||||
out = internal::copy(formatting.delimiter, out);
|
out = detail::copy(formatting.delimiter, out);
|
||||||
}
|
}
|
||||||
out = format_to(out,
|
out = format_to(out,
|
||||||
internal::format_str_quoted(
|
detail::format_str_quoted(
|
||||||
(formatting.add_delimiter_spaces && i > 0), v),
|
(formatting.add_delimiter_spaces && i > 0), v),
|
||||||
v);
|
v);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
formatting_tuple<Char>& formatting;
|
formatting_tuple<Char>& formatting;
|
||||||
std::size_t& i;
|
size_t& i;
|
||||||
typename std::add_lvalue_reference<decltype(
|
typename std::add_lvalue_reference<decltype(
|
||||||
std::declval<FormatContext>().out())>::type out;
|
std::declval<FormatContext>().out())>::type out;
|
||||||
};
|
};
|
||||||
@ -228,14 +226,14 @@ struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
|
|||||||
template <typename FormatContext = format_context>
|
template <typename FormatContext = format_context>
|
||||||
auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) {
|
auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||||
auto out = ctx.out();
|
auto out = ctx.out();
|
||||||
std::size_t i = 0;
|
size_t i = 0;
|
||||||
internal::copy(formatting.prefix, out);
|
detail::copy(formatting.prefix, out);
|
||||||
|
|
||||||
internal::for_each(values, format_each<FormatContext>{formatting, i, out});
|
detail::for_each(values, format_each<FormatContext>{formatting, i, out});
|
||||||
if (formatting.add_prepostfix_space) {
|
if (formatting.add_prepostfix_space) {
|
||||||
*out++ = ' ';
|
*out++ = ' ';
|
||||||
}
|
}
|
||||||
internal::copy(formatting.postfix, out);
|
detail::copy(formatting.postfix, out);
|
||||||
|
|
||||||
return ctx.out();
|
return ctx.out();
|
||||||
}
|
}
|
||||||
@ -243,10 +241,9 @@ struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
|
|||||||
|
|
||||||
template <typename T, typename Char> struct is_range {
|
template <typename T, typename Char> struct is_range {
|
||||||
static FMT_CONSTEXPR_DECL const bool value =
|
static FMT_CONSTEXPR_DECL const bool value =
|
||||||
internal::is_range_<T>::value &&
|
detail::is_range_<T>::value && !detail::is_like_std_string<T>::value &&
|
||||||
!internal::is_like_std_string<T>::value &&
|
|
||||||
!std::is_convertible<T, std::basic_string<Char>>::value &&
|
!std::is_convertible<T, std::basic_string<Char>>::value &&
|
||||||
!std::is_constructible<internal::std_string_view<Char>, T>::value;
|
!std::is_constructible<detail::std_string_view<Char>, T>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename RangeT, typename Char>
|
template <typename RangeT, typename Char>
|
||||||
@ -262,15 +259,17 @@ struct formatter<RangeT, Char,
|
|||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
typename FormatContext::iterator format(const RangeT& values,
|
typename FormatContext::iterator format(const RangeT& values,
|
||||||
FormatContext& ctx) {
|
FormatContext& ctx) {
|
||||||
auto out = internal::copy(formatting.prefix, ctx.out());
|
auto out = detail::copy(formatting.prefix, ctx.out());
|
||||||
std::size_t i = 0;
|
size_t i = 0;
|
||||||
for (auto it = values.begin(), end = values.end(); it != end; ++it) {
|
auto it = values.begin();
|
||||||
|
auto end = values.end();
|
||||||
|
for (; it != end; ++it) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
if (formatting.add_prepostfix_space) *out++ = ' ';
|
if (formatting.add_prepostfix_space) *out++ = ' ';
|
||||||
out = internal::copy(formatting.delimiter, out);
|
out = detail::copy(formatting.delimiter, out);
|
||||||
}
|
}
|
||||||
out = format_to(out,
|
out = format_to(out,
|
||||||
internal::format_str_quoted(
|
detail::format_str_quoted(
|
||||||
(formatting.add_delimiter_spaces && i > 0), *it),
|
(formatting.add_delimiter_spaces && i > 0), *it),
|
||||||
*it);
|
*it);
|
||||||
if (++i > formatting.range_length_limit) {
|
if (++i > formatting.range_length_limit) {
|
||||||
@ -279,11 +278,11 @@ struct formatter<RangeT, Char,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (formatting.add_prepostfix_space) *out++ = ' ';
|
if (formatting.add_prepostfix_space) *out++ = ' ';
|
||||||
return internal::copy(formatting.postfix, out);
|
return detail::copy(formatting.postfix, out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Char, typename... T> struct tuple_arg_join : internal::view {
|
template <typename Char, typename... T> struct tuple_arg_join : detail::view {
|
||||||
const std::tuple<T...>& tuple;
|
const std::tuple<T...>& tuple;
|
||||||
basic_string_view<Char> sep;
|
basic_string_view<Char> sep;
|
||||||
|
|
||||||
@ -301,14 +300,14 @@ struct formatter<tuple_arg_join<Char, T...>, Char> {
|
|||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
typename FormatContext::iterator format(
|
typename FormatContext::iterator format(
|
||||||
const tuple_arg_join<Char, T...>& value, FormatContext& ctx) {
|
const tuple_arg_join<Char, T...>& value, FormatContext& ctx) {
|
||||||
return format(value, ctx, internal::make_index_sequence<sizeof...(T)>{});
|
return format(value, ctx, detail::make_index_sequence<sizeof...(T)>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename FormatContext, size_t... N>
|
template <typename FormatContext, size_t... N>
|
||||||
typename FormatContext::iterator format(
|
typename FormatContext::iterator format(
|
||||||
const tuple_arg_join<Char, T...>& value, FormatContext& ctx,
|
const tuple_arg_join<Char, T...>& value, FormatContext& ctx,
|
||||||
internal::index_sequence<N...>) {
|
detail::index_sequence<N...>) {
|
||||||
return format_args(value, ctx, std::get<N>(value.tuple)...);
|
return format_args(value, ctx, std::get<N>(value.tuple)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,14 +370,14 @@ FMT_CONSTEXPR tuple_arg_join<wchar_t, T...> join(const std::tuple<T...>& tuple,
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
arg_join<internal::iterator_t<const std::initializer_list<T>>, char> join(
|
arg_join<const T*, const T*, char> join(std::initializer_list<T> list,
|
||||||
std::initializer_list<T> list, string_view sep) {
|
string_view sep) {
|
||||||
return join(std::begin(list), std::end(list), sep);
|
return join(std::begin(list), std::end(list), sep);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
arg_join<internal::iterator_t<const std::initializer_list<T>>, wchar_t> join(
|
arg_join<const T*, const T*, wchar_t> join(std::initializer_list<T> list,
|
||||||
std::initializer_list<T> list, wstring_view sep) {
|
wstring_view sep) {
|
||||||
return join(std::begin(list), std::end(list), sep);
|
return join(std::begin(list), std::end(list), sep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
165
externals/dynarmic/externals/fmt/src/format.cc
vendored
165
externals/dynarmic/externals/fmt/src/format.cc
vendored
@ -8,12 +8,12 @@
|
|||||||
#include "fmt/format-inl.h"
|
#include "fmt/format-inl.h"
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
namespace internal {
|
namespace detail {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int format_float(char* buf, std::size_t size, const char* format, int precision,
|
int format_float(char* buf, std::size_t size, const char* format, int precision,
|
||||||
T value) {
|
T value) {
|
||||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
#ifdef FMT_FUZZ
|
||||||
if (precision > 100000)
|
if (precision > 100000)
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"fuzz mode - avoid large allocation inside snprintf");
|
"fuzz mode - avoid large allocation inside snprintf");
|
||||||
@ -23,154 +23,47 @@ int format_float(char* buf, std::size_t size, const char* format, int precision,
|
|||||||
return precision < 0 ? snprintf_ptr(buf, size, format, value)
|
return precision < 0 ? snprintf_ptr(buf, size, format, value)
|
||||||
: snprintf_ptr(buf, size, format, precision, value);
|
: snprintf_ptr(buf, size, format, precision, value);
|
||||||
}
|
}
|
||||||
struct sprintf_specs {
|
} // namespace detail
|
||||||
int precision;
|
|
||||||
char type;
|
|
||||||
bool alt : 1;
|
|
||||||
|
|
||||||
template <typename Char>
|
template struct FMT_INSTANTIATION_DEF_API detail::basic_data<void>;
|
||||||
constexpr sprintf_specs(basic_format_specs<Char> specs)
|
|
||||||
: precision(specs.precision), type(specs.type), alt(specs.alt) {}
|
|
||||||
|
|
||||||
constexpr bool has_precision() const { return precision >= 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is deprecated and is kept only to preserve ABI compatibility.
|
|
||||||
template <typename Double>
|
|
||||||
char* sprintf_format(Double value, internal::buffer<char>& buf,
|
|
||||||
sprintf_specs specs) {
|
|
||||||
// Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail.
|
|
||||||
FMT_ASSERT(buf.capacity() != 0, "empty buffer");
|
|
||||||
|
|
||||||
// Build format string.
|
|
||||||
enum { max_format_size = 10 }; // longest format: %#-*.*Lg
|
|
||||||
char format[max_format_size];
|
|
||||||
char* format_ptr = format;
|
|
||||||
*format_ptr++ = '%';
|
|
||||||
if (specs.alt || !specs.type) *format_ptr++ = '#';
|
|
||||||
if (specs.precision >= 0) {
|
|
||||||
*format_ptr++ = '.';
|
|
||||||
*format_ptr++ = '*';
|
|
||||||
}
|
|
||||||
if (std::is_same<Double, long double>::value) *format_ptr++ = 'L';
|
|
||||||
|
|
||||||
char type = specs.type;
|
|
||||||
|
|
||||||
if (type == '%')
|
|
||||||
type = 'f';
|
|
||||||
else if (type == 0 || type == 'n')
|
|
||||||
type = 'g';
|
|
||||||
#if FMT_MSC_VER
|
|
||||||
if (type == 'F') {
|
|
||||||
// MSVC's printf doesn't support 'F'.
|
|
||||||
type = 'f';
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
*format_ptr++ = type;
|
|
||||||
*format_ptr = '\0';
|
|
||||||
|
|
||||||
// Format using snprintf.
|
|
||||||
char* start = nullptr;
|
|
||||||
char* decimal_point_pos = nullptr;
|
|
||||||
for (;;) {
|
|
||||||
std::size_t buffer_size = buf.capacity();
|
|
||||||
start = &buf[0];
|
|
||||||
int result =
|
|
||||||
format_float(start, buffer_size, format, specs.precision, value);
|
|
||||||
if (result >= 0) {
|
|
||||||
unsigned n = internal::to_unsigned(result);
|
|
||||||
if (n < buf.capacity()) {
|
|
||||||
// Find the decimal point.
|
|
||||||
auto p = buf.data(), end = p + n;
|
|
||||||
if (*p == '+' || *p == '-') ++p;
|
|
||||||
if (specs.type != 'a' && specs.type != 'A') {
|
|
||||||
while (p < end && *p >= '0' && *p <= '9') ++p;
|
|
||||||
if (p < end && *p != 'e' && *p != 'E') {
|
|
||||||
decimal_point_pos = p;
|
|
||||||
if (!specs.type) {
|
|
||||||
// Keep only one trailing zero after the decimal point.
|
|
||||||
++p;
|
|
||||||
if (*p == '0') ++p;
|
|
||||||
while (p != end && *p >= '1' && *p <= '9') ++p;
|
|
||||||
char* where = p;
|
|
||||||
while (p != end && *p == '0') ++p;
|
|
||||||
if (p == end || *p < '0' || *p > '9') {
|
|
||||||
if (p != end) std::memmove(where, p, to_unsigned(end - p));
|
|
||||||
n -= static_cast<unsigned>(p - where);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf.resize(n);
|
|
||||||
break; // The buffer is large enough - continue with formatting.
|
|
||||||
}
|
|
||||||
buf.reserve(n + 1);
|
|
||||||
} else {
|
|
||||||
// If result is negative we ask to increase the capacity by at least 1,
|
|
||||||
// but as std::vector, the buffer grows exponentially.
|
|
||||||
buf.reserve(buf.capacity() + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return decimal_point_pos;
|
|
||||||
}
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
template FMT_API char* internal::sprintf_format(double, internal::buffer<char>&,
|
|
||||||
sprintf_specs);
|
|
||||||
template FMT_API char* internal::sprintf_format(long double,
|
|
||||||
internal::buffer<char>&,
|
|
||||||
sprintf_specs);
|
|
||||||
|
|
||||||
template struct FMT_INSTANTIATION_DEF_API internal::basic_data<void>;
|
|
||||||
|
|
||||||
// Workaround a bug in MSVC2013 that prevents instantiation of format_float.
|
// Workaround a bug in MSVC2013 that prevents instantiation of format_float.
|
||||||
int (*instantiate_format_float)(double, int, internal::float_specs,
|
int (*instantiate_format_float)(double, int, detail::float_specs,
|
||||||
internal::buffer<char>&) =
|
detail::buffer<char>&) = detail::format_float;
|
||||||
internal::format_float;
|
|
||||||
|
|
||||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
||||||
template FMT_API internal::locale_ref::locale_ref(const std::locale& loc);
|
template FMT_API detail::locale_ref::locale_ref(const std::locale& loc);
|
||||||
template FMT_API std::locale internal::locale_ref::get<std::locale>() const;
|
template FMT_API std::locale detail::locale_ref::get<std::locale>() const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Explicit instantiations for char.
|
// Explicit instantiations for char.
|
||||||
|
|
||||||
template FMT_API std::string internal::grouping_impl<char>(locale_ref);
|
template FMT_API std::string detail::grouping_impl<char>(locale_ref);
|
||||||
template FMT_API char internal::thousands_sep_impl(locale_ref);
|
template FMT_API char detail::thousands_sep_impl(locale_ref);
|
||||||
template FMT_API char internal::decimal_point_impl(locale_ref);
|
template FMT_API char detail::decimal_point_impl(locale_ref);
|
||||||
|
|
||||||
template FMT_API void internal::buffer<char>::append(const char*, const char*);
|
template FMT_API void detail::buffer<char>::append(const char*, const char*);
|
||||||
|
|
||||||
template FMT_API void internal::arg_map<format_context>::init(
|
template FMT_API FMT_BUFFER_CONTEXT(char)::iterator detail::vformat_to(
|
||||||
const basic_format_args<format_context>& args);
|
detail::buffer<char>&, string_view,
|
||||||
|
basic_format_args<FMT_BUFFER_CONTEXT(char)>);
|
||||||
|
|
||||||
template FMT_API std::string internal::vformat<char>(
|
template FMT_API int detail::snprintf_float(double, int, detail::float_specs,
|
||||||
string_view, basic_format_args<format_context>);
|
detail::buffer<char>&);
|
||||||
|
template FMT_API int detail::snprintf_float(long double, int,
|
||||||
template FMT_API format_context::iterator internal::vformat_to(
|
detail::float_specs,
|
||||||
internal::buffer<char>&, string_view, basic_format_args<format_context>);
|
detail::buffer<char>&);
|
||||||
|
template FMT_API int detail::format_float(double, int, detail::float_specs,
|
||||||
template FMT_API int internal::snprintf_float(double, int,
|
detail::buffer<char>&);
|
||||||
internal::float_specs,
|
template FMT_API int detail::format_float(long double, int, detail::float_specs,
|
||||||
internal::buffer<char>&);
|
detail::buffer<char>&);
|
||||||
template FMT_API int internal::snprintf_float(long double, int,
|
|
||||||
internal::float_specs,
|
|
||||||
internal::buffer<char>&);
|
|
||||||
template FMT_API int internal::format_float(double, int, internal::float_specs,
|
|
||||||
internal::buffer<char>&);
|
|
||||||
template FMT_API int internal::format_float(long double, int,
|
|
||||||
internal::float_specs,
|
|
||||||
internal::buffer<char>&);
|
|
||||||
|
|
||||||
// Explicit instantiations for wchar_t.
|
// Explicit instantiations for wchar_t.
|
||||||
|
|
||||||
template FMT_API std::string internal::grouping_impl<wchar_t>(locale_ref);
|
template FMT_API std::string detail::grouping_impl<wchar_t>(locale_ref);
|
||||||
template FMT_API wchar_t internal::thousands_sep_impl(locale_ref);
|
template FMT_API wchar_t detail::thousands_sep_impl(locale_ref);
|
||||||
template FMT_API wchar_t internal::decimal_point_impl(locale_ref);
|
template FMT_API wchar_t detail::decimal_point_impl(locale_ref);
|
||||||
|
|
||||||
template FMT_API void internal::buffer<wchar_t>::append(const wchar_t*,
|
template FMT_API void detail::buffer<wchar_t>::append(const wchar_t*,
|
||||||
const wchar_t*);
|
const wchar_t*);
|
||||||
|
|
||||||
template FMT_API std::wstring internal::vformat<wchar_t>(
|
|
||||||
wstring_view, basic_format_args<wformat_context>);
|
|
||||||
FMT_END_NAMESPACE
|
FMT_END_NAMESPACE
|
||||||
|
25
externals/dynarmic/externals/fmt/src/os.cc
vendored
25
externals/dynarmic/externals/fmt/src/os.cc
vendored
@ -73,14 +73,14 @@ inline std::size_t convert_rwcount(std::size_t count) { return count; }
|
|||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
internal::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
|
detail::utf16_to_utf8::utf16_to_utf8(wstring_view s) {
|
||||||
if (int error_code = convert(s)) {
|
if (int error_code = convert(s)) {
|
||||||
FMT_THROW(windows_error(error_code,
|
FMT_THROW(windows_error(error_code,
|
||||||
"cannot convert string from UTF-16 to UTF-8"));
|
"cannot convert string from UTF-16 to UTF-8"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int internal::utf16_to_utf8::convert(wstring_view s) {
|
int detail::utf16_to_utf8::convert(wstring_view s) {
|
||||||
if (s.size() > INT_MAX) return ERROR_INVALID_PARAMETER;
|
if (s.size() > INT_MAX) return ERROR_INVALID_PARAMETER;
|
||||||
int s_size = static_cast<int>(s.size());
|
int s_size = static_cast<int>(s.size());
|
||||||
if (s_size == 0) {
|
if (s_size == 0) {
|
||||||
@ -105,13 +105,13 @@ void windows_error::init(int err_code, string_view format_str,
|
|||||||
format_args args) {
|
format_args args) {
|
||||||
error_code_ = err_code;
|
error_code_ = err_code;
|
||||||
memory_buffer buffer;
|
memory_buffer buffer;
|
||||||
internal::format_windows_error(buffer, err_code, vformat(format_str, args));
|
detail::format_windows_error(buffer, err_code, vformat(format_str, args));
|
||||||
std::runtime_error& base = *this;
|
std::runtime_error& base = *this;
|
||||||
base = std::runtime_error(to_string(buffer));
|
base = std::runtime_error(to_string(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
void internal::format_windows_error(internal::buffer<char>& out, int error_code,
|
void detail::format_windows_error(detail::buffer<char>& out, int error_code,
|
||||||
string_view message) FMT_NOEXCEPT {
|
string_view message) FMT_NOEXCEPT {
|
||||||
FMT_TRY {
|
FMT_TRY {
|
||||||
wmemory_buffer buf;
|
wmemory_buffer buf;
|
||||||
buf.resize(inline_buffer_size);
|
buf.resize(inline_buffer_size);
|
||||||
@ -124,10 +124,7 @@ void internal::format_windows_error(internal::buffer<char>& out, int error_code,
|
|||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
utf16_to_utf8 utf8_message;
|
utf16_to_utf8 utf8_message;
|
||||||
if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
|
if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
|
||||||
internal::writer w(out);
|
format_to(std::back_inserter(out), "{}: {}", message, utf8_message);
|
||||||
w.write(message);
|
|
||||||
w.write(": ");
|
|
||||||
w.write(utf8_message);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -143,7 +140,7 @@ void internal::format_windows_error(internal::buffer<char>& out, int error_code,
|
|||||||
|
|
||||||
void report_windows_error(int error_code,
|
void report_windows_error(int error_code,
|
||||||
fmt::string_view message) FMT_NOEXCEPT {
|
fmt::string_view message) FMT_NOEXCEPT {
|
||||||
report_error(internal::format_windows_error, error_code, message);
|
report_error(detail::format_windows_error, error_code, message);
|
||||||
}
|
}
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
@ -234,14 +231,14 @@ std::size_t file::read(void* buffer, std::size_t count) {
|
|||||||
RWResult result = 0;
|
RWResult result = 0;
|
||||||
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
|
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
|
||||||
if (result < 0) FMT_THROW(system_error(errno, "cannot read from file"));
|
if (result < 0) FMT_THROW(system_error(errno, "cannot read from file"));
|
||||||
return internal::to_unsigned(result);
|
return detail::to_unsigned(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t file::write(const void* buffer, std::size_t count) {
|
std::size_t file::write(const void* buffer, std::size_t count) {
|
||||||
RWResult result = 0;
|
RWResult result = 0;
|
||||||
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
|
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
|
||||||
if (result < 0) FMT_THROW(system_error(errno, "cannot write to file"));
|
if (result < 0) FMT_THROW(system_error(errno, "cannot write to file"));
|
||||||
return internal::to_unsigned(result);
|
return detail::to_unsigned(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
file file::dup(int fd) {
|
file file::dup(int fd) {
|
||||||
@ -292,7 +289,11 @@ void file::pipe(file& read_end, file& write_end) {
|
|||||||
|
|
||||||
buffered_file file::fdopen(const char* mode) {
|
buffered_file file::fdopen(const char* mode) {
|
||||||
// Don't retry as fdopen doesn't return EINTR.
|
// Don't retry as fdopen doesn't return EINTR.
|
||||||
|
#if defined(__MINGW32__) && defined(_POSIX_)
|
||||||
|
FILE* f = ::fdopen(fd_, mode);
|
||||||
|
#else
|
||||||
FILE* f = FMT_POSIX_CALL(fdopen(fd_, mode));
|
FILE* f = FMT_POSIX_CALL(fdopen(fd_, mode));
|
||||||
|
#endif
|
||||||
if (!f)
|
if (!f)
|
||||||
FMT_THROW(
|
FMT_THROW(
|
||||||
system_error(errno, "cannot associate stream with file descriptor"));
|
system_error(errno, "cannot associate stream with file descriptor"));
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
# A vagrant config for testing against gcc-4.8.
|
# A vagrant config for testing against gcc-4.8.
|
||||||
Vagrant.configure("2") do |config|
|
Vagrant.configure("2") do |config|
|
||||||
config.vm.box = "ubuntu/xenial64"
|
config.vm.box = "ubuntu/xenial64"
|
||||||
|
config.disksize.size = '15GB'
|
||||||
|
|
||||||
config.vm.provider "virtualbox" do |vb|
|
config.vm.provider "virtualbox" do |vb|
|
||||||
vb.memory = "4096"
|
vb.memory = "4096"
|
||||||
|
26
externals/dynarmic/externals/fmt/support/cmake/JoinPaths.cmake
vendored
Executable file
26
externals/dynarmic/externals/fmt/support/cmake/JoinPaths.cmake
vendored
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
# This module provides function for joining paths
|
||||||
|
# known from from most languages
|
||||||
|
#
|
||||||
|
# Original license:
|
||||||
|
# SPDX-License-Identifier: (MIT OR CC0-1.0)
|
||||||
|
# Explicit permission given to distribute this module under
|
||||||
|
# the terms of the project as described in /LICENSE.rst.
|
||||||
|
# Copyright 2020 Jan Tojnar
|
||||||
|
# https://github.com/jtojnar/cmake-snips
|
||||||
|
#
|
||||||
|
# Modelled after Python’s os.path.join
|
||||||
|
# https://docs.python.org/3.7/library/os.path.html#os.path.join
|
||||||
|
# Windows not supported
|
||||||
|
function(join_paths joined_path first_path_segment)
|
||||||
|
set(temp_path "${first_path_segment}")
|
||||||
|
foreach(current_segment IN LISTS ARGN)
|
||||||
|
if(NOT ("${current_segment}" STREQUAL ""))
|
||||||
|
if(IS_ABSOLUTE "${current_segment}")
|
||||||
|
set(temp_path "${current_segment}")
|
||||||
|
else()
|
||||||
|
set(temp_path "${temp_path}/${current_segment}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
set(${joined_path} "${temp_path}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
@ -1,7 +1,7 @@
|
|||||||
prefix=@CMAKE_INSTALL_PREFIX@
|
prefix=@CMAKE_INSTALL_PREFIX@
|
||||||
exec_prefix=@CMAKE_INSTALL_PREFIX@
|
exec_prefix=@CMAKE_INSTALL_PREFIX@
|
||||||
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
|
libdir=@libdir_for_pc_file@
|
||||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
includedir=@includedir_for_pc_file@
|
||||||
|
|
||||||
Name: fmt
|
Name: fmt
|
||||||
Description: A modern formatting library
|
Description: A modern formatting library
|
||||||
|
@ -144,9 +144,33 @@ def update_site(env):
|
|||||||
b.data = re.sub(pattern, r'doxygenfunction:: \1(int)', b.data)
|
b.data = re.sub(pattern, r'doxygenfunction:: \1(int)', b.data)
|
||||||
b.data = b.data.replace('std::FILE*', 'std::FILE *')
|
b.data = b.data.replace('std::FILE*', 'std::FILE *')
|
||||||
b.data = b.data.replace('unsigned int', 'unsigned')
|
b.data = b.data.replace('unsigned int', 'unsigned')
|
||||||
b.data = b.data.replace('operator""_', 'operator"" _')
|
#b.data = b.data.replace('operator""_', 'operator"" _')
|
||||||
b.data = b.data.replace(', size_t', ', std::size_t')
|
b.data = b.data.replace(
|
||||||
|
'format_to_n(OutputIt, size_t, string_view, Args&&',
|
||||||
|
'format_to_n(OutputIt, size_t, const S&, const Args&')
|
||||||
|
b.data = b.data.replace(
|
||||||
|
'format_to_n(OutputIt, std::size_t, string_view, Args&&',
|
||||||
|
'format_to_n(OutputIt, std::size_t, const S&, const Args&')
|
||||||
|
if version == ('3.0.2'):
|
||||||
|
b.data = b.data.replace(
|
||||||
|
'fprintf(std::ostream&', 'fprintf(std::ostream &')
|
||||||
|
if version == ('5.3.0'):
|
||||||
|
b.data = b.data.replace(
|
||||||
|
'format_to(OutputIt, const S&, const Args&...)',
|
||||||
|
'format_to(OutputIt, const S &, const Args &...)')
|
||||||
|
if version.startswith('5.') or version.startswith('6.'):
|
||||||
|
b.data = b.data.replace(', size_t', ', std::size_t')
|
||||||
|
if version.startswith('7.'):
|
||||||
|
b.data = b.data.replace(', std::size_t', ', size_t')
|
||||||
|
b.data = b.data.replace('join(It, It', 'join(It, Sentinel')
|
||||||
b.data = b.data.replace('aa long', 'a long')
|
b.data = b.data.replace('aa long', 'a long')
|
||||||
|
b.data = b.data.replace('serveral', 'several')
|
||||||
|
if version.startswith('6.2.'):
|
||||||
|
b.data = b.data.replace(
|
||||||
|
'vformat(const S&, basic_format_args<' +
|
||||||
|
'buffer_context<Char>>)',
|
||||||
|
'vformat(const S&, basic_format_args<' +
|
||||||
|
'buffer_context<type_identity_t<Char>>>)')
|
||||||
# Fix a broken link in index.rst.
|
# Fix a broken link in index.rst.
|
||||||
index = os.path.join(target_doc_dir, 'index.rst')
|
index = os.path.join(target_doc_dir, 'index.rst')
|
||||||
with rewrite(index) as b:
|
with rewrite(index) as b:
|
||||||
|
@ -10,10 +10,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "fmt/chrono.h"
|
#include "fmt/chrono.h"
|
||||||
#include "gtest-extra.h"
|
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
|
#include "gtest-extra.h"
|
||||||
|
|
||||||
std::tm make_tm() {
|
std::tm make_tm() {
|
||||||
auto time = std::tm();
|
auto time = std::tm();
|
||||||
time.tm_mday = 1;
|
time.tm_mday = 1;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
// For the license information refer to format.h.
|
// For the license information refer to format.h.
|
||||||
|
|
||||||
#include "fmt/color.h"
|
#include "fmt/color.h"
|
||||||
|
|
||||||
#include "gtest-extra.h"
|
#include "gtest-extra.h"
|
||||||
|
|
||||||
TEST(ColorsTest, ColorsPrint) {
|
TEST(ColorsTest, ColorsPrint) {
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
// For the license information refer to format.h.
|
// For the license information refer to format.h.
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
@ -39,8 +40,8 @@ using testing::StrictMock;
|
|||||||
#if FMT_USE_CONSTEXPR
|
#if FMT_USE_CONSTEXPR
|
||||||
template <unsigned EXPECTED_PARTS_COUNT, typename Format>
|
template <unsigned EXPECTED_PARTS_COUNT, typename Format>
|
||||||
void check_prepared_parts_type(Format format) {
|
void check_prepared_parts_type(Format format) {
|
||||||
typedef fmt::internal::compiled_format_base<decltype(format)> provider;
|
typedef fmt::detail::compiled_format_base<decltype(format)> provider;
|
||||||
typedef fmt::internal::format_part<char>
|
typedef fmt::detail::format_part<char>
|
||||||
expected_parts_type[EXPECTED_PARTS_COUNT];
|
expected_parts_type[EXPECTED_PARTS_COUNT];
|
||||||
static_assert(std::is_same<typename provider::parts_container,
|
static_assert(std::is_same<typename provider::parts_container,
|
||||||
expected_parts_type>::value,
|
expected_parts_type>::value,
|
||||||
@ -66,46 +67,37 @@ TEST(CompileTest, CompileTimePreparedPartsTypeProvider) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST(CompileTest, PassStringLiteralFormat) {
|
TEST(CompileTest, PassStringLiteralFormat) {
|
||||||
const auto prepared = fmt::compile<int>("test {}");
|
const auto prepared = fmt::detail::compile<int>("test {}");
|
||||||
EXPECT_EQ("test 42", fmt::format(prepared, 42));
|
EXPECT_EQ("test 42", fmt::format(prepared, 42));
|
||||||
const auto wprepared = fmt::compile<int>(L"test {}");
|
const auto wprepared = fmt::detail::compile<int>(L"test {}");
|
||||||
EXPECT_EQ(L"test 42", fmt::format(wprepared, 42));
|
EXPECT_EQ(L"test 42", fmt::format(wprepared, 42));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FMT_USE_CONSTEXPR
|
|
||||||
TEST(CompileTest, PassCompileString) {
|
|
||||||
const auto prepared = fmt::compile<int>(FMT_STRING("test {}"));
|
|
||||||
EXPECT_EQ("test 42", fmt::format(prepared, 42));
|
|
||||||
const auto wprepared = fmt::compile<int>(FMT_STRING(L"test {}"));
|
|
||||||
EXPECT_EQ(L"test 42", fmt::format(wprepared, 42));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TEST(CompileTest, FormatToArrayOfChars) {
|
TEST(CompileTest, FormatToArrayOfChars) {
|
||||||
char buffer[32] = {0};
|
char buffer[32] = {0};
|
||||||
const auto prepared = fmt::compile<int>("4{}");
|
const auto prepared = fmt::detail::compile<int>("4{}");
|
||||||
fmt::format_to(fmt::internal::make_checked(buffer, 32), prepared, 2);
|
fmt::format_to(fmt::detail::make_checked(buffer, 32), prepared, 2);
|
||||||
EXPECT_EQ(std::string("42"), buffer);
|
EXPECT_EQ(std::string("42"), buffer);
|
||||||
wchar_t wbuffer[32] = {0};
|
wchar_t wbuffer[32] = {0};
|
||||||
const auto wprepared = fmt::compile<int>(L"4{}");
|
const auto wprepared = fmt::detail::compile<int>(L"4{}");
|
||||||
fmt::format_to(fmt::internal::make_checked(wbuffer, 32), wprepared, 2);
|
fmt::format_to(fmt::detail::make_checked(wbuffer, 32), wprepared, 2);
|
||||||
EXPECT_EQ(std::wstring(L"42"), wbuffer);
|
EXPECT_EQ(std::wstring(L"42"), wbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CompileTest, FormatToIterator) {
|
TEST(CompileTest, FormatToIterator) {
|
||||||
std::string s(2, ' ');
|
std::string s(2, ' ');
|
||||||
const auto prepared = fmt::compile<int>("4{}");
|
const auto prepared = fmt::detail::compile<int>("4{}");
|
||||||
fmt::format_to(s.begin(), prepared, 2);
|
fmt::format_to(s.begin(), prepared, 2);
|
||||||
EXPECT_EQ("42", s);
|
EXPECT_EQ("42", s);
|
||||||
std::wstring ws(2, L' ');
|
std::wstring ws(2, L' ');
|
||||||
const auto wprepared = fmt::compile<int>(L"4{}");
|
const auto wprepared = fmt::detail::compile<int>(L"4{}");
|
||||||
fmt::format_to(ws.begin(), wprepared, 2);
|
fmt::format_to(ws.begin(), wprepared, 2);
|
||||||
EXPECT_EQ(L"42", ws);
|
EXPECT_EQ(L"42", ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CompileTest, FormatToN) {
|
TEST(CompileTest, FormatToN) {
|
||||||
char buf[5];
|
char buf[5];
|
||||||
auto f = fmt::compile<int>("{:10}");
|
auto f = fmt::detail::compile<int>("{:10}");
|
||||||
auto result = fmt::format_to_n(buf, 5, f, 42);
|
auto result = fmt::format_to_n(buf, 5, f, 42);
|
||||||
EXPECT_EQ(result.size, 10);
|
EXPECT_EQ(result.size, 10);
|
||||||
EXPECT_EQ(result.out, buf + 5);
|
EXPECT_EQ(result.out, buf + 5);
|
||||||
@ -113,12 +105,12 @@ TEST(CompileTest, FormatToN) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(CompileTest, FormattedSize) {
|
TEST(CompileTest, FormattedSize) {
|
||||||
auto f = fmt::compile<int>("{:10}");
|
auto f = fmt::detail::compile<int>("{:10}");
|
||||||
EXPECT_EQ(fmt::formatted_size(f, 42), 10);
|
EXPECT_EQ(fmt::formatted_size(f, 42), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CompileTest, MultipleTypes) {
|
TEST(CompileTest, MultipleTypes) {
|
||||||
auto f = fmt::compile<int, int>("{} {}");
|
auto f = fmt::detail::compile<int, int>("{} {}");
|
||||||
EXPECT_EQ(fmt::format(f, 42, 42), "42 42");
|
EXPECT_EQ(fmt::format(f, 42, 42), "42 42");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,18 +118,49 @@ struct formattable {};
|
|||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
template <> struct formatter<formattable> : formatter<const char*> {
|
template <> struct formatter<formattable> : formatter<const char*> {
|
||||||
auto format(formattable, format_context& ctx) -> decltype(ctx.out()) {
|
template <typename FormatContext>
|
||||||
|
auto format(formattable, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||||
return formatter<const char*>::format("foo", ctx);
|
return formatter<const char*>::format("foo", ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
FMT_END_NAMESPACE
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
TEST(CompileTest, FormatUserDefinedType) {
|
TEST(CompileTest, FormatUserDefinedType) {
|
||||||
auto f = fmt::compile<formattable>("{}");
|
auto f = fmt::detail::compile<formattable>("{}");
|
||||||
EXPECT_EQ(fmt::format(f, formattable()), "foo");
|
EXPECT_EQ(fmt::format(f, formattable()), "foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CompileTest, EmptyFormatString) {
|
TEST(CompileTest, EmptyFormatString) {
|
||||||
auto f = fmt::compile<>("");
|
auto f = fmt::detail::compile<>("");
|
||||||
EXPECT_EQ(fmt::format(f), "");
|
EXPECT_EQ(fmt::format(f), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __cpp_if_constexpr
|
||||||
|
TEST(CompileTest, FormatDefault) {
|
||||||
|
EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), 42));
|
||||||
|
EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), 42u));
|
||||||
|
EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), 42ll));
|
||||||
|
EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), 42ull));
|
||||||
|
EXPECT_EQ("true", fmt::format(FMT_COMPILE("{}"), true));
|
||||||
|
EXPECT_EQ("x", fmt::format(FMT_COMPILE("{}"), 'x'));
|
||||||
|
EXPECT_EQ("4.2", fmt::format(FMT_COMPILE("{}"), 4.2));
|
||||||
|
EXPECT_EQ("foo", fmt::format(FMT_COMPILE("{}"), "foo"));
|
||||||
|
EXPECT_EQ("foo", fmt::format(FMT_COMPILE("{}"), std::string("foo")));
|
||||||
|
EXPECT_EQ("foo", fmt::format(FMT_COMPILE("{}"), formattable()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CompileTest, FormatSpecs) {
|
||||||
|
EXPECT_EQ("42", fmt::format(FMT_COMPILE("{:x}"), 0x42));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CompileTest, FormatTo) {
|
||||||
|
char buf[8];
|
||||||
|
auto end = fmt::format_to(buf, FMT_COMPILE("{}"), 42);
|
||||||
|
*end = '\0';
|
||||||
|
EXPECT_STREQ("42", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CompileTest, TextAndArg) {
|
||||||
|
EXPECT_EQ(">>>42<<<", fmt::format(FMT_COMPILE(">>>{}<<<"), 42));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
184
externals/dynarmic/externals/fmt/test/core-test.cc
vendored
184
externals/dynarmic/externals/fmt/test/core-test.cc
vendored
@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
using fmt::basic_format_arg;
|
using fmt::basic_format_arg;
|
||||||
using fmt::string_view;
|
using fmt::string_view;
|
||||||
using fmt::internal::buffer;
|
using fmt::detail::buffer;
|
||||||
using fmt::internal::value;
|
using fmt::detail::value;
|
||||||
|
|
||||||
using testing::_;
|
using testing::_;
|
||||||
using testing::StrictMock;
|
using testing::StrictMock;
|
||||||
@ -42,7 +42,7 @@ struct test_struct {};
|
|||||||
|
|
||||||
template <typename Context, typename T>
|
template <typename Context, typename T>
|
||||||
basic_format_arg<Context> make_arg(const T& value) {
|
basic_format_arg<Context> make_arg(const T& value) {
|
||||||
return fmt::internal::make_arg<Context>(value);
|
return fmt::detail::make_arg<Context>(value);
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@ -83,20 +83,20 @@ TEST(BufferTest, Nonmoveable) {
|
|||||||
|
|
||||||
// A test buffer with a dummy grow method.
|
// A test buffer with a dummy grow method.
|
||||||
template <typename T> struct test_buffer : buffer<T> {
|
template <typename T> struct test_buffer : buffer<T> {
|
||||||
void grow(std::size_t capacity) { this->set(nullptr, capacity); }
|
void grow(size_t capacity) { this->set(nullptr, capacity); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T> struct mock_buffer : buffer<T> {
|
template <typename T> struct mock_buffer : buffer<T> {
|
||||||
MOCK_METHOD1(do_grow, void(std::size_t capacity));
|
MOCK_METHOD1(do_grow, void(size_t capacity));
|
||||||
|
|
||||||
void grow(std::size_t capacity) {
|
void grow(size_t capacity) {
|
||||||
this->set(this->data(), capacity);
|
this->set(this->data(), capacity);
|
||||||
do_grow(capacity);
|
do_grow(capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
mock_buffer() {}
|
mock_buffer() {}
|
||||||
mock_buffer(T* data) { this->set(data, 0); }
|
mock_buffer(T* data) { this->set(data, 0); }
|
||||||
mock_buffer(T* data, std::size_t capacity) { this->set(data, capacity); }
|
mock_buffer(T* data, size_t capacity) { this->set(data, capacity); }
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(BufferTest, Ctor) {
|
TEST(BufferTest, Ctor) {
|
||||||
@ -115,7 +115,7 @@ TEST(BufferTest, Ctor) {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
int dummy;
|
int dummy;
|
||||||
std::size_t capacity = std::numeric_limits<std::size_t>::max();
|
size_t capacity = std::numeric_limits<size_t>::max();
|
||||||
mock_buffer<int> buffer(&dummy, capacity);
|
mock_buffer<int> buffer(&dummy, capacity);
|
||||||
EXPECT_EQ(&dummy, &buffer[0]);
|
EXPECT_EQ(&dummy, &buffer[0]);
|
||||||
EXPECT_EQ(static_cast<size_t>(0), buffer.size());
|
EXPECT_EQ(static_cast<size_t>(0), buffer.size());
|
||||||
@ -148,7 +148,7 @@ TEST(BufferTest, Access) {
|
|||||||
EXPECT_EQ(11, buffer[0]);
|
EXPECT_EQ(11, buffer[0]);
|
||||||
buffer[3] = 42;
|
buffer[3] = 42;
|
||||||
EXPECT_EQ(42, *(&buffer[0] + 3));
|
EXPECT_EQ(42, *(&buffer[0] + 3));
|
||||||
const fmt::internal::buffer<char>& const_buffer = buffer;
|
const fmt::detail::buffer<char>& const_buffer = buffer;
|
||||||
EXPECT_EQ(42, const_buffer[3]);
|
EXPECT_EQ(42, const_buffer[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +210,8 @@ TEST(ArgTest, FormatArgs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct custom_context {
|
struct custom_context {
|
||||||
typedef char char_type;
|
using char_type = char;
|
||||||
|
using parse_context_type = fmt::format_parse_context;
|
||||||
|
|
||||||
template <typename T> struct formatter_type {
|
template <typename T> struct formatter_type {
|
||||||
template <typename ParseContext>
|
template <typename ParseContext>
|
||||||
@ -233,20 +234,20 @@ struct custom_context {
|
|||||||
|
|
||||||
TEST(ArgTest, MakeValueWithCustomContext) {
|
TEST(ArgTest, MakeValueWithCustomContext) {
|
||||||
test_struct t;
|
test_struct t;
|
||||||
fmt::internal::value<custom_context> arg(
|
fmt::detail::value<custom_context> arg(
|
||||||
fmt::internal::arg_mapper<custom_context>().map(t));
|
fmt::detail::arg_mapper<custom_context>().map(t));
|
||||||
custom_context ctx = {false, fmt::format_parse_context("")};
|
custom_context ctx = {false, fmt::format_parse_context("")};
|
||||||
arg.custom.format(&t, ctx.parse_context(), ctx);
|
arg.custom.format(&t, ctx.parse_context(), ctx);
|
||||||
EXPECT_TRUE(ctx.called);
|
EXPECT_TRUE(ctx.called);
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
namespace internal {
|
namespace detail {
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
bool operator==(custom_value<Char> lhs, custom_value<Char> rhs) {
|
bool operator==(custom_value<Char> lhs, custom_value<Char> rhs) {
|
||||||
return lhs.value == rhs.value;
|
return lhs.value == rhs.value;
|
||||||
}
|
}
|
||||||
} // namespace internal
|
} // namespace detail
|
||||||
FMT_END_NAMESPACE
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
// Use a unique result type to make sure that there are no undesirable
|
// Use a unique result type to make sure that there are no undesirable
|
||||||
@ -371,12 +372,12 @@ TEST(ArgTest, PointerArg) {
|
|||||||
struct check_custom {
|
struct check_custom {
|
||||||
test_result operator()(
|
test_result operator()(
|
||||||
fmt::basic_format_arg<fmt::format_context>::handle h) const {
|
fmt::basic_format_arg<fmt::format_context>::handle h) const {
|
||||||
struct test_buffer : fmt::internal::buffer<char> {
|
struct test_buffer : fmt::detail::buffer<char> {
|
||||||
char data[10];
|
char data[10];
|
||||||
test_buffer() : fmt::internal::buffer<char>(data, 0, 10) {}
|
test_buffer() : fmt::detail::buffer<char>(data, 0, 10) {}
|
||||||
void grow(std::size_t) {}
|
void grow(size_t) {}
|
||||||
} buffer;
|
} buffer;
|
||||||
fmt::internal::buffer<char>& base = buffer;
|
fmt::detail::buffer<char>& base = buffer;
|
||||||
fmt::format_parse_context parse_ctx("");
|
fmt::format_parse_context parse_ctx("");
|
||||||
fmt::format_context ctx(std::back_inserter(base), fmt::format_args());
|
fmt::format_context ctx(std::back_inserter(base), fmt::format_args());
|
||||||
h.format(parse_ctx, ctx);
|
h.format(parse_ctx, ctx);
|
||||||
@ -455,6 +456,25 @@ TEST(FormatDynArgsTest, CustomFormat) {
|
|||||||
EXPECT_EQ("cust=0 and cust=1 and cust=3", result);
|
EXPECT_EQ("cust=0 and cust=1 and cust=3", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(FormatDynArgsTest, NamedInt) {
|
||||||
|
fmt::dynamic_format_arg_store<fmt::format_context> store;
|
||||||
|
store.push_back(fmt::arg("a1", 42));
|
||||||
|
std::string result = fmt::vformat("{a1}", store);
|
||||||
|
EXPECT_EQ("42", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FormatDynArgsTest, NamedStrings) {
|
||||||
|
fmt::dynamic_format_arg_store<fmt::format_context> store;
|
||||||
|
char str[]{"1234567890"};
|
||||||
|
store.push_back(fmt::arg("a1", str));
|
||||||
|
store.push_back(fmt::arg("a2", std::cref(str)));
|
||||||
|
str[0] = 'X';
|
||||||
|
|
||||||
|
std::string result = fmt::vformat("{a1} and {a2}", store);
|
||||||
|
|
||||||
|
EXPECT_EQ("1234567890 and X234567890", result);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(FormatDynArgsTest, NamedArgByRef) {
|
TEST(FormatDynArgsTest, NamedArgByRef) {
|
||||||
fmt::dynamic_format_arg_store<fmt::format_context> store;
|
fmt::dynamic_format_arg_store<fmt::format_context> store;
|
||||||
|
|
||||||
@ -469,12 +489,53 @@ TEST(FormatDynArgsTest, NamedArgByRef) {
|
|||||||
// storages.
|
// storages.
|
||||||
int a1_val{42};
|
int a1_val{42};
|
||||||
auto a1 = fmt::arg("a1_", a1_val);
|
auto a1 = fmt::arg("a1_", a1_val);
|
||||||
|
store.push_back("abc");
|
||||||
|
store.push_back(1.5f);
|
||||||
store.push_back(std::cref(a1));
|
store.push_back(std::cref(a1));
|
||||||
|
|
||||||
std::string result = fmt::vformat("{a1_}", // and {} and {}",
|
std::string result = fmt::vformat("{a1_} and {} and {} and {}", store);
|
||||||
store);
|
|
||||||
|
|
||||||
|
EXPECT_EQ("42 and abc and 1.5 and 42", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FormatDynArgsTest, NamedCustomFormat) {
|
||||||
|
fmt::dynamic_format_arg_store<fmt::format_context> store;
|
||||||
|
custom_type c{};
|
||||||
|
store.push_back(fmt::arg("c1", c));
|
||||||
|
++c.i;
|
||||||
|
store.push_back(fmt::arg("c2", c));
|
||||||
|
++c.i;
|
||||||
|
store.push_back(fmt::arg("c_ref", std::cref(c)));
|
||||||
|
++c.i;
|
||||||
|
|
||||||
|
std::string result = fmt::vformat("{c1} and {c2} and {c_ref}", store);
|
||||||
|
EXPECT_EQ("cust=0 and cust=1 and cust=3", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FormatDynArgsTest, Clear) {
|
||||||
|
fmt::dynamic_format_arg_store<fmt::format_context> store;
|
||||||
|
store.push_back(42);
|
||||||
|
|
||||||
|
std::string result = fmt::vformat("{}", store);
|
||||||
EXPECT_EQ("42", result);
|
EXPECT_EQ("42", result);
|
||||||
|
|
||||||
|
store.push_back(43);
|
||||||
|
result = fmt::vformat("{} and {}", store);
|
||||||
|
EXPECT_EQ("42 and 43", result);
|
||||||
|
|
||||||
|
store.clear();
|
||||||
|
store.push_back(44);
|
||||||
|
result = fmt::vformat("{}", store);
|
||||||
|
EXPECT_EQ("44", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FormatDynArgsTest, Reserve) {
|
||||||
|
fmt::dynamic_format_arg_store<fmt::format_context> store;
|
||||||
|
store.reserve(2, 1);
|
||||||
|
store.push_back(1.5f);
|
||||||
|
store.push_back(fmt::arg("a1", 42));
|
||||||
|
std::string result = fmt::vformat("{a1} and {}", store);
|
||||||
|
EXPECT_EQ("42 and 1.5", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct copy_throwable {
|
struct copy_throwable {
|
||||||
@ -517,9 +578,9 @@ TEST(StringViewTest, Length) {
|
|||||||
// Check string_view's comparison operator.
|
// Check string_view's comparison operator.
|
||||||
template <template <typename> class Op> void check_op() {
|
template <template <typename> class Op> void check_op() {
|
||||||
const char* inputs[] = {"foo", "fop", "fo"};
|
const char* inputs[] = {"foo", "fop", "fo"};
|
||||||
std::size_t num_inputs = sizeof(inputs) / sizeof(*inputs);
|
size_t num_inputs = sizeof(inputs) / sizeof(*inputs);
|
||||||
for (std::size_t i = 0; i < num_inputs; ++i) {
|
for (size_t i = 0; i < num_inputs; ++i) {
|
||||||
for (std::size_t j = 0; j < num_inputs; ++j) {
|
for (size_t j = 0; j < num_inputs; ++j) {
|
||||||
string_view lhs(inputs[i]), rhs(inputs[j]);
|
string_view lhs(inputs[i]), rhs(inputs[j]);
|
||||||
EXPECT_EQ(Op<int>()(lhs.compare(rhs), 0), Op<string_view>()(lhs, rhs));
|
EXPECT_EQ(Op<int>()(lhs.compare(rhs), 0), Op<string_view>()(lhs, rhs));
|
||||||
}
|
}
|
||||||
@ -605,7 +666,7 @@ template <typename Char> class my_string {
|
|||||||
public:
|
public:
|
||||||
my_string(const Char* s) : s_(s) {}
|
my_string(const Char* s) : s_(s) {}
|
||||||
const Char* data() const FMT_NOEXCEPT { return s_.data(); }
|
const Char* data() const FMT_NOEXCEPT { return s_.data(); }
|
||||||
std::size_t length() const FMT_NOEXCEPT { return s_.size(); }
|
size_t length() const FMT_NOEXCEPT { return s_.size(); }
|
||||||
operator const Char*() const { return s_.c_str(); }
|
operator const Char*() const { return s_.c_str(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -621,23 +682,6 @@ inline fmt::basic_string_view<Char> to_string_view(const my_string<Char>& s)
|
|||||||
struct non_string {};
|
struct non_string {};
|
||||||
} // namespace my_ns
|
} // namespace my_ns
|
||||||
|
|
||||||
namespace FakeQt {
|
|
||||||
class QString {
|
|
||||||
public:
|
|
||||||
QString(const wchar_t* s) : s_(std::make_shared<std::wstring>(s)) {}
|
|
||||||
const wchar_t* utf16() const FMT_NOEXCEPT { return s_->data(); }
|
|
||||||
int size() const FMT_NOEXCEPT { return static_cast<int>(s_->size()); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::shared_ptr<std::wstring> s_;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline fmt::basic_string_view<wchar_t> to_string_view(const QString& s)
|
|
||||||
FMT_NOEXCEPT {
|
|
||||||
return {s.utf16(), static_cast<std::size_t>(s.size())};
|
|
||||||
}
|
|
||||||
} // namespace FakeQt
|
|
||||||
|
|
||||||
template <typename T> class IsStringTest : public testing::Test {};
|
template <typename T> class IsStringTest : public testing::Test {};
|
||||||
|
|
||||||
typedef ::testing::Types<char, wchar_t, char16_t, char32_t> StringCharTypes;
|
typedef ::testing::Types<char, wchar_t, char16_t, char32_t> StringCharTypes;
|
||||||
@ -649,21 +693,19 @@ struct derived_from_string_view : fmt::basic_string_view<Char> {};
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TYPED_TEST(IsStringTest, IsString) {
|
TYPED_TEST(IsStringTest, IsString) {
|
||||||
EXPECT_TRUE(fmt::internal::is_string<TypeParam*>::value);
|
EXPECT_TRUE(fmt::detail::is_string<TypeParam*>::value);
|
||||||
EXPECT_TRUE(fmt::internal::is_string<const TypeParam*>::value);
|
EXPECT_TRUE(fmt::detail::is_string<const TypeParam*>::value);
|
||||||
EXPECT_TRUE(fmt::internal::is_string<TypeParam[2]>::value);
|
EXPECT_TRUE(fmt::detail::is_string<TypeParam[2]>::value);
|
||||||
EXPECT_TRUE(fmt::internal::is_string<const TypeParam[2]>::value);
|
EXPECT_TRUE(fmt::detail::is_string<const TypeParam[2]>::value);
|
||||||
EXPECT_TRUE(fmt::internal::is_string<std::basic_string<TypeParam>>::value);
|
EXPECT_TRUE(fmt::detail::is_string<std::basic_string<TypeParam>>::value);
|
||||||
|
EXPECT_TRUE(fmt::detail::is_string<fmt::basic_string_view<TypeParam>>::value);
|
||||||
EXPECT_TRUE(
|
EXPECT_TRUE(
|
||||||
fmt::internal::is_string<fmt::basic_string_view<TypeParam>>::value);
|
fmt::detail::is_string<derived_from_string_view<TypeParam>>::value);
|
||||||
EXPECT_TRUE(
|
using string_view = fmt::detail::std_string_view<TypeParam>;
|
||||||
fmt::internal::is_string<derived_from_string_view<TypeParam>>::value);
|
|
||||||
using string_view = fmt::internal::std_string_view<TypeParam>;
|
|
||||||
EXPECT_TRUE(std::is_empty<string_view>::value !=
|
EXPECT_TRUE(std::is_empty<string_view>::value !=
|
||||||
fmt::internal::is_string<string_view>::value);
|
fmt::detail::is_string<string_view>::value);
|
||||||
EXPECT_TRUE(fmt::internal::is_string<my_ns::my_string<TypeParam>>::value);
|
EXPECT_TRUE(fmt::detail::is_string<my_ns::my_string<TypeParam>>::value);
|
||||||
EXPECT_FALSE(fmt::internal::is_string<my_ns::non_string>::value);
|
EXPECT_FALSE(fmt::detail::is_string<my_ns::non_string>::value);
|
||||||
EXPECT_TRUE(fmt::internal::is_string<FakeQt::QString>::value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTest, Format) {
|
TEST(CoreTest, Format) {
|
||||||
@ -686,33 +728,16 @@ TEST(CoreTest, FormatTo) {
|
|||||||
|
|
||||||
TEST(CoreTest, ToStringViewForeignStrings) {
|
TEST(CoreTest, ToStringViewForeignStrings) {
|
||||||
using namespace my_ns;
|
using namespace my_ns;
|
||||||
using namespace FakeQt;
|
|
||||||
EXPECT_EQ(to_string_view(my_string<char>("42")), "42");
|
EXPECT_EQ(to_string_view(my_string<char>("42")), "42");
|
||||||
EXPECT_EQ(to_string_view(my_string<wchar_t>(L"42")), L"42");
|
fmt::detail::type type =
|
||||||
EXPECT_EQ(to_string_view(QString(L"42")), L"42");
|
fmt::detail::mapped_type_constant<my_string<char>,
|
||||||
fmt::internal::type type =
|
fmt::format_context>::value;
|
||||||
fmt::internal::mapped_type_constant<my_string<char>,
|
EXPECT_EQ(type, fmt::detail::type::string_type);
|
||||||
fmt::format_context>::value;
|
|
||||||
EXPECT_EQ(type, fmt::internal::type::string_type);
|
|
||||||
type = fmt::internal::mapped_type_constant<my_string<wchar_t>,
|
|
||||||
fmt::wformat_context>::value;
|
|
||||||
EXPECT_EQ(type, fmt::internal::type::string_type);
|
|
||||||
type =
|
|
||||||
fmt::internal::mapped_type_constant<QString, fmt::wformat_context>::value;
|
|
||||||
EXPECT_EQ(type, fmt::internal::type::string_type);
|
|
||||||
// Does not compile: only wide format contexts are compatible with QString!
|
|
||||||
// type = fmt::internal::mapped_type_constant<QString,
|
|
||||||
// fmt::format_context>::value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTest, FormatForeignStrings) {
|
TEST(CoreTest, FormatForeignStrings) {
|
||||||
using namespace my_ns;
|
using namespace my_ns;
|
||||||
using namespace FakeQt;
|
|
||||||
EXPECT_EQ(fmt::format(my_string<char>("{}"), 42), "42");
|
EXPECT_EQ(fmt::format(my_string<char>("{}"), 42), "42");
|
||||||
EXPECT_EQ(fmt::format(my_string<wchar_t>(L"{}"), 42), L"42");
|
|
||||||
EXPECT_EQ(fmt::format(QString(L"{}"), 42), L"42");
|
|
||||||
EXPECT_EQ(fmt::format(QString(L"{}"), my_string<wchar_t>(L"42")), L"42");
|
|
||||||
EXPECT_EQ(fmt::format(my_string<wchar_t>(L"{}"), QString(L"42")), L"42");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct implicitly_convertible_to_string {
|
struct implicitly_convertible_to_string {
|
||||||
@ -747,15 +772,6 @@ TEST(FormatterTest, FormatExplicitlyConvertibleToStdStringView) {
|
|||||||
fmt::format("{}", explicitly_convertible_to_std_string_view()));
|
fmt::format("{}", explicitly_convertible_to_std_string_view()));
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
struct explicitly_convertible_to_wstring_view {
|
|
||||||
explicit operator fmt::wstring_view() const { return L"foo"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST(FormatterTest, FormatExplicitlyConvertibleToWStringView) {
|
|
||||||
EXPECT_EQ(L"foo",
|
|
||||||
fmt::format(L"{}", explicitly_convertible_to_wstring_view()));
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct disabled_rvalue_conversion {
|
struct disabled_rvalue_conversion {
|
||||||
|
@ -18,14 +18,14 @@
|
|||||||
// A custom argument formatter that doesn't print `-` for floating-point values
|
// A custom argument formatter that doesn't print `-` for floating-point values
|
||||||
// rounded to 0.
|
// rounded to 0.
|
||||||
class custom_arg_formatter
|
class custom_arg_formatter
|
||||||
: public fmt::arg_formatter<fmt::buffer_range<char>> {
|
: public fmt::detail::arg_formatter<fmt::format_context::iterator, char> {
|
||||||
public:
|
public:
|
||||||
using range = fmt::buffer_range<char>;
|
using base = fmt::detail::arg_formatter<fmt::format_context::iterator, char>;
|
||||||
typedef fmt::arg_formatter<range> base;
|
|
||||||
|
|
||||||
custom_arg_formatter(fmt::format_context& ctx,
|
custom_arg_formatter(fmt::format_context& ctx,
|
||||||
fmt::format_parse_context* parse_ctx,
|
fmt::format_parse_context* parse_ctx,
|
||||||
fmt::format_specs* s = nullptr)
|
fmt::format_specs* s = nullptr,
|
||||||
|
const char* = nullptr)
|
||||||
: base(ctx, parse_ctx, s) {}
|
: base(ctx, parse_ctx, s) {}
|
||||||
|
|
||||||
using base::operator();
|
using base::operator();
|
||||||
@ -39,8 +39,10 @@ class custom_arg_formatter
|
|||||||
|
|
||||||
std::string custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
std::string custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
||||||
fmt::memory_buffer buffer;
|
fmt::memory_buffer buffer;
|
||||||
|
fmt::detail::buffer<char>& base = buffer;
|
||||||
// Pass custom argument formatter as a template arg to vwrite.
|
// Pass custom argument formatter as a template arg to vwrite.
|
||||||
fmt::vformat_to<custom_arg_formatter>(buffer, format_str, args);
|
fmt::vformat_to<custom_arg_formatter>(std::back_inserter(base), format_str,
|
||||||
|
args);
|
||||||
return std::string(buffer.data(), buffer.size());
|
return std::string(buffer.data(), buffer.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
168
externals/dynarmic/externals/fmt/test/format
vendored
168
externals/dynarmic/externals/fmt/test/format
vendored
@ -38,9 +38,9 @@ namespace std {
|
|||||||
|
|
||||||
template<class Out, class charT> class basic_format_context;
|
template<class Out, class charT> class basic_format_context;
|
||||||
using format_context = basic_format_context<
|
using format_context = basic_format_context<
|
||||||
/* unspecified */ std::back_insert_iterator<fmt::internal::buffer<char>>, char>;
|
/* unspecified */ std::back_insert_iterator<fmt::detail::buffer<char>>, char>;
|
||||||
using wformat_context = basic_format_context<
|
using wformat_context = basic_format_context<
|
||||||
/* unspecified */ std::back_insert_iterator<fmt::internal::buffer<wchar_t>>, wchar_t>;
|
/* unspecified */ std::back_insert_iterator<fmt::detail::buffer<wchar_t>>, wchar_t>;
|
||||||
|
|
||||||
template<class T, class charT = char> struct formatter {
|
template<class T, class charT = char> struct formatter {
|
||||||
formatter() = delete;
|
formatter() = delete;
|
||||||
@ -219,7 +219,7 @@ namespace std {
|
|||||||
|
|
||||||
// Implementation details:
|
// Implementation details:
|
||||||
using format_arg = basic_format_arg<basic_format_context>;
|
using format_arg = basic_format_arg<basic_format_context>;
|
||||||
basic_format_context(Out out, basic_format_args<basic_format_context> args, fmt::internal::locale_ref)
|
basic_format_context(Out out, basic_format_args<basic_format_context> args, fmt::detail::locale_ref)
|
||||||
: args_(args), out_(out) {}
|
: args_(args), out_(out) {}
|
||||||
detail::error_handler error_handler() const { return {}; }
|
detail::error_handler error_handler() const { return {}; }
|
||||||
basic_format_arg<basic_format_context> arg(fmt::basic_string_view<charT>) const {
|
basic_format_arg<basic_format_context> arg(fmt::basic_string_view<charT>) const {
|
||||||
@ -488,22 +488,21 @@ template<class... Args>
|
|||||||
namespace std {
|
namespace std {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <typename Range>
|
template <typename OutputIt, typename Char>
|
||||||
class arg_formatter
|
class arg_formatter
|
||||||
: public fmt::internal::arg_formatter_base<Range, error_handler> {
|
: public fmt::detail::arg_formatter_base<OutputIt, Char, error_handler> {
|
||||||
private:
|
private:
|
||||||
using char_type = typename Range::value_type;
|
using char_type = Char;
|
||||||
using base = fmt::internal::arg_formatter_base<Range, error_handler>;
|
using base = fmt::detail::arg_formatter_base<OutputIt, Char, error_handler>;
|
||||||
using format_context = std::basic_format_context<typename base::iterator, char_type>;
|
using format_context = std::basic_format_context<OutputIt, Char>;
|
||||||
using parse_context = basic_format_parse_context<char_type>;
|
using parse_context = basic_format_parse_context<Char>;
|
||||||
|
|
||||||
parse_context* parse_ctx_;
|
parse_context* parse_ctx_;
|
||||||
format_context& ctx_;
|
format_context& ctx_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef Range range;
|
using iterator = OutputIt;
|
||||||
typedef typename base::iterator iterator;
|
using format_specs = typename base::format_specs;
|
||||||
typedef typename base::format_specs format_specs;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
@ -513,7 +512,7 @@ class arg_formatter
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
arg_formatter(format_context& ctx, parse_context* parse_ctx = nullptr, fmt::format_specs* spec = nullptr)
|
arg_formatter(format_context& ctx, parse_context* parse_ctx = nullptr, fmt::format_specs* spec = nullptr)
|
||||||
: base(Range(ctx.out()), spec, {}), parse_ctx_(parse_ctx), ctx_(ctx) {}
|
: base(ctx.out(), spec, {}), parse_ctx_(parse_ctx), ctx_(ctx) {}
|
||||||
|
|
||||||
using base::operator();
|
using base::operator();
|
||||||
|
|
||||||
@ -529,36 +528,36 @@ class arg_formatter
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Context>
|
template <typename Context>
|
||||||
inline fmt::internal::type get_type(basic_format_arg<Context> arg) {
|
inline fmt::detail::type get_type(basic_format_arg<Context> arg) {
|
||||||
return visit_format_arg([&] (auto val) {
|
return visit_format_arg([&] (auto val) {
|
||||||
using char_type = typename Context::char_type;
|
using char_type = typename Context::char_type;
|
||||||
using T = decltype(val);
|
using T = decltype(val);
|
||||||
if (std::is_same_v<T, monostate>)
|
if (std::is_same_v<T, monostate>)
|
||||||
return fmt::internal::type::none_type;
|
return fmt::detail::type::none_type;
|
||||||
if (std::is_same_v<T, bool>)
|
if (std::is_same_v<T, bool>)
|
||||||
return fmt::internal::type::bool_type;
|
return fmt::detail::type::bool_type;
|
||||||
if (std::is_same_v<T, char_type>)
|
if (std::is_same_v<T, char_type>)
|
||||||
return fmt::internal::type::char_type;
|
return fmt::detail::type::char_type;
|
||||||
if (std::is_same_v<T, int>)
|
if (std::is_same_v<T, int>)
|
||||||
return fmt::internal::type::int_type;
|
return fmt::detail::type::int_type;
|
||||||
if (std::is_same_v<T, unsigned int>)
|
if (std::is_same_v<T, unsigned int>)
|
||||||
return fmt::internal::type::uint_type;
|
return fmt::detail::type::uint_type;
|
||||||
if (std::is_same_v<T, long long int>)
|
if (std::is_same_v<T, long long int>)
|
||||||
return fmt::internal::type::long_long_type;
|
return fmt::detail::type::long_long_type;
|
||||||
if (std::is_same_v<T, unsigned long long int>)
|
if (std::is_same_v<T, unsigned long long int>)
|
||||||
return fmt::internal::type::ulong_long_type;
|
return fmt::detail::type::ulong_long_type;
|
||||||
if (std::is_same_v<T, double>)
|
if (std::is_same_v<T, double>)
|
||||||
return fmt::internal::type::double_type;
|
return fmt::detail::type::double_type;
|
||||||
if (std::is_same_v<T, long double>)
|
if (std::is_same_v<T, long double>)
|
||||||
return fmt::internal::type::long_double_type;
|
return fmt::detail::type::long_double_type;
|
||||||
if (std::is_same_v<T, const char_type*>)
|
if (std::is_same_v<T, const char_type*>)
|
||||||
return fmt::internal::type::cstring_type;
|
return fmt::detail::type::cstring_type;
|
||||||
if (std::is_same_v<T, basic_string_view<char_type>>)
|
if (std::is_same_v<T, basic_string_view<char_type>>)
|
||||||
return fmt::internal::type::string_type;
|
return fmt::detail::type::string_type;
|
||||||
if (std::is_same_v<T, const void*>)
|
if (std::is_same_v<T, const void*>)
|
||||||
return fmt::internal::type::pointer_type;
|
return fmt::detail::type::pointer_type;
|
||||||
assert(get_value(arg).index() == 12);
|
assert(get_value(arg).index() == 12);
|
||||||
return fmt::internal::type::custom_type;
|
return fmt::detail::type::custom_type;
|
||||||
}, arg);
|
}, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,45 +581,42 @@ class custom_formatter {
|
|||||||
|
|
||||||
template <typename ArgFormatter, typename Char, typename Context>
|
template <typename ArgFormatter, typename Char, typename Context>
|
||||||
struct format_handler : detail::error_handler {
|
struct format_handler : detail::error_handler {
|
||||||
typedef typename ArgFormatter::range range;
|
using iterator = typename ArgFormatter::iterator;
|
||||||
|
|
||||||
format_handler(range r, basic_string_view<Char> str,
|
format_handler(iterator out, basic_string_view<Char> str,
|
||||||
basic_format_args<Context> format_args,
|
basic_format_args<Context> format_args,
|
||||||
fmt::internal::locale_ref loc)
|
fmt::detail::locale_ref loc)
|
||||||
: parse_ctx(str), context(r.begin(), format_args, loc) {}
|
: parse_ctx(str), context(out, format_args, loc) {}
|
||||||
|
|
||||||
void on_text(const Char* begin, const Char* end) {
|
void on_text(const Char* begin, const Char* end) {
|
||||||
auto size = fmt::internal::to_unsigned(end - begin);
|
auto size = fmt::detail::to_unsigned(end - begin);
|
||||||
auto out = context.out();
|
auto out = context.out();
|
||||||
auto&& it = fmt::internal::reserve(out, size);
|
auto&& it = fmt::detail::reserve(out, size);
|
||||||
it = std::copy_n(begin, size, it);
|
it = std::copy_n(begin, size, it);
|
||||||
context.advance_to(out);
|
context.advance_to(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_arg_id() {
|
int on_arg_id() { return parse_ctx.next_arg_id(); }
|
||||||
arg = context.arg(parse_ctx.next_arg_id());
|
int on_arg_id(unsigned id) { return parse_ctx.check_arg_id(id), id; }
|
||||||
}
|
int on_arg_id(fmt::basic_string_view<Char>) { return 0; }
|
||||||
void on_arg_id(unsigned id) {
|
|
||||||
parse_ctx.check_arg_id(id);
|
|
||||||
arg = context.arg(id);
|
|
||||||
}
|
|
||||||
void on_arg_id(fmt::basic_string_view<Char>) {}
|
|
||||||
|
|
||||||
void on_replacement_field(const Char* p) {
|
void on_replacement_field(int id, const Char* p) {
|
||||||
parse_ctx.advance_to(parse_ctx.begin() + (p - &*parse_ctx.begin()));
|
auto arg = context.arg(id);
|
||||||
|
parse_ctx.advance_to(parse_ctx.begin() + (p - &*parse_ctx.begin()));
|
||||||
custom_formatter<Context> f(parse_ctx, context);
|
custom_formatter<Context> f(parse_ctx, context);
|
||||||
if (!visit_format_arg(f, arg))
|
if (!visit_format_arg(f, arg))
|
||||||
context.advance_to(visit_format_arg(ArgFormatter(context, &parse_ctx), arg));
|
context.advance_to(visit_format_arg(ArgFormatter(context, &parse_ctx), arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
const Char* on_format_specs(const Char* begin, const Char* end) {
|
const Char* on_format_specs(int id, const Char* begin, const Char* end) {
|
||||||
|
auto arg = context.arg(id);
|
||||||
parse_ctx.advance_to(parse_ctx.begin() + (begin - &*parse_ctx.begin()));
|
parse_ctx.advance_to(parse_ctx.begin() + (begin - &*parse_ctx.begin()));
|
||||||
custom_formatter<Context> f(parse_ctx, context);
|
custom_formatter<Context> f(parse_ctx, context);
|
||||||
if (visit_format_arg(f, arg)) return &*parse_ctx.begin();
|
if (visit_format_arg(f, arg)) return &*parse_ctx.begin();
|
||||||
fmt::basic_format_specs<Char> specs;
|
fmt::basic_format_specs<Char> specs;
|
||||||
using fmt::internal::specs_handler;
|
using fmt::detail::specs_handler;
|
||||||
using parse_context = basic_format_parse_context<Char>;
|
using parse_context = basic_format_parse_context<Char>;
|
||||||
fmt::internal::specs_checker<specs_handler<parse_context, Context>> handler(
|
fmt::detail::specs_checker<specs_handler<parse_context, Context>> handler(
|
||||||
specs_handler<parse_context, Context>(specs, parse_ctx, context), get_type(arg));
|
specs_handler<parse_context, Context>(specs, parse_ctx, context), get_type(arg));
|
||||||
begin = parse_format_specs(begin, end, handler);
|
begin = parse_format_specs(begin, end, handler);
|
||||||
if (begin == end || *begin != '}') on_error("missing '}' in format string");
|
if (begin == end || *begin != '}') on_error("missing '}' in format string");
|
||||||
@ -631,7 +627,6 @@ struct format_handler : detail::error_handler {
|
|||||||
|
|
||||||
basic_format_parse_context<Char> parse_ctx;
|
basic_format_parse_context<Char> parse_ctx;
|
||||||
Context context;
|
Context context;
|
||||||
basic_format_arg<Context> arg;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename Char>
|
template <typename T, typename Char>
|
||||||
@ -640,46 +635,45 @@ struct formatter {
|
|||||||
// terminating '}'.
|
// terminating '}'.
|
||||||
template <typename ParseContext>
|
template <typename ParseContext>
|
||||||
FMT_CONSTEXPR typename ParseContext::iterator parse(ParseContext& ctx) {
|
FMT_CONSTEXPR typename ParseContext::iterator parse(ParseContext& ctx) {
|
||||||
namespace internal = fmt::internal;
|
namespace detail = fmt::detail;
|
||||||
typedef internal::dynamic_specs_handler<ParseContext> handler_type;
|
typedef detail::dynamic_specs_handler<ParseContext> handler_type;
|
||||||
auto type = internal::mapped_type_constant<T, fmt::buffer_context<Char>>::value;
|
auto type = detail::mapped_type_constant<T, fmt::buffer_context<Char>>::value;
|
||||||
internal::specs_checker<handler_type> handler(handler_type(specs_, ctx),
|
detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
|
||||||
type);
|
type);
|
||||||
auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
|
auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
|
||||||
auto type_spec = specs_.type;
|
auto type_spec = specs_.type;
|
||||||
auto eh = ctx.error_handler();
|
auto eh = ctx.error_handler();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case internal::type::none_type:
|
case detail::type::none_type:
|
||||||
case internal::type::named_arg_type:
|
|
||||||
FMT_ASSERT(false, "invalid argument type");
|
FMT_ASSERT(false, "invalid argument type");
|
||||||
break;
|
break;
|
||||||
case internal::type::int_type:
|
case detail::type::int_type:
|
||||||
case internal::type::uint_type:
|
case detail::type::uint_type:
|
||||||
case internal::type::long_long_type:
|
case detail::type::long_long_type:
|
||||||
case internal::type::ulong_long_type:
|
case detail::type::ulong_long_type:
|
||||||
case internal::type::bool_type:
|
case detail::type::bool_type:
|
||||||
handle_int_type_spec(type_spec,
|
handle_int_type_spec(type_spec,
|
||||||
internal::int_type_checker<decltype(eh)>(eh));
|
detail::int_type_checker<decltype(eh)>(eh));
|
||||||
break;
|
break;
|
||||||
case internal::type::char_type:
|
case detail::type::char_type:
|
||||||
handle_char_specs(
|
handle_char_specs(
|
||||||
&specs_, internal::char_specs_checker<decltype(eh)>(type_spec, eh));
|
&specs_, detail::char_specs_checker<decltype(eh)>(type_spec, eh));
|
||||||
break;
|
break;
|
||||||
case internal::type::double_type:
|
case detail::type::double_type:
|
||||||
case internal::type::long_double_type:
|
case detail::type::long_double_type:
|
||||||
internal::parse_float_type_spec(specs_, eh);
|
detail::parse_float_type_spec(specs_, eh);
|
||||||
break;
|
break;
|
||||||
case internal::type::cstring_type:
|
case detail::type::cstring_type:
|
||||||
internal::handle_cstring_type_spec(
|
detail::handle_cstring_type_spec(
|
||||||
type_spec, internal::cstring_type_checker<decltype(eh)>(eh));
|
type_spec, detail::cstring_type_checker<decltype(eh)>(eh));
|
||||||
break;
|
break;
|
||||||
case internal::type::string_type:
|
case detail::type::string_type:
|
||||||
internal::check_string_type_spec(type_spec, eh);
|
detail::check_string_type_spec(type_spec, eh);
|
||||||
break;
|
break;
|
||||||
case internal::type::pointer_type:
|
case detail::type::pointer_type:
|
||||||
internal::check_pointer_type_spec(type_spec, eh);
|
detail::check_pointer_type_spec(type_spec, eh);
|
||||||
break;
|
break;
|
||||||
case internal::type::custom_type:
|
case detail::type::custom_type:
|
||||||
// Custom format specifiers should be checked in parse functions of
|
// Custom format specifiers should be checked in parse functions of
|
||||||
// formatter specializations.
|
// formatter specializations.
|
||||||
break;
|
break;
|
||||||
@ -689,18 +683,18 @@ struct formatter {
|
|||||||
|
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
|
auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||||
fmt::internal::handle_dynamic_spec<fmt::internal::width_checker>(
|
fmt::detail::handle_dynamic_spec<fmt::detail::width_checker>(
|
||||||
specs_.width, specs_.width_ref, ctx);
|
specs_.width, specs_.width_ref, ctx);
|
||||||
fmt::internal::handle_dynamic_spec<fmt::internal::precision_checker>(
|
fmt::detail::handle_dynamic_spec<fmt::detail::precision_checker>(
|
||||||
specs_.precision, specs_.precision_ref, ctx);
|
specs_.precision, specs_.precision_ref, ctx);
|
||||||
using range_type = fmt::internal::output_range<typename FormatContext::iterator,
|
using af = arg_formatter<typename FormatContext::iterator,
|
||||||
typename FormatContext::char_type>;
|
typename FormatContext::char_type>;
|
||||||
return visit_format_arg(arg_formatter<range_type>(ctx, nullptr, &specs_),
|
return visit_format_arg(af(ctx, nullptr, &specs_),
|
||||||
basic_format_arg<FormatContext>(val));
|
basic_format_arg<FormatContext>(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
fmt::internal::dynamic_format_specs<Char> specs_;
|
fmt::detail::dynamic_format_specs<Char> specs_;
|
||||||
};
|
};
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
@ -717,11 +711,11 @@ template<class... Args>
|
|||||||
|
|
||||||
string vformat(string_view fmt, format_args args) {
|
string vformat(string_view fmt, format_args args) {
|
||||||
fmt::memory_buffer mbuf;
|
fmt::memory_buffer mbuf;
|
||||||
fmt::internal::buffer<char>& buf = mbuf;
|
fmt::detail::buffer<char>& buf = mbuf;
|
||||||
using range = fmt::buffer_range<char>;
|
using af = detail::arg_formatter<fmt::format_context::iterator, char>;
|
||||||
detail::format_handler<detail::arg_formatter<range>, char, format_context>
|
detail::format_handler<af, char, format_context>
|
||||||
h(range(std::back_inserter(buf)), fmt, args, {});
|
h(std::back_inserter(buf), fmt, args, {});
|
||||||
fmt::internal::parse_format_string<false>(fmt::to_string_view(fmt), h);
|
fmt::detail::parse_format_string<false>(fmt::to_string_view(fmt), h);
|
||||||
return to_string(mbuf);
|
return to_string(mbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,10 +735,10 @@ template<class Out, class... Args>
|
|||||||
|
|
||||||
template<class Out>
|
template<class Out>
|
||||||
Out vformat_to(Out out, string_view fmt, format_args_t<fmt::type_identity_t<Out>, char> args) {
|
Out vformat_to(Out out, string_view fmt, format_args_t<fmt::type_identity_t<Out>, char> args) {
|
||||||
using range = fmt::internal::output_range<Out, char>;
|
using af = detail::arg_formatter<Out, char>;
|
||||||
detail::format_handler<detail::arg_formatter<range>, char, basic_format_context<Out, char>>
|
detail::format_handler<af, char, basic_format_context<Out, char>>
|
||||||
h(range(out), fmt, args, {});
|
h(out, fmt, args, {});
|
||||||
fmt::internal::parse_format_string<false>(fmt::to_string_view(fmt), h);
|
fmt::detail::parse_format_string<false>(fmt::to_string_view(fmt), h);
|
||||||
return h.context.out();
|
return h.context.out();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@
|
|||||||
|
|
||||||
#undef max
|
#undef max
|
||||||
|
|
||||||
using fmt::internal::bigint;
|
using fmt::detail::bigint;
|
||||||
using fmt::internal::fp;
|
using fmt::detail::fp;
|
||||||
using fmt::internal::max_value;
|
using fmt::detail::max_value;
|
||||||
|
|
||||||
static_assert(!std::is_copy_constructible<bigint>::value, "");
|
static_assert(!std::is_copy_constructible<bigint>::value, "");
|
||||||
static_assert(!std::is_copy_assignable<bigint>::value, "");
|
static_assert(!std::is_copy_assignable<bigint>::value, "");
|
||||||
@ -102,7 +102,7 @@ TEST(BigIntTest, Multiply) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(BigIntTest, Accumulator) {
|
TEST(BigIntTest, Accumulator) {
|
||||||
fmt::internal::accumulator acc;
|
fmt::detail::accumulator acc;
|
||||||
EXPECT_EQ(acc.lower, 0);
|
EXPECT_EQ(acc.lower, 0);
|
||||||
EXPECT_EQ(acc.upper, 0);
|
EXPECT_EQ(acc.upper, 0);
|
||||||
acc.upper = 12;
|
acc.upper = 12;
|
||||||
@ -110,7 +110,7 @@ TEST(BigIntTest, Accumulator) {
|
|||||||
EXPECT_EQ(static_cast<uint32_t>(acc), 34);
|
EXPECT_EQ(static_cast<uint32_t>(acc), 34);
|
||||||
acc += 56;
|
acc += 56;
|
||||||
EXPECT_EQ(acc.lower, 90);
|
EXPECT_EQ(acc.lower, 90);
|
||||||
acc += fmt::internal::max_value<uint64_t>();
|
acc += fmt::detail::max_value<uint64_t>();
|
||||||
EXPECT_EQ(acc.upper, 13);
|
EXPECT_EQ(acc.upper, 13);
|
||||||
EXPECT_EQ(acc.lower, 89);
|
EXPECT_EQ(acc.lower, 89);
|
||||||
acc >>= 32;
|
acc >>= 32;
|
||||||
@ -262,7 +262,7 @@ TEST(FPTest, GetCachedPower) {
|
|||||||
typedef std::numeric_limits<double> limits;
|
typedef std::numeric_limits<double> limits;
|
||||||
for (auto exp = limits::min_exponent; exp <= limits::max_exponent; ++exp) {
|
for (auto exp = limits::min_exponent; exp <= limits::max_exponent; ++exp) {
|
||||||
int dec_exp = 0;
|
int dec_exp = 0;
|
||||||
auto fp = fmt::internal::get_cached_power(exp, dec_exp);
|
auto fp = fmt::detail::get_cached_power(exp, dec_exp);
|
||||||
EXPECT_LE(exp, fp.e);
|
EXPECT_LE(exp, fp.e);
|
||||||
int dec_exp_step = 8;
|
int dec_exp_step = 8;
|
||||||
EXPECT_LE(fp.e, exp + dec_exp_step * log2(10));
|
EXPECT_LE(fp.e, exp + dec_exp_step * log2(10));
|
||||||
@ -271,8 +271,8 @@ TEST(FPTest, GetCachedPower) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(FPTest, GetRoundDirection) {
|
TEST(FPTest, GetRoundDirection) {
|
||||||
using fmt::internal::get_round_direction;
|
using fmt::detail::get_round_direction;
|
||||||
using fmt::internal::round_direction;
|
using fmt::detail::round_direction;
|
||||||
EXPECT_EQ(round_direction::down, get_round_direction(100, 50, 0));
|
EXPECT_EQ(round_direction::down, get_round_direction(100, 50, 0));
|
||||||
EXPECT_EQ(round_direction::up, get_round_direction(100, 51, 0));
|
EXPECT_EQ(round_direction::up, get_round_direction(100, 51, 0));
|
||||||
EXPECT_EQ(round_direction::down, get_round_direction(100, 40, 10));
|
EXPECT_EQ(round_direction::down, get_round_direction(100, 40, 10));
|
||||||
@ -295,9 +295,9 @@ TEST(FPTest, GetRoundDirection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(FPTest, FixedHandler) {
|
TEST(FPTest, FixedHandler) {
|
||||||
struct handler : fmt::internal::fixed_handler {
|
struct handler : fmt::detail::fixed_handler {
|
||||||
char buffer[10];
|
char buffer[10];
|
||||||
handler(int prec = 0) : fmt::internal::fixed_handler() {
|
handler(int prec = 0) : fmt::detail::fixed_handler() {
|
||||||
buf = buffer;
|
buf = buffer;
|
||||||
precision = prec;
|
precision = prec;
|
||||||
}
|
}
|
||||||
@ -306,7 +306,7 @@ TEST(FPTest, FixedHandler) {
|
|||||||
handler().on_digit('0', 100, 99, 0, exp, false);
|
handler().on_digit('0', 100, 99, 0, exp, false);
|
||||||
EXPECT_THROW(handler().on_digit('0', 100, 100, 0, exp, false),
|
EXPECT_THROW(handler().on_digit('0', 100, 100, 0, exp, false),
|
||||||
assertion_failure);
|
assertion_failure);
|
||||||
namespace digits = fmt::internal::digits;
|
namespace digits = fmt::detail::digits;
|
||||||
EXPECT_EQ(handler(1).on_digit('0', 100, 10, 10, exp, false), digits::done);
|
EXPECT_EQ(handler(1).on_digit('0', 100, 10, 10, exp, false), digits::done);
|
||||||
// Check that divisor - error doesn't overflow.
|
// Check that divisor - error doesn't overflow.
|
||||||
EXPECT_EQ(handler(1).on_digit('0', 100, 10, 101, exp, false), digits::error);
|
EXPECT_EQ(handler(1).on_digit('0', 100, 10, 101, exp, false), digits::error);
|
||||||
@ -318,7 +318,7 @@ TEST(FPTest, FixedHandler) {
|
|||||||
|
|
||||||
TEST(FPTest, GrisuFormatCompilesWithNonIEEEDouble) {
|
TEST(FPTest, GrisuFormatCompilesWithNonIEEEDouble) {
|
||||||
fmt::memory_buffer buf;
|
fmt::memory_buffer buf;
|
||||||
format_float(0.42, -1, fmt::internal::float_specs(), buf);
|
format_float(0.42, -1, fmt::detail::float_specs(), buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> struct value_extractor {
|
template <typename T> struct value_extractor {
|
||||||
@ -330,11 +330,11 @@ template <typename T> struct value_extractor {
|
|||||||
|
|
||||||
#if FMT_USE_INT128
|
#if FMT_USE_INT128
|
||||||
// Apple Clang does not define typeid for __int128_t and __uint128_t.
|
// Apple Clang does not define typeid for __int128_t and __uint128_t.
|
||||||
FMT_NORETURN T operator()(fmt::internal::int128_t) {
|
FMT_NORETURN T operator()(fmt::detail::int128_t) {
|
||||||
throw std::runtime_error("invalid type __int128_t");
|
throw std::runtime_error("invalid type __int128_t");
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_NORETURN T operator()(fmt::internal::uint128_t) {
|
FMT_NORETURN T operator()(fmt::detail::uint128_t) {
|
||||||
throw std::runtime_error("invalid type __uint128_t");
|
throw std::runtime_error("invalid type __uint128_t");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -342,9 +342,9 @@ template <typename T> struct value_extractor {
|
|||||||
|
|
||||||
TEST(FormatTest, ArgConverter) {
|
TEST(FormatTest, ArgConverter) {
|
||||||
long long value = max_value<long long>();
|
long long value = max_value<long long>();
|
||||||
auto arg = fmt::internal::make_arg<fmt::format_context>(value);
|
auto arg = fmt::detail::make_arg<fmt::format_context>(value);
|
||||||
fmt::visit_format_arg(
|
fmt::visit_format_arg(
|
||||||
fmt::internal::arg_converter<long long, fmt::format_context>(arg, 'd'),
|
fmt::detail::arg_converter<long long, fmt::format_context>(arg, 'd'),
|
||||||
arg);
|
arg);
|
||||||
EXPECT_EQ(value, fmt::visit_format_arg(value_extractor<long long>(), arg));
|
EXPECT_EQ(value, fmt::visit_format_arg(value_extractor<long long>(), arg));
|
||||||
}
|
}
|
||||||
@ -360,9 +360,9 @@ TEST(FormatTest, FormatNegativeNaN) {
|
|||||||
TEST(FormatTest, StrError) {
|
TEST(FormatTest, StrError) {
|
||||||
char* message = nullptr;
|
char* message = nullptr;
|
||||||
char buffer[BUFFER_SIZE];
|
char buffer[BUFFER_SIZE];
|
||||||
EXPECT_ASSERT(fmt::internal::safe_strerror(EDOM, message = nullptr, 0),
|
EXPECT_ASSERT(fmt::detail::safe_strerror(EDOM, message = nullptr, 0),
|
||||||
"invalid buffer");
|
"invalid buffer");
|
||||||
EXPECT_ASSERT(fmt::internal::safe_strerror(EDOM, message = buffer, 0),
|
EXPECT_ASSERT(fmt::detail::safe_strerror(EDOM, message = buffer, 0),
|
||||||
"invalid buffer");
|
"invalid buffer");
|
||||||
buffer[0] = 'x';
|
buffer[0] = 'x';
|
||||||
#if defined(_GNU_SOURCE) && !defined(__COVERITY__)
|
#if defined(_GNU_SOURCE) && !defined(__COVERITY__)
|
||||||
@ -374,18 +374,18 @@ TEST(FormatTest, StrError) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int result =
|
int result =
|
||||||
fmt::internal::safe_strerror(error_code, message = buffer, BUFFER_SIZE);
|
fmt::detail::safe_strerror(error_code, message = buffer, BUFFER_SIZE);
|
||||||
EXPECT_EQ(result, 0);
|
EXPECT_EQ(result, 0);
|
||||||
std::size_t message_size = std::strlen(message);
|
size_t message_size = std::strlen(message);
|
||||||
EXPECT_GE(BUFFER_SIZE - 1u, message_size);
|
EXPECT_GE(BUFFER_SIZE - 1u, message_size);
|
||||||
EXPECT_EQ(get_system_error(error_code), message);
|
EXPECT_EQ(get_system_error(error_code), message);
|
||||||
|
|
||||||
// safe_strerror never uses buffer on MinGW.
|
// safe_strerror never uses buffer on MinGW.
|
||||||
#if !defined(__MINGW32__) && !defined(__sun)
|
#if !defined(__MINGW32__) && !defined(__sun)
|
||||||
result =
|
result =
|
||||||
fmt::internal::safe_strerror(error_code, message = buffer, message_size);
|
fmt::detail::safe_strerror(error_code, message = buffer, message_size);
|
||||||
EXPECT_EQ(ERANGE, result);
|
EXPECT_EQ(ERANGE, result);
|
||||||
result = fmt::internal::safe_strerror(error_code, message = buffer, 1);
|
result = fmt::detail::safe_strerror(error_code, message = buffer, 1);
|
||||||
EXPECT_EQ(buffer, message); // Message should point to buffer.
|
EXPECT_EQ(buffer, message); // Message should point to buffer.
|
||||||
EXPECT_EQ(ERANGE, result);
|
EXPECT_EQ(ERANGE, result);
|
||||||
EXPECT_STREQ("", message);
|
EXPECT_STREQ("", message);
|
||||||
@ -397,51 +397,48 @@ TEST(FormatTest, FormatErrorCode) {
|
|||||||
{
|
{
|
||||||
fmt::memory_buffer buffer;
|
fmt::memory_buffer buffer;
|
||||||
format_to(buffer, "garbage");
|
format_to(buffer, "garbage");
|
||||||
fmt::internal::format_error_code(buffer, 42, "test");
|
fmt::detail::format_error_code(buffer, 42, "test");
|
||||||
EXPECT_EQ("test: " + msg, to_string(buffer));
|
EXPECT_EQ("test: " + msg, to_string(buffer));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
fmt::memory_buffer buffer;
|
fmt::memory_buffer buffer;
|
||||||
std::string prefix(fmt::inline_buffer_size - msg.size() - sep.size() + 1,
|
std::string prefix(fmt::inline_buffer_size - msg.size() - sep.size() + 1,
|
||||||
'x');
|
'x');
|
||||||
fmt::internal::format_error_code(buffer, 42, prefix);
|
fmt::detail::format_error_code(buffer, 42, prefix);
|
||||||
EXPECT_EQ(msg, to_string(buffer));
|
EXPECT_EQ(msg, to_string(buffer));
|
||||||
}
|
}
|
||||||
int codes[] = {42, -1};
|
int codes[] = {42, -1};
|
||||||
for (std::size_t i = 0, n = sizeof(codes) / sizeof(*codes); i < n; ++i) {
|
for (size_t i = 0, n = sizeof(codes) / sizeof(*codes); i < n; ++i) {
|
||||||
// Test maximum buffer size.
|
// Test maximum buffer size.
|
||||||
msg = fmt::format("error {}", codes[i]);
|
msg = fmt::format("error {}", codes[i]);
|
||||||
fmt::memory_buffer buffer;
|
fmt::memory_buffer buffer;
|
||||||
std::string prefix(fmt::inline_buffer_size - msg.size() - sep.size(), 'x');
|
std::string prefix(fmt::inline_buffer_size - msg.size() - sep.size(), 'x');
|
||||||
fmt::internal::format_error_code(buffer, codes[i], prefix);
|
fmt::detail::format_error_code(buffer, codes[i], prefix);
|
||||||
EXPECT_EQ(prefix + sep + msg, to_string(buffer));
|
EXPECT_EQ(prefix + sep + msg, to_string(buffer));
|
||||||
std::size_t size = fmt::inline_buffer_size;
|
size_t size = fmt::inline_buffer_size;
|
||||||
EXPECT_EQ(size, buffer.size());
|
EXPECT_EQ(size, buffer.size());
|
||||||
buffer.resize(0);
|
buffer.resize(0);
|
||||||
// Test with a message that doesn't fit into the buffer.
|
// Test with a message that doesn't fit into the buffer.
|
||||||
prefix += 'x';
|
prefix += 'x';
|
||||||
fmt::internal::format_error_code(buffer, codes[i], prefix);
|
fmt::detail::format_error_code(buffer, codes[i], prefix);
|
||||||
EXPECT_EQ(msg, to_string(buffer));
|
EXPECT_EQ(msg, to_string(buffer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatTest, CountCodePoints) {
|
TEST(FormatTest, CountCodePoints) {
|
||||||
#ifndef __cpp_char8_t
|
EXPECT_EQ(4,
|
||||||
using fmt::char8_t;
|
fmt::detail::count_code_points(
|
||||||
#endif
|
fmt::basic_string_view<fmt::detail::char8_type>(
|
||||||
EXPECT_EQ(
|
reinterpret_cast<const fmt::detail::char8_type*>("ёжик"))));
|
||||||
4, fmt::internal::count_code_points(
|
|
||||||
fmt::basic_string_view<fmt::internal::char8_type>(
|
|
||||||
reinterpret_cast<const fmt::internal::char8_type*>("ёжик"))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests fmt::internal::count_digits for integer type Int.
|
// Tests fmt::detail::count_digits for integer type Int.
|
||||||
template <typename Int> void test_count_digits() {
|
template <typename Int> void test_count_digits() {
|
||||||
for (Int i = 0; i < 10; ++i) EXPECT_EQ(1u, fmt::internal::count_digits(i));
|
for (Int i = 0; i < 10; ++i) EXPECT_EQ(1u, fmt::detail::count_digits(i));
|
||||||
for (Int i = 1, n = 1, end = max_value<Int>() / 10; n <= end; ++i) {
|
for (Int i = 1, n = 1, end = max_value<Int>() / 10; n <= end; ++i) {
|
||||||
n *= 10;
|
n *= 10;
|
||||||
EXPECT_EQ(i, fmt::internal::count_digits(n - 1));
|
EXPECT_EQ(i, fmt::detail::count_digits(n - 1));
|
||||||
EXPECT_EQ(i + 1, fmt::internal::count_digits(n));
|
EXPECT_EQ(i + 1, fmt::detail::count_digits(n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,11 +447,10 @@ TEST(UtilTest, CountDigits) {
|
|||||||
test_count_digits<uint64_t>();
|
test_count_digits<uint64_t>();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UtilTest, WriteUIntPtr) {
|
TEST(UtilTest, WriteFallbackUIntPtr) {
|
||||||
fmt::memory_buffer buf;
|
std::string s;
|
||||||
fmt::internal::writer writer(buf);
|
fmt::detail::write_ptr<char>(
|
||||||
writer.write_pointer(
|
std::back_inserter(s),
|
||||||
fmt::internal::fallback_uintptr(reinterpret_cast<void*>(0xface)),
|
fmt::detail::fallback_uintptr(reinterpret_cast<void*>(0xface)), nullptr);
|
||||||
nullptr);
|
EXPECT_EQ(s, "0xface");
|
||||||
EXPECT_EQ("0xface", to_string(buf));
|
|
||||||
}
|
}
|
||||||
|
447
externals/dynarmic/externals/fmt/test/format-test.cc
vendored
447
externals/dynarmic/externals/fmt/test/format-test.cc
vendored
@ -35,10 +35,6 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#undef ERROR
|
#undef ERROR
|
||||||
#undef min
|
|
||||||
#undef max
|
|
||||||
|
|
||||||
using std::size_t;
|
|
||||||
|
|
||||||
using fmt::basic_memory_buffer;
|
using fmt::basic_memory_buffer;
|
||||||
using fmt::format;
|
using fmt::format;
|
||||||
@ -47,8 +43,7 @@ using fmt::memory_buffer;
|
|||||||
using fmt::string_view;
|
using fmt::string_view;
|
||||||
using fmt::wmemory_buffer;
|
using fmt::wmemory_buffer;
|
||||||
using fmt::wstring_view;
|
using fmt::wstring_view;
|
||||||
using fmt::internal::basic_writer;
|
using fmt::detail::max_value;
|
||||||
using fmt::internal::max_value;
|
|
||||||
|
|
||||||
using testing::Return;
|
using testing::Return;
|
||||||
using testing::StrictMock;
|
using testing::StrictMock;
|
||||||
@ -102,47 +97,6 @@ void std_format(long double value, std::wstring& result) {
|
|||||||
result = buffer;
|
result = buffer;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Checks if writing value to BasicWriter<Char> produces the same result
|
|
||||||
// as writing it to std::basic_ostringstream<Char>.
|
|
||||||
template <typename Char, typename T>
|
|
||||||
::testing::AssertionResult check_write(const T& value, const char* type) {
|
|
||||||
fmt::basic_memory_buffer<Char> buffer;
|
|
||||||
using range = fmt::buffer_range<Char>;
|
|
||||||
basic_writer<range> writer(buffer);
|
|
||||||
writer.write(value);
|
|
||||||
std::basic_string<Char> actual = to_string(buffer);
|
|
||||||
std::basic_string<Char> expected;
|
|
||||||
std_format(value, expected);
|
|
||||||
if (expected == actual) return ::testing::AssertionSuccess();
|
|
||||||
return ::testing::AssertionFailure()
|
|
||||||
<< "Value of: (Writer<" << type << ">() << value).str()\n"
|
|
||||||
<< " Actual: " << actual << "\n"
|
|
||||||
<< "Expected: " << expected << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AnyWriteChecker {
|
|
||||||
template <typename T>
|
|
||||||
::testing::AssertionResult operator()(const char*, const T& value) const {
|
|
||||||
::testing::AssertionResult result = check_write<char>(value, "char");
|
|
||||||
return result ? check_write<wchar_t>(value, "wchar_t") : result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Char> struct WriteChecker {
|
|
||||||
template <typename T>
|
|
||||||
::testing::AssertionResult operator()(const char*, const T& value) const {
|
|
||||||
return check_write<Char>(value, "char");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Checks if writing value to BasicWriter produces the same result
|
|
||||||
// as writing it to std::ostringstream both for char and wchar_t.
|
|
||||||
#define CHECK_WRITE(value) EXPECT_PRED_FORMAT1(AnyWriteChecker(), value)
|
|
||||||
|
|
||||||
#define CHECK_WRITE_CHAR(value) EXPECT_PRED_FORMAT1(WriteChecker<char>(), value)
|
|
||||||
#define CHECK_WRITE_WCHAR(value) \
|
|
||||||
EXPECT_PRED_FORMAT1(WriteChecker<wchar_t>(), value)
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
struct uint32_pair {
|
struct uint32_pair {
|
||||||
@ -150,10 +104,10 @@ struct uint32_pair {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TEST(UtilTest, BitCast) {
|
TEST(UtilTest, BitCast) {
|
||||||
auto s = fmt::internal::bit_cast<uint32_pair>(uint64_t{42});
|
auto s = fmt::detail::bit_cast<uint32_pair>(uint64_t{42});
|
||||||
EXPECT_EQ(fmt::internal::bit_cast<uint64_t>(s), 42ull);
|
EXPECT_EQ(fmt::detail::bit_cast<uint64_t>(s), 42ull);
|
||||||
s = fmt::internal::bit_cast<uint32_pair>(uint64_t(~0ull));
|
s = fmt::detail::bit_cast<uint32_pair>(uint64_t(~0ull));
|
||||||
EXPECT_EQ(fmt::internal::bit_cast<uint64_t>(s), ~0ull);
|
EXPECT_EQ(fmt::detail::bit_cast<uint64_t>(s), ~0ull);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UtilTest, Increment) {
|
TEST(UtilTest, Increment) {
|
||||||
@ -178,18 +132,18 @@ TEST(UtilTest, ParseNonnegativeInt) {
|
|||||||
fmt::string_view s = "10000000000";
|
fmt::string_view s = "10000000000";
|
||||||
auto begin = s.begin(), end = s.end();
|
auto begin = s.begin(), end = s.end();
|
||||||
EXPECT_THROW_MSG(
|
EXPECT_THROW_MSG(
|
||||||
parse_nonnegative_int(begin, end, fmt::internal::error_handler()),
|
parse_nonnegative_int(begin, end, fmt::detail::error_handler()),
|
||||||
fmt::format_error, "number is too big");
|
fmt::format_error, "number is too big");
|
||||||
s = "2147483649";
|
s = "2147483649";
|
||||||
begin = s.begin();
|
begin = s.begin();
|
||||||
end = s.end();
|
end = s.end();
|
||||||
EXPECT_THROW_MSG(
|
EXPECT_THROW_MSG(
|
||||||
parse_nonnegative_int(begin, end, fmt::internal::error_handler()),
|
parse_nonnegative_int(begin, end, fmt::detail::error_handler()),
|
||||||
fmt::format_error, "number is too big");
|
fmt::format_error, "number is too big");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(IteratorTest, CountingIterator) {
|
TEST(IteratorTest, CountingIterator) {
|
||||||
fmt::internal::counting_iterator it;
|
fmt::detail::counting_iterator it;
|
||||||
auto prev = it++;
|
auto prev = it++;
|
||||||
EXPECT_EQ(prev.count(), 0);
|
EXPECT_EQ(prev.count(), 0);
|
||||||
EXPECT_EQ(it.count(), 1);
|
EXPECT_EQ(it.count(), 1);
|
||||||
@ -197,7 +151,7 @@ TEST(IteratorTest, CountingIterator) {
|
|||||||
|
|
||||||
TEST(IteratorTest, TruncatingIterator) {
|
TEST(IteratorTest, TruncatingIterator) {
|
||||||
char* p = nullptr;
|
char* p = nullptr;
|
||||||
fmt::internal::truncating_iterator<char*> it(p, 3);
|
fmt::detail::truncating_iterator<char*> it(p, 3);
|
||||||
auto prev = it++;
|
auto prev = it++;
|
||||||
EXPECT_EQ(prev.base(), p);
|
EXPECT_EQ(prev.base(), p);
|
||||||
EXPECT_EQ(it.base(), p + 1);
|
EXPECT_EQ(it.base(), p + 1);
|
||||||
@ -206,7 +160,7 @@ TEST(IteratorTest, TruncatingIterator) {
|
|||||||
TEST(IteratorTest, TruncatingBackInserter) {
|
TEST(IteratorTest, TruncatingBackInserter) {
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
auto bi = std::back_inserter(buffer);
|
auto bi = std::back_inserter(buffer);
|
||||||
fmt::internal::truncating_iterator<decltype(bi)> it(bi, 2);
|
fmt::detail::truncating_iterator<decltype(bi)> it(bi, 2);
|
||||||
*it++ = '4';
|
*it++ = '4';
|
||||||
*it++ = '2';
|
*it++ = '2';
|
||||||
*it++ = '1';
|
*it++ = '1';
|
||||||
@ -215,20 +169,20 @@ TEST(IteratorTest, TruncatingBackInserter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(IteratorTest, IsOutputIterator) {
|
TEST(IteratorTest, IsOutputIterator) {
|
||||||
EXPECT_TRUE(fmt::internal::is_output_iterator<char*>::value);
|
EXPECT_TRUE(fmt::detail::is_output_iterator<char*>::value);
|
||||||
EXPECT_FALSE(fmt::internal::is_output_iterator<const char*>::value);
|
EXPECT_FALSE(fmt::detail::is_output_iterator<const char*>::value);
|
||||||
EXPECT_FALSE(fmt::internal::is_output_iterator<std::string>::value);
|
EXPECT_FALSE(fmt::detail::is_output_iterator<std::string>::value);
|
||||||
EXPECT_TRUE(fmt::internal::is_output_iterator<
|
EXPECT_TRUE(fmt::detail::is_output_iterator<
|
||||||
std::back_insert_iterator<std::string>>::value);
|
std::back_insert_iterator<std::string>>::value);
|
||||||
EXPECT_TRUE(fmt::internal::is_output_iterator<std::string::iterator>::value);
|
EXPECT_TRUE(fmt::detail::is_output_iterator<std::string::iterator>::value);
|
||||||
EXPECT_FALSE(
|
EXPECT_FALSE(
|
||||||
fmt::internal::is_output_iterator<std::string::const_iterator>::value);
|
fmt::detail::is_output_iterator<std::string::const_iterator>::value);
|
||||||
EXPECT_FALSE(fmt::internal::is_output_iterator<std::list<char>>::value);
|
EXPECT_FALSE(fmt::detail::is_output_iterator<std::list<char>>::value);
|
||||||
EXPECT_TRUE(
|
EXPECT_TRUE(
|
||||||
fmt::internal::is_output_iterator<std::list<char>::iterator>::value);
|
fmt::detail::is_output_iterator<std::list<char>::iterator>::value);
|
||||||
EXPECT_FALSE(fmt::internal::is_output_iterator<
|
EXPECT_FALSE(
|
||||||
std::list<char>::const_iterator>::value);
|
fmt::detail::is_output_iterator<std::list<char>::const_iterator>::value);
|
||||||
EXPECT_FALSE(fmt::internal::is_output_iterator<uint32_pair>::value);
|
EXPECT_FALSE(fmt::detail::is_output_iterator<uint32_pair>::value);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(MemoryBufferTest, Ctor) {
|
TEST(MemoryBufferTest, Ctor) {
|
||||||
@ -343,10 +297,10 @@ TEST(MemoryBufferTest, Grow) {
|
|||||||
mock_allocator<int> alloc;
|
mock_allocator<int> alloc;
|
||||||
struct TestMemoryBuffer : Base {
|
struct TestMemoryBuffer : Base {
|
||||||
TestMemoryBuffer(Allocator alloc) : Base(alloc) {}
|
TestMemoryBuffer(Allocator alloc) : Base(alloc) {}
|
||||||
void grow(std::size_t size) { Base::grow(size); }
|
void grow(size_t size) { Base::grow(size); }
|
||||||
} buffer((Allocator(&alloc)));
|
} buffer((Allocator(&alloc)));
|
||||||
buffer.resize(7);
|
buffer.resize(7);
|
||||||
using fmt::internal::to_unsigned;
|
using fmt::detail::to_unsigned;
|
||||||
for (int i = 0; i < 7; ++i) buffer[to_unsigned(i)] = i * i;
|
for (int i = 0; i < 7; ++i) buffer[to_unsigned(i)] = i * i;
|
||||||
EXPECT_EQ(10u, buffer.capacity());
|
EXPECT_EQ(10u, buffer.capacity());
|
||||||
int mem[20];
|
int mem[20];
|
||||||
@ -371,7 +325,7 @@ TEST(MemoryBufferTest, Allocator) {
|
|||||||
basic_memory_buffer<char, 10, TestAllocator> buffer2(
|
basic_memory_buffer<char, 10, TestAllocator> buffer2(
|
||||||
(TestAllocator(&alloc)));
|
(TestAllocator(&alloc)));
|
||||||
EXPECT_EQ(&alloc, buffer2.get_allocator().get());
|
EXPECT_EQ(&alloc, buffer2.get_allocator().get());
|
||||||
std::size_t size = 2 * fmt::inline_buffer_size;
|
size_t size = 2 * fmt::inline_buffer_size;
|
||||||
EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem));
|
EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem));
|
||||||
buffer2.reserve(size);
|
buffer2.reserve(size);
|
||||||
EXPECT_CALL(alloc, deallocate(&mem, size));
|
EXPECT_CALL(alloc, deallocate(&mem, size));
|
||||||
@ -382,7 +336,7 @@ TEST(MemoryBufferTest, ExceptionInDeallocate) {
|
|||||||
typedef allocator_ref<mock_allocator<char>> TestAllocator;
|
typedef allocator_ref<mock_allocator<char>> TestAllocator;
|
||||||
StrictMock<mock_allocator<char>> alloc;
|
StrictMock<mock_allocator<char>> alloc;
|
||||||
basic_memory_buffer<char, 10, TestAllocator> buffer((TestAllocator(&alloc)));
|
basic_memory_buffer<char, 10, TestAllocator> buffer((TestAllocator(&alloc)));
|
||||||
std::size_t size = 2 * fmt::inline_buffer_size;
|
size_t size = 2 * fmt::inline_buffer_size;
|
||||||
std::vector<char> mem(size);
|
std::vector<char> mem(size);
|
||||||
{
|
{
|
||||||
EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem[0]));
|
EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem[0]));
|
||||||
@ -397,27 +351,27 @@ TEST(MemoryBufferTest, ExceptionInDeallocate) {
|
|||||||
EXPECT_THROW(buffer.reserve(2 * size), std::exception);
|
EXPECT_THROW(buffer.reserve(2 * size), std::exception);
|
||||||
EXPECT_EQ(&mem2[0], &buffer[0]);
|
EXPECT_EQ(&mem2[0], &buffer[0]);
|
||||||
// Check that the data has been copied.
|
// Check that the data has been copied.
|
||||||
for (std::size_t i = 0; i < size; ++i) EXPECT_EQ('x', buffer[i]);
|
for (size_t i = 0; i < size; ++i) EXPECT_EQ('x', buffer[i]);
|
||||||
}
|
}
|
||||||
EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size));
|
EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UtilTest, UTF8ToUTF16) {
|
TEST(UtilTest, UTF8ToUTF16) {
|
||||||
fmt::internal::utf8_to_utf16 u("лошадка");
|
fmt::detail::utf8_to_utf16 u("лошадка");
|
||||||
EXPECT_EQ(L"\x043B\x043E\x0448\x0430\x0434\x043A\x0430", u.str());
|
EXPECT_EQ(L"\x043B\x043E\x0448\x0430\x0434\x043A\x0430", u.str());
|
||||||
EXPECT_EQ(7, u.size());
|
EXPECT_EQ(7, u.size());
|
||||||
// U+10437 { DESERET SMALL LETTER YEE }
|
// U+10437 { DESERET SMALL LETTER YEE }
|
||||||
EXPECT_EQ(L"\xD801\xDC37", fmt::internal::utf8_to_utf16("𐐷").str());
|
EXPECT_EQ(L"\xD801\xDC37", fmt::detail::utf8_to_utf16("𐐷").str());
|
||||||
EXPECT_THROW_MSG(fmt::internal::utf8_to_utf16("\xc3\x28"), std::runtime_error,
|
EXPECT_THROW_MSG(fmt::detail::utf8_to_utf16("\xc3\x28"), std::runtime_error,
|
||||||
"invalid utf8");
|
"invalid utf8");
|
||||||
EXPECT_THROW_MSG(fmt::internal::utf8_to_utf16(fmt::string_view("л", 1)),
|
EXPECT_THROW_MSG(fmt::detail::utf8_to_utf16(fmt::string_view("л", 1)),
|
||||||
std::runtime_error, "invalid utf8");
|
std::runtime_error, "invalid utf8");
|
||||||
EXPECT_EQ(L"123456", fmt::internal::utf8_to_utf16("123456").str());
|
EXPECT_EQ(L"123456", fmt::detail::utf8_to_utf16("123456").str());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UtilTest, UTF8ToUTF16EmptyString) {
|
TEST(UtilTest, UTF8ToUTF16EmptyString) {
|
||||||
std::string s = "";
|
std::string s = "";
|
||||||
fmt::internal::utf8_to_utf16 u(s.c_str());
|
fmt::detail::utf8_to_utf16 u(s.c_str());
|
||||||
EXPECT_EQ(L"", u.str());
|
EXPECT_EQ(L"", u.str());
|
||||||
EXPECT_EQ(s.size(), u.size());
|
EXPECT_EQ(s.size(), u.size());
|
||||||
}
|
}
|
||||||
@ -479,101 +433,6 @@ TEST(StringViewTest, Ctor) {
|
|||||||
EXPECT_EQ(4u, string_view(std::string("defg")).size());
|
EXPECT_EQ(4u, string_view(std::string("defg")).size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WriterTest, Data) {
|
|
||||||
memory_buffer buf;
|
|
||||||
fmt::internal::writer w(buf);
|
|
||||||
w.write(42);
|
|
||||||
EXPECT_EQ("42", to_string(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(WriterTest, WriteInt) {
|
|
||||||
CHECK_WRITE(42);
|
|
||||||
CHECK_WRITE(-42);
|
|
||||||
CHECK_WRITE(static_cast<short>(12));
|
|
||||||
CHECK_WRITE(34u);
|
|
||||||
CHECK_WRITE(std::numeric_limits<int>::min());
|
|
||||||
CHECK_WRITE(max_value<int>());
|
|
||||||
CHECK_WRITE(max_value<unsigned>());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(WriterTest, WriteLong) {
|
|
||||||
CHECK_WRITE(56l);
|
|
||||||
CHECK_WRITE(78ul);
|
|
||||||
CHECK_WRITE(std::numeric_limits<long>::min());
|
|
||||||
CHECK_WRITE(max_value<long>());
|
|
||||||
CHECK_WRITE(max_value<unsigned long>());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(WriterTest, WriteLongLong) {
|
|
||||||
CHECK_WRITE(56ll);
|
|
||||||
CHECK_WRITE(78ull);
|
|
||||||
CHECK_WRITE(std::numeric_limits<long long>::min());
|
|
||||||
CHECK_WRITE(max_value<long long>());
|
|
||||||
CHECK_WRITE(max_value<unsigned long long>());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(WriterTest, WriteDouble) {
|
|
||||||
CHECK_WRITE(4.2);
|
|
||||||
CHECK_WRITE(-4.2);
|
|
||||||
auto min = std::numeric_limits<double>::min();
|
|
||||||
auto max = max_value<double>();
|
|
||||||
if (fmt::internal::use_grisu<double>()) {
|
|
||||||
EXPECT_EQ("2.2250738585072014e-308", fmt::format("{}", min));
|
|
||||||
EXPECT_EQ("1.7976931348623157e+308", fmt::format("{}", max));
|
|
||||||
} else {
|
|
||||||
CHECK_WRITE(min);
|
|
||||||
CHECK_WRITE(max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(WriterTest, WriteLongDouble) {
|
|
||||||
CHECK_WRITE(4.2l);
|
|
||||||
CHECK_WRITE_CHAR(-4.2l);
|
|
||||||
std::wstring str;
|
|
||||||
std_format(4.2l, str);
|
|
||||||
if (str[0] != '-')
|
|
||||||
CHECK_WRITE_WCHAR(-4.2l);
|
|
||||||
else
|
|
||||||
fmt::print("warning: long double formatting with std::swprintf is broken");
|
|
||||||
auto min = std::numeric_limits<long double>::min();
|
|
||||||
auto max = max_value<long double>();
|
|
||||||
if (fmt::internal::use_grisu<long double>()) {
|
|
||||||
EXPECT_EQ("2.2250738585072014e-308", fmt::format("{}", min));
|
|
||||||
EXPECT_EQ("1.7976931348623157e+308", fmt::format("{}", max));
|
|
||||||
} else {
|
|
||||||
CHECK_WRITE(min);
|
|
||||||
CHECK_WRITE(max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(WriterTest, WriteDoubleAtBufferBoundary) {
|
|
||||||
memory_buffer buf;
|
|
||||||
fmt::internal::writer writer(buf);
|
|
||||||
for (int i = 0; i < 100; ++i) writer.write(1.23456789);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(WriterTest, WriteDoubleWithFilledBuffer) {
|
|
||||||
memory_buffer buf;
|
|
||||||
fmt::internal::writer writer(buf);
|
|
||||||
// Fill the buffer.
|
|
||||||
for (int i = 0; i < fmt::inline_buffer_size; ++i) writer.write(' ');
|
|
||||||
writer.write(1.2);
|
|
||||||
fmt::string_view sv(buf.data(), buf.size());
|
|
||||||
sv.remove_prefix(fmt::inline_buffer_size);
|
|
||||||
EXPECT_EQ("1.2", sv);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(WriterTest, WriteChar) { CHECK_WRITE('a'); }
|
|
||||||
|
|
||||||
TEST(WriterTest, WriteWideChar) { CHECK_WRITE_WCHAR(L'a'); }
|
|
||||||
|
|
||||||
TEST(WriterTest, WriteString) {
|
|
||||||
CHECK_WRITE_CHAR("abc");
|
|
||||||
CHECK_WRITE_WCHAR("abc");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(WriterTest, WriteWideString) { CHECK_WRITE_WCHAR(L"abc"); }
|
|
||||||
|
|
||||||
TEST(FormatToTest, FormatWithoutArgs) {
|
TEST(FormatToTest, FormatWithoutArgs) {
|
||||||
std::string s;
|
std::string s;
|
||||||
fmt::format_to(std::back_inserter(s), "test");
|
fmt::format_to(std::back_inserter(s), "test");
|
||||||
@ -640,15 +499,14 @@ TEST(FormatterTest, ArgErrors) {
|
|||||||
EXPECT_THROW_MSG(format("{"), format_error, "invalid format string");
|
EXPECT_THROW_MSG(format("{"), format_error, "invalid format string");
|
||||||
EXPECT_THROW_MSG(format("{?}"), format_error, "invalid format string");
|
EXPECT_THROW_MSG(format("{?}"), format_error, "invalid format string");
|
||||||
EXPECT_THROW_MSG(format("{0"), format_error, "invalid format string");
|
EXPECT_THROW_MSG(format("{0"), format_error, "invalid format string");
|
||||||
EXPECT_THROW_MSG(format("{0}"), format_error, "argument index out of range");
|
EXPECT_THROW_MSG(format("{0}"), format_error, "argument not found");
|
||||||
EXPECT_THROW_MSG(format("{00}", 42), format_error, "invalid format string");
|
EXPECT_THROW_MSG(format("{00}", 42), format_error, "invalid format string");
|
||||||
|
|
||||||
char format_str[BUFFER_SIZE];
|
char format_str[BUFFER_SIZE];
|
||||||
safe_sprintf(format_str, "{%u", INT_MAX);
|
safe_sprintf(format_str, "{%u", INT_MAX);
|
||||||
EXPECT_THROW_MSG(format(format_str), format_error, "invalid format string");
|
EXPECT_THROW_MSG(format(format_str), format_error, "invalid format string");
|
||||||
safe_sprintf(format_str, "{%u}", INT_MAX);
|
safe_sprintf(format_str, "{%u}", INT_MAX);
|
||||||
EXPECT_THROW_MSG(format(format_str), format_error,
|
EXPECT_THROW_MSG(format(format_str), format_error, "argument not found");
|
||||||
"argument index out of range");
|
|
||||||
|
|
||||||
safe_sprintf(format_str, "{%u", INT_MAX + 1u);
|
safe_sprintf(format_str, "{%u", INT_MAX + 1u);
|
||||||
EXPECT_THROW_MSG(format(format_str), format_error, "number is too big");
|
EXPECT_THROW_MSG(format(format_str), format_error, "number is too big");
|
||||||
@ -673,19 +531,18 @@ template <> struct TestFormat<0> {
|
|||||||
TEST(FormatterTest, ManyArgs) {
|
TEST(FormatterTest, ManyArgs) {
|
||||||
EXPECT_EQ("19", TestFormat<20>::format("{19}"));
|
EXPECT_EQ("19", TestFormat<20>::format("{19}"));
|
||||||
EXPECT_THROW_MSG(TestFormat<20>::format("{20}"), format_error,
|
EXPECT_THROW_MSG(TestFormat<20>::format("{20}"), format_error,
|
||||||
"argument index out of range");
|
"argument not found");
|
||||||
EXPECT_THROW_MSG(TestFormat<21>::format("{21}"), format_error,
|
EXPECT_THROW_MSG(TestFormat<21>::format("{21}"), format_error,
|
||||||
"argument index out of range");
|
"argument not found");
|
||||||
enum { max_packed_args = fmt::internal::max_packed_args };
|
enum { max_packed_args = fmt::detail::max_packed_args };
|
||||||
std::string format_str = fmt::format("{{{}}}", max_packed_args + 1);
|
std::string format_str = fmt::format("{{{}}}", max_packed_args + 1);
|
||||||
EXPECT_THROW_MSG(TestFormat<max_packed_args>::format(format_str),
|
EXPECT_THROW_MSG(TestFormat<max_packed_args>::format(format_str),
|
||||||
format_error, "argument index out of range");
|
format_error, "argument not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, NamedArg) {
|
TEST(FormatterTest, NamedArg) {
|
||||||
EXPECT_EQ("1/a/A", format("{_1}/{a_}/{A_}", fmt::arg("a_", 'a'),
|
EXPECT_EQ("1/a/A", format("{_1}/{a_}/{A_}", fmt::arg("a_", 'a'),
|
||||||
fmt::arg("A_", "A"), fmt::arg("_1", 1)));
|
fmt::arg("A_", "A"), fmt::arg("_1", 1)));
|
||||||
EXPECT_THROW_MSG(format("{a}"), format_error, "argument not found");
|
|
||||||
EXPECT_EQ(" -42", format("{0:{width}}", -42, fmt::arg("width", 4)));
|
EXPECT_EQ(" -42", format("{0:{width}}", -42, fmt::arg("width", 4)));
|
||||||
EXPECT_EQ("st", format("{0:.{precision}}", "str", fmt::arg("precision", 2)));
|
EXPECT_EQ("st", format("{0:.{precision}}", "str", fmt::arg("precision", 2)));
|
||||||
EXPECT_EQ("1 2", format("{} {two}", 1, fmt::arg("two", 2)));
|
EXPECT_EQ("1 2", format("{} {two}", 1, fmt::arg("two", 2)));
|
||||||
@ -695,6 +552,8 @@ TEST(FormatterTest, NamedArg) {
|
|||||||
fmt::arg("i", 0), fmt::arg("j", 0), fmt::arg("k", 0),
|
fmt::arg("i", 0), fmt::arg("j", 0), fmt::arg("k", 0),
|
||||||
fmt::arg("l", 0), fmt::arg("m", 0), fmt::arg("n", 0),
|
fmt::arg("l", 0), fmt::arg("m", 0), fmt::arg("n", 0),
|
||||||
fmt::arg("o", 0), fmt::arg("p", 0)));
|
fmt::arg("o", 0), fmt::arg("p", 0)));
|
||||||
|
EXPECT_THROW_MSG(format("{a}"), format_error, "argument not found");
|
||||||
|
EXPECT_THROW_MSG(format("{a}", 42), format_error, "argument not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, AutoArgIndex) {
|
TEST(FormatterTest, AutoArgIndex) {
|
||||||
@ -708,7 +567,7 @@ TEST(FormatterTest, AutoArgIndex) {
|
|||||||
"cannot switch from manual to automatic argument indexing");
|
"cannot switch from manual to automatic argument indexing");
|
||||||
EXPECT_THROW_MSG(format("{:.{0}}", 1.2345, 2), format_error,
|
EXPECT_THROW_MSG(format("{:.{0}}", 1.2345, 2), format_error,
|
||||||
"cannot switch from automatic to manual argument indexing");
|
"cannot switch from automatic to manual argument indexing");
|
||||||
EXPECT_THROW_MSG(format("{}"), format_error, "argument index out of range");
|
EXPECT_THROW_MSG(format("{}"), format_error, "argument not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, EmptySpecs) { EXPECT_EQ("42", format("{0:}", 42)); }
|
TEST(FormatterTest, EmptySpecs) { EXPECT_EQ("42", format("{0:}", 42)); }
|
||||||
@ -747,38 +606,8 @@ TEST(FormatterTest, RightAlign) {
|
|||||||
EXPECT_EQ(" 0xface", format("{0:>8}", reinterpret_cast<void*>(0xface)));
|
EXPECT_EQ(" 0xface", format("{0:>8}", reinterpret_cast<void*>(0xface)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FMT_NUMERIC_ALIGN
|
#if FMT_DEPRECATED_NUMERIC_ALIGN
|
||||||
TEST(FormatterTest, NumericAlign) {
|
TEST(FormatterTest, NumericAlign) { EXPECT_EQ("0042", format("{0:=4}", 42)); }
|
||||||
EXPECT_EQ(" 42", format("{0:=4}", 42));
|
|
||||||
EXPECT_EQ("+ 42", format("{0:=+4}", 42));
|
|
||||||
EXPECT_EQ(" 42", format("{0:=4o}", 042));
|
|
||||||
EXPECT_EQ("+ 42", format("{0:=+4o}", 042));
|
|
||||||
EXPECT_EQ(" 42", format("{0:=4x}", 0x42));
|
|
||||||
EXPECT_EQ("+ 42", format("{0:=+4x}", 0x42));
|
|
||||||
EXPECT_EQ("- 42", format("{0:=5}", -42));
|
|
||||||
EXPECT_EQ(" 42", format("{0:=5}", 42u));
|
|
||||||
EXPECT_EQ("- 42", format("{0:=5}", -42l));
|
|
||||||
EXPECT_EQ(" 42", format("{0:=5}", 42ul));
|
|
||||||
EXPECT_EQ("- 42", format("{0:=5}", -42ll));
|
|
||||||
EXPECT_EQ(" 42", format("{0:=5}", 42ull));
|
|
||||||
EXPECT_EQ("- 42.0", format("{0:=7}", -42.0));
|
|
||||||
EXPECT_EQ("- 42.0", format("{0:=7}", -42.0l));
|
|
||||||
EXPECT_THROW_MSG(format("{0:=5", 'c'), format_error,
|
|
||||||
"missing '}' in format string");
|
|
||||||
EXPECT_THROW_MSG(format("{0:=5}", 'c'), format_error,
|
|
||||||
"invalid format specifier for char");
|
|
||||||
EXPECT_THROW_MSG(format("{0:=5}", "abc"), format_error,
|
|
||||||
"format specifier requires numeric argument");
|
|
||||||
EXPECT_THROW_MSG(format("{0:=8}", reinterpret_cast<void*>(0xface)),
|
|
||||||
format_error, "format specifier requires numeric argument");
|
|
||||||
EXPECT_EQ(" 1.0", fmt::format("{:= }", 1.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FormatToTest, FormatToNonbackInsertIteratorWithSignAndNumericAlignment) {
|
|
||||||
char buffer[16] = {};
|
|
||||||
fmt::format_to(fmt::internal::make_checked(buffer, 16), "{: =+}", 42.0);
|
|
||||||
EXPECT_STREQ("+42.0", buffer);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST(FormatterTest, CenterAlign) {
|
TEST(FormatterTest, CenterAlign) {
|
||||||
@ -969,7 +798,7 @@ TEST(FormatterTest, Width) {
|
|||||||
safe_sprintf(format_str, "{0:%u", UINT_MAX);
|
safe_sprintf(format_str, "{0:%u", UINT_MAX);
|
||||||
increment(format_str + 3);
|
increment(format_str + 3);
|
||||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||||
std::size_t size = std::strlen(format_str);
|
size_t size = std::strlen(format_str);
|
||||||
format_str[size] = '}';
|
format_str[size] = '}';
|
||||||
format_str[size + 1] = 0;
|
format_str[size + 1] = 0;
|
||||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||||
@ -999,7 +828,7 @@ TEST(FormatterTest, RuntimeWidth) {
|
|||||||
safe_sprintf(format_str, "{0:{%u", UINT_MAX);
|
safe_sprintf(format_str, "{0:{%u", UINT_MAX);
|
||||||
increment(format_str + 4);
|
increment(format_str + 4);
|
||||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||||
std::size_t size = std::strlen(format_str);
|
size_t size = std::strlen(format_str);
|
||||||
format_str[size] = '}';
|
format_str[size] = '}';
|
||||||
format_str[size + 1] = 0;
|
format_str[size + 1] = 0;
|
||||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||||
@ -1011,8 +840,7 @@ TEST(FormatterTest, RuntimeWidth) {
|
|||||||
EXPECT_THROW_MSG(format("{0:{}", 0), format_error,
|
EXPECT_THROW_MSG(format("{0:{}", 0), format_error,
|
||||||
"cannot switch from manual to automatic argument indexing");
|
"cannot switch from manual to automatic argument indexing");
|
||||||
EXPECT_THROW_MSG(format("{0:{?}}", 0), format_error, "invalid format string");
|
EXPECT_THROW_MSG(format("{0:{?}}", 0), format_error, "invalid format string");
|
||||||
EXPECT_THROW_MSG(format("{0:{1}}", 0), format_error,
|
EXPECT_THROW_MSG(format("{0:{1}}", 0), format_error, "argument not found");
|
||||||
"argument index out of range");
|
|
||||||
|
|
||||||
EXPECT_THROW_MSG(format("{0:{0:}}", 0), format_error,
|
EXPECT_THROW_MSG(format("{0:{0:}}", 0), format_error,
|
||||||
"invalid format string");
|
"invalid format string");
|
||||||
@ -1053,7 +881,7 @@ TEST(FormatterTest, Precision) {
|
|||||||
safe_sprintf(format_str, "{0:.%u", UINT_MAX);
|
safe_sprintf(format_str, "{0:.%u", UINT_MAX);
|
||||||
increment(format_str + 4);
|
increment(format_str + 4);
|
||||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||||
std::size_t size = std::strlen(format_str);
|
size_t size = std::strlen(format_str);
|
||||||
format_str[size] = '}';
|
format_str[size] = '}';
|
||||||
format_str[size + 1] = 0;
|
format_str[size + 1] = 0;
|
||||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||||
@ -1134,7 +962,7 @@ TEST(FormatterTest, Precision) {
|
|||||||
EXPECT_THROW_MSG(format("{0:.2f}", reinterpret_cast<void*>(0xcafe)),
|
EXPECT_THROW_MSG(format("{0:.2f}", reinterpret_cast<void*>(0xcafe)),
|
||||||
format_error,
|
format_error,
|
||||||
"precision not allowed for this argument type");
|
"precision not allowed for this argument type");
|
||||||
EXPECT_THROW_MSG(format("{:.{}e}", 42.0, fmt::internal::max_value<int>()),
|
EXPECT_THROW_MSG(format("{:.{}e}", 42.0, fmt::detail::max_value<int>()),
|
||||||
format_error, "number is too big");
|
format_error, "number is too big");
|
||||||
|
|
||||||
EXPECT_EQ("st", format("{0:.2}", "str"));
|
EXPECT_EQ("st", format("{0:.2}", "str"));
|
||||||
@ -1145,7 +973,7 @@ TEST(FormatterTest, RuntimePrecision) {
|
|||||||
safe_sprintf(format_str, "{0:.{%u", UINT_MAX);
|
safe_sprintf(format_str, "{0:.{%u", UINT_MAX);
|
||||||
increment(format_str + 5);
|
increment(format_str + 5);
|
||||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||||
std::size_t size = std::strlen(format_str);
|
size_t size = std::strlen(format_str);
|
||||||
format_str[size] = '}';
|
format_str[size] = '}';
|
||||||
format_str[size + 1] = 0;
|
format_str[size + 1] = 0;
|
||||||
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
|
||||||
@ -1160,8 +988,7 @@ TEST(FormatterTest, RuntimePrecision) {
|
|||||||
"invalid format string");
|
"invalid format string");
|
||||||
EXPECT_THROW_MSG(format("{0:.{1}", 0, 0), format_error,
|
EXPECT_THROW_MSG(format("{0:.{1}", 0, 0), format_error,
|
||||||
"precision not allowed for this argument type");
|
"precision not allowed for this argument type");
|
||||||
EXPECT_THROW_MSG(format("{0:.{1}}", 0), format_error,
|
EXPECT_THROW_MSG(format("{0:.{1}}", 0), format_error, "argument not found");
|
||||||
"argument index out of range");
|
|
||||||
|
|
||||||
EXPECT_THROW_MSG(format("{0:.{0:}}", 0), format_error,
|
EXPECT_THROW_MSG(format("{0:.{0:}}", 0), format_error,
|
||||||
"invalid format string");
|
"invalid format string");
|
||||||
@ -1256,7 +1083,8 @@ TEST(FormatterTest, FormatShort) {
|
|||||||
TEST(FormatterTest, FormatInt) {
|
TEST(FormatterTest, FormatInt) {
|
||||||
EXPECT_THROW_MSG(format("{0:v", 42), format_error,
|
EXPECT_THROW_MSG(format("{0:v", 42), format_error,
|
||||||
"missing '}' in format string");
|
"missing '}' in format string");
|
||||||
check_unknown_types(42, "bBdoxXnL", "integer");
|
check_unknown_types(42, "bBdoxXnLc", "integer");
|
||||||
|
EXPECT_EQ("x", format("{:c}", static_cast<int>('x')));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, FormatBin) {
|
TEST(FormatterTest, FormatBin) {
|
||||||
@ -1396,7 +1224,6 @@ TEST(FormatterTest, FormatOct) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, FormatIntLocale) {
|
TEST(FormatterTest, FormatIntLocale) {
|
||||||
EXPECT_EQ("1234", format("{:n}", 1234));
|
|
||||||
EXPECT_EQ("1234", format("{:L}", 1234));
|
EXPECT_EQ("1234", format("{:L}", 1234));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1413,7 +1240,7 @@ TEST(FormatterTest, FormatFloat) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, FormatDouble) {
|
TEST(FormatterTest, FormatDouble) {
|
||||||
check_unknown_types(1.2, "eEfFgGaAn%", "double");
|
check_unknown_types(1.2, "eEfFgGaAnL%", "double");
|
||||||
EXPECT_EQ("0.0", format("{:}", 0.0));
|
EXPECT_EQ("0.0", format("{:}", 0.0));
|
||||||
EXPECT_EQ("0.000000", format("{:f}", 0.0));
|
EXPECT_EQ("0.000000", format("{:f}", 0.0));
|
||||||
EXPECT_EQ("0", format("{:g}", 0.0));
|
EXPECT_EQ("0", format("{:g}", 0.0));
|
||||||
@ -1422,6 +1249,7 @@ TEST(FormatterTest, FormatDouble) {
|
|||||||
EXPECT_EQ("392.65", format("{:G}", 392.65));
|
EXPECT_EQ("392.65", format("{:G}", 392.65));
|
||||||
EXPECT_EQ("392.650000", format("{:f}", 392.65));
|
EXPECT_EQ("392.650000", format("{:f}", 392.65));
|
||||||
EXPECT_EQ("392.650000", format("{:F}", 392.65));
|
EXPECT_EQ("392.650000", format("{:F}", 392.65));
|
||||||
|
EXPECT_EQ("42", format("{:L}", 42.0));
|
||||||
char buffer[BUFFER_SIZE];
|
char buffer[BUFFER_SIZE];
|
||||||
safe_sprintf(buffer, "%e", 392.65);
|
safe_sprintf(buffer, "%e", 392.65);
|
||||||
EXPECT_EQ(buffer, format("{0:e}", 392.65));
|
EXPECT_EQ(buffer, format("{0:e}", 392.65));
|
||||||
@ -1492,7 +1320,7 @@ TEST(FormatterTest, FormatLongDouble) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, FormatChar) {
|
TEST(FormatterTest, FormatChar) {
|
||||||
const char types[] = "cbBdoxXnL";
|
const char types[] = "cbBdoxXL";
|
||||||
check_unknown_types('a', types, "char");
|
check_unknown_types('a', types, "char");
|
||||||
EXPECT_EQ("a", format("{0}", 'a'));
|
EXPECT_EQ("a", format("{0}", 'a'));
|
||||||
EXPECT_EQ("z", format("{0:c}", 'z'));
|
EXPECT_EQ("z", format("{0:c}", 'z'));
|
||||||
@ -1608,12 +1436,46 @@ TEST(FormatterTest, FormatExplicitlyConvertibleToStdStringView) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// std::is_constructible is broken in MSVC until version 2015.
|
||||||
|
#if !FMT_MSC_VER || FMT_MSC_VER >= 1900
|
||||||
|
struct explicitly_convertible_to_wstring_view {
|
||||||
|
explicit operator fmt::wstring_view() const { return L"foo"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(FormatTest, FormatExplicitlyConvertibleToWStringView) {
|
||||||
|
EXPECT_EQ(L"foo",
|
||||||
|
fmt::format(L"{}", explicitly_convertible_to_wstring_view()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace fake_qt {
|
||||||
|
class QString {
|
||||||
|
public:
|
||||||
|
QString(const wchar_t* s) : s_(std::make_shared<std::wstring>(s)) {}
|
||||||
|
const wchar_t* utf16() const FMT_NOEXCEPT { return s_->data(); }
|
||||||
|
int size() const FMT_NOEXCEPT { return static_cast<int>(s_->size()); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<std::wstring> s_;
|
||||||
|
};
|
||||||
|
|
||||||
|
fmt::basic_string_view<wchar_t> to_string_view(const QString& s) FMT_NOEXCEPT {
|
||||||
|
return {s.utf16(), static_cast<size_t>(s.size())};
|
||||||
|
}
|
||||||
|
} // namespace fake_qt
|
||||||
|
|
||||||
|
TEST(FormatTest, FormatForeignStrings) {
|
||||||
|
using fake_qt::QString;
|
||||||
|
EXPECT_EQ(fmt::format(QString(L"{}"), 42), L"42");
|
||||||
|
EXPECT_EQ(fmt::format(QString(L"{}"), QString(L"42")), L"42");
|
||||||
|
}
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
template <> struct formatter<Date> {
|
template <> struct formatter<Date> {
|
||||||
template <typename ParseContext>
|
template <typename ParseContext>
|
||||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||||
auto it = ctx.begin();
|
auto it = ctx.begin();
|
||||||
if (*it == 'd') ++it;
|
if (it != ctx.end() && *it == 'd') ++it;
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1649,7 +1511,7 @@ TEST(FormatterTest, CustomFormat) {
|
|||||||
TEST(FormatterTest, CustomFormatTo) {
|
TEST(FormatterTest, CustomFormatTo) {
|
||||||
char buf[10] = {};
|
char buf[10] = {};
|
||||||
auto end =
|
auto end =
|
||||||
&*fmt::format_to(fmt::internal::make_checked(buf, 10), "{}", Answer());
|
&*fmt::format_to(fmt::detail::make_checked(buf, 10), "{}", Answer());
|
||||||
EXPECT_EQ(end, buf + 2);
|
EXPECT_EQ(end, buf + 2);
|
||||||
EXPECT_STREQ(buf, "42");
|
EXPECT_STREQ(buf, "42");
|
||||||
}
|
}
|
||||||
@ -1759,7 +1621,7 @@ TEST(FormatTest, Print) {
|
|||||||
"Don't panic!");
|
"Don't panic!");
|
||||||
#endif
|
#endif
|
||||||
// Check that the wide print overload compiles.
|
// Check that the wide print overload compiles.
|
||||||
if (fmt::internal::const_check(false)) fmt::print(L"test");
|
if (fmt::detail::const_check(false)) fmt::print(L"test");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatTest, Variadic) {
|
TEST(FormatTest, Variadic) {
|
||||||
@ -1770,9 +1632,9 @@ TEST(FormatTest, Variadic) {
|
|||||||
TEST(FormatTest, Dynamic) {
|
TEST(FormatTest, Dynamic) {
|
||||||
typedef fmt::format_context ctx;
|
typedef fmt::format_context ctx;
|
||||||
std::vector<fmt::basic_format_arg<ctx>> args;
|
std::vector<fmt::basic_format_arg<ctx>> args;
|
||||||
args.emplace_back(fmt::internal::make_arg<ctx>(42));
|
args.emplace_back(fmt::detail::make_arg<ctx>(42));
|
||||||
args.emplace_back(fmt::internal::make_arg<ctx>("abc1"));
|
args.emplace_back(fmt::detail::make_arg<ctx>("abc1"));
|
||||||
args.emplace_back(fmt::internal::make_arg<ctx>(1.5f));
|
args.emplace_back(fmt::detail::make_arg<ctx>(1.5f));
|
||||||
|
|
||||||
std::string result = fmt::vformat(
|
std::string result = fmt::vformat(
|
||||||
"{} and {} and {}",
|
"{} and {} and {}",
|
||||||
@ -1944,10 +1806,10 @@ TEST(FormatTest, StrongEnum) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using buffer_range = fmt::buffer_range<char>;
|
using buffer_iterator = fmt::format_context::iterator;
|
||||||
|
|
||||||
class mock_arg_formatter
|
class mock_arg_formatter
|
||||||
: public fmt::internal::arg_formatter_base<buffer_range> {
|
: public fmt::detail::arg_formatter_base<buffer_iterator, char> {
|
||||||
private:
|
private:
|
||||||
#if FMT_USE_INT128
|
#if FMT_USE_INT128
|
||||||
MOCK_METHOD1(call, void(__int128_t value));
|
MOCK_METHOD1(call, void(__int128_t value));
|
||||||
@ -1956,24 +1818,23 @@ class mock_arg_formatter
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef fmt::internal::arg_formatter_base<buffer_range> base;
|
using base = fmt::detail::arg_formatter_base<buffer_iterator, char>;
|
||||||
typedef buffer_range range;
|
|
||||||
|
|
||||||
mock_arg_formatter(fmt::format_context& ctx, fmt::format_parse_context*,
|
mock_arg_formatter(fmt::format_context& ctx, fmt::format_parse_context*,
|
||||||
fmt::format_specs* s = nullptr)
|
fmt::format_specs* s = nullptr, const char* = nullptr)
|
||||||
: base(fmt::internal::get_container(ctx.out()), s, ctx.locale()) {
|
: base(ctx.out(), s, ctx.locale()) {
|
||||||
EXPECT_CALL(*this, call(42));
|
EXPECT_CALL(*this, call(42));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename std::enable_if<fmt::internal::is_integral<T>::value, iterator>::type
|
typename std::enable_if<fmt::detail::is_integral<T>::value, iterator>::type
|
||||||
operator()(T value) {
|
operator()(T value) {
|
||||||
call(value);
|
call(value);
|
||||||
return base::operator()(value);
|
return base::operator()(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename std::enable_if<!fmt::internal::is_integral<T>::value, iterator>::type
|
typename std::enable_if<!fmt::detail::is_integral<T>::value, iterator>::type
|
||||||
operator()(T value) {
|
operator()(T value) {
|
||||||
return base::operator()(value);
|
return base::operator()(value);
|
||||||
}
|
}
|
||||||
@ -1985,7 +1846,9 @@ class mock_arg_formatter
|
|||||||
|
|
||||||
static void custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
static void custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
||||||
fmt::memory_buffer buffer;
|
fmt::memory_buffer buffer;
|
||||||
fmt::vformat_to<mock_arg_formatter>(buffer, format_str, args);
|
fmt::detail::buffer<char>& base = buffer;
|
||||||
|
fmt::vformat_to<mock_arg_formatter>(std::back_inserter(base), format_str,
|
||||||
|
args);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
@ -2025,7 +1888,7 @@ TEST(FormatTest, DynamicFormatter) {
|
|||||||
"cannot switch from manual to automatic argument indexing");
|
"cannot switch from manual to automatic argument indexing");
|
||||||
EXPECT_THROW_MSG(format("{:{0}}", num), format_error,
|
EXPECT_THROW_MSG(format("{:{0}}", num), format_error,
|
||||||
"cannot switch from automatic to manual argument indexing");
|
"cannot switch from automatic to manual argument indexing");
|
||||||
#if FMT_NUMERIC_ALIGN
|
#if FMT_DEPRECATED_NUMERIC_ALIGN
|
||||||
EXPECT_THROW_MSG(format("{:=}", str), format_error,
|
EXPECT_THROW_MSG(format("{:=}", str), format_error,
|
||||||
"format specifier requires numeric argument");
|
"format specifier requires numeric argument");
|
||||||
#endif
|
#endif
|
||||||
@ -2043,9 +1906,30 @@ TEST(FormatTest, DynamicFormatter) {
|
|||||||
"precision not allowed for this argument type");
|
"precision not allowed for this argument type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace adl_test {
|
||||||
|
namespace fmt {
|
||||||
|
namespace detail {
|
||||||
|
struct foo {};
|
||||||
|
template <typename, typename OutputIt> void write(OutputIt, foo) = delete;
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace fmt
|
||||||
|
} // namespace adl_test
|
||||||
|
|
||||||
|
FMT_BEGIN_NAMESPACE
|
||||||
|
template <>
|
||||||
|
struct formatter<adl_test::fmt::detail::foo> : formatter<std::string> {
|
||||||
|
template <typename FormatContext>
|
||||||
|
auto format(adl_test::fmt::detail::foo, FormatContext& ctx)
|
||||||
|
-> decltype(ctx.out()) {
|
||||||
|
return formatter<std::string>::format("foo", ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
TEST(FormatTest, ToString) {
|
TEST(FormatTest, ToString) {
|
||||||
EXPECT_EQ("42", fmt::to_string(42));
|
EXPECT_EQ("42", fmt::to_string(42));
|
||||||
EXPECT_EQ("0x1234", fmt::to_string(reinterpret_cast<void*>(0x1234)));
|
EXPECT_EQ("0x1234", fmt::to_string(reinterpret_cast<void*>(0x1234)));
|
||||||
|
EXPECT_EQ("foo", fmt::to_string(adl_test::fmt::detail::foo()));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatTest, ToWString) { EXPECT_EQ(L"42", fmt::to_wstring(42)); }
|
TEST(FormatTest, ToWString) { EXPECT_EQ(L"42", fmt::to_wstring(42)); }
|
||||||
@ -2159,7 +2043,7 @@ struct test_arg_id_handler {
|
|||||||
template <size_t N>
|
template <size_t N>
|
||||||
FMT_CONSTEXPR test_arg_id_handler parse_arg_id(const char (&s)[N]) {
|
FMT_CONSTEXPR test_arg_id_handler parse_arg_id(const char (&s)[N]) {
|
||||||
test_arg_id_handler h;
|
test_arg_id_handler h;
|
||||||
fmt::internal::parse_arg_id(s, s + N, h);
|
fmt::detail::parse_arg_id(s, s + N, h);
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2180,9 +2064,9 @@ struct test_format_specs_handler {
|
|||||||
fmt::align_t align = fmt::align::none;
|
fmt::align_t align = fmt::align::none;
|
||||||
char fill = 0;
|
char fill = 0;
|
||||||
int width = 0;
|
int width = 0;
|
||||||
fmt::internal::arg_ref<char> width_ref;
|
fmt::detail::arg_ref<char> width_ref;
|
||||||
int precision = 0;
|
int precision = 0;
|
||||||
fmt::internal::arg_ref<char> precision_ref;
|
fmt::detail::arg_ref<char> precision_ref;
|
||||||
char type = 0;
|
char type = 0;
|
||||||
|
|
||||||
// Workaround for MSVC2017 bug that results in "expression did not evaluate
|
// Workaround for MSVC2017 bug that results in "expression did not evaluate
|
||||||
@ -2208,12 +2092,12 @@ struct test_format_specs_handler {
|
|||||||
FMT_CONSTEXPR void on_zero() { res = ZERO; }
|
FMT_CONSTEXPR void on_zero() { res = ZERO; }
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_width(int w) { width = w; }
|
FMT_CONSTEXPR void on_width(int w) { width = w; }
|
||||||
FMT_CONSTEXPR void on_dynamic_width(fmt::internal::auto_id) {}
|
FMT_CONSTEXPR void on_dynamic_width(fmt::detail::auto_id) {}
|
||||||
FMT_CONSTEXPR void on_dynamic_width(int index) { width_ref = index; }
|
FMT_CONSTEXPR void on_dynamic_width(int index) { width_ref = index; }
|
||||||
FMT_CONSTEXPR void on_dynamic_width(string_view) {}
|
FMT_CONSTEXPR void on_dynamic_width(string_view) {}
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_precision(int p) { precision = p; }
|
FMT_CONSTEXPR void on_precision(int p) { precision = p; }
|
||||||
FMT_CONSTEXPR void on_dynamic_precision(fmt::internal::auto_id) {}
|
FMT_CONSTEXPR void on_dynamic_precision(fmt::detail::auto_id) {}
|
||||||
FMT_CONSTEXPR void on_dynamic_precision(int index) { precision_ref = index; }
|
FMT_CONSTEXPR void on_dynamic_precision(int index) { precision_ref = index; }
|
||||||
FMT_CONSTEXPR void on_dynamic_precision(string_view) {}
|
FMT_CONSTEXPR void on_dynamic_precision(string_view) {}
|
||||||
|
|
||||||
@ -2225,7 +2109,7 @@ struct test_format_specs_handler {
|
|||||||
template <size_t N>
|
template <size_t N>
|
||||||
FMT_CONSTEXPR test_format_specs_handler parse_test_specs(const char (&s)[N]) {
|
FMT_CONSTEXPR test_format_specs_handler parse_test_specs(const char (&s)[N]) {
|
||||||
test_format_specs_handler h;
|
test_format_specs_handler h;
|
||||||
fmt::internal::parse_format_specs(s, s + N, h);
|
fmt::detail::parse_format_specs(s, s + N, h);
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2259,8 +2143,9 @@ struct test_parse_context {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct test_context {
|
struct test_context {
|
||||||
typedef char char_type;
|
using char_type = char;
|
||||||
typedef fmt::basic_format_arg<test_context> format_arg;
|
using format_arg = fmt::basic_format_arg<test_context>;
|
||||||
|
using parse_context_type = fmt::format_parse_context;
|
||||||
|
|
||||||
template <typename T> struct formatter_type {
|
template <typename T> struct formatter_type {
|
||||||
typedef fmt::formatter<T, char_type> type;
|
typedef fmt::formatter<T, char_type> type;
|
||||||
@ -2268,7 +2153,7 @@ struct test_context {
|
|||||||
|
|
||||||
template <typename Id>
|
template <typename Id>
|
||||||
FMT_CONSTEXPR fmt::basic_format_arg<test_context> arg(Id id) {
|
FMT_CONSTEXPR fmt::basic_format_arg<test_context> arg(Id id) {
|
||||||
return fmt::internal::make_arg<test_context>(id);
|
return fmt::detail::make_arg<test_context>(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_error(const char*) {}
|
void on_error(const char*) {}
|
||||||
@ -2281,7 +2166,7 @@ FMT_CONSTEXPR fmt::format_specs parse_specs(const char (&s)[N]) {
|
|||||||
auto specs = fmt::format_specs();
|
auto specs = fmt::format_specs();
|
||||||
auto parse_ctx = test_parse_context();
|
auto parse_ctx = test_parse_context();
|
||||||
auto ctx = test_context();
|
auto ctx = test_context();
|
||||||
fmt::internal::specs_handler<test_parse_context, test_context> h(
|
fmt::detail::specs_handler<test_parse_context, test_context> h(
|
||||||
specs, parse_ctx, ctx);
|
specs, parse_ctx, ctx);
|
||||||
parse_format_specs(s, s + N, h);
|
parse_format_specs(s, s + N, h);
|
||||||
return specs;
|
return specs;
|
||||||
@ -2305,11 +2190,11 @@ TEST(FormatTest, ConstexprSpecsHandler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
FMT_CONSTEXPR fmt::internal::dynamic_format_specs<char> parse_dynamic_specs(
|
FMT_CONSTEXPR fmt::detail::dynamic_format_specs<char> parse_dynamic_specs(
|
||||||
const char (&s)[N]) {
|
const char (&s)[N]) {
|
||||||
fmt::internal::dynamic_format_specs<char> specs;
|
fmt::detail::dynamic_format_specs<char> specs;
|
||||||
test_parse_context ctx{};
|
test_parse_context ctx{};
|
||||||
fmt::internal::dynamic_specs_handler<test_parse_context> h(specs, ctx);
|
fmt::detail::dynamic_specs_handler<test_parse_context> h(specs, ctx);
|
||||||
parse_format_specs(s, s + N, h);
|
parse_format_specs(s, s + N, h);
|
||||||
return specs;
|
return specs;
|
||||||
}
|
}
|
||||||
@ -2333,8 +2218,8 @@ TEST(FormatTest, ConstexprDynamicSpecsHandler) {
|
|||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
FMT_CONSTEXPR test_format_specs_handler check_specs(const char (&s)[N]) {
|
FMT_CONSTEXPR test_format_specs_handler check_specs(const char (&s)[N]) {
|
||||||
fmt::internal::specs_checker<test_format_specs_handler> checker(
|
fmt::detail::specs_checker<test_format_specs_handler> checker(
|
||||||
test_format_specs_handler(), fmt::internal::type::double_type);
|
test_format_specs_handler(), fmt::detail::type::double_type);
|
||||||
parse_format_specs(s, s + N, checker);
|
parse_format_specs(s, s + N, checker);
|
||||||
return checker;
|
return checker;
|
||||||
}
|
}
|
||||||
@ -2359,13 +2244,14 @@ TEST(FormatTest, ConstexprSpecsChecker) {
|
|||||||
struct test_format_string_handler {
|
struct test_format_string_handler {
|
||||||
FMT_CONSTEXPR void on_text(const char*, const char*) {}
|
FMT_CONSTEXPR void on_text(const char*, const char*) {}
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_arg_id() {}
|
FMT_CONSTEXPR int on_arg_id() { return 0; }
|
||||||
|
|
||||||
template <typename T> FMT_CONSTEXPR void on_arg_id(T) {}
|
template <typename T> FMT_CONSTEXPR int on_arg_id(T) { return 0; }
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_replacement_field(const char*) {}
|
FMT_CONSTEXPR void on_replacement_field(int, const char*) {}
|
||||||
|
|
||||||
FMT_CONSTEXPR const char* on_format_specs(const char* begin, const char*) {
|
FMT_CONSTEXPR const char* on_format_specs(int, const char* begin,
|
||||||
|
const char*) {
|
||||||
return begin;
|
return begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2376,7 +2262,7 @@ struct test_format_string_handler {
|
|||||||
|
|
||||||
template <size_t N> FMT_CONSTEXPR bool parse_string(const char (&s)[N]) {
|
template <size_t N> FMT_CONSTEXPR bool parse_string(const char (&s)[N]) {
|
||||||
test_format_string_handler h;
|
test_format_string_handler h;
|
||||||
fmt::internal::parse_format_string<true>(fmt::string_view(s, N - 1), h);
|
fmt::detail::parse_format_string<true>(fmt::string_view(s, N - 1), h);
|
||||||
return !h.error;
|
return !h.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2420,8 +2306,10 @@ FMT_CONSTEXPR bool equal(const char* s1, const char* s2) {
|
|||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
FMT_CONSTEXPR bool test_error(const char* fmt, const char* expected_error) {
|
FMT_CONSTEXPR bool test_error(const char* fmt, const char* expected_error) {
|
||||||
const char* actual_error = nullptr;
|
const char* actual_error = nullptr;
|
||||||
fmt::internal::do_check_format_string<char, test_error_handler, Args...>(
|
string_view s(fmt, len(fmt));
|
||||||
string_view(fmt, len(fmt)), test_error_handler(actual_error));
|
fmt::detail::format_string_checker<char, test_error_handler, Args...> checker(
|
||||||
|
s, test_error_handler(actual_error));
|
||||||
|
fmt::detail::parse_format_string<true>(s, checker);
|
||||||
return equal(actual_error, expected_error);
|
return equal(actual_error, expected_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2434,13 +2322,13 @@ TEST(FormatTest, FormatStringErrors) {
|
|||||||
EXPECT_ERROR_NOARGS("foo", nullptr);
|
EXPECT_ERROR_NOARGS("foo", nullptr);
|
||||||
EXPECT_ERROR_NOARGS("}", "unmatched '}' in format string");
|
EXPECT_ERROR_NOARGS("}", "unmatched '}' in format string");
|
||||||
EXPECT_ERROR("{0:s", "unknown format specifier", Date);
|
EXPECT_ERROR("{0:s", "unknown format specifier", Date);
|
||||||
# if FMT_MSC_VER >= 1916
|
# if !FMT_MSC_VER || FMT_MSC_VER >= 1916
|
||||||
// This causes an internal compiler error in MSVC2017.
|
// This causes an detail compiler error in MSVC2017.
|
||||||
EXPECT_ERROR("{:{<}", "invalid fill character '{'", int);
|
EXPECT_ERROR("{:{<}", "invalid fill character '{'", int);
|
||||||
EXPECT_ERROR("{:10000000000}", "number is too big", int);
|
EXPECT_ERROR("{:10000000000}", "number is too big", int);
|
||||||
EXPECT_ERROR("{:.10000000000}", "number is too big", int);
|
EXPECT_ERROR("{:.10000000000}", "number is too big", int);
|
||||||
EXPECT_ERROR_NOARGS("{:x}", "argument index out of range");
|
EXPECT_ERROR_NOARGS("{:x}", "argument not found");
|
||||||
# if FMT_NUMERIC_ALIGN
|
# if FMT_DEPRECATED_NUMERIC_ALIGN
|
||||||
EXPECT_ERROR("{0:=5", "unknown format specifier", int);
|
EXPECT_ERROR("{0:=5", "unknown format specifier", int);
|
||||||
EXPECT_ERROR("{:=}", "format specifier requires numeric argument",
|
EXPECT_ERROR("{:=}", "format specifier requires numeric argument",
|
||||||
const char*);
|
const char*);
|
||||||
@ -2458,6 +2346,8 @@ TEST(FormatTest, FormatStringErrors) {
|
|||||||
EXPECT_ERROR("{:+}", "format specifier requires signed argument", unsigned);
|
EXPECT_ERROR("{:+}", "format specifier requires signed argument", unsigned);
|
||||||
EXPECT_ERROR("{:-}", "format specifier requires signed argument", unsigned);
|
EXPECT_ERROR("{:-}", "format specifier requires signed argument", unsigned);
|
||||||
EXPECT_ERROR("{: }", "format specifier requires signed argument", unsigned);
|
EXPECT_ERROR("{: }", "format specifier requires signed argument", unsigned);
|
||||||
|
EXPECT_ERROR("{:{}}", "argument not found", int);
|
||||||
|
EXPECT_ERROR("{:.{}}", "argument not found", double);
|
||||||
EXPECT_ERROR("{:.2}", "precision not allowed for this argument type", int);
|
EXPECT_ERROR("{:.2}", "precision not allowed for this argument type", int);
|
||||||
EXPECT_ERROR("{:s}", "invalid type specifier", int);
|
EXPECT_ERROR("{:s}", "invalid type specifier", int);
|
||||||
EXPECT_ERROR("{:s}", "invalid type specifier", bool);
|
EXPECT_ERROR("{:s}", "invalid type specifier", bool);
|
||||||
@ -2480,8 +2370,8 @@ TEST(FormatTest, FormatStringErrors) {
|
|||||||
EXPECT_ERROR("{:.{0x}}", "invalid format string", int);
|
EXPECT_ERROR("{:.{0x}}", "invalid format string", int);
|
||||||
EXPECT_ERROR("{:.{-}}", "invalid format string", int);
|
EXPECT_ERROR("{:.{-}}", "invalid format string", int);
|
||||||
EXPECT_ERROR("{:.x}", "missing precision specifier", int);
|
EXPECT_ERROR("{:.x}", "missing precision specifier", int);
|
||||||
EXPECT_ERROR_NOARGS("{}", "argument index out of range");
|
EXPECT_ERROR_NOARGS("{}", "argument not found");
|
||||||
EXPECT_ERROR("{1}", "argument index out of range", int);
|
EXPECT_ERROR("{1}", "argument not found", int);
|
||||||
EXPECT_ERROR("{1}{}",
|
EXPECT_ERROR("{1}{}",
|
||||||
"cannot switch from manual to automatic argument indexing", int,
|
"cannot switch from manual to automatic argument indexing", int,
|
||||||
int);
|
int);
|
||||||
@ -2492,7 +2382,7 @@ TEST(FormatTest, FormatStringErrors) {
|
|||||||
|
|
||||||
TEST(FormatTest, VFormatTo) {
|
TEST(FormatTest, VFormatTo) {
|
||||||
typedef fmt::format_context context;
|
typedef fmt::format_context context;
|
||||||
fmt::basic_format_arg<context> arg = fmt::internal::make_arg<context>(42);
|
fmt::basic_format_arg<context> arg = fmt::detail::make_arg<context>(42);
|
||||||
fmt::basic_format_args<context> args(&arg, 1);
|
fmt::basic_format_args<context> args(&arg, 1);
|
||||||
std::string s;
|
std::string s;
|
||||||
fmt::vformat_to(std::back_inserter(s), "{}", args);
|
fmt::vformat_to(std::back_inserter(s), "{}", args);
|
||||||
@ -2502,7 +2392,7 @@ TEST(FormatTest, VFormatTo) {
|
|||||||
EXPECT_EQ("42", s);
|
EXPECT_EQ("42", s);
|
||||||
|
|
||||||
typedef fmt::wformat_context wcontext;
|
typedef fmt::wformat_context wcontext;
|
||||||
fmt::basic_format_arg<wcontext> warg = fmt::internal::make_arg<wcontext>(42);
|
fmt::basic_format_arg<wcontext> warg = fmt::detail::make_arg<wcontext>(42);
|
||||||
fmt::basic_format_args<wcontext> wargs(&warg, 1);
|
fmt::basic_format_args<wcontext> wargs(&warg, 1);
|
||||||
std::wstring w;
|
std::wstring w;
|
||||||
fmt::vformat_to(std::back_inserter(w), L"{}", wargs);
|
fmt::vformat_to(std::back_inserter(w), L"{}", wargs);
|
||||||
@ -2530,7 +2420,7 @@ TEST(FormatTest, EmphasisNonHeaderOnly) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatTest, CharTraitsIsNotAmbiguous) {
|
TEST(FormatTest, CharTraitsIsNotAmbiguous) {
|
||||||
// Test that we don't inject internal names into the std namespace.
|
// Test that we don't inject detail names into the std namespace.
|
||||||
using namespace std;
|
using namespace std;
|
||||||
char_traits<char>::char_type c;
|
char_traits<char>::char_type c;
|
||||||
(void)c;
|
(void)c;
|
||||||
@ -2568,13 +2458,12 @@ template <typename S> std::string from_u8str(const S& str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatTest, FormatUTF8Precision) {
|
TEST(FormatTest, FormatUTF8Precision) {
|
||||||
using str_type = std::basic_string<fmt::internal::char8_type>;
|
using str_type = std::basic_string<fmt::detail::char8_type>;
|
||||||
str_type format(
|
str_type format(reinterpret_cast<const fmt::detail::char8_type*>(u8"{:.4}"));
|
||||||
reinterpret_cast<const fmt::internal::char8_type*>(u8"{:.4}"));
|
str_type str(reinterpret_cast<const fmt::detail::char8_type*>(
|
||||||
str_type str(reinterpret_cast<const fmt::internal::char8_type*>(
|
|
||||||
u8"caf\u00e9s")); // cafés
|
u8"caf\u00e9s")); // cafés
|
||||||
auto result = fmt::format(format, str);
|
auto result = fmt::format(format, str);
|
||||||
EXPECT_EQ(fmt::internal::count_code_points(result), 4);
|
EXPECT_EQ(fmt::detail::count_code_points(result), 4);
|
||||||
EXPECT_EQ(result.size(), 5);
|
EXPECT_EQ(result.size(), 5);
|
||||||
EXPECT_EQ(from_u8str(result), from_u8str(str.substr(0, 5)));
|
EXPECT_EQ(from_u8str(result), from_u8str(str.substr(0, 5)));
|
||||||
}
|
}
|
||||||
|
@ -7,14 +7,19 @@ in fmt. It is a part of the continous fuzzing at
|
|||||||
The source code is modified to make the fuzzing possible without locking up on
|
The source code is modified to make the fuzzing possible without locking up on
|
||||||
resource exhaustion:
|
resource exhaustion:
|
||||||
```cpp
|
```cpp
|
||||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
#ifdef FMT_FUZZ
|
||||||
if(spec.precision>100000) {
|
if(spec.precision>100000) {
|
||||||
throw std::runtime_error("fuzz mode - avoiding large precision");
|
throw std::runtime_error("fuzz mode - avoiding large precision");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
```
|
```
|
||||||
This macro is the defacto standard for making fuzzing practically possible, see
|
This macro `FMT_FUZZ` is enabled on OSS-Fuzz builds and makes fuzzing
|
||||||
[the libFuzzer documentation](https://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode).
|
practically possible. It is used in fmt code to prevent resource exhaustion in
|
||||||
|
fuzzing mode.
|
||||||
|
The macro `FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION` is the
|
||||||
|
defacto standard for making fuzzing practically possible to disable certain
|
||||||
|
fuzzing-unfriendly features (for example, randomness), see [the libFuzzer
|
||||||
|
documentation](https://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode).
|
||||||
|
|
||||||
## Running the fuzzers locally
|
## Running the fuzzers locally
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ void invoke_inner(fmt::string_view formatstring, const Item item) {
|
|||||||
|
|
||||||
// Item is the underlying type for duration (int, long etc)
|
// Item is the underlying type for duration (int, long etc)
|
||||||
template <typename Item>
|
template <typename Item>
|
||||||
void invoke_outer(const uint8_t* Data, std::size_t Size, const int scaling) {
|
void invoke_outer(const uint8_t* Data, size_t Size, const int scaling) {
|
||||||
// always use a fixed location of the data
|
// always use a fixed location of the data
|
||||||
using fmt_fuzzer::Nfixed;
|
using fmt_fuzzer::Nfixed;
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ void invoke_outer(const uint8_t* Data, std::size_t Size, const int scaling) {
|
|||||||
// doit_impl<Item,std::yotta>(buf.data(),item);
|
// doit_impl<Item,std::yotta>(buf.data(),item);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, std::size_t Size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
|
||||||
if (Size <= 4) {
|
if (Size <= 4) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include "fuzzer_common.h"
|
#include "fuzzer_common.h"
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, std::size_t Size);
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size);
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
for (int i = 1; i < argc; ++i) {
|
for (int i = 1; i < argc; ++i) {
|
||||||
std::ifstream in(argv[i]);
|
std::ifstream in(argv[i]);
|
||||||
@ -13,7 +13,7 @@ int main(int argc, char* argv[]) {
|
|||||||
const auto pos = in.tellg();
|
const auto pos = in.tellg();
|
||||||
assert(pos >= 0);
|
assert(pos >= 0);
|
||||||
in.seekg(0, std::ios_base::beg);
|
in.seekg(0, std::ios_base::beg);
|
||||||
std::vector<char> buf(static_cast<std::size_t>(pos));
|
std::vector<char> buf(static_cast<size_t>(pos));
|
||||||
in.read(buf.data(), static_cast<long>(buf.size()));
|
in.read(buf.data(), static_cast<long>(buf.size()));
|
||||||
assert(in.gcount() == pos);
|
assert(in.gcount() == pos);
|
||||||
LLVMFuzzerTestOneInput(fmt_fuzzer::as_bytes(buf.data()), buf.size());
|
LLVMFuzzerTestOneInput(fmt_fuzzer::as_bytes(buf.data()), buf.size());
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "fuzzer_common.h"
|
#include "fuzzer_common.h"
|
||||||
|
|
||||||
template <typename Item1>
|
template <typename Item1>
|
||||||
void invoke_fmt(const uint8_t* Data, std::size_t Size, unsigned int argsize) {
|
void invoke_fmt(const uint8_t* Data, size_t Size, unsigned int argsize) {
|
||||||
constexpr auto N1 = sizeof(Item1);
|
constexpr auto N1 = sizeof(Item1);
|
||||||
static_assert(N1 <= fmt_fuzzer::Nfixed, "Nfixed too small");
|
static_assert(N1 <= fmt_fuzzer::Nfixed, "Nfixed too small");
|
||||||
if (Size <= fmt_fuzzer::Nfixed) {
|
if (Size <= fmt_fuzzer::Nfixed) {
|
||||||
@ -29,11 +29,11 @@ void invoke_fmt(const uint8_t* Data, std::size_t Size, unsigned int argsize) {
|
|||||||
// allocating buffers separately is slower, but increases chances
|
// allocating buffers separately is slower, but increases chances
|
||||||
// of detecting memory errors
|
// of detecting memory errors
|
||||||
#if FMT_FUZZ_SEPARATE_ALLOCATION
|
#if FMT_FUZZ_SEPARATE_ALLOCATION
|
||||||
std::vector<char> argnamebuffer(argsize);
|
std::vector<char> argnamebuffer(argsize + 1);
|
||||||
std::memcpy(argnamebuffer.data(), Data, argsize);
|
std::memcpy(argnamebuffer.data(), Data, argsize);
|
||||||
auto argname = fmt::string_view(argnamebuffer.data(), argsize);
|
auto argname = argnamebuffer.data();
|
||||||
#else
|
#else
|
||||||
auto argname = fmt::string_view(fmt_fuzzer::as_chars(Data), argsize);
|
auto argname = fmt_fuzzer::as_chars(Data);
|
||||||
#endif
|
#endif
|
||||||
Data += argsize;
|
Data += argsize;
|
||||||
Size -= argsize;
|
Size -= argsize;
|
||||||
@ -105,7 +105,7 @@ template <typename Callback> void invoke(int index, Callback callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, std::size_t Size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
|
||||||
if (Size <= 3) {
|
if (Size <= 3) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
using fmt_fuzzer::Nfixed;
|
using fmt_fuzzer::Nfixed;
|
||||||
|
|
||||||
template <typename Item>
|
template <typename Item>
|
||||||
void invoke_fmt(const uint8_t* Data, std::size_t Size) {
|
void invoke_fmt(const uint8_t* Data, size_t Size) {
|
||||||
constexpr auto N = sizeof(Item);
|
constexpr auto N = sizeof(Item);
|
||||||
static_assert(N <= Nfixed, "Nfixed is too small");
|
static_assert(N <= Nfixed, "Nfixed is too small");
|
||||||
if (Size <= Nfixed) {
|
if (Size <= Nfixed) {
|
||||||
@ -40,7 +40,7 @@ void invoke_fmt(const uint8_t* Data, std::size_t Size) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void invoke_fmt_time(const uint8_t* Data, std::size_t Size) {
|
void invoke_fmt_time(const uint8_t* Data, size_t Size) {
|
||||||
using Item = std::time_t;
|
using Item = std::time_t;
|
||||||
constexpr auto N = sizeof(Item);
|
constexpr auto N = sizeof(Item);
|
||||||
static_assert(N <= Nfixed, "Nfixed too small");
|
static_assert(N <= Nfixed, "Nfixed too small");
|
||||||
@ -69,7 +69,7 @@ void invoke_fmt_time(const uint8_t* Data, std::size_t Size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, std::size_t Size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
|
||||||
if (Size <= 3) {
|
if (Size <= 3) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
using fmt_fuzzer::Nfixed;
|
using fmt_fuzzer::Nfixed;
|
||||||
|
|
||||||
template <typename Item1, typename Item2>
|
template <typename Item1, typename Item2>
|
||||||
void invoke_fmt(const uint8_t* Data, std::size_t Size) {
|
void invoke_fmt(const uint8_t* Data, size_t Size) {
|
||||||
constexpr auto N1 = sizeof(Item1);
|
constexpr auto N1 = sizeof(Item1);
|
||||||
constexpr auto N2 = sizeof(Item2);
|
constexpr auto N2 = sizeof(Item2);
|
||||||
static_assert(N1 <= Nfixed, "size1 exceeded");
|
static_assert(N1 <= Nfixed, "size1 exceeded");
|
||||||
@ -90,7 +90,7 @@ template <typename Callback> void invoke(int index, Callback callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, std::size_t Size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
|
||||||
if (Size <= 3) {
|
if (Size <= 3) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
constexpr auto Nfixed = fmt_fuzzer::Nfixed;
|
constexpr auto Nfixed = fmt_fuzzer::Nfixed;
|
||||||
|
|
||||||
template <typename Item1, typename Item2>
|
template <typename Item1, typename Item2>
|
||||||
void invoke_fmt(const uint8_t* Data, std::size_t Size) {
|
void invoke_fmt(const uint8_t* Data, size_t Size) {
|
||||||
constexpr auto N1 = sizeof(Item1);
|
constexpr auto N1 = sizeof(Item1);
|
||||||
constexpr auto N2 = sizeof(Item2);
|
constexpr auto N2 = sizeof(Item2);
|
||||||
static_assert(N1 <= Nfixed, "size1 exceeded");
|
static_assert(N1 <= Nfixed, "size1 exceeded");
|
||||||
@ -86,7 +86,7 @@ template <typename Callback> void invoke(int index, Callback callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, std::size_t Size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
|
||||||
if (Size <= 3) {
|
if (Size <= 3) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -344,6 +344,7 @@ class GTEST_API_ SingleFailureChecker {
|
|||||||
# include <sys/mman.h> // NOLINT
|
# include <sys/mman.h> // NOLINT
|
||||||
# include <sys/time.h> // NOLINT
|
# include <sys/time.h> // NOLINT
|
||||||
# include <unistd.h> // NOLINT
|
# include <unistd.h> // NOLINT
|
||||||
|
|
||||||
# include <string>
|
# include <string>
|
||||||
|
|
||||||
#elif GTEST_OS_SYMBIAN
|
#elif GTEST_OS_SYMBIAN
|
||||||
@ -7728,6 +7729,7 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
|
|||||||
# include <sys/syslimits.h>
|
# include <sys/syslimits.h>
|
||||||
#else
|
#else
|
||||||
# include <limits.h>
|
# include <limits.h>
|
||||||
|
|
||||||
# include <climits> // Some Linux distributions define PATH_MAX here.
|
# include <climits> // Some Linux distributions define PATH_MAX here.
|
||||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
|
||||||
@ -8899,6 +8901,7 @@ const char* StringFromGTestEnv(const char* flag, const char* default_value) {
|
|||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <ostream> // NOLINT
|
#include <ostream> // NOLINT
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -9494,6 +9497,7 @@ const char* TypedTestCasePState::VerifyRegisteredTestNames(
|
|||||||
// This file implements cardinalities.
|
// This file implements cardinalities.
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
#include <ostream> // NOLINT
|
#include <ostream> // NOLINT
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -9646,6 +9650,7 @@ GTEST_API_ Cardinality Exactly(int n) { return Between(n, n); }
|
|||||||
// USE THEM IN USER CODE.
|
// USE THEM IN USER CODE.
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include <ostream> // NOLINT
|
#include <ostream> // NOLINT
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -9808,6 +9813,7 @@ GTEST_API_ void Log(LogSeverity severity, const string& message,
|
|||||||
// utilities for defining matchers.
|
// utilities for defining matchers.
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -10291,6 +10297,7 @@ bool UnorderedElementsAreMatcherImplBase::
|
|||||||
// EXPECT_CALL).
|
// EXPECT_CALL).
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <iostream> // NOLINT
|
#include <iostream> // NOLINT
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "gtest-extra.h"
|
#include "gtest-extra.h"
|
||||||
|
|
||||||
#include <gtest/gtest-spi.h>
|
#include <gtest/gtest-spi.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -167,22 +168,24 @@ TEST_F(SingleEvaluationTest, FailedEXPECT_WRITE) {
|
|||||||
// Tests that assertion arguments are evaluated exactly once.
|
// Tests that assertion arguments are evaluated exactly once.
|
||||||
TEST_F(SingleEvaluationTest, WriteTests) {
|
TEST_F(SingleEvaluationTest, WriteTests) {
|
||||||
// successful EXPECT_WRITE
|
// successful EXPECT_WRITE
|
||||||
EXPECT_WRITE(stdout,
|
EXPECT_WRITE(
|
||||||
{ // NOLINT
|
stdout,
|
||||||
a_++;
|
{ // NOLINT
|
||||||
std::printf("test");
|
a_++;
|
||||||
},
|
std::printf("test");
|
||||||
(b_++, "test"));
|
},
|
||||||
|
(b_++, "test"));
|
||||||
EXPECT_EQ(1, a_);
|
EXPECT_EQ(1, a_);
|
||||||
EXPECT_EQ(1, b_);
|
EXPECT_EQ(1, b_);
|
||||||
|
|
||||||
// failed EXPECT_WRITE
|
// failed EXPECT_WRITE
|
||||||
EXPECT_NONFATAL_FAILURE(EXPECT_WRITE(stdout,
|
EXPECT_NONFATAL_FAILURE(EXPECT_WRITE(
|
||||||
{ // NOLINT
|
stdout,
|
||||||
a_++;
|
{ // NOLINT
|
||||||
std::printf("test");
|
a_++;
|
||||||
},
|
std::printf("test");
|
||||||
(b_++, "other")),
|
},
|
||||||
|
(b_++, "other")),
|
||||||
"Actual: test");
|
"Actual: test");
|
||||||
EXPECT_EQ(2, a_);
|
EXPECT_EQ(2, a_);
|
||||||
EXPECT_EQ(2, b_);
|
EXPECT_EQ(2, b_);
|
||||||
@ -417,16 +420,17 @@ TEST(OutputRedirectTest, ErrorInDtor) {
|
|||||||
std::unique_ptr<OutputRedirect> redir(new OutputRedirect(f.get()));
|
std::unique_ptr<OutputRedirect> redir(new OutputRedirect(f.get()));
|
||||||
// Put a character in a file buffer.
|
// Put a character in a file buffer.
|
||||||
EXPECT_EQ('x', fputc('x', f.get()));
|
EXPECT_EQ('x', fputc('x', f.get()));
|
||||||
EXPECT_WRITE(stderr,
|
EXPECT_WRITE(
|
||||||
{
|
stderr,
|
||||||
// The close function must be called inside EXPECT_WRITE,
|
{
|
||||||
// otherwise the system may recycle closed file descriptor when
|
// The close function must be called inside EXPECT_WRITE,
|
||||||
// redirecting the output in EXPECT_STDERR and the second close
|
// otherwise the system may recycle closed file descriptor when
|
||||||
// will break output redirection.
|
// redirecting the output in EXPECT_STDERR and the second close
|
||||||
FMT_POSIX(close(write_fd));
|
// will break output redirection.
|
||||||
SUPPRESS_ASSERT(redir.reset(nullptr));
|
FMT_POSIX(close(write_fd));
|
||||||
},
|
SUPPRESS_ASSERT(redir.reset(nullptr));
|
||||||
format_system_error(EBADF, "cannot flush stream"));
|
},
|
||||||
|
format_system_error(EBADF, "cannot flush stream"));
|
||||||
write_copy.dup2(write_fd); // "undo" close or dtor of buffered_file will fail
|
write_copy.dup2(write_fd); // "undo" close or dtor of buffered_file will fail
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ std::string OutputRedirect::restore_and_read() {
|
|||||||
if (read_end_.descriptor() == -1) return content; // Already read.
|
if (read_end_.descriptor() == -1) return content; // Already read.
|
||||||
enum { BUFFER_SIZE = 4096 };
|
enum { BUFFER_SIZE = 4096 };
|
||||||
char buffer[BUFFER_SIZE];
|
char buffer[BUFFER_SIZE];
|
||||||
std::size_t count = 0;
|
size_t count = 0;
|
||||||
do {
|
do {
|
||||||
count = read_end_.read(buffer, BUFFER_SIZE);
|
count = read_end_.read(buffer, BUFFER_SIZE);
|
||||||
content.append(buffer, count);
|
content.append(buffer, count);
|
||||||
@ -66,9 +66,9 @@ std::string OutputRedirect::restore_and_read() {
|
|||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string read(file& f, std::size_t count) {
|
std::string read(file& f, size_t count) {
|
||||||
std::string buffer(count, '\0');
|
std::string buffer(count, '\0');
|
||||||
std::size_t n = 0, offset = 0;
|
size_t n = 0, offset = 0;
|
||||||
do {
|
do {
|
||||||
n = f.read(&buffer[offset], count - offset);
|
n = f.read(&buffer[offset], count - offset);
|
||||||
// We can't read more than size_t bytes since count has type size_t.
|
// We can't read more than size_t bytes since count has type size_t.
|
||||||
|
@ -9,8 +9,9 @@
|
|||||||
#define FMT_GTEST_EXTRA_H_
|
#define FMT_GTEST_EXTRA_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "gmock.h"
|
|
||||||
#include "fmt/os.h"
|
#include "fmt/os.h"
|
||||||
|
#include "gmock.h"
|
||||||
|
|
||||||
#define FMT_TEST_THROW_(statement, expected_exception, expected_message, fail) \
|
#define FMT_TEST_THROW_(statement, expected_exception, expected_message, fail) \
|
||||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
@ -137,10 +138,11 @@ class SuppressAssert {
|
|||||||
EXPECT_SYSTEM_ERROR(SUPPRESS_ASSERT(statement), error_code, message)
|
EXPECT_SYSTEM_ERROR(SUPPRESS_ASSERT(statement), error_code, message)
|
||||||
|
|
||||||
// Attempts to read count characters from a file.
|
// Attempts to read count characters from a file.
|
||||||
std::string read(fmt::file& f, std::size_t count);
|
std::string read(fmt::file& f, size_t count);
|
||||||
|
|
||||||
# define EXPECT_READ(file, expected_content) \
|
# define EXPECT_READ(file, expected_content) \
|
||||||
EXPECT_EQ(expected_content, read(file, std::strlen(expected_content)))
|
EXPECT_EQ(expected_content, \
|
||||||
|
read(file, fmt::string_view(expected_content).size()))
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# define EXPECT_WRITE(file, statement, expected_output) SUCCEED()
|
# define EXPECT_WRITE(file, statement, expected_output) SUCCEED()
|
||||||
|
@ -6,9 +6,10 @@
|
|||||||
// For the license information refer to format.h.
|
// For the license information refer to format.h.
|
||||||
|
|
||||||
#include "fmt/locale.h"
|
#include "fmt/locale.h"
|
||||||
|
|
||||||
#include "gmock.h"
|
#include "gmock.h"
|
||||||
|
|
||||||
using fmt::internal::max_value;
|
using fmt::detail::max_value;
|
||||||
|
|
||||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
||||||
template <typename Char> struct numpunct : std::numpunct<Char> {
|
template <typename Char> struct numpunct : std::numpunct<Char> {
|
||||||
@ -41,49 +42,68 @@ template <typename Char> struct small_grouping : std::numpunct<Char> {
|
|||||||
|
|
||||||
TEST(LocaleTest, DoubleDecimalPoint) {
|
TEST(LocaleTest, DoubleDecimalPoint) {
|
||||||
std::locale loc(std::locale(), new numpunct<char>());
|
std::locale loc(std::locale(), new numpunct<char>());
|
||||||
EXPECT_EQ("1?23", fmt::format(loc, "{:n}", 1.23));
|
EXPECT_EQ("1?23", fmt::format(loc, "{:L}", 1.23));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(LocaleTest, Format) {
|
TEST(LocaleTest, Format) {
|
||||||
std::locale loc(std::locale(), new numpunct<char>());
|
std::locale loc(std::locale(), new numpunct<char>());
|
||||||
EXPECT_EQ("1234567", fmt::format(std::locale(), "{:n}", 1234567));
|
EXPECT_EQ("1234567", fmt::format(std::locale(), "{:L}", 1234567));
|
||||||
EXPECT_EQ("1~234~567", fmt::format(loc, "{:n}", 1234567));
|
EXPECT_EQ("1~234~567", fmt::format(loc, "{:L}", 1234567));
|
||||||
|
EXPECT_EQ("-1~234~567", fmt::format(loc, "{:L}", -1234567));
|
||||||
fmt::format_arg_store<fmt::format_context, int> as{1234567};
|
fmt::format_arg_store<fmt::format_context, int> as{1234567};
|
||||||
EXPECT_EQ("1~234~567", fmt::vformat(loc, "{:n}", fmt::format_args(as)));
|
EXPECT_EQ("1~234~567", fmt::vformat(loc, "{:L}", fmt::format_args(as)));
|
||||||
std::string s;
|
std::string s;
|
||||||
fmt::format_to(std::back_inserter(s), loc, "{:n}", 1234567);
|
fmt::format_to(std::back_inserter(s), loc, "{:L}", 1234567);
|
||||||
EXPECT_EQ("1~234~567", s);
|
EXPECT_EQ("1~234~567", s);
|
||||||
|
|
||||||
std::locale no_grouping_loc(std::locale(), new no_grouping<char>());
|
std::locale no_grouping_loc(std::locale(), new no_grouping<char>());
|
||||||
EXPECT_EQ("1234567", fmt::format(no_grouping_loc, "{:n}", 1234567));
|
EXPECT_EQ("1234567", fmt::format(no_grouping_loc, "{:L}", 1234567));
|
||||||
|
|
||||||
std::locale special_grouping_loc(std::locale(), new special_grouping<char>());
|
std::locale special_grouping_loc(std::locale(), new special_grouping<char>());
|
||||||
EXPECT_EQ("1,23,45,678", fmt::format(special_grouping_loc, "{:n}", 12345678));
|
EXPECT_EQ("1,23,45,678", fmt::format(special_grouping_loc, "{:L}", 12345678));
|
||||||
|
EXPECT_EQ("12,345", fmt::format(special_grouping_loc, "{:L}", 12345));
|
||||||
|
|
||||||
std::locale small_grouping_loc(std::locale(), new small_grouping<char>());
|
std::locale small_grouping_loc(std::locale(), new small_grouping<char>());
|
||||||
EXPECT_EQ("4,2,9,4,9,6,7,2,9,5",
|
EXPECT_EQ("4,2,9,4,9,6,7,2,9,5",
|
||||||
fmt::format(small_grouping_loc, "{:n}", max_value<uint32_t>()));
|
fmt::format(small_grouping_loc, "{:L}", max_value<uint32_t>()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(LocaleTest, FormatDetaultAlign) {
|
||||||
|
std::locale special_grouping_loc(std::locale(), new special_grouping<char>());
|
||||||
|
EXPECT_EQ(" 12,345", fmt::format(special_grouping_loc, "{:8L}", 12345));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(LocaleTest, WFormat) {
|
TEST(LocaleTest, WFormat) {
|
||||||
std::locale loc(std::locale(), new numpunct<wchar_t>());
|
std::locale loc(std::locale(), new numpunct<wchar_t>());
|
||||||
EXPECT_EQ(L"1234567", fmt::format(std::locale(), L"{:n}", 1234567));
|
EXPECT_EQ(L"1234567", fmt::format(std::locale(), L"{:L}", 1234567));
|
||||||
EXPECT_EQ(L"1~234~567", fmt::format(loc, L"{:n}", 1234567));
|
EXPECT_EQ(L"1~234~567", fmt::format(loc, L"{:L}", 1234567));
|
||||||
fmt::format_arg_store<fmt::wformat_context, int> as{1234567};
|
fmt::format_arg_store<fmt::wformat_context, int> as{1234567};
|
||||||
EXPECT_EQ(L"1~234~567", fmt::vformat(loc, L"{:n}", fmt::wformat_args(as)));
|
EXPECT_EQ(L"1~234~567", fmt::vformat(loc, L"{:L}", fmt::wformat_args(as)));
|
||||||
EXPECT_EQ(L"1234567", fmt::format(std::locale("C"), L"{:n}", 1234567));
|
EXPECT_EQ(L"1234567", fmt::format(std::locale("C"), L"{:L}", 1234567));
|
||||||
|
|
||||||
std::locale no_grouping_loc(std::locale(), new no_grouping<wchar_t>());
|
std::locale no_grouping_loc(std::locale(), new no_grouping<wchar_t>());
|
||||||
EXPECT_EQ(L"1234567", fmt::format(no_grouping_loc, L"{:n}", 1234567));
|
EXPECT_EQ(L"1234567", fmt::format(no_grouping_loc, L"{:L}", 1234567));
|
||||||
|
|
||||||
std::locale special_grouping_loc(std::locale(),
|
std::locale special_grouping_loc(std::locale(),
|
||||||
new special_grouping<wchar_t>());
|
new special_grouping<wchar_t>());
|
||||||
EXPECT_EQ(L"1,23,45,678",
|
EXPECT_EQ(L"1,23,45,678",
|
||||||
fmt::format(special_grouping_loc, L"{:n}", 12345678));
|
fmt::format(special_grouping_loc, L"{:L}", 12345678));
|
||||||
|
|
||||||
std::locale small_grouping_loc(std::locale(), new small_grouping<wchar_t>());
|
std::locale small_grouping_loc(std::locale(), new small_grouping<wchar_t>());
|
||||||
EXPECT_EQ(L"4,2,9,4,9,6,7,2,9,5",
|
EXPECT_EQ(L"4,2,9,4,9,6,7,2,9,5",
|
||||||
fmt::format(small_grouping_loc, L"{:n}", max_value<uint32_t>()));
|
fmt::format(small_grouping_loc, L"{:L}", max_value<uint32_t>()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(LocaleTest, DoubleFormatter) {
|
||||||
|
auto loc = std::locale(std::locale(), new special_grouping<char>());
|
||||||
|
auto f = fmt::formatter<int>();
|
||||||
|
auto parse_ctx = fmt::format_parse_context("L");
|
||||||
|
f.parse(parse_ctx);
|
||||||
|
char buf[10] = {};
|
||||||
|
fmt::basic_format_context<char*, char> format_ctx(
|
||||||
|
buf, {}, fmt::detail::locale_ref(loc));
|
||||||
|
*f.format(12345, format_ctx) = 0;
|
||||||
|
EXPECT_STREQ("12,345", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FMT_STATIC_THOUSANDS_SEPARATOR
|
#endif // FMT_STATIC_THOUSANDS_SEPARATOR
|
||||||
|
@ -16,8 +16,8 @@ template <typename T> class mock_allocator {
|
|||||||
mock_allocator() {}
|
mock_allocator() {}
|
||||||
mock_allocator(const mock_allocator&) {}
|
mock_allocator(const mock_allocator&) {}
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
MOCK_METHOD1_T(allocate, T*(std::size_t n));
|
MOCK_METHOD1_T(allocate, T*(size_t n));
|
||||||
MOCK_METHOD2_T(deallocate, void(T* p, std::size_t n));
|
MOCK_METHOD2_T(deallocate, void(T* p, size_t n));
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Allocator> class allocator_ref {
|
template <typename Allocator> class allocator_ref {
|
||||||
@ -51,10 +51,10 @@ template <typename Allocator> class allocator_ref {
|
|||||||
public:
|
public:
|
||||||
Allocator* get() const { return alloc_; }
|
Allocator* get() const { return alloc_; }
|
||||||
|
|
||||||
value_type* allocate(std::size_t n) {
|
value_type* allocate(size_t n) {
|
||||||
return std::allocator_traits<Allocator>::allocate(*alloc_, n);
|
return std::allocator_traits<Allocator>::allocate(*alloc_, n);
|
||||||
}
|
}
|
||||||
void deallocate(value_type* p, std::size_t n) { alloc_->deallocate(p, n); }
|
void deallocate(value_type* p, size_t n) { alloc_->deallocate(p, n); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FMT_MOCK_ALLOCATOR_H_
|
#endif // FMT_MOCK_ALLOCATOR_H_
|
||||||
|
102
externals/dynarmic/externals/fmt/test/os-test.cc
vendored
102
externals/dynarmic/externals/fmt/test/os-test.cc
vendored
@ -5,11 +5,12 @@
|
|||||||
//
|
//
|
||||||
// For the license information refer to format.h.
|
// For the license information refer to format.h.
|
||||||
|
|
||||||
|
#include "fmt/os.h"
|
||||||
|
|
||||||
#include <cstdlib> // std::exit
|
#include <cstdlib> // std::exit
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "fmt/os.h"
|
|
||||||
#include "gtest-extra.h"
|
#include "gtest-extra.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@ -26,14 +27,14 @@ using fmt::error_code;
|
|||||||
|
|
||||||
TEST(UtilTest, UTF16ToUTF8) {
|
TEST(UtilTest, UTF16ToUTF8) {
|
||||||
std::string s = "ёжик";
|
std::string s = "ёжик";
|
||||||
fmt::internal::utf16_to_utf8 u(L"\x0451\x0436\x0438\x043A");
|
fmt::detail::utf16_to_utf8 u(L"\x0451\x0436\x0438\x043A");
|
||||||
EXPECT_EQ(s, u.str());
|
EXPECT_EQ(s, u.str());
|
||||||
EXPECT_EQ(s.size(), u.size());
|
EXPECT_EQ(s.size(), u.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UtilTest, UTF16ToUTF8EmptyString) {
|
TEST(UtilTest, UTF16ToUTF8EmptyString) {
|
||||||
std::string s = "";
|
std::string s = "";
|
||||||
fmt::internal::utf16_to_utf8 u(L"");
|
fmt::detail::utf16_to_utf8 u(L"");
|
||||||
EXPECT_EQ(s, u.str());
|
EXPECT_EQ(s, u.str());
|
||||||
EXPECT_EQ(s.size(), u.size());
|
EXPECT_EQ(s.size(), u.size());
|
||||||
}
|
}
|
||||||
@ -43,7 +44,7 @@ void check_utf_conversion_error(
|
|||||||
const char* message,
|
const char* message,
|
||||||
fmt::basic_string_view<Char> str = fmt::basic_string_view<Char>(0, 1)) {
|
fmt::basic_string_view<Char> str = fmt::basic_string_view<Char>(0, 1)) {
|
||||||
fmt::memory_buffer out;
|
fmt::memory_buffer out;
|
||||||
fmt::internal::format_windows_error(out, ERROR_INVALID_PARAMETER, message);
|
fmt::detail::format_windows_error(out, ERROR_INVALID_PARAMETER, message);
|
||||||
fmt::system_error error(0, "");
|
fmt::system_error error(0, "");
|
||||||
try {
|
try {
|
||||||
(Converter)(str);
|
(Converter)(str);
|
||||||
@ -55,12 +56,12 @@ void check_utf_conversion_error(
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(UtilTest, UTF16ToUTF8Error) {
|
TEST(UtilTest, UTF16ToUTF8Error) {
|
||||||
check_utf_conversion_error<fmt::internal::utf16_to_utf8, wchar_t>(
|
check_utf_conversion_error<fmt::detail::utf16_to_utf8, wchar_t>(
|
||||||
"cannot convert string from UTF-16 to UTF-8");
|
"cannot convert string from UTF-16 to UTF-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UtilTest, UTF16ToUTF8Convert) {
|
TEST(UtilTest, UTF16ToUTF8Convert) {
|
||||||
fmt::internal::utf16_to_utf8 u;
|
fmt::detail::utf16_to_utf8 u;
|
||||||
EXPECT_EQ(ERROR_INVALID_PARAMETER, u.convert(fmt::wstring_view(0, 1)));
|
EXPECT_EQ(ERROR_INVALID_PARAMETER, u.convert(fmt::wstring_view(0, 1)));
|
||||||
EXPECT_EQ(ERROR_INVALID_PARAMETER,
|
EXPECT_EQ(ERROR_INVALID_PARAMETER,
|
||||||
u.convert(fmt::wstring_view(L"foo", INT_MAX + 1u)));
|
u.convert(fmt::wstring_view(L"foo", INT_MAX + 1u)));
|
||||||
@ -73,17 +74,16 @@ TEST(UtilTest, FormatWindowsError) {
|
|||||||
0, ERROR_FILE_EXISTS,
|
0, ERROR_FILE_EXISTS,
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
reinterpret_cast<LPWSTR>(&message), 0, 0);
|
reinterpret_cast<LPWSTR>(&message), 0, 0);
|
||||||
fmt::internal::utf16_to_utf8 utf8_message(message);
|
fmt::detail::utf16_to_utf8 utf8_message(message);
|
||||||
LocalFree(message);
|
LocalFree(message);
|
||||||
fmt::memory_buffer actual_message;
|
fmt::memory_buffer actual_message;
|
||||||
fmt::internal::format_windows_error(actual_message, ERROR_FILE_EXISTS,
|
fmt::detail::format_windows_error(actual_message, ERROR_FILE_EXISTS, "test");
|
||||||
"test");
|
|
||||||
EXPECT_EQ(fmt::format("test: {}", utf8_message.str()),
|
EXPECT_EQ(fmt::format("test: {}", utf8_message.str()),
|
||||||
fmt::to_string(actual_message));
|
fmt::to_string(actual_message));
|
||||||
actual_message.resize(0);
|
actual_message.resize(0);
|
||||||
auto max_size = fmt::internal::max_value<size_t>();
|
auto max_size = fmt::detail::max_value<size_t>();
|
||||||
fmt::internal::format_windows_error(actual_message, ERROR_FILE_EXISTS,
|
fmt::detail::format_windows_error(actual_message, ERROR_FILE_EXISTS,
|
||||||
fmt::string_view(0, max_size));
|
fmt::string_view(0, max_size));
|
||||||
EXPECT_EQ(fmt::format("error {}", ERROR_FILE_EXISTS),
|
EXPECT_EQ(fmt::format("error {}", ERROR_FILE_EXISTS),
|
||||||
fmt::to_string(actual_message));
|
fmt::to_string(actual_message));
|
||||||
}
|
}
|
||||||
@ -103,11 +103,11 @@ TEST(UtilTest, FormatLongWindowsError) {
|
|||||||
reinterpret_cast<LPWSTR>(&message), 0, 0) == 0) {
|
reinterpret_cast<LPWSTR>(&message), 0, 0) == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fmt::internal::utf16_to_utf8 utf8_message(message);
|
fmt::detail::utf16_to_utf8 utf8_message(message);
|
||||||
LocalFree(message);
|
LocalFree(message);
|
||||||
fmt::memory_buffer actual_message;
|
fmt::memory_buffer actual_message;
|
||||||
fmt::internal::format_windows_error(actual_message, provisioning_not_allowed,
|
fmt::detail::format_windows_error(actual_message, provisioning_not_allowed,
|
||||||
"test");
|
"test");
|
||||||
EXPECT_EQ(fmt::format("test: {}", utf8_message.str()),
|
EXPECT_EQ(fmt::format("test: {}", utf8_message.str()),
|
||||||
fmt::to_string(actual_message));
|
fmt::to_string(actual_message));
|
||||||
}
|
}
|
||||||
@ -120,14 +120,14 @@ TEST(UtilTest, WindowsError) {
|
|||||||
error = e;
|
error = e;
|
||||||
}
|
}
|
||||||
fmt::memory_buffer message;
|
fmt::memory_buffer message;
|
||||||
fmt::internal::format_windows_error(message, ERROR_FILE_EXISTS, "test error");
|
fmt::detail::format_windows_error(message, ERROR_FILE_EXISTS, "test error");
|
||||||
EXPECT_EQ(to_string(message), error.what());
|
EXPECT_EQ(to_string(message), error.what());
|
||||||
EXPECT_EQ(ERROR_FILE_EXISTS, error.error_code());
|
EXPECT_EQ(ERROR_FILE_EXISTS, error.error_code());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UtilTest, ReportWindowsError) {
|
TEST(UtilTest, ReportWindowsError) {
|
||||||
fmt::memory_buffer out;
|
fmt::memory_buffer out;
|
||||||
fmt::internal::format_windows_error(out, ERROR_FILE_EXISTS, "test error");
|
fmt::detail::format_windows_error(out, ERROR_FILE_EXISTS, "test error");
|
||||||
out.push_back('\n');
|
out.push_back('\n');
|
||||||
EXPECT_WRITE(stderr,
|
EXPECT_WRITE(stderr,
|
||||||
fmt::report_windows_error(ERROR_FILE_EXISTS, "test error"),
|
fmt::report_windows_error(ERROR_FILE_EXISTS, "test error"),
|
||||||
@ -164,10 +164,10 @@ static file open_file() {
|
|||||||
|
|
||||||
// Attempts to write a string to a file.
|
// Attempts to write a string to a file.
|
||||||
static void write(file& f, fmt::string_view s) {
|
static void write(file& f, fmt::string_view s) {
|
||||||
std::size_t num_chars_left = s.size();
|
size_t num_chars_left = s.size();
|
||||||
const char* ptr = s.data();
|
const char* ptr = s.data();
|
||||||
do {
|
do {
|
||||||
std::size_t count = f.write(ptr, num_chars_left);
|
size_t count = f.write(ptr, num_chars_left);
|
||||||
ptr += count;
|
ptr += count;
|
||||||
// We can't write more than size_t bytes since num_chars_left
|
// We can't write more than size_t bytes since num_chars_left
|
||||||
// has type size_t.
|
// has type size_t.
|
||||||
@ -238,16 +238,17 @@ TEST(BufferedFileTest, CloseFileInDtor) {
|
|||||||
|
|
||||||
TEST(BufferedFileTest, CloseErrorInDtor) {
|
TEST(BufferedFileTest, CloseErrorInDtor) {
|
||||||
std::unique_ptr<buffered_file> f(new buffered_file(open_buffered_file()));
|
std::unique_ptr<buffered_file> f(new buffered_file(open_buffered_file()));
|
||||||
EXPECT_WRITE(stderr,
|
EXPECT_WRITE(
|
||||||
{
|
stderr,
|
||||||
// The close function must be called inside EXPECT_WRITE,
|
{
|
||||||
// otherwise the system may recycle closed file descriptor when
|
// The close function must be called inside EXPECT_WRITE,
|
||||||
// redirecting the output in EXPECT_STDERR and the second close
|
// otherwise the system may recycle closed file descriptor when
|
||||||
// will break output redirection.
|
// redirecting the output in EXPECT_STDERR and the second close
|
||||||
FMT_POSIX(close(f->fileno()));
|
// will break output redirection.
|
||||||
SUPPRESS_ASSERT(f.reset(nullptr));
|
FMT_POSIX(close(f->fileno()));
|
||||||
},
|
SUPPRESS_ASSERT(f.reset(nullptr));
|
||||||
format_system_error(EBADF, "cannot close file") + "\n");
|
},
|
||||||
|
format_system_error(EBADF, "cannot close file") + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BufferedFileTest, Close) {
|
TEST(BufferedFileTest, Close) {
|
||||||
@ -286,6 +287,26 @@ TEST(BufferedFileTest, Fileno) {
|
|||||||
EXPECT_READ(copy, FILE_CONTENT);
|
EXPECT_READ(copy, FILE_CONTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(DirectBufferedFileTest, Print) {
|
||||||
|
fmt::direct_buffered_file out(
|
||||||
|
"test-file", fmt::file::WRONLY | fmt::file::CREATE);
|
||||||
|
fmt::print(out, "The answer is {}.\n", 42);
|
||||||
|
out.close();
|
||||||
|
file in("test-file", file::RDONLY);
|
||||||
|
EXPECT_READ(in, "The answer is 42.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DirectBufferedFileTest, BufferBoundary) {
|
||||||
|
auto str = std::string(4096, 'x');
|
||||||
|
fmt::direct_buffered_file out(
|
||||||
|
"test-file", fmt::file::WRONLY | fmt::file::CREATE);
|
||||||
|
fmt::print(out, "{}", str);
|
||||||
|
fmt::print(out, "{}", str);
|
||||||
|
out.close();
|
||||||
|
file in("test-file", file::RDONLY);
|
||||||
|
EXPECT_READ(in, str + str);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(FileTest, DefaultCtor) {
|
TEST(FileTest, DefaultCtor) {
|
||||||
file f;
|
file f;
|
||||||
EXPECT_EQ(-1, f.descriptor());
|
EXPECT_EQ(-1, f.descriptor());
|
||||||
@ -369,16 +390,17 @@ TEST(FileTest, CloseFileInDtor) {
|
|||||||
|
|
||||||
TEST(FileTest, CloseErrorInDtor) {
|
TEST(FileTest, CloseErrorInDtor) {
|
||||||
std::unique_ptr<file> f(new file(open_file()));
|
std::unique_ptr<file> f(new file(open_file()));
|
||||||
EXPECT_WRITE(stderr,
|
EXPECT_WRITE(
|
||||||
{
|
stderr,
|
||||||
// The close function must be called inside EXPECT_WRITE,
|
{
|
||||||
// otherwise the system may recycle closed file descriptor when
|
// The close function must be called inside EXPECT_WRITE,
|
||||||
// redirecting the output in EXPECT_STDERR and the second close
|
// otherwise the system may recycle closed file descriptor when
|
||||||
// will break output redirection.
|
// redirecting the output in EXPECT_STDERR and the second close
|
||||||
FMT_POSIX(close(f->descriptor()));
|
// will break output redirection.
|
||||||
SUPPRESS_ASSERT(f.reset(nullptr));
|
FMT_POSIX(close(f->descriptor()));
|
||||||
},
|
SUPPRESS_ASSERT(f.reset(nullptr));
|
||||||
format_system_error(EBADF, "cannot close file") + "\n");
|
},
|
||||||
|
format_system_error(EBADF, "cannot close file") + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FileTest, Close) {
|
TEST(FileTest, Close) {
|
||||||
@ -495,4 +517,4 @@ TEST(LocaleTest, Strtod) {
|
|||||||
EXPECT_EQ(start + 3, ptr);
|
EXPECT_EQ(start + 3, ptr);
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
#endif // FMT_USE_FCNTL
|
#endif // FMT_USE_FCNTL
|
||||||
|
@ -21,9 +21,9 @@ template <> struct formatter<test> : formatter<int> {
|
|||||||
};
|
};
|
||||||
} // namespace fmt
|
} // namespace fmt
|
||||||
|
|
||||||
#include "fmt/ostream.h"
|
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "fmt/ostream.h"
|
||||||
#include "gmock.h"
|
#include "gmock.h"
|
||||||
#include "gtest-extra.h"
|
#include "gtest-extra.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@ -64,22 +64,23 @@ TEST(OStreamTest, Enum) {
|
|||||||
EXPECT_EQ(L"0", fmt::format(L"{}", unstreamable_enum()));
|
EXPECT_EQ(L"0", fmt::format(L"{}", unstreamable_enum()));
|
||||||
}
|
}
|
||||||
|
|
||||||
using range = fmt::buffer_range<char>;
|
struct test_arg_formatter
|
||||||
|
: fmt::detail::arg_formatter<fmt::format_context::iterator, char> {
|
||||||
struct test_arg_formatter : fmt::arg_formatter<range> {
|
|
||||||
fmt::format_parse_context parse_ctx;
|
fmt::format_parse_context parse_ctx;
|
||||||
test_arg_formatter(fmt::format_context& ctx, fmt::format_specs& s)
|
test_arg_formatter(fmt::format_context& ctx, fmt::format_specs& s)
|
||||||
: fmt::arg_formatter<range>(ctx, &parse_ctx, &s), parse_ctx("") {}
|
: fmt::detail::arg_formatter<fmt::format_context::iterator, char>(
|
||||||
|
ctx, &parse_ctx, &s),
|
||||||
|
parse_ctx("") {}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(OStreamTest, CustomArg) {
|
TEST(OStreamTest, CustomArg) {
|
||||||
fmt::memory_buffer buffer;
|
fmt::memory_buffer buffer;
|
||||||
fmt::internal::buffer<char>& base = buffer;
|
fmt::detail::buffer<char>& base = buffer;
|
||||||
fmt::format_context ctx(std::back_inserter(base), fmt::format_args());
|
fmt::format_context ctx(std::back_inserter(base), fmt::format_args());
|
||||||
fmt::format_specs spec;
|
fmt::format_specs spec;
|
||||||
test_arg_formatter af(ctx, spec);
|
test_arg_formatter af(ctx, spec);
|
||||||
fmt::visit_format_arg(
|
fmt::visit_format_arg(
|
||||||
af, fmt::internal::make_arg<fmt::format_context>(streamable_enum()));
|
af, fmt::detail::make_arg<fmt::format_context>(streamable_enum()));
|
||||||
EXPECT_EQ("streamable_enum", std::string(buffer.data(), buffer.size()));
|
EXPECT_EQ("streamable_enum", std::string(buffer.data(), buffer.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +96,7 @@ TEST(OStreamTest, Format) {
|
|||||||
TEST(OStreamTest, FormatSpecs) {
|
TEST(OStreamTest, FormatSpecs) {
|
||||||
EXPECT_EQ("def ", format("{0:<5}", TestString("def")));
|
EXPECT_EQ("def ", format("{0:<5}", TestString("def")));
|
||||||
EXPECT_EQ(" def", format("{0:>5}", TestString("def")));
|
EXPECT_EQ(" def", format("{0:>5}", TestString("def")));
|
||||||
#if FMT_NUMERIC_ALIGN
|
#if FMT_DEPRECATED_NUMERIC_ALIGN
|
||||||
EXPECT_THROW_MSG(format("{0:=5}", TestString("def")), format_error,
|
EXPECT_THROW_MSG(format("{0:=5}", TestString("def")), format_error,
|
||||||
"format specifier requires numeric argument");
|
"format specifier requires numeric argument");
|
||||||
#endif
|
#endif
|
||||||
@ -140,18 +141,18 @@ TEST(OStreamTest, WriteToOStream) {
|
|||||||
fmt::memory_buffer buffer;
|
fmt::memory_buffer buffer;
|
||||||
const char* foo = "foo";
|
const char* foo = "foo";
|
||||||
buffer.append(foo, foo + std::strlen(foo));
|
buffer.append(foo, foo + std::strlen(foo));
|
||||||
fmt::internal::write(os, buffer);
|
fmt::detail::write_buffer(os, buffer);
|
||||||
EXPECT_EQ("foo", os.str());
|
EXPECT_EQ("foo", os.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(OStreamTest, WriteToOStreamMaxSize) {
|
TEST(OStreamTest, WriteToOStreamMaxSize) {
|
||||||
std::size_t max_size = fmt::internal::max_value<std::size_t>();
|
size_t max_size = fmt::detail::max_value<size_t>();
|
||||||
std::streamsize max_streamsize = fmt::internal::max_value<std::streamsize>();
|
std::streamsize max_streamsize = fmt::detail::max_value<std::streamsize>();
|
||||||
if (max_size <= fmt::internal::to_unsigned(max_streamsize)) return;
|
if (max_size <= fmt::detail::to_unsigned(max_streamsize)) return;
|
||||||
|
|
||||||
struct test_buffer : fmt::internal::buffer<char> {
|
struct test_buffer : fmt::detail::buffer<char> {
|
||||||
explicit test_buffer(std::size_t size) { resize(size); }
|
explicit test_buffer(size_t size) { resize(size); }
|
||||||
void grow(std::size_t) {}
|
void grow(size_t) {}
|
||||||
} buffer(max_size);
|
} buffer(max_size);
|
||||||
|
|
||||||
struct mock_streambuf : std::streambuf {
|
struct mock_streambuf : std::streambuf {
|
||||||
@ -171,13 +172,13 @@ TEST(OStreamTest, WriteToOStreamMaxSize) {
|
|||||||
typedef std::make_unsigned<std::streamsize>::type ustreamsize;
|
typedef std::make_unsigned<std::streamsize>::type ustreamsize;
|
||||||
ustreamsize size = max_size;
|
ustreamsize size = max_size;
|
||||||
do {
|
do {
|
||||||
auto n = std::min(size, fmt::internal::to_unsigned(max_streamsize));
|
auto n = std::min(size, fmt::detail::to_unsigned(max_streamsize));
|
||||||
EXPECT_CALL(streambuf, xsputn(data, static_cast<std::streamsize>(n)))
|
EXPECT_CALL(streambuf, xsputn(data, static_cast<std::streamsize>(n)))
|
||||||
.WillOnce(testing::Return(max_streamsize));
|
.WillOnce(testing::Return(max_streamsize));
|
||||||
data += n;
|
data += n;
|
||||||
size -= n;
|
size -= n;
|
||||||
} while (size != 0);
|
} while (size != 0);
|
||||||
fmt::internal::write(os, buffer);
|
fmt::detail::write_buffer(os, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(OStreamTest, Join) {
|
TEST(OStreamTest, Join) {
|
||||||
@ -258,7 +259,7 @@ TEST(OStreamTest, DisableBuiltinOStreamOperators) {
|
|||||||
struct explicitly_convertible_to_string_like {
|
struct explicitly_convertible_to_string_like {
|
||||||
template <typename String,
|
template <typename String,
|
||||||
typename = typename std::enable_if<std::is_constructible<
|
typename = typename std::enable_if<std::is_constructible<
|
||||||
String, const char*, std::size_t>::value>::type>
|
String, const char*, size_t>::value>::type>
|
||||||
explicit operator String() const {
|
explicit operator String() const {
|
||||||
return String("foo", 3u);
|
return String("foo", 3u);
|
||||||
}
|
}
|
||||||
@ -269,13 +270,13 @@ std::ostream& operator<<(std::ostream& os,
|
|||||||
return os << "bar";
|
return os << "bar";
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, FormatExplicitlyConvertibleToStringLike) {
|
TEST(OStreamTest, FormatExplicitlyConvertibleToStringLike) {
|
||||||
EXPECT_EQ("bar", fmt::format("{}", explicitly_convertible_to_string_like()));
|
EXPECT_EQ("bar", fmt::format("{}", explicitly_convertible_to_string_like()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FMT_USE_STRING_VIEW
|
#ifdef FMT_USE_STRING_VIEW
|
||||||
struct explicitly_convertible_to_std_string_view {
|
struct explicitly_convertible_to_std_string_view {
|
||||||
explicit operator fmt::internal::std_string_view<char>() const {
|
explicit operator fmt::detail::std_string_view<char>() const {
|
||||||
return {"foo", 3u};
|
return {"foo", 3u};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -285,8 +286,24 @@ std::ostream& operator<<(std::ostream& os,
|
|||||||
return os << "bar";
|
return os << "bar";
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, FormatExplicitlyConvertibleToStdStringView) {
|
TEST(OStreamTest, FormatExplicitlyConvertibleToStdStringView) {
|
||||||
EXPECT_EQ("bar", fmt::format("{}", explicitly_convertible_to_string_like()));
|
EXPECT_EQ("bar", fmt::format("{}", explicitly_convertible_to_string_like()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FMT_USE_STRING_VIEW
|
#endif // FMT_USE_STRING_VIEW
|
||||||
|
|
||||||
|
struct copyfmt_test {};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, copyfmt_test) {
|
||||||
|
std::ios ios(nullptr);
|
||||||
|
ios.copyfmt(os);
|
||||||
|
return os << "foo";
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(OStreamTest, CopyFmt) {
|
||||||
|
EXPECT_EQ("foo", fmt::format("{}", copyfmt_test()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(OStreamTest, CompileTimeString) {
|
||||||
|
EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), 42));
|
||||||
|
}
|
||||||
|
@ -49,8 +49,8 @@ int pipe_count;
|
|||||||
int fopen_count;
|
int fopen_count;
|
||||||
int fclose_count;
|
int fclose_count;
|
||||||
int fileno_count;
|
int fileno_count;
|
||||||
std::size_t read_nbyte;
|
size_t read_nbyte;
|
||||||
std::size_t write_nbyte;
|
size_t write_nbyte;
|
||||||
bool sysconf_error;
|
bool sysconf_error;
|
||||||
|
|
||||||
enum { NONE, MAX_SIZE, ERROR } fstat_sim;
|
enum { NONE, MAX_SIZE, ERROR } fstat_sim;
|
||||||
@ -261,8 +261,8 @@ TEST(FileTest, Size) {
|
|||||||
EXPECT_EQ(content.size(), static_cast<unsigned long long>(f.size()));
|
EXPECT_EQ(content.size(), static_cast<unsigned long long>(f.size()));
|
||||||
# ifdef _WIN32
|
# ifdef _WIN32
|
||||||
fmt::memory_buffer message;
|
fmt::memory_buffer message;
|
||||||
fmt::internal::format_windows_error(message, ERROR_ACCESS_DENIED,
|
fmt::detail::format_windows_error(message, ERROR_ACCESS_DENIED,
|
||||||
"cannot get file size");
|
"cannot get file size");
|
||||||
fstat_sim = ERROR;
|
fstat_sim = ERROR;
|
||||||
EXPECT_THROW_MSG(f.size(), fmt::windows_error, fmt::to_string(message));
|
EXPECT_THROW_MSG(f.size(), fmt::windows_error, fmt::to_string(message));
|
||||||
fstat_sim = NONE;
|
fstat_sim = NONE;
|
||||||
@ -288,7 +288,7 @@ TEST(FileTest, ReadRetry) {
|
|||||||
write_end.write("test", SIZE);
|
write_end.write("test", SIZE);
|
||||||
write_end.close();
|
write_end.close();
|
||||||
char buffer[SIZE];
|
char buffer[SIZE];
|
||||||
std::size_t count = 0;
|
size_t count = 0;
|
||||||
EXPECT_RETRY(count = read_end.read(buffer, SIZE), read,
|
EXPECT_RETRY(count = read_end.read(buffer, SIZE), read,
|
||||||
"cannot read from file");
|
"cannot read from file");
|
||||||
EXPECT_EQ_POSIX(static_cast<std::streamsize>(SIZE), count);
|
EXPECT_EQ_POSIX(static_cast<std::streamsize>(SIZE), count);
|
||||||
@ -298,7 +298,7 @@ TEST(FileTest, WriteRetry) {
|
|||||||
file read_end, write_end;
|
file read_end, write_end;
|
||||||
file::pipe(read_end, write_end);
|
file::pipe(read_end, write_end);
|
||||||
enum { SIZE = 4 };
|
enum { SIZE = 4 };
|
||||||
std::size_t count = 0;
|
size_t count = 0;
|
||||||
EXPECT_RETRY(count = write_end.write("test", SIZE), write,
|
EXPECT_RETRY(count = write_end.write("test", SIZE), write,
|
||||||
"cannot write to file");
|
"cannot write to file");
|
||||||
write_end.close();
|
write_end.close();
|
||||||
@ -316,8 +316,8 @@ TEST(FileTest, ConvertReadCount) {
|
|||||||
file read_end, write_end;
|
file read_end, write_end;
|
||||||
file::pipe(read_end, write_end);
|
file::pipe(read_end, write_end);
|
||||||
char c;
|
char c;
|
||||||
std::size_t size = UINT_MAX;
|
size_t size = UINT_MAX;
|
||||||
if (sizeof(unsigned) != sizeof(std::size_t)) ++size;
|
if (sizeof(unsigned) != sizeof(size_t)) ++size;
|
||||||
read_count = 1;
|
read_count = 1;
|
||||||
read_nbyte = 0;
|
read_nbyte = 0;
|
||||||
EXPECT_THROW(read_end.read(&c, size), fmt::system_error);
|
EXPECT_THROW(read_end.read(&c, size), fmt::system_error);
|
||||||
@ -329,8 +329,8 @@ TEST(FileTest, ConvertWriteCount) {
|
|||||||
file read_end, write_end;
|
file read_end, write_end;
|
||||||
file::pipe(read_end, write_end);
|
file::pipe(read_end, write_end);
|
||||||
char c;
|
char c;
|
||||||
std::size_t size = UINT_MAX;
|
size_t size = UINT_MAX;
|
||||||
if (sizeof(unsigned) != sizeof(std::size_t)) ++size;
|
if (sizeof(unsigned) != sizeof(size_t)) ++size;
|
||||||
write_count = 1;
|
write_count = 1;
|
||||||
write_nbyte = 0;
|
write_nbyte = 0;
|
||||||
EXPECT_THROW(write_end.write(&c, size), fmt::system_error);
|
EXPECT_THROW(write_end.write(&c, size), fmt::system_error);
|
||||||
|
127
externals/dynarmic/externals/fmt/test/printf-test.cc
vendored
127
externals/dynarmic/externals/fmt/test/printf-test.cc
vendored
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
using fmt::format;
|
using fmt::format;
|
||||||
using fmt::format_error;
|
using fmt::format_error;
|
||||||
using fmt::internal::max_value;
|
using fmt::detail::max_value;
|
||||||
|
|
||||||
const unsigned BIG_NUM = INT_MAX + 1u;
|
const unsigned BIG_NUM = INT_MAX + 1u;
|
||||||
|
|
||||||
@ -113,14 +113,13 @@ TEST(PrintfTest, SwitchArgIndexing) {
|
|||||||
|
|
||||||
TEST(PrintfTest, InvalidArgIndex) {
|
TEST(PrintfTest, InvalidArgIndex) {
|
||||||
EXPECT_THROW_MSG(test_sprintf("%0$d", 42), format_error,
|
EXPECT_THROW_MSG(test_sprintf("%0$d", 42), format_error,
|
||||||
"argument index out of range");
|
"argument not found");
|
||||||
EXPECT_THROW_MSG(test_sprintf("%2$d", 42), format_error,
|
EXPECT_THROW_MSG(test_sprintf("%2$d", 42), format_error,
|
||||||
"argument index out of range");
|
"argument not found");
|
||||||
EXPECT_THROW_MSG(test_sprintf(format("%{}$d", INT_MAX), 42), format_error,
|
EXPECT_THROW_MSG(test_sprintf(format("%{}$d", INT_MAX), 42), format_error,
|
||||||
"argument index out of range");
|
"argument not found");
|
||||||
|
|
||||||
EXPECT_THROW_MSG(test_sprintf("%2$", 42), format_error,
|
EXPECT_THROW_MSG(test_sprintf("%2$", 42), format_error, "argument not found");
|
||||||
"argument index out of range");
|
|
||||||
EXPECT_THROW_MSG(test_sprintf(format("%{}$d", BIG_NUM), 42), format_error,
|
EXPECT_THROW_MSG(test_sprintf(format("%{}$d", BIG_NUM), 42), format_error,
|
||||||
"number is too big");
|
"number is too big");
|
||||||
}
|
}
|
||||||
@ -140,8 +139,11 @@ TEST(PrintfTest, ZeroFlag) {
|
|||||||
|
|
||||||
EXPECT_PRINTF("+00042", "%00+6d", 42);
|
EXPECT_PRINTF("+00042", "%00+6d", 42);
|
||||||
|
|
||||||
|
EXPECT_PRINTF(" 42", "%05.d", 42);
|
||||||
|
EXPECT_PRINTF(" 0042", "%05.4d", 42);
|
||||||
|
|
||||||
// '0' flag is ignored for non-numeric types.
|
// '0' flag is ignored for non-numeric types.
|
||||||
EXPECT_PRINTF("0000x", "%05c", 'x');
|
EXPECT_PRINTF(" x", "%05c", 'x');
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PrintfTest, PlusFlag) {
|
TEST(PrintfTest, PlusFlag) {
|
||||||
@ -152,11 +154,38 @@ TEST(PrintfTest, PlusFlag) {
|
|||||||
|
|
||||||
// '+' flag is ignored for non-numeric types.
|
// '+' flag is ignored for non-numeric types.
|
||||||
EXPECT_PRINTF("x", "%+c", 'x');
|
EXPECT_PRINTF("x", "%+c", 'x');
|
||||||
|
|
||||||
|
// '+' flag wins over space flag
|
||||||
|
EXPECT_PRINTF("+42", "%+ d", 42);
|
||||||
|
EXPECT_PRINTF("-42", "%+ d", -42);
|
||||||
|
EXPECT_PRINTF("+42", "% +d", 42);
|
||||||
|
EXPECT_PRINTF("-42", "% +d", -42);
|
||||||
|
EXPECT_PRINTF("+0042", "% +05d", 42);
|
||||||
|
EXPECT_PRINTF("+0042", "%0+ 5d", 42);
|
||||||
|
|
||||||
|
// '+' flag and space flag are both ignored for non-numeric types.
|
||||||
|
EXPECT_PRINTF("x", "%+ c", 'x');
|
||||||
|
EXPECT_PRINTF("x", "% +c", 'x');
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PrintfTest, MinusFlag) {
|
TEST(PrintfTest, MinusFlag) {
|
||||||
EXPECT_PRINTF("abc ", "%-5s", "abc");
|
EXPECT_PRINTF("abc ", "%-5s", "abc");
|
||||||
EXPECT_PRINTF("abc ", "%0--5s", "abc");
|
EXPECT_PRINTF("abc ", "%0--5s", "abc");
|
||||||
|
|
||||||
|
EXPECT_PRINTF("7 ", "%-5d", 7);
|
||||||
|
EXPECT_PRINTF("97 ", "%-5hhi", 'a');
|
||||||
|
EXPECT_PRINTF("a ", "%-5c", 'a');
|
||||||
|
|
||||||
|
// '0' flag is ignored if '-' flag is given
|
||||||
|
EXPECT_PRINTF("7 ", "%-05d", 7);
|
||||||
|
EXPECT_PRINTF("7 ", "%0-5d", 7);
|
||||||
|
EXPECT_PRINTF("a ", "%-05c", 'a');
|
||||||
|
EXPECT_PRINTF("a ", "%0-5c", 'a');
|
||||||
|
EXPECT_PRINTF("97 ", "%-05hhi", 'a');
|
||||||
|
EXPECT_PRINTF("97 ", "%0-5hhi", 'a');
|
||||||
|
|
||||||
|
// '-' and space flag don't interfere
|
||||||
|
EXPECT_PRINTF(" 42", "%- d", 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PrintfTest, SpaceFlag) {
|
TEST(PrintfTest, SpaceFlag) {
|
||||||
@ -222,8 +251,7 @@ TEST(PrintfTest, DynamicWidth) {
|
|||||||
EXPECT_EQ("42 ", test_sprintf("%*d", -5, 42));
|
EXPECT_EQ("42 ", test_sprintf("%*d", -5, 42));
|
||||||
EXPECT_THROW_MSG(test_sprintf("%*d", 5.0, 42), format_error,
|
EXPECT_THROW_MSG(test_sprintf("%*d", 5.0, 42), format_error,
|
||||||
"width is not integer");
|
"width is not integer");
|
||||||
EXPECT_THROW_MSG(test_sprintf("%*d"), format_error,
|
EXPECT_THROW_MSG(test_sprintf("%*d"), format_error, "argument not found");
|
||||||
"argument index out of range");
|
|
||||||
EXPECT_THROW_MSG(test_sprintf("%*d", BIG_NUM, 42), format_error,
|
EXPECT_THROW_MSG(test_sprintf("%*d", BIG_NUM, 42), format_error,
|
||||||
"number is too big");
|
"number is too big");
|
||||||
}
|
}
|
||||||
@ -259,6 +287,11 @@ TEST(PrintfTest, FloatPrecision) {
|
|||||||
EXPECT_PRINTF(buffer, "%.3a", 1234.5678);
|
EXPECT_PRINTF(buffer, "%.3a", 1234.5678);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(PrintfTest, StringPrecision) {
|
||||||
|
char test[] = {'H', 'e', 'l', 'l', 'o'};
|
||||||
|
EXPECT_EQ(fmt::sprintf("%.4s", test), "Hell");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(PrintfTest, IgnorePrecisionForNonNumericArg) {
|
TEST(PrintfTest, IgnorePrecisionForNonNumericArg) {
|
||||||
EXPECT_PRINTF("abc", "%.5s", "abc");
|
EXPECT_PRINTF("abc", "%.5s", "abc");
|
||||||
}
|
}
|
||||||
@ -268,8 +301,7 @@ TEST(PrintfTest, DynamicPrecision) {
|
|||||||
EXPECT_EQ("42", test_sprintf("%.*d", -5, 42));
|
EXPECT_EQ("42", test_sprintf("%.*d", -5, 42));
|
||||||
EXPECT_THROW_MSG(test_sprintf("%.*d", 5.0, 42), format_error,
|
EXPECT_THROW_MSG(test_sprintf("%.*d", 5.0, 42), format_error,
|
||||||
"precision is not integer");
|
"precision is not integer");
|
||||||
EXPECT_THROW_MSG(test_sprintf("%.*d"), format_error,
|
EXPECT_THROW_MSG(test_sprintf("%.*d"), format_error, "argument not found");
|
||||||
"argument index out of range");
|
|
||||||
EXPECT_THROW_MSG(test_sprintf("%.*d", BIG_NUM, 42), format_error,
|
EXPECT_THROW_MSG(test_sprintf("%.*d", BIG_NUM, 42), format_error,
|
||||||
"number is too big");
|
"number is too big");
|
||||||
if (sizeof(long long) != sizeof(int)) {
|
if (sizeof(long long) != sizeof(int)) {
|
||||||
@ -298,7 +330,7 @@ void TestLength(const char* length_spec, U value) {
|
|||||||
unsigned long long unsigned_value = 0;
|
unsigned long long unsigned_value = 0;
|
||||||
// Apply integer promotion to the argument.
|
// Apply integer promotion to the argument.
|
||||||
unsigned long long max = max_value<U>();
|
unsigned long long max = max_value<U>();
|
||||||
using fmt::internal::const_check;
|
using fmt::detail::const_check;
|
||||||
if (const_check(max <= static_cast<unsigned>(max_value<int>()))) {
|
if (const_check(max <= static_cast<unsigned>(max_value<int>()))) {
|
||||||
signed_value = static_cast<int>(value);
|
signed_value = static_cast<int>(value);
|
||||||
unsigned_value = static_cast<unsigned long long>(value);
|
unsigned_value = static_cast<unsigned long long>(value);
|
||||||
@ -367,7 +399,7 @@ TEST(PrintfTest, Length) {
|
|||||||
TestLength<long long>("ll");
|
TestLength<long long>("ll");
|
||||||
TestLength<unsigned long long>("ll");
|
TestLength<unsigned long long>("ll");
|
||||||
TestLength<intmax_t>("j");
|
TestLength<intmax_t>("j");
|
||||||
TestLength<std::size_t>("z");
|
TestLength<size_t>("z");
|
||||||
TestLength<std::ptrdiff_t>("t");
|
TestLength<std::ptrdiff_t>("t");
|
||||||
long double max = max_value<long double>();
|
long double max = max_value<long double>();
|
||||||
EXPECT_PRINTF(fmt::format("{:.6}", max), "%g", max);
|
EXPECT_PRINTF(fmt::format("{:.6}", max), "%g", max);
|
||||||
@ -447,6 +479,12 @@ TEST(PrintfTest, String) {
|
|||||||
EXPECT_PRINTF(L" (null)", L"%10s", null_wstr);
|
EXPECT_PRINTF(L" (null)", L"%10s", null_wstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(PrintfTest, UCharString) {
|
||||||
|
unsigned char str[] = "test";
|
||||||
|
unsigned char* pstr = str;
|
||||||
|
EXPECT_EQ("test", fmt::sprintf("%s", pstr));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(PrintfTest, Pointer) {
|
TEST(PrintfTest, Pointer) {
|
||||||
int n;
|
int n;
|
||||||
void* p = &n;
|
void* p = &n;
|
||||||
@ -502,9 +540,7 @@ TEST(PrintfTest, PrintfError) {
|
|||||||
TEST(PrintfTest, WideString) { EXPECT_EQ(L"abc", fmt::sprintf(L"%s", L"abc")); }
|
TEST(PrintfTest, WideString) { EXPECT_EQ(L"abc", fmt::sprintf(L"%s", L"abc")); }
|
||||||
|
|
||||||
TEST(PrintfTest, PrintfCustom) {
|
TEST(PrintfTest, PrintfCustom) {
|
||||||
// The test is disabled for now because it requires decoupling
|
EXPECT_EQ("abc", test_sprintf("%s", TestString("abc")));
|
||||||
// fallback_formatter::format from format_context.
|
|
||||||
//EXPECT_EQ("abc", test_sprintf("%s", TestString("abc")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PrintfTest, OStream) {
|
TEST(PrintfTest, OStream) {
|
||||||
@ -571,51 +607,22 @@ TEST(PrintfTest, VSPrintfMakeWArgsExample) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef fmt::printf_arg_formatter<fmt::buffer_range<char>> formatter_t;
|
TEST(PrintfTest, PrintfDetermineOutputSize) {
|
||||||
typedef fmt::basic_printf_context<formatter_t::iterator, char> context_t;
|
using backit = std::back_insert_iterator<std::vector<char>>;
|
||||||
|
using truncated_printf_context =
|
||||||
|
fmt::basic_printf_context<fmt::detail::truncating_iterator<backit>, char>;
|
||||||
|
|
||||||
// A custom printf argument formatter that doesn't print `-` for floating-point
|
auto v = std::vector<char>{};
|
||||||
// values rounded to 0.
|
auto it = std::back_inserter(v);
|
||||||
class custom_printf_arg_formatter : public formatter_t {
|
|
||||||
public:
|
|
||||||
using formatter_t::iterator;
|
|
||||||
|
|
||||||
custom_printf_arg_formatter(formatter_t::iterator iter,
|
const auto format_string = "%s";
|
||||||
formatter_t::format_specs& specs, context_t& ctx)
|
const auto format_arg = "Hello";
|
||||||
: formatter_t(iter, specs, ctx) {}
|
const auto expected_size = fmt::sprintf(format_string, format_arg).size();
|
||||||
|
|
||||||
using formatter_t::operator();
|
EXPECT_EQ((truncated_printf_context(
|
||||||
|
fmt::detail::truncating_iterator<backit>(it, 0), format_string,
|
||||||
#if FMT_MSC_VER > 0 && FMT_MSC_VER <= 1804
|
fmt::make_format_args<truncated_printf_context>(format_arg))
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
.format()
|
||||||
iterator operator()(T value){
|
.count()),
|
||||||
#else
|
expected_size);
|
||||||
iterator operator()(double value) {
|
|
||||||
#endif
|
|
||||||
// Comparing a float to 0.0 is safe.
|
|
||||||
if (round(value * pow(10, specs()->precision)) == 0.0) value = 0;
|
|
||||||
return formatter_t::operator()(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
typedef fmt::basic_format_args<context_t> format_args_t;
|
|
||||||
|
|
||||||
std::string custom_vformat(fmt::string_view format_str, format_args_t args) {
|
|
||||||
fmt::memory_buffer buffer;
|
|
||||||
fmt::vprintf<custom_printf_arg_formatter>(buffer, format_str, args);
|
|
||||||
return std::string(buffer.data(), buffer.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
std::string custom_format(const char* format_str, const Args&... args) {
|
|
||||||
auto va = fmt::make_printf_args(args...);
|
|
||||||
return custom_vformat(format_str, {va});
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(PrintfTest, CustomFormat) {
|
|
||||||
EXPECT_EQ("0.00", custom_format("%.2f", -.00001));
|
|
||||||
EXPECT_EQ("0.00", custom_format("%.2f", .00001));
|
|
||||||
EXPECT_EQ("1.00", custom_format("%.2f", 1.00001));
|
|
||||||
EXPECT_EQ("-1.00", custom_format("%.2f", -1.00001));
|
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ TEST(RangesTest, JoinInitializerList) {
|
|||||||
struct my_struct {
|
struct my_struct {
|
||||||
int32_t i;
|
int32_t i;
|
||||||
std::string str; // can throw
|
std::string str; // can throw
|
||||||
template <std::size_t N> decltype(auto) get() const noexcept {
|
template <size_t N> decltype(auto) get() const noexcept {
|
||||||
if constexpr (N == 0)
|
if constexpr (N == 0)
|
||||||
return i;
|
return i;
|
||||||
else if constexpr (N == 1)
|
else if constexpr (N == 1)
|
||||||
@ -87,16 +87,15 @@ struct my_struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t N> decltype(auto) get(const my_struct& s) noexcept {
|
template <size_t N> decltype(auto) get(const my_struct& s) noexcept {
|
||||||
return s.get<N>();
|
return s.get<N>();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
|
|
||||||
template <>
|
template <> struct tuple_size<my_struct> : std::integral_constant<size_t, 2> {};
|
||||||
struct tuple_size<my_struct> : std::integral_constant<std::size_t, 2> {};
|
|
||||||
|
|
||||||
template <std::size_t N> struct tuple_element<N, my_struct> {
|
template <size_t N> struct tuple_element<N, my_struct> {
|
||||||
using type = decltype(std::declval<my_struct>().get<N>());
|
using type = decltype(std::declval<my_struct>().get<N>());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -140,3 +139,17 @@ TEST(RangesTest, FormatStringLike) {
|
|||||||
EXPECT_EQ("foo", fmt::format("{}", string_like()));
|
EXPECT_EQ("foo", fmt::format("{}", string_like()));
|
||||||
}
|
}
|
||||||
#endif // FMT_USE_STRING_VIEW
|
#endif // FMT_USE_STRING_VIEW
|
||||||
|
|
||||||
|
struct zstring_sentinel {};
|
||||||
|
bool operator==(const char* p, zstring_sentinel) { return *p == '\0'; }
|
||||||
|
bool operator!=(const char* p, zstring_sentinel) { return *p != '\0'; }
|
||||||
|
struct zstring {
|
||||||
|
const char* p;
|
||||||
|
const char* begin() const { return p; }
|
||||||
|
zstring_sentinel end() const { return {}; }
|
||||||
|
};
|
||||||
|
TEST(RangesTest, JoinSentinel) {
|
||||||
|
zstring hello{"hello"};
|
||||||
|
EXPECT_EQ("{'h', 'e', 'l', 'l', 'o'}", fmt::format("{}", hello));
|
||||||
|
EXPECT_EQ("h_e_l_l_o", fmt::format("{}", fmt::join(hello, "_")));
|
||||||
|
}
|
||||||
|
@ -5,12 +5,14 @@
|
|||||||
//
|
//
|
||||||
// For the license information refer to format.h.
|
// For the license information refer to format.h.
|
||||||
|
|
||||||
|
#include "scan.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
#include "gmock.h"
|
#include "gmock.h"
|
||||||
#include "gtest-extra.h"
|
#include "gtest-extra.h"
|
||||||
#include "scan.h"
|
|
||||||
|
|
||||||
TEST(ScanTest, ReadText) {
|
TEST(ScanTest, ReadText) {
|
||||||
fmt::string_view s = "foo";
|
fmt::string_view s = "foo";
|
||||||
@ -73,7 +75,7 @@ template <> struct scanner<tm> {
|
|||||||
if (it != ctx.end() && *it == ':') ++it;
|
if (it != ctx.end() && *it == ':') ++it;
|
||||||
auto end = it;
|
auto end = it;
|
||||||
while (end != ctx.end() && *end != '}') ++end;
|
while (end != ctx.end() && *end != '}') ++end;
|
||||||
format.reserve(internal::to_unsigned(end - it + 1));
|
format.reserve(detail::to_unsigned(end - it + 1));
|
||||||
format.append(it, end);
|
format.append(it, end);
|
||||||
format.push_back('\0');
|
format.push_back('\0');
|
||||||
return end;
|
return end;
|
||||||
|
33
externals/dynarmic/externals/fmt/test/scan.h
vendored
33
externals/dynarmic/externals/fmt/test/scan.h
vendored
@ -31,7 +31,7 @@ class scan_parse_context {
|
|||||||
FMT_CONSTEXPR iterator end() const { return format_.end(); }
|
FMT_CONSTEXPR iterator end() const { return format_.end(); }
|
||||||
|
|
||||||
void advance_to(iterator it) {
|
void advance_to(iterator it) {
|
||||||
format_.remove_prefix(internal::to_unsigned(it - begin()));
|
format_.remove_prefix(detail::to_unsigned(it - begin()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -48,11 +48,11 @@ struct scan_context {
|
|||||||
iterator end() const { return begin() + input_.size(); }
|
iterator end() const { return begin() + input_.size(); }
|
||||||
|
|
||||||
void advance_to(iterator it) {
|
void advance_to(iterator it) {
|
||||||
input_.remove_prefix(internal::to_unsigned(it - begin()));
|
input_.remove_prefix(detail::to_unsigned(it - begin()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace internal {
|
namespace detail {
|
||||||
enum class scan_type {
|
enum class scan_type {
|
||||||
none_type,
|
none_type,
|
||||||
int_type,
|
int_type,
|
||||||
@ -107,20 +107,20 @@ class scan_arg {
|
|||||||
ctx.advance_to(s.scan(*static_cast<T*>(arg), ctx));
|
ctx.advance_to(s.scan(*static_cast<T*>(arg), ctx));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace internal
|
} // namespace detail
|
||||||
|
|
||||||
struct scan_args {
|
struct scan_args {
|
||||||
int size;
|
int size;
|
||||||
const internal::scan_arg* data;
|
const detail::scan_arg* data;
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
scan_args(const std::array<internal::scan_arg, N>& store)
|
scan_args(const std::array<detail::scan_arg, N>& store)
|
||||||
: size(N), data(store.data()) {
|
: size(N), data(store.data()) {
|
||||||
static_assert(N < INT_MAX, "too many arguments");
|
static_assert(N < INT_MAX, "too many arguments");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace internal {
|
namespace detail {
|
||||||
|
|
||||||
struct scan_handler : error_handler {
|
struct scan_handler : error_handler {
|
||||||
private:
|
private:
|
||||||
@ -169,14 +169,15 @@ struct scan_handler : error_handler {
|
|||||||
scan_ctx_.advance_to(it + size);
|
scan_ctx_.advance_to(it + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_arg_id() { on_arg_id(next_arg_id_++); }
|
int on_arg_id() { return on_arg_id(next_arg_id_++); }
|
||||||
void on_arg_id(int id) {
|
int on_arg_id(int id) {
|
||||||
if (id >= args_.size) on_error("argument index out of range");
|
if (id >= args_.size) on_error("argument index out of range");
|
||||||
arg_ = args_.data[id];
|
arg_ = args_.data[id];
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
void on_arg_id(string_view) { on_error("invalid format"); }
|
int on_arg_id(string_view) { return on_error("invalid format"), 0; }
|
||||||
|
|
||||||
void on_replacement_field(const char*) {
|
void on_replacement_field(int, const char*) {
|
||||||
auto it = scan_ctx_.begin(), end = scan_ctx_.end();
|
auto it = scan_ctx_.begin(), end = scan_ctx_.end();
|
||||||
switch (arg_.type) {
|
switch (arg_.type) {
|
||||||
case scan_type::int_type:
|
case scan_type::int_type:
|
||||||
@ -208,24 +209,24 @@ struct scan_handler : error_handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* on_format_specs(const char* begin, const char*) {
|
const char* on_format_specs(int, const char* begin, const char*) {
|
||||||
if (arg_.type != scan_type::custom_type) return begin;
|
if (arg_.type != scan_type::custom_type) return begin;
|
||||||
parse_ctx_.advance_to(begin);
|
parse_ctx_.advance_to(begin);
|
||||||
arg_.custom.scan(arg_.custom.value, parse_ctx_, scan_ctx_);
|
arg_.custom.scan(arg_.custom.value, parse_ctx_, scan_ctx_);
|
||||||
return parse_ctx_.begin();
|
return parse_ctx_.begin();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace internal
|
} // namespace detail
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
std::array<internal::scan_arg, sizeof...(Args)> make_scan_args(Args&... args) {
|
std::array<detail::scan_arg, sizeof...(Args)> make_scan_args(Args&... args) {
|
||||||
return {{args...}};
|
return {{args...}};
|
||||||
}
|
}
|
||||||
|
|
||||||
string_view::iterator vscan(string_view input, string_view format_str,
|
string_view::iterator vscan(string_view input, string_view format_str,
|
||||||
scan_args args) {
|
scan_args args) {
|
||||||
internal::scan_handler h(format_str, input, args);
|
detail::scan_handler h(format_str, input, args);
|
||||||
internal::parse_format_string<false>(format_str, h);
|
detail::parse_format_string<false>(format_str, h);
|
||||||
return input.begin() + (h.pos() - &*input.begin());
|
return input.begin() + (h.pos() - &*input.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <format>
|
#include <format>
|
||||||
|
|
||||||
#include "gtest.h"
|
#include "gtest.h"
|
||||||
|
|
||||||
TEST(StdFormatTest, Escaping) {
|
TEST(StdFormatTest, Escaping) {
|
||||||
@ -61,7 +62,7 @@ TEST(StdFormatTest, Int) {
|
|||||||
string s0 = format("{}", 42); // s0 == "42"
|
string s0 = format("{}", 42); // s0 == "42"
|
||||||
string s1 = format("{0:b} {0:d} {0:o} {0:x}", 42); // s1 == "101010 42 52 2a"
|
string s1 = format("{0:b} {0:d} {0:o} {0:x}", 42); // s1 == "101010 42 52 2a"
|
||||||
string s2 = format("{0:#x} {0:#X}", 42); // s2 == "0x2a 0X2A"
|
string s2 = format("{0:#x} {0:#X}", 42); // s2 == "0x2a 0X2A"
|
||||||
string s3 = format("{:n}", 1234); // s3 == "1234" (depends on the locale)
|
string s3 = format("{:L}", 1234); // s3 == "1234" (depends on the locale)
|
||||||
EXPECT_EQ(s0, "42");
|
EXPECT_EQ(s0, "42");
|
||||||
EXPECT_EQ(s1, "101010 42 52 2a");
|
EXPECT_EQ(s1, "101010 42 52 2a");
|
||||||
EXPECT_EQ(s2, "0x2a 0X2A");
|
EXPECT_EQ(s2, "0x2a 0X2A");
|
||||||
@ -123,7 +124,7 @@ template <> struct std::formatter<S> {
|
|||||||
if constexpr (!is_integral_v<type> || is_same_v<type, bool>)
|
if constexpr (!is_integral_v<type> || is_same_v<type, bool>)
|
||||||
throw format_error("width is not integral");
|
throw format_error("width is not integral");
|
||||||
// else if (value < 0 || value > numeric_limits<int>::max())
|
// else if (value < 0 || value > numeric_limits<int>::max())
|
||||||
else if (fmt::internal::is_negative(value) ||
|
else if (fmt::detail::is_negative(value) ||
|
||||||
value > numeric_limits<int>::max())
|
value > numeric_limits<int>::max())
|
||||||
throw format_error("invalid width");
|
throw format_error("invalid width");
|
||||||
else
|
else
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#define FMT_TEST_ASSERT_H_
|
#define FMT_TEST_ASSERT_H_
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "gtest.h"
|
#include "gtest.h"
|
||||||
|
|
||||||
class assertion_failure : public std::logic_error {
|
class assertion_failure : public std::logic_error {
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
// For the license information refer to format.h.
|
// For the license information refer to format.h.
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#include "gtest.h"
|
#include "gtest.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
// For the license information refer to format.h.
|
// For the license information refer to format.h.
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
void increment(char* s) {
|
void increment(char* s) {
|
||||||
|
2
externals/dynarmic/externals/fmt/test/util.h
vendored
2
externals/dynarmic/externals/fmt/test/util.h
vendored
@ -19,7 +19,7 @@ enum { BUFFER_SIZE = 256 };
|
|||||||
# define FMT_VSNPRINTF vsnprintf
|
# define FMT_VSNPRINTF vsnprintf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <std::size_t SIZE>
|
template <size_t SIZE>
|
||||||
void safe_sprintf(char (&buffer)[SIZE], const char* format, ...) {
|
void safe_sprintf(char (&buffer)[SIZE], const char* format, ...) {
|
||||||
std::va_list args;
|
std::va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
|
12
externals/dynarmic/externals/xbyak/.travis.yml
vendored
Executable file
12
externals/dynarmic/externals/xbyak/.travis.yml
vendored
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
sudo: true
|
||||||
|
dist: bionic
|
||||||
|
language: cpp
|
||||||
|
compiler:
|
||||||
|
- gcc
|
||||||
|
- clang
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- nasm yasm g++-multilib tcsh
|
||||||
|
script:
|
||||||
|
- make test
|
2
externals/dynarmic/externals/xbyak/Makefile
vendored
2
externals/dynarmic/externals/xbyak/Makefile
vendored
@ -1,4 +1,4 @@
|
|||||||
PREFIX=/usr/local
|
PREFIX?=/usr/local
|
||||||
INSTALL_DIR=$(PREFIX)/include/xbyak
|
INSTALL_DIR=$(PREFIX)/include/xbyak
|
||||||
|
|
||||||
all:
|
all:
|
||||||
|
@ -23,7 +23,7 @@ void putOpmask(bool only64bit)
|
|||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "kadd", 0x4A },
|
{ "kadd", 0x4A },
|
||||||
{ "kand", 0x41 },
|
{ "kand", 0x41 },
|
||||||
@ -46,7 +46,7 @@ void putOpmask(bool only64bit)
|
|||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "knot", 0x44 },
|
{ "knot", 0x44 },
|
||||||
{ "kortest", 0x98 },
|
{ "kortest", 0x98 },
|
||||||
@ -63,23 +63,23 @@ void putOpmask(bool only64bit)
|
|||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "kshiftl", 0x32 },
|
{ "kshiftl", 0x32 },
|
||||||
{ "kshiftr", 0x30 },
|
{ "kshiftr", 0x30 },
|
||||||
};
|
};
|
||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
const Tbl& p = tbl[i];
|
const Tbl& p = tbl[i];
|
||||||
printf("void %sw(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x%02X, imm); }\n", p.name, p.code);
|
printf("void %sw(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x%02X, imm); }\n", p.name, p.code);
|
||||||
printf("void %sq(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x%02X, imm); }\n", p.name, p.code + 1);
|
printf("void %sq(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x%02X, imm); }\n", p.name, p.code + 1);
|
||||||
printf("void %sb(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x%02X, imm); }\n", p.name, p.code);
|
printf("void %sb(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x%02X, imm); }\n", p.name, p.code);
|
||||||
printf("void %sd(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x%02X, imm); }\n", p.name, p.code + 1);
|
printf("void %sd(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x%02X, imm); }\n", p.name, p.code + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
puts("void kmovw(const Opmask& k, const Operand& op) { opVex(k, 0, op, T_L0 | T_0F | T_W0, 0x90); }");
|
puts("void kmovw(const Opmask& k, const Operand& op) { if (!op.isMEM() && !op.isOPMASK()) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(k, 0, op, T_L0 | T_0F | T_W0, 0x90); }");
|
||||||
puts("void kmovq(const Opmask& k, const Operand& op) { opVex(k, 0, op, T_L0 | T_0F | T_W1, 0x90); }");
|
puts("void kmovq(const Opmask& k, const Operand& op) { if (!op.isMEM() && !op.isOPMASK()) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(k, 0, op, T_L0 | T_0F | T_W1, 0x90); }");
|
||||||
puts("void kmovb(const Opmask& k, const Operand& op) { opVex(k, 0, op, T_L0 | T_0F | T_66 | T_W0, 0x90); }");
|
puts("void kmovb(const Opmask& k, const Operand& op) { if (!op.isMEM() && !op.isOPMASK()) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(k, 0, op, T_L0 | T_0F | T_66 | T_W0, 0x90); }");
|
||||||
puts("void kmovd(const Opmask& k, const Operand& op) { opVex(k, 0, op, T_L0 | T_0F | T_66 | T_W1, 0x90); }");
|
puts("void kmovd(const Opmask& k, const Operand& op) { if (!op.isMEM() && !op.isOPMASK()) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(k, 0, op, T_L0 | T_0F | T_66 | T_W1, 0x90); }");
|
||||||
|
|
||||||
puts("void kmovw(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_W0, 0x91); }");
|
puts("void kmovw(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_W0, 0x91); }");
|
||||||
puts("void kmovq(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_W1, 0x91); }");
|
puts("void kmovq(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_W1, 0x91); }");
|
||||||
@ -98,13 +98,13 @@ void putOpmask(bool only64bit)
|
|||||||
void putVcmp()
|
void putVcmp()
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
bool hasIMM;
|
bool hasIMM;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0xC2, "vcmppd", T_0F | T_MUST_EVEX | T_EW1 | T_SAE_Z | T_YMM | T_66, true },
|
{ 0xC2, "vcmppd", T_0F | T_MUST_EVEX | T_EW1 | T_SAE_Z | T_YMM | T_66 | T_B64, true },
|
||||||
{ 0xC2, "vcmpps", T_0F | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_YMM, true },
|
{ 0xC2, "vcmpps", T_0F | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_YMM | T_B32, true },
|
||||||
{ 0xC2, "vcmpsd", T_0F | T_MUST_EVEX | T_EW1 | T_SAE_Z | T_F2 | T_N8, true },
|
{ 0xC2, "vcmpsd", T_0F | T_MUST_EVEX | T_EW1 | T_SAE_Z | T_F2 | T_N8, true },
|
||||||
{ 0xC2, "vcmpss", T_0F | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_F3 | T_N4, true },
|
{ 0xC2, "vcmpss", T_0F | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_F3 | T_N4, true },
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ void putVcmp()
|
|||||||
const Tbl *p = &tbl[i];
|
const Tbl *p = &tbl[i];
|
||||||
std::string type = type2String(p->type);
|
std::string type = type2String(p->type);
|
||||||
printf("void %s(const Opmask& k, const Xmm& x, const Operand& op%s) { opAVX_K_X_XM(k, x, op, %s, 0x%02X%s); }\n"
|
printf("void %s(const Opmask& k, const Xmm& x, const Operand& op%s) { opAVX_K_X_XM(k, x, op, %s, 0x%02X%s); }\n"
|
||||||
, p->name, p->hasIMM ? ", uint8 imm" : "", type.c_str(), p->code, p->hasIMM ? ", imm" : "");
|
, p->name, p->hasIMM ? ", uint8_t imm" : "", type.c_str(), p->code, p->hasIMM ? ", imm" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ void putVcmp()
|
|||||||
void putX_XM()
|
void putX_XM()
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -198,7 +198,7 @@ void putX_XM()
|
|||||||
void putM_X()
|
void putM_X()
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -219,7 +219,7 @@ void putM_X()
|
|||||||
void putXM_X()
|
void putXM_X()
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -242,7 +242,7 @@ void putXM_X()
|
|||||||
void putX_X_XM_IMM()
|
void putX_X_XM_IMM()
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
bool hasIMM;
|
bool hasIMM;
|
||||||
@ -368,12 +368,15 @@ void putX_X_XM_IMM()
|
|||||||
|
|
||||||
{ 0x52, "vpdpwssd", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_B32, false },
|
{ 0x52, "vpdpwssd", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_B32, false },
|
||||||
{ 0x53, "vpdpwssds", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_B32, false },
|
{ 0x53, "vpdpwssds", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_B32, false },
|
||||||
|
|
||||||
|
{ 0x72, "vcvtne2ps2bf16", T_F2 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_B32, false },
|
||||||
|
{ 0x52, "vdpbf16ps", T_F3 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_SAE_Z | T_B32, false },
|
||||||
};
|
};
|
||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
const Tbl *p = &tbl[i];
|
const Tbl *p = &tbl[i];
|
||||||
std::string type = type2String(p->type);
|
std::string type = type2String(p->type);
|
||||||
printf("void %s(const Xmm& x1, const Xmm& x2, const Operand& op%s) { opAVX_X_X_XM(x1, x2, op, %s, 0x%02X%s); }\n"
|
printf("void %s(const Xmm& x1, const Xmm& x2, const Operand& op%s) { opAVX_X_X_XM(x1, x2, op, %s, 0x%02X%s); }\n"
|
||||||
, p->name, p->hasIMM ? ", uint8 imm" : "", type.c_str(), p->code, p->hasIMM ? ", imm" : "");
|
, p->name, p->hasIMM ? ", uint8_t imm" : "", type.c_str(), p->code, p->hasIMM ? ", imm" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,7 +384,7 @@ void putShift()
|
|||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
int idx;
|
int idx;
|
||||||
int type;
|
int type;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -394,7 +397,7 @@ void putShift()
|
|||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
const Tbl& p = tbl[i];
|
const Tbl& p = tbl[i];
|
||||||
std::string type = type2String(p.type);
|
std::string type = type2String(p.type);
|
||||||
printf("void %s(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), %d), x, op, %s, 0x%02X, imm); }\n", p.name, p.idx, type.c_str(), p.code);
|
printf("void %s(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), %d), x, op, %s, 0x%02X, imm); }\n", p.name, p.idx, type.c_str(), p.code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,7 +406,7 @@ void putExtractInsert()
|
|||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
int type;
|
int type;
|
||||||
bool isZMM;
|
bool isZMM;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -421,13 +424,13 @@ void putExtractInsert()
|
|||||||
const Tbl& p = tbl[i];
|
const Tbl& p = tbl[i];
|
||||||
std::string type = type2String(p.type);
|
std::string type = type2String(p.type);
|
||||||
const char *kind = p.isZMM ? "Operand::MEM | Operand::YMM" : "Operand::MEM | Operand::XMM";
|
const char *kind = p.isZMM ? "Operand::MEM | Operand::YMM" : "Operand::MEM | Operand::XMM";
|
||||||
printf("void %s(const Operand& op, const %s& r, uint8 imm) { if (!op.is(%s)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, %s, 0x%2X, imm); }\n", p.name, p.isZMM ? "Zmm" : "Ymm", kind, type.c_str(), p.code);
|
printf("void %s(const Operand& op, const %s& r, uint8_t imm) { if (!op.is(%s)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, %s, 0x%2X, imm); }\n", p.name, p.isZMM ? "Zmm" : "Ymm", kind, type.c_str(), p.code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
int type;
|
int type;
|
||||||
bool isZMM;
|
bool isZMM;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -446,8 +449,8 @@ void putExtractInsert()
|
|||||||
std::string type = type2String(p.type);
|
std::string type = type2String(p.type);
|
||||||
const char *x = p.isZMM ? "Zmm" : "Ymm";
|
const char *x = p.isZMM ? "Zmm" : "Ymm";
|
||||||
const char *cond = p.isZMM ? "op.is(Operand::MEM | Operand::YMM)" : "(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))";
|
const char *cond = p.isZMM ? "op.is(Operand::MEM | Operand::YMM)" : "(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))";
|
||||||
printf("void %s(const %s& r1, const %s& r2, const Operand& op, uint8 imm) {"
|
printf("void %s(const %s& r1, const %s& r2, const Operand& op, uint8_t imm) {"
|
||||||
"if (!%s) throw Error(ERR_BAD_COMBINATION); "
|
"if (!%s) XBYAK_THROW(ERR_BAD_COMBINATION) "
|
||||||
"opVex(r1, &r2, op, %s, 0x%2X, imm); }\n", p.name, x, x, cond, type.c_str(), p.code);
|
"opVex(r1, &r2, op, %s, 0x%2X, imm); }\n", p.name, x, x, cond, type.c_str(), p.code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -457,7 +460,7 @@ void putBroadcast(bool only64bit)
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
int reg;
|
int reg;
|
||||||
@ -519,7 +522,7 @@ void putGather()
|
|||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
int mode;
|
int mode;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "vpgatherdd", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N4, 0x90, xx_yy_zz },
|
{ "vpgatherdd", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N4, 0x90, xx_yy_zz },
|
||||||
@ -542,7 +545,7 @@ void putScatter()
|
|||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
int mode; // reverse of gather
|
int mode; // reverse of gather
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "vpscatterdd", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N4 | T_M_K, 0xA0, xx_yy_zz },
|
{ "vpscatterdd", T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N4 | T_M_K, 0xA0, xx_yy_zz },
|
||||||
@ -564,10 +567,10 @@ void putScatter()
|
|||||||
|
|
||||||
void putShuff()
|
void putShuff()
|
||||||
{
|
{
|
||||||
puts("void vshuff32x4(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_B32, 0x23, imm); }");
|
puts("void vshuff32x4(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_B32, 0x23, imm); }");
|
||||||
puts("void vshuff64x2(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, 0x23, imm); }");
|
puts("void vshuff64x2(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, 0x23, imm); }");
|
||||||
puts("void vshufi32x4(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_B32, 0x43, imm); }");
|
puts("void vshufi32x4(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_B32, 0x43, imm); }");
|
||||||
puts("void vshufi64x2(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, 0x43, imm); }");
|
puts("void vshufi64x2(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, 0x43, imm); }");
|
||||||
}
|
}
|
||||||
|
|
||||||
void putMov()
|
void putMov()
|
||||||
@ -624,7 +627,7 @@ void putMov()
|
|||||||
void putX_XM_IMM()
|
void putX_XM_IMM()
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
bool hasIMM;
|
bool hasIMM;
|
||||||
@ -661,7 +664,7 @@ void putX_XM_IMM()
|
|||||||
const Tbl *p = &tbl[i];
|
const Tbl *p = &tbl[i];
|
||||||
std::string type = type2String(p->type);
|
std::string type = type2String(p->type);
|
||||||
printf("void %s(const Xmm& x, const Operand& op%s) { opAVX_X_XM_IMM(x, op, %s, 0x%02X%s); }\n"
|
printf("void %s(const Xmm& x, const Operand& op%s) { opAVX_X_XM_IMM(x, op, %s, 0x%02X%s); }\n"
|
||||||
, p->name, p->hasIMM ? ", uint8 imm" : "", type.c_str(), p->code, p->hasIMM ? ", imm" : "");
|
, p->name, p->hasIMM ? ", uint8_t imm" : "", type.c_str(), p->code, p->hasIMM ? ", imm" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -674,7 +677,7 @@ void putMisc()
|
|||||||
const char *name;
|
const char *name;
|
||||||
int zm;
|
int zm;
|
||||||
int type;
|
int type;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
bool isZmm;
|
bool isZmm;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "vgatherpf0dps", 1, T_EW0 | T_N4, 0xC6, true },
|
{ "vgatherpf0dps", 1, T_EW0 | T_N4, 0xC6, true },
|
||||||
@ -705,12 +708,16 @@ void putMisc()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
puts("void vfpclasspd(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isBit(128|256|512)) throw Error(ERR_BAD_MEM_SIZE); opVex(k.changeBit(op.getBit()), 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_YMM | T_EW1 | T_B64, 0x66, imm); }");
|
puts("void vfpclasspd(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isBit(128|256|512)) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k.changeBit(op.getBit()), 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_YMM | T_EW1 | T_B64, 0x66, imm); }");
|
||||||
puts("void vfpclassps(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isBit(128|256|512)) throw Error(ERR_BAD_MEM_SIZE); opVex(k.changeBit(op.getBit()), 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_YMM | T_EW0 | T_B32, 0x66, imm); }");
|
puts("void vfpclassps(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isBit(128|256|512)) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k.changeBit(op.getBit()), 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_YMM | T_EW0 | T_B32, 0x66, imm); }");
|
||||||
puts("void vfpclasssd(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isXMEM()) throw Error(ERR_BAD_MEM_SIZE); opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW1 | T_N8, 0x67, imm); }");
|
puts("void vfpclasssd(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isXMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW1 | T_N8, 0x67, imm); }");
|
||||||
puts("void vfpclassss(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isXMEM()) throw Error(ERR_BAD_MEM_SIZE); opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW0 | T_N4, 0x67, imm); }");
|
puts("void vfpclassss(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isXMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW0 | T_N4, 0x67, imm); }");
|
||||||
|
|
||||||
puts("void vpshufbitqmb(const Opmask& k, const Xmm& x, const Operand& op) { opVex(k, &x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8F); }");
|
puts("void vpshufbitqmb(const Opmask& k, const Xmm& x, const Operand& op) { opVex(k, &x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8F); }");
|
||||||
|
puts("void vcvtneps2bf16(const Xmm& x, const Operand& op) { opCvt2(x, op, T_F3 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x72); }");
|
||||||
|
|
||||||
|
puts("void vp2intersectd(const Opmask& k, const Xmm& x, const Operand& op) { if (k.getOpmaskIdx() != 0) XBYAK_THROW(ERR_OPMASK_IS_ALREADY_SET) opAVX_K_X_XM(k, x, op, T_F2 | T_0F38 | T_YMM | T_EVEX | T_EW0 | T_B32, 0x68); }");
|
||||||
|
puts("void vp2intersectq(const Opmask& k, const Xmm& x, const Operand& op) { if (k.getOpmaskIdx() != 0) XBYAK_THROW(ERR_OPMASK_IS_ALREADY_SET) opAVX_K_X_XM(k, x, op, T_F2 | T_0F38 | T_YMM | T_EVEX | T_EW1 | T_B64, 0x68); }");
|
||||||
}
|
}
|
||||||
|
|
||||||
void putV4FMA()
|
void putV4FMA()
|
||||||
@ -728,7 +735,9 @@ int main(int argc, char *[])
|
|||||||
bool only64bit = argc == 2;
|
bool only64bit = argc == 2;
|
||||||
putOpmask(only64bit);
|
putOpmask(only64bit);
|
||||||
putBroadcast(only64bit);
|
putBroadcast(only64bit);
|
||||||
if (only64bit) return 0;
|
if (only64bit) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
putVcmp();
|
putVcmp();
|
||||||
putX_XM();
|
putX_XM();
|
||||||
putM_X();
|
putM_X();
|
||||||
|
380
externals/dynarmic/externals/xbyak/gen/gen_code.cpp
vendored
380
externals/dynarmic/externals/xbyak/gen/gen_code.cpp
vendored
@ -23,9 +23,9 @@ void put_jREGz(const char *reg, bool prefix)
|
|||||||
|
|
||||||
struct GenericTbl {
|
struct GenericTbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 code1;
|
uint8_t code1;
|
||||||
uint8 code2;
|
uint8_t code2;
|
||||||
uint8 code3;
|
uint8_t code3;
|
||||||
};
|
};
|
||||||
|
|
||||||
void putGeneric(const GenericTbl *p, size_t n)
|
void putGeneric(const GenericTbl *p, size_t n)
|
||||||
@ -44,7 +44,7 @@ void putX_X_XM(bool omitOnly)
|
|||||||
// (x, x, x/m[, imm]) or (y, y, y/m[, imm])
|
// (x, x, x/m[, imm]) or (y, y, y/m[, imm])
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
bool hasIMM;
|
bool hasIMM;
|
||||||
@ -212,25 +212,37 @@ void putX_X_XM(bool omitOnly)
|
|||||||
std::string type = type2String(p->type);
|
std::string type = type2String(p->type);
|
||||||
if (omitOnly) {
|
if (omitOnly) {
|
||||||
if (p->enableOmit) {
|
if (p->enableOmit) {
|
||||||
printf("void v%s(const Xmm& x, const Operand& op%s) { v%s(x, x, op%s); }\n", p->name, p->hasIMM ? ", uint8 imm" : "", p->name, p->hasIMM ? ", imm" : "");
|
printf("void v%s(const Xmm& x, const Operand& op%s) { v%s(x, x, op%s); }\n", p->name, p->hasIMM ? ", uint8_t imm" : "", p->name, p->hasIMM ? ", imm" : "");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (p->mode & 1) {
|
if (p->mode & 1) {
|
||||||
if (p->hasIMM) {
|
if (p->hasIMM) {
|
||||||
printf("void %s(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x%02X, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }\n", p->name, p->code);
|
printf("void %s(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x%02X, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); }\n", p->name, p->code);
|
||||||
} else {
|
} else {
|
||||||
printf("void %s(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x%02X, 0x66, isXMM_XMMorMEM, NONE, 0x38); }\n", p->name, p->code);
|
printf("void %s(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x%02X, 0x66, isXMM_XMMorMEM, NONE, 0x38); }\n", p->name, p->code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p->mode & 2) {
|
if (p->mode & 2) {
|
||||||
printf("void v%s(const Xmm& x1, const Xmm& x2, const Operand& op%s) { opAVX_X_X_XM(x1, x2, op, %s, 0x%02X%s); }\n"
|
printf("void v%s(const Xmm& x1, const Xmm& x2, const Operand& op%s) { opAVX_X_X_XM(x1, x2, op, %s, 0x%02X%s); }\n"
|
||||||
, p->name, p->hasIMM ? ", uint8 imm" : "", type.c_str(), p->code, p->hasIMM ? ", imm" : "");
|
, p->name, p->hasIMM ? ", uint8_t imm" : "", type.c_str(), p->code, p->hasIMM ? ", imm" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void putMemOp(const char *name, uint8_t prefix, uint8_t ext, uint8_t code1, int code2, int bit = 32)
|
||||||
|
{
|
||||||
|
printf("void %s(const Address& addr) { ", name);
|
||||||
|
if (prefix) printf("db(0x%02X); ", prefix);
|
||||||
|
printf("opModM(addr, Reg%d(%d), 0x%02X, 0x%02X); }\n", bit, ext, code1, code2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void putLoadSeg(const char *name, uint8_t code1, int code2 = NONE)
|
||||||
|
{
|
||||||
|
printf("void %s(const Reg& reg, const Address& addr) { opLoadSeg(addr, reg, 0x%02X, 0x%02X); }\n", name, code1, code2);
|
||||||
|
}
|
||||||
|
|
||||||
void put()
|
void put()
|
||||||
{
|
{
|
||||||
const int NO = CodeGenerator::NONE;
|
const int NO = CodeGenerator::NONE;
|
||||||
@ -250,7 +262,7 @@ void put()
|
|||||||
const int Q = 1 << 3;
|
const int Q = 1 << 3;
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
// MMX
|
// MMX
|
||||||
@ -300,7 +312,7 @@ void put()
|
|||||||
|
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
int mode;
|
int mode;
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -334,7 +346,7 @@ void put()
|
|||||||
|
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
int ext;
|
int ext;
|
||||||
int mode;
|
int mode;
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -364,8 +376,8 @@ void put()
|
|||||||
|
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
uint8 pref;
|
uint8_t pref;
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0x70, 0, "pshufw" },
|
{ 0x70, 0, "pshufw" },
|
||||||
@ -375,13 +387,13 @@ void put()
|
|||||||
};
|
};
|
||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
const Tbl *p = &tbl[i];
|
const Tbl *p = &tbl[i];
|
||||||
printf("void %s(const Mmx& mmx, const Operand& op, uint8 imm8) { opMMX(mmx, op, 0x%02X, 0x%02X, imm8); }\n", p->name, p->code, p->pref);
|
printf("void %s(const Mmx& mmx, const Operand& op, uint8_t imm8) { opMMX(mmx, op, 0x%02X, 0x%02X, imm8); }\n", p->name, p->code, p->pref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const struct MmxTbl6 {
|
const struct MmxTbl6 {
|
||||||
uint8 code; // for (reg, reg/[mem])
|
uint8_t code; // for (reg, reg/[mem])
|
||||||
uint8 code2; // for ([mem], reg)
|
uint8_t code2; // for ([mem], reg)
|
||||||
int pref;
|
int pref;
|
||||||
const char *name;
|
const char *name;
|
||||||
} mmxTbl6[] = {
|
} mmxTbl6[] = {
|
||||||
@ -420,7 +432,7 @@ void put()
|
|||||||
{ 0xF2, "sd" },
|
{ 0xF2, "sd" },
|
||||||
};
|
};
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
int mode;
|
int mode;
|
||||||
const char *name;
|
const char *name;
|
||||||
bool hasImm;
|
bool hasImm;
|
||||||
@ -449,8 +461,8 @@ void put()
|
|||||||
for (size_t j = 0; j < NUM_OF_ARRAY(sufTbl); j++) {
|
for (size_t j = 0; j < NUM_OF_ARRAY(sufTbl); j++) {
|
||||||
if (!(p->mode & (1 << j))) continue;
|
if (!(p->mode & (1 << j))) continue;
|
||||||
if (p->hasImm) {
|
if (p->hasImm) {
|
||||||
// don't change uint8 to int because NO is not in byte
|
// don't change uint8_t to int because NO is not in byte
|
||||||
printf("void %s%s(const Xmm& xmm, const Operand& op, uint8 imm8) { opGen(xmm, op, 0x%2X, 0x%02X, isXMM_XMMorMEM, imm8); }\n", p->name, sufTbl[j].name, p->code, sufTbl[j].code);
|
printf("void %s%s(const Xmm& xmm, const Operand& op, uint8_t imm8) { opGen(xmm, op, 0x%2X, 0x%02X, isXMM_XMMorMEM, imm8); }\n", p->name, sufTbl[j].name, p->code, sufTbl[j].code);
|
||||||
} else {
|
} else {
|
||||||
printf("void %s%s(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x%2X, 0x%02X, isXMM_XMMorMEM); }\n", p->name, sufTbl[j].name, p->code, sufTbl[j].code);
|
printf("void %s%s(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x%2X, 0x%02X, isXMM_XMMorMEM); }\n", p->name, sufTbl[j].name, p->code, sufTbl[j].code);
|
||||||
}
|
}
|
||||||
@ -460,8 +472,8 @@ void put()
|
|||||||
{
|
{
|
||||||
// (XMM, XMM)
|
// (XMM, XMM)
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
uint8 pref;
|
uint8_t pref;
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0xF7, 0x66, "maskmovdqu" },
|
{ 0xF7, 0x66, "maskmovdqu" },
|
||||||
@ -478,7 +490,7 @@ void put()
|
|||||||
{
|
{
|
||||||
// (XMM, XMM|MEM)
|
// (XMM, XMM|MEM)
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
int pref;
|
int pref;
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -510,7 +522,7 @@ void put()
|
|||||||
{
|
{
|
||||||
// special type
|
// special type
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
int pref;
|
int pref;
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *cond;
|
const char *cond;
|
||||||
@ -554,7 +566,7 @@ void put()
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
int pref;
|
int pref;
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -571,7 +583,7 @@ void put()
|
|||||||
{
|
{
|
||||||
// cmov
|
// cmov
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 ext;
|
uint8_t ext;
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0, "o" },
|
{ 0, "o" },
|
||||||
@ -616,6 +628,22 @@ void put()
|
|||||||
printf("void set%s(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | %d); }%s\n", p->name, p->ext, msg);
|
printf("void set%s(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | %d); }%s\n", p->name, p->ext, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
const struct Tbl {
|
||||||
|
const char *name;
|
||||||
|
uint8_t code;
|
||||||
|
} tbl[] = {
|
||||||
|
{ "loop", 0xE2 },
|
||||||
|
{ "loope", 0xE1 },
|
||||||
|
{ "loopne", 0xE0 },
|
||||||
|
};
|
||||||
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
|
const Tbl *p = &tbl[i];
|
||||||
|
printf("void %s(std::string label) { opJmp(label, T_SHORT, 0x%02X, 0, 0); }\n", p->name, p->code);
|
||||||
|
printf("void %s(const Label& label) { opJmp(label, T_SHORT, 0x%02X, 0, 0); }\n", p->name, p->code);
|
||||||
|
printf("void %s(const char *label) { %s(std::string(label)); }\n", p->name, p->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
{
|
{
|
||||||
const GenericTbl tbl[] = {
|
const GenericTbl tbl[] = {
|
||||||
@ -633,16 +661,28 @@ void put()
|
|||||||
{ "cmpsb", 0xA6 },
|
{ "cmpsb", 0xA6 },
|
||||||
{ "cmpsw", 0x66, 0xA7 },
|
{ "cmpsw", 0x66, 0xA7 },
|
||||||
{ "cmpsd", 0xA7 },
|
{ "cmpsd", 0xA7 },
|
||||||
|
{ "int3", 0xCC },
|
||||||
{ "scasb", 0xAE },
|
{ "scasb", 0xAE },
|
||||||
{ "scasw", 0x66, 0xAF },
|
{ "scasw", 0x66, 0xAF },
|
||||||
{ "scasd", 0xAF },
|
{ "scasd", 0xAF },
|
||||||
{ "movsb", 0xA4 },
|
{ "movsb", 0xA4 },
|
||||||
|
{ "leave", 0xC9 },
|
||||||
|
{ "lodsb", 0xAC },
|
||||||
|
{ "lodsw", 0x66, 0xAD },
|
||||||
|
{ "lodsd", 0xAD },
|
||||||
{ "movsw", 0x66, 0xA5 },
|
{ "movsw", 0x66, 0xA5 },
|
||||||
{ "movsd", 0xA5 },
|
{ "movsd", 0xA5 },
|
||||||
|
{ "outsb", 0x6E },
|
||||||
|
{ "outsw", 0x66, 0x6F },
|
||||||
|
{ "outsd", 0x6F },
|
||||||
{ "stosb", 0xAA },
|
{ "stosb", 0xAA },
|
||||||
{ "stosw", 0x66, 0xAB },
|
{ "stosw", 0x66, 0xAB },
|
||||||
{ "stosd", 0xAB },
|
{ "stosd", 0xAB },
|
||||||
{ "rep", 0xF3 },
|
{ "rep", 0xF3 },
|
||||||
|
{ "repe", 0xF3 },
|
||||||
|
{ "repz", 0xF3 },
|
||||||
|
{ "repne", 0xF2 },
|
||||||
|
{ "repnz", 0xF2 },
|
||||||
|
|
||||||
{ "lahf", 0x9F },
|
{ "lahf", 0x9F },
|
||||||
{ "lock", 0xF0 },
|
{ "lock", 0xF0 },
|
||||||
@ -651,6 +691,8 @@ void put()
|
|||||||
{ "stc", 0xF9 },
|
{ "stc", 0xF9 },
|
||||||
{ "std", 0xFD },
|
{ "std", 0xFD },
|
||||||
{ "sti", 0xFB },
|
{ "sti", 0xFB },
|
||||||
|
{ "sysenter", 0x0F, 0x34 },
|
||||||
|
{ "sysexit", 0x0F, 0x35 },
|
||||||
|
|
||||||
{ "emms", 0x0F, 0x77 },
|
{ "emms", 0x0F, 0x77 },
|
||||||
{ "pause", 0xF3, 0x90 },
|
{ "pause", 0xF3, 0x90 },
|
||||||
@ -684,7 +726,8 @@ void put()
|
|||||||
{ "fabs", 0xD9, 0xE1 },
|
{ "fabs", 0xD9, 0xE1 },
|
||||||
{ "faddp", 0xDE, 0xC1 },
|
{ "faddp", 0xDE, 0xC1 },
|
||||||
{ "fchs", 0xD9, 0xE0 },
|
{ "fchs", 0xD9, 0xE0 },
|
||||||
|
{ "fclex", 0x9B, 0xDB, 0xE2 },
|
||||||
|
{ "fnclex", 0xDB, 0xE2 },
|
||||||
{ "fcom", 0xD8, 0xD1 },
|
{ "fcom", 0xD8, 0xD1 },
|
||||||
{ "fcomp", 0xD8, 0xD9 },
|
{ "fcomp", 0xD8, 0xD9 },
|
||||||
{ "fcompp", 0xDE, 0xD9 },
|
{ "fcompp", 0xDE, 0xD9 },
|
||||||
@ -724,13 +767,23 @@ void put()
|
|||||||
{ "fxtract", 0xD9, 0xF4 },
|
{ "fxtract", 0xD9, 0xF4 },
|
||||||
{ "fyl2x", 0xD9, 0xF1 },
|
{ "fyl2x", 0xD9, 0xF1 },
|
||||||
{ "fyl2xp1", 0xD9, 0xF9 },
|
{ "fyl2xp1", 0xD9, 0xF9 },
|
||||||
|
|
||||||
|
// AMD Zen
|
||||||
|
{ "monitorx", 0x0F, 0x01, 0xFA },
|
||||||
|
{ "mwaitx", 0x0F, 0x01, 0xFB },
|
||||||
|
{ "clzero", 0x0F, 0x01, 0xFC },
|
||||||
};
|
};
|
||||||
putGeneric(tbl, NUM_OF_ARRAY(tbl));
|
putGeneric(tbl, NUM_OF_ARRAY(tbl));
|
||||||
|
puts("void enter(uint16_t x, uint8_t y) { db(0xC8); dw(x); db(y); }");
|
||||||
|
puts("void int_(uint8_t x) { db(0xCD); db(x); }");
|
||||||
|
putLoadSeg("lss", 0x0F, 0xB2);
|
||||||
|
putLoadSeg("lfs", 0x0F, 0xB4);
|
||||||
|
putLoadSeg("lgs", 0x0F, 0xB5);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code; // (reg, reg)
|
uint8_t code; // (reg, reg)
|
||||||
uint8 ext; // (reg, imm)
|
uint8_t ext; // (reg, imm)
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0x10, 2, "adc" },
|
{ 0x10, 2, "adc" },
|
||||||
@ -745,14 +798,14 @@ void put()
|
|||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
const Tbl *p = &tbl[i];
|
const Tbl *p = &tbl[i];
|
||||||
printf("void %s(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x%02X); }\n", p->name, p->code);
|
printf("void %s(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x%02X); }\n", p->name, p->code);
|
||||||
printf("void %s(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x%02X, %d); }\n", p->name, p->code, p->ext);
|
printf("void %s(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x%02X, %d); }\n", p->name, p->code, p->ext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
uint8 ext;
|
uint8_t ext;
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0x48, 1, "dec" },
|
{ 0x48, 1, "dec" },
|
||||||
@ -765,8 +818,8 @@ void put()
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
uint8 ext;
|
uint8_t ext;
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0xa3, 4, "bt" },
|
{ 0xa3, 4, "bt" },
|
||||||
@ -777,13 +830,13 @@ void put()
|
|||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
const Tbl *p = &tbl[i];
|
const Tbl *p = &tbl[i];
|
||||||
printf("void %s(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0x%02X); }\n", p->name, p->code);
|
printf("void %s(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0x%02X); }\n", p->name, p->code);
|
||||||
printf("void %s(const Operand& op, uint8 imm) { opR_ModM(op, 16|32|64, %d, 0x0f, 0xba, NONE, false, 1); db(imm); }\n", p->name, p->ext);
|
printf("void %s(const Operand& op, uint8_t imm) { opR_ModM(op, 16|32|64, %d, 0x0f, 0xba, NONE, false, 1); db(imm); }\n", p->name, p->ext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
uint8 ext;
|
uint8_t ext;
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0xF6, 6, "div" },
|
{ 0xF6, 6, "div" },
|
||||||
@ -802,7 +855,7 @@ void put()
|
|||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 ext;
|
uint8_t ext;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "rcl", 2 },
|
{ "rcl", 2 },
|
||||||
{ "rcr", 3 },
|
{ "rcr", 3 },
|
||||||
@ -823,21 +876,21 @@ void put()
|
|||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "shld", 0xA4 },
|
{ "shld", 0xA4 },
|
||||||
{ "shrd", 0xAC },
|
{ "shrd", 0xAC },
|
||||||
};
|
};
|
||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
const Tbl *p = &tbl[i];
|
const Tbl *p = &tbl[i];
|
||||||
printf("void %s(const Operand& op, const Reg& reg, uint8 imm) { opShxd(op, reg, imm, 0x%02X); }\n", p->name, p->code);
|
printf("void %s(const Operand& op, const Reg& reg, uint8_t imm) { opShxd(op, reg, imm, 0x%02X); }\n", p->name, p->code);
|
||||||
printf("void %s(const Operand& op, const Reg& reg, const Reg8& _cl) { opShxd(op, reg, 0, 0x%02X, &_cl); }\n", p->name, p->code);
|
printf("void %s(const Operand& op, const Reg& reg, const Reg8& _cl) { opShxd(op, reg, 0, 0x%02X, &_cl); }\n", p->name, p->code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "bsf", 0xBC },
|
{ "bsf", 0xBC },
|
||||||
{ "bsr", 0xBD },
|
{ "bsr", 0xBD },
|
||||||
@ -850,7 +903,7 @@ void put()
|
|||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "popcnt", 0xB8 },
|
{ "popcnt", 0xB8 },
|
||||||
{ "tzcnt", 0xBC },
|
{ "tzcnt", 0xBC },
|
||||||
@ -864,7 +917,7 @@ void put()
|
|||||||
// SSSE3
|
// SSSE3
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0x00, "pshufb" },
|
{ 0x00, "pshufb" },
|
||||||
@ -887,12 +940,12 @@ void put()
|
|||||||
const Tbl *p = &tbl[i];
|
const Tbl *p = &tbl[i];
|
||||||
printf("void %s(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x%02X, 0x66, NONE, 0x38); }\n", p->name, p->code);
|
printf("void %s(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x%02X, 0x66, NONE, 0x38); }\n", p->name, p->code);
|
||||||
}
|
}
|
||||||
printf("void palignr(const Mmx& mmx, const Operand& op, int imm) { opMMX(mmx, op, 0x0f, 0x66, static_cast<uint8>(imm), 0x3a); }\n");
|
printf("void palignr(const Mmx& mmx, const Operand& op, int imm) { opMMX(mmx, op, 0x0f, 0x66, static_cast<uint8_t>(imm), 0x3a); }\n");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "pclmullqlqdq", 0 },
|
{ "pclmullqlqdq", 0 },
|
||||||
{ "pclmulhqlqdq", 1 },
|
{ "pclmulhqlqdq", 1 },
|
||||||
@ -906,26 +959,41 @@ void put()
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code1;
|
uint8_t code1;
|
||||||
int code2;
|
int code2;
|
||||||
uint8 ext;
|
uint8_t ext;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
uint8_t prefix;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0x0F, 0xAE, 2, "ldmxcsr" },
|
{ 0x0F, 0xAE, 2, "ldmxcsr", 0 },
|
||||||
{ 0x0F, 0xAE, 3, "stmxcsr" },
|
{ 0x0F, 0xAE, 3, "stmxcsr", 0 },
|
||||||
{ 0x0F, 0xAE, 7, "clflush" }, // 0x80 is bug of nasm ?
|
{ 0x0F, 0xAE, 7, "clflush", 0 },
|
||||||
{ 0xD9, NONE, 5, "fldcw" },
|
{ 0x0F, 0xAE, 7, "clflushopt", 0x66 },
|
||||||
// { 0x9B, 0xD9, 7, "fstcw" }, // not correct order for fstcw [eax] on 64bit OS
|
{ 0xDF, NONE, 4, "fbld", 0 },
|
||||||
|
{ 0xDF, NONE, 6, "fbstp", 0 },
|
||||||
|
{ 0xD9, NONE, 5, "fldcw", 0 },
|
||||||
|
{ 0xD9, NONE, 4, "fldenv", 0 },
|
||||||
|
{ 0xDD, NONE, 4, "frstor", 0 },
|
||||||
|
{ 0xDD, NONE, 6, "fsave", 0x9B },
|
||||||
|
{ 0xDD, NONE, 6, "fnsave", 0 },
|
||||||
|
{ 0xD9, NONE, 7, "fstcw", 0x9B },
|
||||||
|
{ 0xD9, NONE, 7, "fnstcw", 0 },
|
||||||
|
{ 0xD9, NONE, 6, "fstenv", 0x9B },
|
||||||
|
{ 0xD9, NONE, 6, "fnstenv", 0 },
|
||||||
|
{ 0xDD, NONE, 7, "fstsw", 0x9B },
|
||||||
|
{ 0xDD, NONE, 7, "fnstsw", 0 },
|
||||||
|
{ 0x0F, 0xAE, 1, "fxrstor", 0 },
|
||||||
};
|
};
|
||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
const Tbl *p = &tbl[i];
|
const Tbl *p = &tbl[i];
|
||||||
printf("void %s(const Address& addr) { opModM(addr, Reg32(%d), 0x%02X, 0x%02X); }\n", p->name, p->ext, p->code1, p->code2);
|
putMemOp(p->name, p->prefix, p->ext, p->code1, p->code2);
|
||||||
}
|
}
|
||||||
printf("void fstcw(const Address& addr) { db(0x9B); opModM(addr, Reg32(7), 0xD9, NONE); }\n");
|
puts("void fstsw(const Reg16& r) { if (r.getIdx() != Operand::AX) XBYAK_THROW(ERR_BAD_PARAMETER) db(0x9B); db(0xDF); db(0xE0); }");
|
||||||
|
puts("void fnstsw(const Reg16& r) { if (r.getIdx() != Operand::AX) XBYAK_THROW(ERR_BAD_PARAMETER) db(0xDF); db(0xE0); }");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0x2B, "movntpd" },
|
{ 0x2B, "movntpd" },
|
||||||
@ -939,7 +1007,7 @@ void put()
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0xBE, "movsx" },
|
{ 0xBE, "movsx" },
|
||||||
@ -950,6 +1018,12 @@ void put()
|
|||||||
printf("void %s(const Reg& reg, const Operand& op) { opMovxx(reg, op, 0x%02X); }\n", p->name, p->code);
|
printf("void %s(const Reg& reg, const Operand& op) { opMovxx(reg, op, 0x%02X); }\n", p->name, p->code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{ // in/out
|
||||||
|
puts("void in_(const Reg& a, uint8_t v) { opInOut(a, 0xE4, v); }");
|
||||||
|
puts("void in_(const Reg& a, const Reg& d) { opInOut(a, d, 0xEC); }");
|
||||||
|
puts("void out_(uint8_t v, const Reg& a) { opInOut(a, 0xE6, v); }");
|
||||||
|
puts("void out_(const Reg& d, const Reg& a) { opInOut(a, d, 0xEE); }");
|
||||||
|
}
|
||||||
// mpx
|
// mpx
|
||||||
{
|
{
|
||||||
puts("void bndcl(const BoundsReg& bnd, const Operand& op) { db(0xF3); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }");
|
puts("void bndcl(const BoundsReg& bnd, const Operand& op) { db(0xF3); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }");
|
||||||
@ -963,7 +1037,7 @@ void put()
|
|||||||
}
|
}
|
||||||
// misc
|
// misc
|
||||||
{
|
{
|
||||||
puts("void lea(const Reg& reg, const Address& addr) { if (!reg.isBit(16 | i32e)) throw Error(ERR_BAD_SIZE_OF_REGISTER); opModM(addr, reg, 0x8D); }");
|
puts("void lea(const Reg& reg, const Address& addr) { if (!reg.isBit(16 | i32e)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opModM(addr, reg, 0x8D); }");
|
||||||
puts("void bswap(const Reg32e& reg) { opModR(Reg32(1), reg, 0x0F); }");
|
puts("void bswap(const Reg32e& reg) { opModR(Reg32(1), reg, 0x0F); }");
|
||||||
puts("void ret(int imm = 0) { if (imm) { db(0xC2); dw(imm); } else { db(0xC3); } }");
|
puts("void ret(int imm = 0) { if (imm) { db(0xC2); dw(imm); } else { db(0xC3); } }");
|
||||||
|
|
||||||
@ -975,24 +1049,24 @@ void put()
|
|||||||
puts("void adox(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0xF3, isREG32_REG32orMEM, NONE, 0x38); }");
|
puts("void adox(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0xF3, isREG32_REG32orMEM, NONE, 0x38); }");
|
||||||
puts("void cmpxchg8b(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0xC7); }");
|
puts("void cmpxchg8b(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0xC7); }");
|
||||||
|
|
||||||
puts("void pextrw(const Operand& op, const Mmx& xmm, uint8 imm) { opExt(op, xmm, 0x15, imm, true); }");
|
puts("void pextrw(const Operand& op, const Mmx& xmm, uint8_t imm) { opExt(op, xmm, 0x15, imm, true); }");
|
||||||
puts("void pextrb(const Operand& op, const Xmm& xmm, uint8 imm) { opExt(op, xmm, 0x14, imm); }");
|
puts("void pextrb(const Operand& op, const Xmm& xmm, uint8_t imm) { opExt(op, xmm, 0x14, imm); }");
|
||||||
puts("void pextrd(const Operand& op, const Xmm& xmm, uint8 imm) { opExt(op, xmm, 0x16, imm); }");
|
puts("void pextrd(const Operand& op, const Xmm& xmm, uint8_t imm) { opExt(op, xmm, 0x16, imm); }");
|
||||||
puts("void extractps(const Operand& op, const Xmm& xmm, uint8 imm) { opExt(op, xmm, 0x17, imm); }");
|
puts("void extractps(const Operand& op, const Xmm& xmm, uint8_t imm) { opExt(op, xmm, 0x17, imm); }");
|
||||||
puts("void pinsrw(const Mmx& mmx, const Operand& op, int imm) { if (!op.isREG(32) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opGen(mmx, op, 0xC4, mmx.isXMM() ? 0x66 : NONE, 0, imm); }");
|
puts("void pinsrw(const Mmx& mmx, const Operand& op, int imm) { if (!op.isREG(32) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opGen(mmx, op, 0xC4, mmx.isXMM() ? 0x66 : NONE, 0, imm); }");
|
||||||
puts("void insertps(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x21, 0x66, isXMM_XMMorMEM, imm, 0x3A); }");
|
puts("void insertps(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x21, 0x66, isXMM_XMMorMEM, imm, 0x3A); }");
|
||||||
puts("void pinsrb(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x20, 0x66, isXMM_REG32orMEM, imm, 0x3A); }");
|
puts("void pinsrb(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x20, 0x66, isXMM_REG32orMEM, imm, 0x3A); }");
|
||||||
puts("void pinsrd(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x22, 0x66, isXMM_REG32orMEM, imm, 0x3A); }");
|
puts("void pinsrd(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x22, 0x66, isXMM_REG32orMEM, imm, 0x3A); }");
|
||||||
|
|
||||||
puts("void pmovmskb(const Reg32e& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(reg, mmx, 0x0F, 0xD7); }");
|
puts("void pmovmskb(const Reg32e& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(reg, mmx, 0x0F, 0xD7); }");
|
||||||
puts("void maskmovq(const Mmx& reg1, const Mmx& reg2) { if (!reg1.isMMX() || !reg2.isMMX()) throw Error(ERR_BAD_COMBINATION); opModR(reg1, reg2, 0x0F, 0xF7); }");
|
puts("void maskmovq(const Mmx& reg1, const Mmx& reg2) { if (!reg1.isMMX() || !reg2.isMMX()) XBYAK_THROW(ERR_BAD_COMBINATION) opModR(reg1, reg2, 0x0F, 0xF7); }");
|
||||||
puts("void movmskps(const Reg32e& reg, const Xmm& xmm) { opModR(reg, xmm, 0x0F, 0x50); }");
|
puts("void movmskps(const Reg32e& reg, const Xmm& xmm) { opModR(reg, xmm, 0x0F, 0x50); }");
|
||||||
puts("void movmskpd(const Reg32e& reg, const Xmm& xmm) { db(0x66); movmskps(reg, xmm); }");
|
puts("void movmskpd(const Reg32e& reg, const Xmm& xmm) { db(0x66); movmskps(reg, xmm); }");
|
||||||
puts("void movntps(const Address& addr, const Xmm& xmm) { opModM(addr, Mmx(xmm.getIdx()), 0x0F, 0x2B); }");
|
puts("void movntps(const Address& addr, const Xmm& xmm) { opModM(addr, Mmx(xmm.getIdx()), 0x0F, 0x2B); }");
|
||||||
puts("void movntdqa(const Xmm& xmm, const Address& addr) { db(0x66); opModM(addr, xmm, 0x0F, 0x38, 0x2A); }");
|
puts("void movntdqa(const Xmm& xmm, const Address& addr) { db(0x66); opModM(addr, xmm, 0x0F, 0x38, 0x2A); }");
|
||||||
puts("void lddqu(const Xmm& xmm, const Address& addr) { db(0xF2); opModM(addr, xmm, 0x0F, 0xF0); }");
|
puts("void lddqu(const Xmm& xmm, const Address& addr) { db(0xF2); opModM(addr, xmm, 0x0F, 0xF0); }");
|
||||||
puts("void movnti(const Address& addr, const Reg32e& reg) { opModM(addr, reg, 0x0F, 0xC3); }");
|
puts("void movnti(const Address& addr, const Reg32e& reg) { opModM(addr, reg, 0x0F, 0xC3); }");
|
||||||
puts("void movntq(const Address& addr, const Mmx& mmx) { if (!mmx.isMMX()) throw Error(ERR_BAD_COMBINATION); opModM(addr, mmx, 0x0F, 0xE7); }");
|
puts("void movntq(const Address& addr, const Mmx& mmx) { if (!mmx.isMMX()) XBYAK_THROW(ERR_BAD_COMBINATION) opModM(addr, mmx, 0x0F, 0xE7); }");
|
||||||
|
|
||||||
puts("void movd(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x7E); }");
|
puts("void movd(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x7E); }");
|
||||||
puts("void movd(const Reg32& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); }");
|
puts("void movd(const Reg32& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); }");
|
||||||
@ -1002,18 +1076,18 @@ void put()
|
|||||||
puts("void movdq2q(const Mmx& mmx, const Xmm& xmm) { db(0xF2); opModR(mmx, xmm, 0x0F, 0xD6); }");
|
puts("void movdq2q(const Mmx& mmx, const Xmm& xmm) { db(0xF2); opModR(mmx, xmm, 0x0F, 0xD6); }");
|
||||||
puts("void movq(const Mmx& mmx, const Operand& op) { if (mmx.isXMM()) db(0xF3); opModRM(mmx, op, (mmx.getKind() == op.getKind()), op.isMEM(), 0x0F, mmx.isXMM() ? 0x7E : 0x6F); }");
|
puts("void movq(const Mmx& mmx, const Operand& op) { if (mmx.isXMM()) db(0xF3); opModRM(mmx, op, (mmx.getKind() == op.getKind()), op.isMEM(), 0x0F, mmx.isXMM() ? 0x7E : 0x6F); }");
|
||||||
puts("void movq(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, mmx.isXMM() ? 0xD6 : 0x7F); }");
|
puts("void movq(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, mmx.isXMM() ? 0xD6 : 0x7F); }");
|
||||||
puts("void rdrand(const Reg& r) { if (r.isBit(8)) throw Error(ERR_BAD_SIZE_OF_REGISTER); opModR(Reg(6, Operand::REG, r.getBit()), r, 0x0F, 0xC7); }");
|
puts("void rdrand(const Reg& r) { if (r.isBit(8)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opModR(Reg(6, Operand::REG, r.getBit()), r, 0x0F, 0xC7); }");
|
||||||
puts("void rdseed(const Reg& r) { if (r.isBit(8)) throw Error(ERR_BAD_SIZE_OF_REGISTER); opModR(Reg(7, Operand::REG, r.getBit()), r, 0x0F, 0xC7); }");
|
puts("void rdseed(const Reg& r) { if (r.isBit(8)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opModR(Reg(7, Operand::REG, r.getBit()), r, 0x0F, 0xC7); }");
|
||||||
puts("void crc32(const Reg32e& reg, const Operand& op) { if (reg.isBit(32) && op.isBit(16)) db(0x66); db(0xF2); opModRM(reg, op, op.isREG(), op.isMEM(), 0x0F, 0x38, 0xF0 | (op.isBit(8) ? 0 : 1)); }");
|
puts("void crc32(const Reg32e& reg, const Operand& op) { if (reg.isBit(32) && op.isBit(16)) db(0x66); db(0xF2); opModRM(reg, op, op.isREG(), op.isMEM(), 0x0F, 0x38, 0xF0 | (op.isBit(8) ? 0 : 1)); }");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 m16;
|
uint8_t m16;
|
||||||
uint8 m32;
|
uint8_t m32;
|
||||||
uint8 m64;
|
uint8_t m64;
|
||||||
uint8 ext;
|
uint8_t ext;
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 m64ext;
|
uint8_t m64ext;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0x00, 0xD8, 0xDC, 0, "fadd" },
|
{ 0x00, 0xD8, 0xDC, 0, "fadd" },
|
||||||
{ 0xDE, 0xDA, 0x00, 0, "fiadd" },
|
{ 0xDE, 0xDA, 0x00, 0, "fiadd" },
|
||||||
@ -1046,8 +1120,8 @@ void put()
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint32 code1;
|
uint32_t code1;
|
||||||
uint32 code2;
|
uint32_t code2;
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0xD8C0, 0xDCC0, "fadd" },
|
{ 0xD8C0, 0xDCC0, "fadd" },
|
||||||
@ -1091,8 +1165,8 @@ void put()
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code1;
|
uint8_t code1;
|
||||||
uint8 code2;
|
uint8_t code2;
|
||||||
const char *name;
|
const char *name;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0xD8, 0xD0, "fcom" },
|
{ 0xD8, 0xD0, "fcom" },
|
||||||
@ -1113,7 +1187,7 @@ void put()
|
|||||||
// AVX
|
// AVX
|
||||||
{ // pd, ps, sd, ss
|
{ // pd, ps, sd, ss
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
bool only_pd_ps;
|
bool only_pd_ps;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -1142,7 +1216,7 @@ void put()
|
|||||||
// (x, x/m[, imm]) or (y, y/m[, imm])
|
// (x, x/m[, imm]) or (y, y/m[, imm])
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
bool hasIMM;
|
bool hasIMM;
|
||||||
@ -1223,7 +1297,7 @@ void put()
|
|||||||
const Tbl *p = &tbl[i];
|
const Tbl *p = &tbl[i];
|
||||||
std::string type = type2String(p->type);
|
std::string type = type2String(p->type);
|
||||||
if (p->mode & 1) {
|
if (p->mode & 1) {
|
||||||
const char *immS1 = p->hasIMM ? ", uint8 imm" : "";
|
const char *immS1 = p->hasIMM ? ", uint8_t imm" : "";
|
||||||
const char *immS2 = p->hasIMM ? ", imm" : ", NONE";
|
const char *immS2 = p->hasIMM ? ", imm" : ", NONE";
|
||||||
const char *pref = p->type & T_66 ? "0x66" : p->type & T_F2 ? "0xF2" : p->type & T_F3 ? "0xF3" : "NONE";
|
const char *pref = p->type & T_66 ? "0x66" : p->type & T_F2 ? "0xF2" : p->type & T_F3 ? "0xF3" : "NONE";
|
||||||
const char *suf = p->type & T_0F38 ? "0x38" : p->type & T_0F3A ? "0x3A" : "NONE";
|
const char *suf = p->type & T_0F38 ? "0x38" : p->type & T_0F3A ? "0x3A" : "NONE";
|
||||||
@ -1231,14 +1305,14 @@ void put()
|
|||||||
}
|
}
|
||||||
if (p->mode & 2) {
|
if (p->mode & 2) {
|
||||||
printf("void v%s(const Xmm& xm, const Operand& op%s) { opAVX_X_XM_IMM(xm, op, %s, 0x%02X%s); }\n"
|
printf("void v%s(const Xmm& xm, const Operand& op%s) { opAVX_X_XM_IMM(xm, op, %s, 0x%02X%s); }\n"
|
||||||
, p->name, p->hasIMM ? ", uint8 imm" : "", type.c_str(), p->code, p->hasIMM ? ", imm" : "");
|
, p->name, p->hasIMM ? ", uint8_t imm" : "", type.c_str(), p->code, p->hasIMM ? ", imm" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// (m, x), (m, y)
|
// (m, x), (m, y)
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -1259,7 +1333,7 @@ void put()
|
|||||||
// (x, x/m), (y, y/m), (x, x, x/m), (y, y, y/m)
|
// (x, x/m), (y, y/m), (x, x, x/m), (y, y, y/m)
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
int mode; // 1 : sse, 2 : avx, 3 : sse + avx
|
int mode; // 1 : sse, 2 : avx, 3 : sse + avx
|
||||||
@ -1280,7 +1354,7 @@ void put()
|
|||||||
const Tbl *p = &tbl[i];
|
const Tbl *p = &tbl[i];
|
||||||
std::string type = type2String(p->type);
|
std::string type = type2String(p->type);
|
||||||
if (p->mode & 1) {
|
if (p->mode & 1) {
|
||||||
uint8 pref = p->type & T_66 ? 0x66 : p->type & T_F2 ? 0xF2 : p->type & T_F3 ? 0xF3 : 0;
|
uint8_t pref = p->type & T_66 ? 0x66 : p->type & T_F2 ? 0xF2 : p->type & T_F3 ? 0xF3 : 0;
|
||||||
printf("void %s(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x%02X, 0x%02X, isXMM_XMMorMEM%s); }\n", p->name, p->code, pref, p->type & T_0F38 ? ", NONE, 0x38" : "");
|
printf("void %s(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x%02X, 0x%02X, isXMM_XMMorMEM%s); }\n", p->name, p->code, pref, p->type & T_0F38 ? ", NONE, 0x38" : "");
|
||||||
}
|
}
|
||||||
if (p->mode & 2) {
|
if (p->mode & 2) {
|
||||||
@ -1308,7 +1382,7 @@ void put()
|
|||||||
// vpermd, vpermps
|
// vpermd, vpermps
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -1326,7 +1400,7 @@ void put()
|
|||||||
// vpermq, vpermpd
|
// vpermq, vpermpd
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -1336,7 +1410,7 @@ void put()
|
|||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
const Tbl& p = tbl[i];
|
const Tbl& p = tbl[i];
|
||||||
std::string type = type2String(p.type);
|
std::string type = type2String(p.type);
|
||||||
printf("void %s(const Ymm& y, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(y, op, %s, 0x%02X, imm); }\n", p.name, type.c_str(), p.code);
|
printf("void %s(const Ymm& y, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(y, op, %s, 0x%02X, imm); }\n", p.name, type.c_str(), p.code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// vcmpeqps
|
// vcmpeqps
|
||||||
@ -1363,7 +1437,7 @@ void put()
|
|||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
bool isH;
|
bool isH;
|
||||||
bool isPd;
|
bool isPd;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ true, true, 0x16 },
|
{ true, true, 0x16 },
|
||||||
{ true, false, 0x16 },
|
{ true, false, 0x16 },
|
||||||
@ -1375,7 +1449,7 @@ void put()
|
|||||||
char c = p.isH ? 'h' : 'l';
|
char c = p.isH ? 'h' : 'l';
|
||||||
const char *suf = p.isPd ? "pd" : "ps";
|
const char *suf = p.isPd ? "pd" : "ps";
|
||||||
const char *type = p.isPd ? "T_0F | T_66 | T_EVEX | T_EW1 | T_N8" : "T_0F | T_EVEX | T_EW0 | T_N8";
|
const char *type = p.isPd ? "T_0F | T_66 | T_EVEX | T_EW1 | T_N8" : "T_0F | T_EVEX | T_EW0 | T_N8";
|
||||||
printf("void vmov%c%s(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, op1, op2, %s, 0x%02X); }\n"
|
printf("void vmov%c%s(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, op1, op2, %s, 0x%02X); }\n"
|
||||||
, c, suf, type, p.code);
|
, c, suf, type, p.code);
|
||||||
printf("void vmov%c%s(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, %s, 0x%02X); }\n"
|
printf("void vmov%c%s(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, %s, 0x%02X); }\n"
|
||||||
, c, suf, type, p.code + 1);
|
, c, suf, type, p.code + 1);
|
||||||
@ -1384,7 +1458,7 @@ void put()
|
|||||||
// FMA
|
// FMA
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
bool supportYMM;
|
bool supportYMM;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -1408,7 +1482,7 @@ void put()
|
|||||||
for (int k = 0; k < 3; k++) {
|
for (int k = 0; k < 3; k++) {
|
||||||
const struct Ord {
|
const struct Ord {
|
||||||
const char *str;
|
const char *str;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
} ord[] = {
|
} ord[] = {
|
||||||
{ "132", 0x90 },
|
{ "132", 0x90 },
|
||||||
{ "213", 0xA0 },
|
{ "213", 0xA0 },
|
||||||
@ -1438,10 +1512,10 @@ void put()
|
|||||||
{
|
{
|
||||||
printf("void vbroadcastf128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x1A); }\n");
|
printf("void vbroadcastf128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x1A); }\n");
|
||||||
printf("void vbroadcasti128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x5A); }\n");
|
printf("void vbroadcasti128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x5A); }\n");
|
||||||
printf("void vbroadcastsd(const Ymm& y, const Operand& op) { if (!op.isMEM() && !(y.isYMM() && op.isXMM()) && !(y.isZMM() && op.isXMM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(y, op, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_N8, 0x19); }\n");
|
printf("void vbroadcastsd(const Ymm& y, const Operand& op) { if (!op.isMEM() && !(y.isYMM() && op.isXMM()) && !(y.isZMM() && op.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(y, op, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_N8, 0x19); }\n");
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
int type;
|
int type;
|
||||||
bool ew1;
|
bool ew1;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -1454,40 +1528,40 @@ void put()
|
|||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
const Tbl& p = tbl[i];
|
const Tbl& p = tbl[i];
|
||||||
std::string type = type2String(p.type);
|
std::string type = type2String(p.type);
|
||||||
printf("void %s(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, %s, 0x%02X); }\n", p.name, type.c_str(), p.code);
|
printf("void %s(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(x, op, %s, 0x%02X); }\n", p.name, type.c_str(), p.code);
|
||||||
}
|
}
|
||||||
|
|
||||||
puts("void vextractf128(const Operand& op, const Ymm& y, uint8 imm) { if (!(op.isXMEM() && y.isYMM())) throw Error(ERR_BAD_COMBINATION); opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x19, imm); }");
|
puts("void vextractf128(const Operand& op, const Ymm& y, uint8_t imm) { if (!(op.isXMEM() && y.isYMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x19, imm); }");
|
||||||
puts("void vextracti128(const Operand& op, const Ymm& y, uint8 imm) { if (!(op.isXMEM() && y.isYMM())) throw Error(ERR_BAD_COMBINATION); opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x39, imm); }");
|
puts("void vextracti128(const Operand& op, const Ymm& y, uint8_t imm) { if (!(op.isXMEM() && y.isYMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x39, imm); }");
|
||||||
puts("void vextractps(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_N4, 0x17, imm); }");
|
puts("void vextractps(const Operand& op, const Xmm& x, uint8_t imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_N4, 0x17, imm); }");
|
||||||
puts("void vinsertf128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x18, imm); }");
|
puts("void vinsertf128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x18, imm); }");
|
||||||
puts("void vinserti128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x38, imm); }");
|
puts("void vinserti128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x38, imm); }");
|
||||||
puts("void vperm2f128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x06, imm); }");
|
puts("void vperm2f128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x06, imm); }");
|
||||||
puts("void vperm2i128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x46, imm); }");
|
puts("void vperm2i128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x46, imm); }");
|
||||||
|
|
||||||
puts("void vlddqu(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, cvtIdx0(x), addr, T_0F | T_F2 | T_W0 | T_YMM, 0xF0); }");
|
puts("void vlddqu(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, cvtIdx0(x), addr, T_0F | T_F2 | T_W0 | T_YMM, 0xF0); }");
|
||||||
puts("void vldmxcsr(const Address& addr) { opAVX_X_X_XM(xm2, xm0, addr, T_0F, 0xAE); }");
|
puts("void vldmxcsr(const Address& addr) { opAVX_X_X_XM(xm2, xm0, addr, T_0F, 0xAE); }");
|
||||||
puts("void vstmxcsr(const Address& addr) { opAVX_X_X_XM(xm3, xm0, addr, T_0F, 0xAE); }");
|
puts("void vstmxcsr(const Address& addr) { opAVX_X_X_XM(xm3, xm0, addr, T_0F, 0xAE); }");
|
||||||
puts("void vmaskmovdqu(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_66, 0xF7); }");
|
puts("void vmaskmovdqu(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_66, 0xF7); }");
|
||||||
|
|
||||||
puts("void vpextrb(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(8|16|i32e) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x14, imm); }");
|
puts("void vpextrb(const Operand& op, const Xmm& x, uint8_t imm) { if (!((op.isREG(8|16|i32e) || op.isMEM()) && x.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x14, imm); }");
|
||||||
puts("void vpextrw(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(16|i32e) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); if (op.isREG() && x.getIdx() < 16) { opAVX_X_X_XM(Xmm(op.getIdx()), xm0, x, T_0F | T_66, 0xC5, imm); } else { opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N2, 0x15, imm); } }");
|
puts("void vpextrw(const Operand& op, const Xmm& x, uint8_t imm) { if (!((op.isREG(16|i32e) || op.isMEM()) && x.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) if (op.isREG() && x.getIdx() < 16) { opAVX_X_X_XM(Xmm(op.getIdx()), xm0, x, T_0F | T_66, 0xC5, imm); } else { opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N2, 0x15, imm); } }");
|
||||||
puts("void vpextrd(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x16, imm); }");
|
puts("void vpextrd(const Operand& op, const Xmm& x, uint8_t imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x16, imm); }");
|
||||||
puts("void vpextrq(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(64) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x16, imm); }");
|
puts("void vpextrq(const Operand& op, const Xmm& x, uint8_t imm) { if (!((op.isREG(64) || op.isMEM()) && x.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x, 0, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x16, imm); }");
|
||||||
|
|
||||||
puts("void vpinsrb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x20, imm); }");
|
puts("void vpinsrb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x1, &x2, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x20, imm); }");
|
||||||
puts("void vpinsrw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F | T_66 | T_EVEX | T_N2, 0xC4, imm); }");
|
puts("void vpinsrw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x1, &x2, op, T_0F | T_66 | T_EVEX | T_N2, 0xC4, imm); }");
|
||||||
puts("void vpinsrd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x22, imm); }");
|
puts("void vpinsrd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x1, &x2, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x22, imm); }");
|
||||||
puts("void vpinsrq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(64) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x22, imm); }");
|
puts("void vpinsrq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(64) || op.isMEM()))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x1, &x2, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x22, imm); }");
|
||||||
|
|
||||||
puts("void vpmovmskb(const Reg32e& r, const Xmm& x) { if (!x.is(Operand::XMM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(x.isYMM() ? Ymm(r.getIdx()) : Xmm(r.getIdx()), 0, x, T_0F | T_66 | T_YMM, 0xD7); }");
|
puts("void vpmovmskb(const Reg32e& r, const Xmm& x) { if (!x.is(Operand::XMM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x.isYMM() ? Ymm(r.getIdx()) : Xmm(r.getIdx()), 0, x, T_0F | T_66 | T_YMM, 0xD7); }");
|
||||||
|
|
||||||
}
|
}
|
||||||
// (x, x, imm), (x, imm)
|
// (x, x, imm), (x, imm)
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
int idx;
|
int idx;
|
||||||
int type;
|
int type;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -1505,14 +1579,14 @@ void put()
|
|||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
const Tbl& p = tbl[i];
|
const Tbl& p = tbl[i];
|
||||||
std::string type = type2String(p.type);
|
std::string type = type2String(p.type);
|
||||||
printf("void v%s(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), %d), x, op, %s, 0x%02X, imm); }\n", p.name, p.idx, type.c_str(), p.code);
|
printf("void v%s(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), %d), x, op, %s, 0x%02X, imm); }\n", p.name, p.idx, type.c_str(), p.code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 4-op
|
// 4-op
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "vblendvpd", 0x4B },
|
{ "vblendvpd", 0x4B },
|
||||||
{ "vblendvps", 0x4A },
|
{ "vblendvps", 0x4A },
|
||||||
@ -1525,18 +1599,18 @@ void put()
|
|||||||
}
|
}
|
||||||
// mov
|
// mov
|
||||||
{
|
{
|
||||||
printf("void vmovd(const Xmm& x, const Operand& op) { if (!op.isREG(32) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x6E); }\n");
|
printf("void vmovd(const Xmm& x, const Operand& op) { if (!op.isREG(32) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x6E); }\n");
|
||||||
printf("void vmovd(const Operand& op, const Xmm& x) { if (!op.isREG(32) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x7E); }\n");
|
printf("void vmovd(const Operand& op, const Xmm& x) { if (!op.isREG(32) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x7E); }\n");
|
||||||
|
|
||||||
printf("void vmovq(const Xmm& x, const Address& addr) { int type, code; if (x.getIdx() < 16) { type = T_0F | T_F3; code = 0x7E; } else { type = T_0F | T_66 | T_EVEX | T_EW1 | T_N8; code = 0x6E; } opAVX_X_X_XM(x, xm0, addr, type, code); }\n");
|
printf("void vmovq(const Xmm& x, const Address& addr) { int type, code; if (x.getIdx() < 16) { type = T_0F | T_F3; code = 0x7E; } else { type = T_0F | T_66 | T_EVEX | T_EW1 | T_N8; code = 0x6E; } opAVX_X_X_XM(x, xm0, addr, type, code); }\n");
|
||||||
printf("void vmovq(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, x.getIdx() < 16 ? 0xD6 : 0x7E); }\n");
|
printf("void vmovq(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, x.getIdx() < 16 ? 0xD6 : 0x7E); }\n");
|
||||||
printf("void vmovq(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_F3 | T_EVEX | T_EW1 | T_N8, 0x7E); }\n");
|
printf("void vmovq(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_F3 | T_EVEX | T_EW1 | T_N8, 0x7E); }\n");
|
||||||
|
|
||||||
printf("void vmovhlps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x12); }\n");
|
printf("void vmovhlps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x12); }\n");
|
||||||
printf("void vmovlhps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x16); }\n");
|
printf("void vmovlhps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x16); }\n");
|
||||||
|
|
||||||
printf("void vmovmskpd(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_66 | T_W0 | T_YMM, 0x50); }\n");
|
printf("void vmovmskpd(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_66 | T_W0 | T_YMM, 0x50); }\n");
|
||||||
printf("void vmovmskps(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_W0 | T_YMM, 0x50); }\n");
|
printf("void vmovmskps(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_W0 | T_YMM, 0x50); }\n");
|
||||||
|
|
||||||
puts("void vmovntdq(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW0, 0xE7); }");
|
puts("void vmovntdq(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW0, 0xE7); }");
|
||||||
puts("void vmovntpd(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW1, 0x2B); }");
|
puts("void vmovntpd(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW1, 0x2B); }");
|
||||||
@ -1549,7 +1623,7 @@ void put()
|
|||||||
int type = T_0F | T_EVEX;
|
int type = T_0F | T_EVEX;
|
||||||
type |= i == 0 ? (T_F2 | T_EW1 | T_N8) : (T_F3 | T_EW0 | T_N4);
|
type |= i == 0 ? (T_F2 | T_EW1 | T_N8) : (T_F3 | T_EW0 | T_N4);
|
||||||
std::string s = type2String(type);
|
std::string s = type2String(type);
|
||||||
printf("void vmovs%c(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, %s, 0x10); }\n", c1, s.c_str());
|
printf("void vmovs%c(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x1, x2, op, %s, 0x10); }\n", c1, s.c_str());
|
||||||
printf("void vmovs%c(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, xm0, addr, %s, 0x10); }\n", c1, s.c_str());
|
printf("void vmovs%c(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, xm0, addr, %s, 0x10); }\n", c1, s.c_str());
|
||||||
printf("void vmovs%c(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, %s | T_M_K, 0x11); }\n", c1, s.c_str());
|
printf("void vmovs%c(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, %s | T_M_K, 0x11); }\n", c1, s.c_str());
|
||||||
}
|
}
|
||||||
@ -1574,7 +1648,7 @@ void put()
|
|||||||
puts("void vcvttpd2dq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_66 | T_0F | T_YMM | T_EVEX |T_EW1 | T_B64 | T_ER_Z, 0xE6); }");
|
puts("void vcvttpd2dq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_66 | T_0F | T_YMM | T_EVEX |T_EW1 | T_B64 | T_ER_Z, 0xE6); }");
|
||||||
|
|
||||||
puts("void vcvtph2ps(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F38 | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y, 0x13); }");
|
puts("void vcvtph2ps(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F38 | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y, 0x13); }");
|
||||||
puts("void vcvtps2ph(const Operand& op, const Xmm& x, uint8 imm) { checkCvt1(x, op); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y, 0x1D, imm); }");
|
puts("void vcvtps2ph(const Operand& op, const Xmm& x, uint8_t imm) { checkCvt1(x, op); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y, 0x1D, imm); }");
|
||||||
|
|
||||||
}
|
}
|
||||||
// haswell gpr(reg, reg, r/m)
|
// haswell gpr(reg, reg, r/m)
|
||||||
@ -1582,7 +1656,7 @@ void put()
|
|||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "andn", T_0F38, 0xF2 },
|
{ "andn", T_0F38, 0xF2 },
|
||||||
{ "mulx", T_F2 | T_0F38, 0xF6 },
|
{ "mulx", T_F2 | T_0F38, 0xF6 },
|
||||||
@ -1599,7 +1673,7 @@ void put()
|
|||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "bextr", T_0F38, 0xF7 },
|
{ "bextr", T_0F38, 0xF7 },
|
||||||
{ "bzhi", T_0F38, 0xF5 },
|
{ "bzhi", T_0F38, 0xF5 },
|
||||||
@ -1611,15 +1685,15 @@ void put()
|
|||||||
const Tbl& p = tbl[i];
|
const Tbl& p = tbl[i];
|
||||||
printf("void %s(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, %s, 0x%x, false); }\n", p.name, type2String(p.type).c_str(), p.code);
|
printf("void %s(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, %s, 0x%x, false); }\n", p.name, type2String(p.type).c_str(), p.code);
|
||||||
}
|
}
|
||||||
puts("void rorx(const Reg32e& r, const Operand& op, uint8 imm) { opGpr(r, op, Reg32e(0, r.getBit()), T_0F3A | T_F2, 0xF0, false, imm); }");
|
puts("void rorx(const Reg32e& r, const Operand& op, uint8_t imm) { opGpr(r, op, Reg32e(0, r.getBit()), T_0F3A | T_F2, 0xF0, false, imm); }");
|
||||||
}
|
}
|
||||||
// gpr(reg, r/m)
|
// gpr(reg, r/m)
|
||||||
{
|
{
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
uint8 idx;
|
uint8_t idx;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "blsi", T_0F38, 0xF3, 3 },
|
{ "blsi", T_0F38, 0xF3, 3 },
|
||||||
{ "blsmsk", T_0F38, 0xF3, 2 },
|
{ "blsmsk", T_0F38, 0xF3, 2 },
|
||||||
@ -1637,7 +1711,7 @@ void put()
|
|||||||
const int x_vy_x = 2;
|
const int x_vy_x = 2;
|
||||||
const struct Tbl {
|
const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
int w;
|
int w;
|
||||||
int mode;
|
int mode;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
@ -1669,6 +1743,7 @@ void put32()
|
|||||||
{ "aas", 0x3F },
|
{ "aas", 0x3F },
|
||||||
{ "daa", 0x27 },
|
{ "daa", 0x27 },
|
||||||
{ "das", 0x2F },
|
{ "das", 0x2F },
|
||||||
|
{ "into", 0xCE },
|
||||||
{ "popad", 0x61 },
|
{ "popad", 0x61 },
|
||||||
{ "popfd", 0x9D },
|
{ "popfd", 0x9D },
|
||||||
{ "pusha", 0x60 },
|
{ "pusha", 0x60 },
|
||||||
@ -1677,6 +1752,8 @@ void put32()
|
|||||||
{ "popa", 0x61 },
|
{ "popa", 0x61 },
|
||||||
};
|
};
|
||||||
putGeneric(tbl, NUM_OF_ARRAY(tbl));
|
putGeneric(tbl, NUM_OF_ARRAY(tbl));
|
||||||
|
putLoadSeg("lds", 0xC5, NONE);
|
||||||
|
putLoadSeg("les", 0xC4, NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void put64()
|
void put64()
|
||||||
@ -1688,18 +1765,24 @@ void put64()
|
|||||||
{ "cdqe", 0x48, 0x98 },
|
{ "cdqe", 0x48, 0x98 },
|
||||||
{ "cqo", 0x48, 0x99 },
|
{ "cqo", 0x48, 0x99 },
|
||||||
{ "cmpsq", 0x48, 0xA7 },
|
{ "cmpsq", 0x48, 0xA7 },
|
||||||
|
{ "popfq", 0x9D },
|
||||||
|
{ "pushfq", 0x9C },
|
||||||
|
{ "lodsq", 0x48, 0xAD },
|
||||||
{ "movsq", 0x48, 0xA5 },
|
{ "movsq", 0x48, 0xA5 },
|
||||||
{ "scasq", 0x48, 0xAF },
|
{ "scasq", 0x48, 0xAF },
|
||||||
{ "stosq", 0x48, 0xAB },
|
{ "stosq", 0x48, 0xAB },
|
||||||
|
{ "syscall", 0x0F, 0x05 },
|
||||||
|
{ "sysret", 0x0F, 0x07 },
|
||||||
};
|
};
|
||||||
putGeneric(tbl, NUM_OF_ARRAY(tbl));
|
putGeneric(tbl, NUM_OF_ARRAY(tbl));
|
||||||
|
|
||||||
puts("void cmpxchg16b(const Address& addr) { opModM(addr, Reg64(1), 0x0F, 0xC7); }");
|
putMemOp("cmpxchg16b", 0, 1, 0x0F, 0xC7, 64);
|
||||||
|
putMemOp("fxrstor64", 0, 1, 0x0F, 0xAE, 64);
|
||||||
puts("void movq(const Reg64& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); }");
|
puts("void movq(const Reg64& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); }");
|
||||||
puts("void movq(const Mmx& mmx, const Reg64& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); }");
|
puts("void movq(const Mmx& mmx, const Reg64& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); }");
|
||||||
puts("void movsxd(const Reg64& reg, const Operand& op) { if (!op.isBit(32)) throw Error(ERR_BAD_COMBINATION); opModRM(reg, op, op.isREG(), op.isMEM(), 0x63); }");
|
puts("void movsxd(const Reg64& reg, const Operand& op) { if (!op.isBit(32)) XBYAK_THROW(ERR_BAD_COMBINATION) opModRM(reg, op, op.isREG(), op.isMEM(), 0x63); }");
|
||||||
puts("void pextrq(const Operand& op, const Xmm& xmm, uint8 imm) { if (!op.isREG(64) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opGen(Reg64(xmm.getIdx()), op, 0x16, 0x66, 0, imm, 0x3A); }");
|
puts("void pextrq(const Operand& op, const Xmm& xmm, uint8_t imm) { if (!op.isREG(64) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opGen(Reg64(xmm.getIdx()), op, 0x16, 0x66, 0, imm, 0x3A); }");
|
||||||
puts("void pinsrq(const Xmm& xmm, const Operand& op, uint8 imm) { if (!op.isREG(64) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opGen(Reg64(xmm.getIdx()), op, 0x22, 0x66, 0, imm, 0x3A); }");
|
puts("void pinsrq(const Xmm& xmm, const Operand& op, uint8_t imm) { if (!op.isREG(64) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opGen(Reg64(xmm.getIdx()), op, 0x22, 0x66, 0, imm, 0x3A); }");
|
||||||
|
|
||||||
puts("void vcvtss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_ER_X | T_N8, 0x2D); }");
|
puts("void vcvtss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_ER_X | T_N8, 0x2D); }");
|
||||||
puts("void vcvttss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_SAE_X | T_N8, 0x2C); }");
|
puts("void vcvttss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_SAE_X | T_N8, 0x2C); }");
|
||||||
@ -1710,10 +1793,35 @@ void put64()
|
|||||||
puts("void vmovq(const Reg64& r, const Xmm& x) { opAVX_X_X_XM(x, xm0, Xmm(r.getIdx()), T_66 | T_0F | T_W1 | T_EVEX | T_EW1, 0x7E); }");
|
puts("void vmovq(const Reg64& r, const Xmm& x) { opAVX_X_X_XM(x, xm0, Xmm(r.getIdx()), T_66 | T_0F | T_W1 | T_EVEX | T_EW1, 0x7E); }");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void putAMX_TILE()
|
||||||
|
{
|
||||||
|
puts("void ldtilecfg(const Address& addr) { opVex(tmm0, &tmm0, addr, T_0F38 | T_W0, 0x49); }");
|
||||||
|
puts("void sttilecfg(const Address& addr) { opVex(tmm0, &tmm0, addr, T_66 | T_0F38 | T_W0, 0x49); }");
|
||||||
|
puts("void tileloadd(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_F2 | T_0F38 | T_W0, 0x4b); }");
|
||||||
|
puts("void tileloaddt1(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_66 | T_0F38 | T_W0, 0x4b); }");
|
||||||
|
puts("void tilerelease() { db(0xc4); db(0xe2); db(0x78); db(0x49); db(0xc0); }");
|
||||||
|
puts("void tilestored(const Address& addr, const Tmm& tm) { opVex(tm, &tmm0, addr, T_F3 | T_0F38 | T_W0, 0x4b); }");
|
||||||
|
puts("void tilezero(const Tmm& Tmm) { opVex(Tmm, &tmm0, tmm0, T_F2 | T_0F38 | T_W0, 0x49); }");
|
||||||
|
}
|
||||||
|
void putAMX_INT8()
|
||||||
|
{
|
||||||
|
puts("void tdpbssd(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_F2 | T_0F38 | T_W0, 0x5e); }");
|
||||||
|
puts("void tdpbsud(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_F3 | T_0F38 | T_W0, 0x5e); }");
|
||||||
|
puts("void tdpbusd(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_66 | T_0F38 | T_W0, 0x5e); }");
|
||||||
|
puts("void tdpbuud(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_0F38 | T_W0, 0x5e); }");
|
||||||
|
}
|
||||||
|
void putAMX_BF16()
|
||||||
|
{
|
||||||
|
puts("void tdpbf16ps(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_F3 | T_0F38 | T_W0, 0x5c); }");
|
||||||
|
}
|
||||||
|
|
||||||
void putFixed()
|
void putFixed()
|
||||||
{
|
{
|
||||||
puts("#ifdef XBYAK64");
|
puts("#ifdef XBYAK64");
|
||||||
put64();
|
put64();
|
||||||
|
putAMX_TILE();
|
||||||
|
putAMX_INT8();
|
||||||
|
putAMX_BF16();
|
||||||
puts("#else");
|
puts("#else");
|
||||||
put32();
|
put32();
|
||||||
puts("#endif");
|
puts("#endif");
|
||||||
@ -1724,7 +1832,7 @@ void putFixed()
|
|||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
const char *name = tbl[i];
|
const char *name = tbl[i];
|
||||||
printf("void %s(const Operand& op1, const Operand& op2) { %s_(op1, op2); }\n", name, name);
|
printf("void %s(const Operand& op1, const Operand& op2) { %s_(op1, op2); }\n", name, name);
|
||||||
printf("void %s(const Operand& op, uint32 imm) { %s_(op, imm); }\n", name, name);
|
printf("void %s(const Operand& op, uint32_t imm) { %s_(op, imm); }\n", name, name);
|
||||||
}
|
}
|
||||||
puts("void not(const Operand& op) { not_(op); }");
|
puts("void not(const Operand& op) { not_(op); }");
|
||||||
puts("#endif");
|
puts("#endif");
|
||||||
@ -1732,10 +1840,10 @@ void putFixed()
|
|||||||
|
|
||||||
void putOmit()
|
void putOmit()
|
||||||
{
|
{
|
||||||
puts("void vpinsrb(const Xmm& x, const Operand& op, uint8 imm) { vpinsrb(x, x, op, imm); }");
|
puts("void vpinsrb(const Xmm& x, const Operand& op, uint8_t imm) { vpinsrb(x, x, op, imm); }");
|
||||||
puts("void vpinsrd(const Xmm& x, const Operand& op, uint8 imm) { vpinsrd(x, x, op, imm); }");
|
puts("void vpinsrd(const Xmm& x, const Operand& op, uint8_t imm) { vpinsrd(x, x, op, imm); }");
|
||||||
puts("void vpinsrq(const Xmm& x, const Operand& op, uint8 imm) { vpinsrq(x, x, op, imm); }");
|
puts("void vpinsrq(const Xmm& x, const Operand& op, uint8_t imm) { vpinsrq(x, x, op, imm); }");
|
||||||
puts("void vpinsrw(const Xmm& x, const Operand& op, uint8 imm) { vpinsrw(x, x, op, imm); }");
|
puts("void vpinsrw(const Xmm& x, const Operand& op, uint8_t imm) { vpinsrw(x, x, op, imm); }");
|
||||||
|
|
||||||
puts("void vcvtsi2sd(const Xmm& x, const Operand& op) { vcvtsi2sd(x, x, op); }");
|
puts("void vcvtsi2sd(const Xmm& x, const Operand& op) { vcvtsi2sd(x, x, op); }");
|
||||||
puts("void vcvtsi2ss(const Xmm& x, const Operand& op) { vcvtsi2ss(x, x, op); }");
|
puts("void vcvtsi2ss(const Xmm& x, const Operand& op) { vcvtsi2ss(x, x, op); }");
|
||||||
@ -1769,7 +1877,7 @@ void putOmit()
|
|||||||
};
|
};
|
||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
const char *name = tbl[i];
|
const char *name = tbl[i];
|
||||||
printf("void v%s(const Xmm& x, uint8 imm) { v%s(x, x, imm); }\n", name, name);
|
printf("void v%s(const Xmm& x, uint8_t imm) { v%s(x, x, imm); }\n", name, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
101
externals/dynarmic/externals/xbyak/readme.md
vendored
101
externals/dynarmic/externals/xbyak/readme.md
vendored
@ -1,22 +1,25 @@
|
|||||||
|
[![Build Status](https://travis-ci.org/herumi/xbyak.png)](https://travis-ci.org/herumi/xbyak)
|
||||||
|
|
||||||
# Xbyak 5.78 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
|
# Xbyak 5.97 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
|
||||||
|
|
||||||
## Abstract
|
## Abstract
|
||||||
|
|
||||||
This is a header file which enables dynamically to assemble x86(IA32), x64(AMD64, x86-64) mnemonic.
|
Xbyak is a C++ header library that enables dynamically to assemble x86(IA32), x64(AMD64, x86-64) mnemonic.
|
||||||
|
|
||||||
## Feature
|
## Feature
|
||||||
* header file only
|
* header file only
|
||||||
* Intel/MASM like syntax
|
* Intel/MASM like syntax
|
||||||
* fully support AVX-512
|
* fully support AVX-512
|
||||||
|
|
||||||
**Note**: Xbyak uses and(), or(), xor(), not() functions, so `-fno-operator-names` option is necessary for gcc/clang.
|
**Note**:
|
||||||
|
Use `and_()`, `or_()`, ... instead of `and()`, `or()`.
|
||||||
|
If you want to use them, then specify `-fno-operator-names` option to gcc/clang.
|
||||||
|
|
||||||
Or define `XBYAK_NO_OP_NAMES` before including `xbyak.h` and use and_(), or_(), xor_(), not_() instead of them.
|
### News
|
||||||
|
- (break backward compatibility) `push(byte, imm)` (resp. `push(word, imm)`) forces to cast `imm` to 8(resp. 16) bit.
|
||||||
and_(), or_(), xor_(), not_() are always available.
|
- (Windows) `#include <winsock2.h>` has been removed from xbyak.h, so add it explicitly if you need it.
|
||||||
|
- support exception-less mode see. [Exception-less mode](#exception-less-mode)
|
||||||
`XBYAK_NO_OP_NAMES` will be defined in the feature version.
|
- `XBYAK_USE_MMAP_ALLOCATOR` will be defined on Linux/macOS unless `XBYAK_DONT_USE_MMAP_ALLOCATOR` is defined.
|
||||||
|
|
||||||
### Supported OS
|
### Supported OS
|
||||||
|
|
||||||
@ -47,7 +50,6 @@ These files are copied into `/usr/local/include/xbyak`.
|
|||||||
|
|
||||||
Inherit `Xbyak::CodeGenerator` class and make the class method.
|
Inherit `Xbyak::CodeGenerator` class and make the class method.
|
||||||
```
|
```
|
||||||
#define XBYAK_NO_OP_NAMES
|
|
||||||
#include <xbyak/xbyak.h>
|
#include <xbyak/xbyak.h>
|
||||||
|
|
||||||
struct Code : Xbyak::CodeGenerator {
|
struct Code : Xbyak::CodeGenerator {
|
||||||
@ -58,6 +60,15 @@ struct Code : Xbyak::CodeGenerator {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
Or you can pass the instance of CodeGenerator without inheriting.
|
||||||
|
```
|
||||||
|
void genCode(Xbyak::CodeGenerator& code, int x) {
|
||||||
|
using namespace Xbyak::util;
|
||||||
|
code.mov(eax, x);
|
||||||
|
code.ret();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Make an instance of the class and get the function
|
Make an instance of the class and get the function
|
||||||
pointer by calling `getCode()` and call it.
|
pointer by calling `getCode()` and call it.
|
||||||
```
|
```
|
||||||
@ -146,6 +157,8 @@ vfpclassps k5{k3}, [rax+64]{1to4}, 5 --> vfpclassps(k5|k3, yword_b [rax+64],
|
|||||||
```
|
```
|
||||||
### Remark
|
### Remark
|
||||||
* `k1`, ..., `k7` are opmask registers.
|
* `k1`, ..., `k7` are opmask registers.
|
||||||
|
- `k0` is dealt as no mask.
|
||||||
|
- e.g. `vmovaps(zmm0|k0, ptr[rax]);` and `vmovaps(zmm0|T_z, ptr[rax]);` are same to `vmovaps(zmm0, ptr[rax]);`.
|
||||||
* use `| T_z`, `| T_sae`, `| T_rn_sae`, `| T_rd_sae`, `| T_ru_sae`, `| T_rz_sae` instead of `,{z}`, `,{sae}`, `,{rn-sae}`, `,{rd-sae}`, `,{ru-sae}`, `,{rz-sae}` respectively.
|
* use `| T_z`, `| T_sae`, `| T_rn_sae`, `| T_rd_sae`, `| T_ru_sae`, `| T_rz_sae` instead of `,{z}`, `,{sae}`, `,{rn-sae}`, `,{rd-sae}`, `,{ru-sae}`, `,{rz-sae}` respectively.
|
||||||
* `k4 | k3` is different from `k3 | k4`.
|
* `k4 | k3` is different from `k3 | k4`.
|
||||||
* use `ptr_b` for broadcast `{1toX}`. X is automatically determined.
|
* use `ptr_b` for broadcast `{1toX}`. X is automatically determined.
|
||||||
@ -212,6 +225,32 @@ void func1()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### short and long jump
|
||||||
|
Xbyak deals with jump mnemonics of an undefined label as short jump if no type is specified.
|
||||||
|
So if the size between jmp and label is larger than 127 byte, then xbyak will cause an error.
|
||||||
|
|
||||||
|
```
|
||||||
|
jmp("short-jmp"); // short jmp
|
||||||
|
// small code
|
||||||
|
L("short-jmp");
|
||||||
|
|
||||||
|
jmp("long-jmp");
|
||||||
|
// long code
|
||||||
|
L("long-jmp"); // throw exception
|
||||||
|
```
|
||||||
|
Then specify T_NEAR for jmp.
|
||||||
|
```
|
||||||
|
jmp("long-jmp", T_NEAR); // long jmp
|
||||||
|
// long code
|
||||||
|
L("long-jmp");
|
||||||
|
```
|
||||||
|
Or call `setDefaultJmpNEAR(true);` once, then the default type is set to T_NEAR.
|
||||||
|
```
|
||||||
|
jmp("long-jmp"); // long jmp
|
||||||
|
// long code
|
||||||
|
L("long-jmp");
|
||||||
|
```
|
||||||
|
|
||||||
### Label class
|
### Label class
|
||||||
|
|
||||||
`L()` and `jxx()` support Label class.
|
`L()` and `jxx()` support Label class.
|
||||||
@ -369,15 +408,22 @@ c.setProtectModeRE();
|
|||||||
Call `readyRE()` instead of `ready()` when using `AutoGrow` mode.
|
Call `readyRE()` instead of `ready()` when using `AutoGrow` mode.
|
||||||
See [protect-re.cpp](sample/protect-re.cpp).
|
See [protect-re.cpp](sample/protect-re.cpp).
|
||||||
|
|
||||||
|
## Exception-less mode
|
||||||
|
If `XBYAK_NO_EXCEPTION` is defined, then gcc/clang can compile xbyak with `-fno-exceptions`.
|
||||||
|
In stead of throwing an exception, `Xbyak::GetError()` returns non-zero value (e.g. `ERR_BAD_ADDRESSING`) if there is something wrong.
|
||||||
|
The status will not be changed automatically, then you should reset it by `Xbyak::ClearError()`.
|
||||||
|
`CodeGenerator::reset()` calls `ClearError()`.
|
||||||
|
|
||||||
## Macro
|
## Macro
|
||||||
|
|
||||||
* **XBYAK32** is defined on 32bit.
|
* **XBYAK32** is defined on 32bit.
|
||||||
* **XBYAK64** is defined on 64bit.
|
* **XBYAK64** is defined on 64bit.
|
||||||
* **XBYAK64_WIN** is defined on 64bit Windows(VC)
|
* **XBYAK64_WIN** is defined on 64bit Windows(VC).
|
||||||
* **XBYAK64_GCC** is defined on 64bit gcc, cygwin
|
* **XBYAK64_GCC** is defined on 64bit gcc, cygwin.
|
||||||
* define **XBYAK_NO_OP_NAMES** on gcc without `-fno-operator-names`
|
* define **XBYAK_USE_OP_NAMES** on gcc with `-fno-operator-names` if you want to use `and()`, ....
|
||||||
* define **XBYAK_ENABLE_OMITTED_OPERAND** if you use omitted destination such as `vaddps(xmm2, xmm3);`(deprecated in the future)
|
* define **XBYAK_ENABLE_OMITTED_OPERAND** if you use omitted destination such as `vaddps(xmm2, xmm3);`(deprecated in the future).
|
||||||
* define **XBYAK_UNDEF_JNL** if Bessel function jnl is defined as macro
|
* define **XBYAK_UNDEF_JNL** if Bessel function jnl is defined as macro.
|
||||||
|
* define **XBYAK_NO_EXCEPTION** for a compiler option `-fno-exceptions`.
|
||||||
|
|
||||||
## Sample
|
## Sample
|
||||||
|
|
||||||
@ -392,6 +438,31 @@ modified new BSD License
|
|||||||
http://opensource.org/licenses/BSD-3-Clause
|
http://opensource.org/licenses/BSD-3-Clause
|
||||||
|
|
||||||
## History
|
## History
|
||||||
|
* 2020/Sep/08 ver 5.97 replace uint32 with uint32_t etc.
|
||||||
|
* 2020/Aug/28 ver 5.95 some constructors of register classes support constexpr if C++14 or later
|
||||||
|
* 2020/Aug/04 ver 5.941 `CodeGenerator::reset()` calls `ClearError()`.
|
||||||
|
* 2020/Jul/28 ver 5.94 remove #include <winsock2.h> (only windows)
|
||||||
|
* 2020/Jul/21 ver 5.93 support exception-less mode
|
||||||
|
* 2020/Jun/30 ver 5.92 support Intel AMX instruction set (Thanks to nshustrov)
|
||||||
|
* 2020/Jun/22 ver 5.913 fix mov(r64, imm64) on 32-bit env with XBYAK64
|
||||||
|
* 2020/Jun/19 ver 5.912 define MAP_JIT on macOS regardless of Xcode version (Thanks to rsdubtso)
|
||||||
|
* 2020/May/10 ver 5.911 XBYAK_USE_MMAP_ALLOCATOR is defined unless XBYAK_DONT_USE_MMAP_ALLOCATOR is defined.
|
||||||
|
* 2020/Apr/20 ver 5.91 accept mask register k0 (it means no mask)
|
||||||
|
* 2020/Apr/09 ver 5.90 kmov{b,d,w,q} throws exception for an unsupported register
|
||||||
|
* 2020/Feb/26 ver 5.891 fix typo of type
|
||||||
|
* 2020/Jan/03 ver 5.89 fix error of vfpclasspd
|
||||||
|
* 2019/Dec/20 ver 5.88 fix compile error on Windows
|
||||||
|
* 2019/Dec/19 ver 5.87 add setDefaultJmpNEAR(), which deals with `jmp` of an undefined label as T_NEAR if no type is specified.
|
||||||
|
* 2019/Dec/13 ver 5.86 [changed] revert to the behavior before v5.84 if -fno-operator-names is defined (and() is available)
|
||||||
|
* 2019/Dec/07 ver 5.85 append MAP_JIT flag to mmap for macOS mojave or later
|
||||||
|
* 2019/Nov/29 ver 5.84 [changed] XBYAK_NO_OP_NAMES is defined unless XBYAK_USE_OP_NAMES is defined
|
||||||
|
* 2019/Oct/12 ver 5.83 exit(1) was removed
|
||||||
|
* 2019/Sep/23 ver 5.82 support monitorx, mwaitx, clzero (thanks to @MagurosanTeam)
|
||||||
|
* 2019/Sep/14 ver 5.81 support some generic mnemonics.
|
||||||
|
* 2019/Aug/01 ver 5.802 fix detection of AVX512_BF16 (thanks to vpirogov)
|
||||||
|
* 2019/May/27 support vp2intersectd, vp2intersectq (not tested)
|
||||||
|
* 2019/May/26 ver 5.80 support vcvtne2ps2bf16, vcvtneps2bf16, vdpbf16ps
|
||||||
|
* 2019/Apr/27 ver 5.79 vcmppd/vcmpps supports ptr_b(thanks to jkopinsky)
|
||||||
* 2019/Apr/15 ver 5.78 rewrite Reg::changeBit() (thanks to MerryMage)
|
* 2019/Apr/15 ver 5.78 rewrite Reg::changeBit() (thanks to MerryMage)
|
||||||
* 2019/Mar/06 ver 5.77 fix number of cores that share LLC cache by densamoilov
|
* 2019/Mar/06 ver 5.77 fix number of cores that share LLC cache by densamoilov
|
||||||
* 2019/Jan/17 ver 5.76 add Cpu::getNumCores() by shelleygoel
|
* 2019/Jan/17 ver 5.76 add Cpu::getNumCores() by shelleygoel
|
||||||
@ -530,3 +601,5 @@ http://opensource.org/licenses/BSD-3-Clause
|
|||||||
## Author
|
## Author
|
||||||
MITSUNARI Shigeo(herumi@nifty.com)
|
MITSUNARI Shigeo(herumi@nifty.com)
|
||||||
|
|
||||||
|
## Sponsors welcome
|
||||||
|
[GitHub Sponsor](https://github.com/sponsors/herumi)
|
||||||
|
45
externals/dynarmic/externals/xbyak/readme.txt
vendored
45
externals/dynarmic/externals/xbyak/readme.txt
vendored
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 5.78
|
C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 5.97
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
◎概要
|
◎概要
|
||||||
@ -22,21 +22,21 @@
|
|||||||
Intel Mac
|
Intel Mac
|
||||||
などで動作確認をしています。
|
などで動作確認をしています。
|
||||||
|
|
||||||
※ Xbyakはデフォルトでand(), or(), xor(), not()関数を使います。
|
※ and, orなどの代わりにand_, or_を使用してください。
|
||||||
gccではそれらを演算子として解釈してしまうため、-fno-operator-namesオプションを追加してコンパイルしてください。
|
and, orなどを使いたい場合は-fno-operator-namesをgcc/clangに指定してください。
|
||||||
あるいはXBYAK_NO_OP_NAMESを定義してand_(), or_(), xor_(), not_()を使ってください。
|
|
||||||
and_(), or_(), xor_(), not_()はXBYAK_NO_OP_NAMESされていないときでも使えます。
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
◎準備
|
◎準備
|
||||||
xbyak.h
|
xbyak.h
|
||||||
xbyak_bin2hex.h
|
xbyak_bin2hex.h
|
||||||
xbyak_mnemonic.h
|
|
||||||
これらを同一のパスに入れてインクルードパスに追加してください。
|
これらを同一のパスに入れてインクルードパスに追加してください。
|
||||||
|
|
||||||
Linuxではmake installで/usr/local/include/xbyakにコピーされます。
|
Linuxではmake installで/usr/local/include/xbyakにコピーされます。
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
◎下位互換性の破れ
|
◎下位互換性の破れ
|
||||||
|
* push byte, immまたはpush word, immが下位8bit, 16bitにキャストした値を使うように変更。
|
||||||
|
* (Windows) `<winsock2.h>`をincludeしなくなったので必要なら明示的にincludeしてください。
|
||||||
|
* XBYAK_USE_MMAP_ALLOCATORがデフォルトで有効になりました。従来の方式にする場合はXBYAK_DONT_USE_MMAP_ALLOCATORを定義してください。
|
||||||
* Xbyak::Errorの型をenumからclassに変更
|
* Xbyak::Errorの型をenumからclassに変更
|
||||||
** 従来のenumの値をとるにはintにキャストしてください。
|
** 従来のenumの値をとるにはintにキャストしてください。
|
||||||
* (古い)Reg32eクラスを(新しい)Reg32eとRegExpに分ける。
|
* (古い)Reg32eクラスを(新しい)Reg32eとRegExpに分ける。
|
||||||
@ -46,6 +46,13 @@ Linuxではmake installで/usr/local/include/xbyakにコピーされます。
|
|||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
◎新機能
|
◎新機能
|
||||||
|
|
||||||
|
例外なしモード追加
|
||||||
|
XBYAK_NO_EXCEPTIONを定義してコンパイルするとgcc/clangで-fno-exceptionsオプションでコンパイルできます。
|
||||||
|
エラーは例外の代わりに`Xbyak::GetError()`で通達されます。
|
||||||
|
この値が0でなければ何か問題が発生しています。
|
||||||
|
この値は自動的に変更されないので`Xbyak::ClearError()`でリセットしてください。
|
||||||
|
`CodeGenerator::reset()`は`ClearError()`を呼びます。
|
||||||
|
|
||||||
MmapAllocator追加
|
MmapAllocator追加
|
||||||
これはUnix系OSでのみの仕様です。XBYAK_USE_MMAP_ALLOCATORを使うと利用できます。
|
これはUnix系OSでのみの仕様です。XBYAK_USE_MMAP_ALLOCATORを使うと利用できます。
|
||||||
デフォルトのAllocatorはメモリ確保時にposix_memalignを使います。
|
デフォルトのAllocatorはメモリ確保時にposix_memalignを使います。
|
||||||
@ -54,7 +61,6 @@ map countの最大値は/proc/sys/vm/max_map_countに書かれています。
|
|||||||
デフォルトでは3万個ほどのXbyak::CodeGeneratorインスタンスを生成するとエラーになります。
|
デフォルトでは3万個ほどのXbyak::CodeGeneratorインスタンスを生成するとエラーになります。
|
||||||
test/mprotect_test.cppで確認できます。
|
test/mprotect_test.cppで確認できます。
|
||||||
これを避けるためにはmmapを使うMmapAllocatorを使ってください。
|
これを避けるためにはmmapを使うMmapAllocatorを使ってください。
|
||||||
将来この挙動がデフォルトになるかもしれません。
|
|
||||||
|
|
||||||
|
|
||||||
AutoGrowモード追加
|
AutoGrowモード追加
|
||||||
@ -373,6 +379,31 @@ sample/{echo,hello}.bfは http://www.kmonos.net/alang/etc/brainfuck.php から
|
|||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
◎履歴
|
◎履歴
|
||||||
|
|
||||||
|
2020/09/08 ver 5.97 uint32などをuint32_tに置換
|
||||||
|
2020/08/28 ver 5.95 レジスタクラスのコンストラクタがconstexprに対応(C++14以降)
|
||||||
|
2020/08/04 ver 5.941 `CodeGenerator::reset()`が`ClearError()`を呼ぶように変更
|
||||||
|
2020/07/28 ver 5.94 #include <winsock2.h>の削除 (only windows)
|
||||||
|
2020/07/21 ver 5.93 例外なしモード追加
|
||||||
|
2020/06/30 ver 5.92 Intel AMX命令サポート (Thanks to nshustrov)
|
||||||
|
2020/06/19 ver 5.913 32ビット環境でXBYAK64を定義したときのmov(r64, imm64)を修正
|
||||||
|
2020/06/19 ver 5.912 macOSの古いXcodeでもMAP_JITを有効にする(Thanks to rsdubtso)
|
||||||
|
2020/05/10 ver 5.911 Linux/macOSでXBYAK_USE_MMAP_ALLOCATORがデフォルト有効になる
|
||||||
|
2020/04/20 ver 5.91 マスクレジスタk0を受け入れる(マスクをしない)
|
||||||
|
2020/04/09 ver 5.90 kmov{b,w,d,q}がサポートされないレジスタを受けると例外を投げる
|
||||||
|
2020/02/26 ver 5.891 zm0のtype修正
|
||||||
|
2020/01/03 ver 5.89 vfpclasspdの処理エラー修正
|
||||||
|
2019/12/20 ver 5.88 Windowsでのコンパイルエラー修正
|
||||||
|
2019/12/19 ver 5.87 未定義ラベルへのjmp命令のデフォルト挙動をT_NEARにするsetDefaultJmpNEAR()を追加
|
||||||
|
2019/12/13 ver 5.86 [変更] -fno-operator-namesが指定されたときは5.84以前の挙動に戻す
|
||||||
|
2019/12/07 ver 5.85 mmapにMAP_JITフラグを追加(macOS mojave以上)
|
||||||
|
2019/11/29 ver 5.84 [変更] XBYAK_USE_OP_NAMESが定義されていない限りXBYAK_NO_OP_NAMESが定義されるように変更
|
||||||
|
2019/10/12 ver 5.83 exit(1)の除去
|
||||||
|
2019/09/23 ver 5.82 monitorx, mwaitx, clzero対応 (thanks to MagurosanTeam)
|
||||||
|
2019/09/14 ver 5.81 いくつかの一般命令をサポート
|
||||||
|
2019/08/01 ver 5.802 AVX512_BF16判定修正 (thanks to vpirogov)
|
||||||
|
2019/05/27 support vp2intersectd, vp2intersectq (not tested)
|
||||||
|
2019/05/26 ver 5.80 support vcvtne2ps2bf16, vcvtneps2bf16, vdpbf16ps
|
||||||
|
2019/04/27 ver 5.79 vcmppd/vcmppsのptr_b対応忘れ(thanks to jkopinsky)
|
||||||
2019/04/15 ver 5.78 Reg::changeBit()のリファクタリング(thanks to MerryMage)
|
2019/04/15 ver 5.78 Reg::changeBit()のリファクタリング(thanks to MerryMage)
|
||||||
2019/03/06 ver 5.77 LLCキャッシュを共有数CPU数の修整(by densamoilov)
|
2019/03/06 ver 5.77 LLCキャッシュを共有数CPU数の修整(by densamoilov)
|
||||||
2019/01/17 ver 5.76 Cpu::getNumCores()追加(by shelleygoel)
|
2019/01/17 ver 5.76 Cpu::getNumCores()追加(by shelleygoel)
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
TARGET = test quantize bf toyvm test_util memfunc static_buf jmp_table
|
|
||||||
XBYAK_INC=../xbyak/xbyak.h
|
XBYAK_INC=../xbyak/xbyak.h
|
||||||
|
|
||||||
BOOST_EXIST=$(shell echo "\#include <boost/spirit/core.hpp>" | (gcc -E - 2>/dev/null) | grep "boost/spirit/core.hpp" >/dev/null && echo "1")
|
BOOST_EXIST=$(shell echo "\#include <boost/spirit/core.hpp>" | (gcc -E - 2>/dev/null) | grep "boost/spirit/core.hpp" >/dev/null && echo "1")
|
||||||
UNAME_M=$(shell uname -m)
|
UNAME_M=$(shell uname -m)
|
||||||
|
|
||||||
|
ONLY_64BIT=0
|
||||||
ifeq ($(shell uname -s),Darwin)
|
ifeq ($(shell uname -s),Darwin)
|
||||||
|
ONLY_64BIT=1
|
||||||
|
OS=mac
|
||||||
ifeq ($(UNAME_M),x86_64)
|
ifeq ($(UNAME_M),x86_64)
|
||||||
BIT=64
|
BIT=64
|
||||||
endif
|
endif
|
||||||
@ -27,19 +29,27 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(BIT),64)
|
ifeq ($(BIT),64)
|
||||||
TARGET += test64 bf64 memfunc64 test_util64 static_buf64 jmp_table64
|
TARGET += test64 bf64 memfunc64 test_util64 jmp_table64
|
||||||
ifeq ($(BOOST_EXIST),1)
|
ifeq ($(BOOST_EXIST),1)
|
||||||
TARGET += calc64 #calc2_64
|
TARGET += calc64 #calc2_64
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq ($(OS),mac)
|
||||||
|
TARGET += static_buf64
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
ifneq ($(ONLY_64BIT),1)
|
||||||
|
TARGET += test quantize bf toyvm test_util memfunc static_buf jmp_table
|
||||||
ifeq ($(BOOST_EXIST),1)
|
ifeq ($(BOOST_EXIST),1)
|
||||||
TARGET += calc #calc2
|
TARGET += calc #calc2
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
CFLAGS_WARN=-Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith -pedantic
|
CFLAGS_WARN=-Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith #-pedantic
|
||||||
|
|
||||||
CFLAGS=-g -O2 -fomit-frame-pointer -Wall -I../ $(CFLAGS_WARN)
|
CFLAGS=-g -O2 -fomit-frame-pointer -Wall -I../ $(CFLAGS_WARN)
|
||||||
|
|
||||||
@ -85,9 +95,13 @@ jmp_table:
|
|||||||
$(CXX) $(CFLAGS) jmp_table.cpp -o $@ -m32
|
$(CXX) $(CFLAGS) jmp_table.cpp -o $@ -m32
|
||||||
jmp_table64:
|
jmp_table64:
|
||||||
$(CXX) $(CFLAGS) jmp_table.cpp -o $@ -m64
|
$(CXX) $(CFLAGS) jmp_table.cpp -o $@ -m64
|
||||||
|
profiler: profiler.cpp ../xbyak/xbyak_util.h
|
||||||
|
$(CXX) $(CFLAGS) profiler.cpp -o $@
|
||||||
|
profiler-vtune: profiler.cpp ../xbyak/xbyak_util.h
|
||||||
|
$(CXX) $(CFLAGS) profiler.cpp -o $@ -DXBYAK_USE_VTUNE -I /opt/intel/vtune_amplifier/include/ -L /opt/intel/vtune_amplifier/lib64 -ljitprofiling -ldl
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf *.o $(TARGET) *.exe
|
rm -rf *.o $(TARGET) *.exe profiler profiler-vtune
|
||||||
|
|
||||||
test : test0.cpp $(XBYAK_INC)
|
test : test0.cpp $(XBYAK_INC)
|
||||||
test64: test0.cpp $(XBYAK_INC)
|
test64: test0.cpp $(XBYAK_INC)
|
||||||
|
@ -148,7 +148,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void dump(const Xbyak::uint8 *code, size_t size)
|
void dump(const uint8_t *code, size_t size)
|
||||||
{
|
{
|
||||||
puts("#include <stdio.h>\nstatic int stack[128 * 1024];");
|
puts("#include <stdio.h>\nstatic int stack[128 * 1024];");
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
228
externals/dynarmic/externals/xbyak/sample/bf.vcxproj
vendored
Executable file
228
externals/dynarmic/externals/xbyak/sample/bf.vcxproj
vendored
Executable file
@ -0,0 +1,228 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{654BD79B-59D3-4B10-BBAA-158BAB272828}</ProjectGuid>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<_ProjectFileVersion>15.0.27924.0</_ProjectFileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Midl>
|
||||||
|
<TypeLibraryName>.\Release/bf.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Release/bf.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Midl>
|
||||||
|
<TypeLibraryName>.\Debug/bf.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Debug/bf.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\Debug/bf.pdb</ProgramDatabaseFile>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\Release/bf.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Release/bf.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\Debug/bf.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Debug/bf.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\Debug/bf.pdb</ProgramDatabaseFile>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="bf.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
@ -155,9 +155,9 @@ struct Grammar : public boost::spirit::classic::grammar<Grammar> {
|
|||||||
|
|
||||||
void put(const std::vector<double>& x)
|
void put(const std::vector<double>& x)
|
||||||
{
|
{
|
||||||
printf("%f", x[0]);
|
for (size_t i = 0, n = x.size(); i < n; i++) {
|
||||||
for (size_t i = 1, n = x.size(); i < n; i++) {
|
if (i > 0) printf(", ");
|
||||||
printf(", %f", x[i]);
|
printf("%f", x[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
228
externals/dynarmic/externals/xbyak/sample/calc.vcxproj
vendored
Executable file
228
externals/dynarmic/externals/xbyak/sample/calc.vcxproj
vendored
Executable file
@ -0,0 +1,228 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{5FDDFAA6-B947-491D-A17E-BBD863846579}</ProjectGuid>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<_ProjectFileVersion>15.0.27924.0</_ProjectFileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Midl>
|
||||||
|
<TypeLibraryName>.\Release/calc.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Release/calc.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Midl>
|
||||||
|
<TypeLibraryName>.\Debug/calc.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Debug/calc.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\Debug/calc.pdb</ProgramDatabaseFile>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\Release/calc.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Release/calc.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\Debug/calc.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Debug/calc.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\Debug/calc.pdb</ProgramDatabaseFile>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="calc.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
@ -102,7 +102,7 @@ private:
|
|||||||
MAX_CONST_NUM = 32
|
MAX_CONST_NUM = 32
|
||||||
};
|
};
|
||||||
MIE_ALIGN(16) double constTbl_[MAX_CONST_NUM];
|
MIE_ALIGN(16) double constTbl_[MAX_CONST_NUM];
|
||||||
Xbyak::uint64 negConst_;
|
Xbyak::uint64_t negConst_;
|
||||||
size_t constTblPos_;
|
size_t constTblPos_;
|
||||||
#ifdef XBYAK32
|
#ifdef XBYAK32
|
||||||
const Xbyak::Reg32& varTbl_;
|
const Xbyak::Reg32& varTbl_;
|
||||||
@ -118,7 +118,7 @@ public:
|
|||||||
64bit: x [rcx](win), xmm0(gcc), return xmm0
|
64bit: x [rcx](win), xmm0(gcc), return xmm0
|
||||||
*/
|
*/
|
||||||
Jit()
|
Jit()
|
||||||
: negConst_(Xbyak::uint64(1) << 63)
|
: negConst_(Xbyak::uint64_t(1) << 63)
|
||||||
, constTblPos_(0)
|
, constTblPos_(0)
|
||||||
#ifdef XBYAK32
|
#ifdef XBYAK32
|
||||||
, varTbl_(eax)
|
, varTbl_(eax)
|
||||||
|
90
externals/dynarmic/externals/xbyak/sample/profiler.cpp
vendored
Executable file
90
externals/dynarmic/externals/xbyak/sample/profiler.cpp
vendored
Executable file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
How to profile JIT-code with perf or VTune
|
||||||
|
sudo perf record ./profiler 1
|
||||||
|
amplxe-cl -collect hotspots -result-dir r001hs -quiet ./profiler-vtune 2
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <xbyak/xbyak_util.h>
|
||||||
|
|
||||||
|
const int N = 3000000;
|
||||||
|
struct Code : public Xbyak::CodeGenerator {
|
||||||
|
Code()
|
||||||
|
{
|
||||||
|
mov(eax, N);
|
||||||
|
Xbyak::Label lp = L();
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
sub(eax, 1);
|
||||||
|
}
|
||||||
|
jg(lp);
|
||||||
|
mov(eax, 1);
|
||||||
|
ret();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Code2 : public Xbyak::CodeGenerator {
|
||||||
|
Code2()
|
||||||
|
{
|
||||||
|
mov(eax, N);
|
||||||
|
Xbyak::Label lp = L();
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
xorps(xm0, xm0);
|
||||||
|
}
|
||||||
|
sub(eax, 1);
|
||||||
|
jg(lp);
|
||||||
|
mov(eax, 1);
|
||||||
|
ret();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
double s1(int n)
|
||||||
|
{
|
||||||
|
double r = 0;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
r += 1.0 / (i + 1);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
double s2(int n)
|
||||||
|
{
|
||||||
|
double r = 0;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
r += 1.0 / (i * i + 1) + 2.0 / (i + 3);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int mode = argc == 1 ? 0 : atoi(argv[1]);
|
||||||
|
Code c;
|
||||||
|
Code2 c2;
|
||||||
|
int (*f)() = (int (*)())c.getCode();
|
||||||
|
int (*g)() = (int (*)())c2.getCode();
|
||||||
|
|
||||||
|
printf("f:%p, %d\n", (const void*)f, (int)c.getSize());
|
||||||
|
printf("g:%p, %d\n", (const void*)g, (int)c2.getSize());
|
||||||
|
Xbyak::util::Profiler prof;
|
||||||
|
printf("mode=%d\n", mode);
|
||||||
|
prof.init(mode);
|
||||||
|
prof.set("f", (const void*)f, c.getSize());
|
||||||
|
prof.set("g", (const void*)g, c2.getSize());
|
||||||
|
|
||||||
|
double sum = 0;
|
||||||
|
for (int i = 0; i < 20000; i++) {
|
||||||
|
sum += s1(i);
|
||||||
|
sum += s2(i);
|
||||||
|
}
|
||||||
|
printf("sum=%f\n", sum);
|
||||||
|
for (int i = 0; i < 2000; i++) {
|
||||||
|
sum += f();
|
||||||
|
}
|
||||||
|
printf("f=%f\n", sum);
|
||||||
|
for (int i = 0; i < 2000; i++) {
|
||||||
|
sum += g();
|
||||||
|
}
|
||||||
|
printf("g=%f\n", sum);
|
||||||
|
puts("end");
|
||||||
|
}
|
@ -5,12 +5,12 @@
|
|||||||
This program generates a quantization routine by using fast division algorithm in run-time.
|
This program generates a quantization routine by using fast division algorithm in run-time.
|
||||||
|
|
||||||
time(sec)
|
time(sec)
|
||||||
quality 1(low) 10 50 100(high)
|
quality 1(high) 10 50 100(low)
|
||||||
VC2005 8.0 8.0 8.0 8.0
|
VC2005 8.0 8.0 8.0 8.0
|
||||||
Xbyak 1.6 0.8 0.5 0.5
|
Xbyak 1.6 0.8 0.5 0.5
|
||||||
|
|
||||||
|
|
||||||
; generated code at q = 100
|
; generated code at q = 1
|
||||||
push esi
|
push esi
|
||||||
push edi
|
push edi
|
||||||
mov edi,dword ptr [esp+0Ch]
|
mov edi,dword ptr [esp+0Ch]
|
||||||
@ -48,9 +48,6 @@
|
|||||||
#pragma warning(disable : 4996) // scanf
|
#pragma warning(disable : 4996) // scanf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef Xbyak::uint64 uint64;
|
|
||||||
typedef Xbyak::uint32 uint32;
|
|
||||||
|
|
||||||
const int N = 64;
|
const int N = 64;
|
||||||
|
|
||||||
class Quantize : public Xbyak::CodeGenerator {
|
class Quantize : public Xbyak::CodeGenerator {
|
||||||
@ -66,7 +63,7 @@ public:
|
|||||||
output : eax = [esi+offset] / dividend
|
output : eax = [esi+offset] / dividend
|
||||||
destroy : edx
|
destroy : edx
|
||||||
*/
|
*/
|
||||||
void udiv(uint32 dividend, int offset)
|
void udiv(uint32_t dividend, int offset)
|
||||||
{
|
{
|
||||||
mov(eax, ptr[esi + offset]);
|
mov(eax, ptr[esi + offset]);
|
||||||
|
|
||||||
@ -83,11 +80,11 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 mLow, mHigh;
|
uint64_t mLow, mHigh;
|
||||||
int len = ilog2(odd) + 1;
|
int len = ilog2(odd) + 1;
|
||||||
{
|
{
|
||||||
uint64 roundUp = uint64(1) << (32 + len);
|
uint64_t roundUp = uint64_t(1) << (32 + len);
|
||||||
uint64 k = roundUp / (0xFFFFFFFFL - (0xFFFFFFFFL % odd));
|
uint64_t k = roundUp / (0xFFFFFFFFL - (0xFFFFFFFFL % odd));
|
||||||
mLow = roundUp / odd;
|
mLow = roundUp / odd;
|
||||||
mHigh = (roundUp + k) / odd;
|
mHigh = (roundUp + k) / odd;
|
||||||
}
|
}
|
||||||
@ -96,12 +93,12 @@ public:
|
|||||||
mLow >>= 1; mHigh >>= 1; len--;
|
mLow >>= 1; mHigh >>= 1; len--;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 m; int a;
|
uint64_t m; int a;
|
||||||
if ((mHigh >> 32) == 0) {
|
if ((mHigh >> 32) == 0) {
|
||||||
m = mHigh; a = 0;
|
m = mHigh; a = 0;
|
||||||
} else {
|
} else {
|
||||||
len = ilog2(odd);
|
len = ilog2(odd);
|
||||||
uint64 roundDown = uint64(1) << (32 + len);
|
uint64_t roundDown = uint64_t(1) << (32 + len);
|
||||||
mLow = roundDown / odd;
|
mLow = roundDown / odd;
|
||||||
int r = (int)(roundDown % odd);
|
int r = (int)(roundDown % odd);
|
||||||
m = (r <= (odd >> 1)) ? mLow : mLow + 1;
|
m = (r <= (odd >> 1)) ? mLow : mLow + 1;
|
||||||
@ -124,9 +121,9 @@ public:
|
|||||||
mov(eax, edx);
|
mov(eax, edx);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
quantize(uint32 dest[64], const uint32 src[64]);
|
quantize(uint32_t dest[64], const uint32_t src[64]);
|
||||||
*/
|
*/
|
||||||
Quantize(const uint32 qTbl[64])
|
Quantize(const uint32_t qTbl[64])
|
||||||
{
|
{
|
||||||
push(esi);
|
push(esi);
|
||||||
push(edi);
|
push(edi);
|
||||||
@ -143,7 +140,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void quantize(uint32 dest[64], const uint32 src[64], const uint32 qTbl[64])
|
void quantize(uint32_t dest[64], const uint32_t src[64], const uint32_t qTbl[64])
|
||||||
{
|
{
|
||||||
for (int i = 0; i < N; i++) {
|
for (int i = 0; i < N; i++) {
|
||||||
dest[i] = src[i] / qTbl[i];
|
dest[i] = src[i] / qTbl[i];
|
||||||
@ -170,7 +167,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("q=%d\n", q);
|
printf("q=%d\n", q);
|
||||||
uint32 qTbl[] = {
|
uint32_t qTbl[] = {
|
||||||
16, 11, 10, 16, 24, 40, 51, 61,
|
16, 11, 10, 16, 24, 40, 51, 61,
|
||||||
12, 12, 14, 19, 26, 58, 60, 55,
|
12, 12, 14, 19, 26, 58, 60, 55,
|
||||||
14, 13, 16, 24, 40, 57, 69, 56,
|
14, 13, 16, 24, 40, 57, 69, 56,
|
||||||
@ -187,16 +184,16 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
uint32 src[N];
|
uint32_t src[N];
|
||||||
uint32 dest[N];
|
uint32_t dest[N];
|
||||||
uint32 dest2[N];
|
uint32_t dest2[N];
|
||||||
for (int i = 0; i < N; i++) {
|
for (int i = 0; i < N; i++) {
|
||||||
src[i] = rand() % 2048;
|
src[i] = rand() % 2048;
|
||||||
}
|
}
|
||||||
|
|
||||||
Quantize jit(qTbl);
|
Quantize jit(qTbl);
|
||||||
//printf("jit size=%d, ptr=%p\n", jit.getSize(), jit.getCode());
|
//printf("jit size=%d, ptr=%p\n", jit.getSize(), jit.getCode());
|
||||||
void (*quantize2)(uint32*, const uint32*, const uint32 *) = jit.getCode<void (*)(uint32*, const uint32*, const uint32 *)>();
|
void (*quantize2)(uint32_t*, const uint32_t*, const uint32_t *) = jit.getCode<void (*)(uint32_t*, const uint32_t*, const uint32_t *)>();
|
||||||
|
|
||||||
quantize(dest, src, qTbl);
|
quantize(dest, src, qTbl);
|
||||||
quantize2(dest2, src, qTbl);
|
quantize2(dest2, src, qTbl);
|
||||||
|
228
externals/dynarmic/externals/xbyak/sample/quantize.vcxproj
vendored
Executable file
228
externals/dynarmic/externals/xbyak/sample/quantize.vcxproj
vendored
Executable file
@ -0,0 +1,228 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{D06753BF-E1F3-4578-9B18-08673327F77C}</ProjectGuid>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<_ProjectFileVersion>15.0.27924.0</_ProjectFileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Midl>
|
||||||
|
<TypeLibraryName>.\Debug/quantize.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Debug/quantize.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\Debug/quantize.pdb</ProgramDatabaseFile>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Midl>
|
||||||
|
<TypeLibraryName>.\Release/quantize.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Release/quantize.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\Debug/quantize.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Debug/quantize.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\Debug/quantize.pdb</ProgramDatabaseFile>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\Release/quantize.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Release/quantize.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="quantize.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
@ -163,15 +163,15 @@ int main()
|
|||||||
// use memory allocated by user
|
// use memory allocated by user
|
||||||
using namespace Xbyak;
|
using namespace Xbyak;
|
||||||
const size_t codeSize = 4096;
|
const size_t codeSize = 4096;
|
||||||
uint8 buf[codeSize + 16];
|
uint8_t buf[codeSize + 16];
|
||||||
uint8 *p = CodeArray::getAlignedAddress(buf);
|
uint8_t *p = CodeArray::getAlignedAddress(buf);
|
||||||
Sample s(p, codeSize);
|
Sample s(p, codeSize);
|
||||||
if (!CodeArray::protect(p, codeSize, CodeArray::PROTECT_RWE)) {
|
if (!CodeArray::protect(p, codeSize, CodeArray::PROTECT_RWE)) {
|
||||||
fprintf(stderr, "can't protect\n");
|
fprintf(stderr, "can't protect\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int (*func)(int) = s.getCode<int (*)(int)>();
|
int (*func)(int) = s.getCode<int (*)(int)>();
|
||||||
const uint8 *funcp = reinterpret_cast<const uint8*>(func);
|
const uint8_t *funcp = reinterpret_cast<const uint8_t*>(func);
|
||||||
if (funcp != p) {
|
if (funcp != p) {
|
||||||
fprintf(stderr, "internal error %p %p\n", p, funcp);
|
fprintf(stderr, "internal error %p %p\n", p, funcp);
|
||||||
return 1;
|
return 1;
|
||||||
|
228
externals/dynarmic/externals/xbyak/sample/test0.vcxproj
vendored
Executable file
228
externals/dynarmic/externals/xbyak/sample/test0.vcxproj
vendored
Executable file
@ -0,0 +1,228 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{1CDE4D2A-BE3A-4B9B-B28F-524A23084A8E}</ProjectGuid>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<_ProjectFileVersion>15.0.27924.0</_ProjectFileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Midl>
|
||||||
|
<TypeLibraryName>.\Debug/test0.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Debug/test0.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\Debug/test0.pdb</ProgramDatabaseFile>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Midl>
|
||||||
|
<TypeLibraryName>.\Release/test0.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Release/test0.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\Debug/test0.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Debug/test0.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\Debug/test0.pdb</ProgramDatabaseFile>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\Release/test0.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Release/test0.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="test0.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
@ -78,6 +78,8 @@ void putCPUinfo()
|
|||||||
{ Cpu::tAVX512_VNNI, "avx512_vnni" },
|
{ Cpu::tAVX512_VNNI, "avx512_vnni" },
|
||||||
{ Cpu::tAVX512_BITALG, "avx512_bitalg" },
|
{ Cpu::tAVX512_BITALG, "avx512_bitalg" },
|
||||||
{ Cpu::tAVX512_VPOPCNTDQ, "avx512_vpopcntdq" },
|
{ Cpu::tAVX512_VPOPCNTDQ, "avx512_vpopcntdq" },
|
||||||
|
{ Cpu::tAVX512_BF16, "avx512_bf16" },
|
||||||
|
{ Cpu::tAVX512_VP2INTERSECT, "avx512_vp2intersect" },
|
||||||
};
|
};
|
||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
if (cpu.has(tbl[i].type)) printf(" %s", tbl[i].str);
|
if (cpu.has(tbl[i].type)) printf(" %s", tbl[i].str);
|
||||||
|
228
externals/dynarmic/externals/xbyak/sample/test_util.vcxproj
vendored
Executable file
228
externals/dynarmic/externals/xbyak/sample/test_util.vcxproj
vendored
Executable file
@ -0,0 +1,228 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{CFC9B272-FDA1-4C87-B4EF-CDCA9B57F4DD}</ProjectGuid>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<_ProjectFileVersion>15.0.27924.0</_ProjectFileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Midl>
|
||||||
|
<TypeLibraryName>.\Debug/test_util.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Debug/test_util.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\Debug/test_util.pdb</ProgramDatabaseFile>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\Debug/test_util.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Debug/test_util.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\Debug/test_util.pdb</ProgramDatabaseFile>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Midl>
|
||||||
|
<TypeLibraryName>.\Release/test_util.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Release/test_util.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\Release/test_util.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Release/test_util.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="test_util.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
@ -39,7 +39,7 @@
|
|||||||
using namespace Xbyak;
|
using namespace Xbyak;
|
||||||
|
|
||||||
class ToyVm : public Xbyak::CodeGenerator {
|
class ToyVm : public Xbyak::CodeGenerator {
|
||||||
typedef std::vector<uint32> Buffer;
|
typedef std::vector<uint32_t> Buffer;
|
||||||
public:
|
public:
|
||||||
enum Reg {
|
enum Reg {
|
||||||
A, B
|
A, B
|
||||||
@ -53,14 +53,14 @@ public:
|
|||||||
{
|
{
|
||||||
::memset(mem_, 0, sizeof(mem_));
|
::memset(mem_, 0, sizeof(mem_));
|
||||||
}
|
}
|
||||||
void vldi(Reg r, uint16 imm) { encode(LDI, r, imm); }
|
void vldi(Reg r, uint16_t imm) { encode(LDI, r, imm); }
|
||||||
void vld(Reg r, uint16 idx) { encode(LD, r, idx); }
|
void vld(Reg r, uint16_t idx) { encode(LD, r, idx); }
|
||||||
void vst(Reg r, uint16 idx) { encode(ST, r, idx); }
|
void vst(Reg r, uint16_t idx) { encode(ST, r, idx); }
|
||||||
void vadd(Reg r, uint16 idx) { encode(ADD, r, idx); }
|
void vadd(Reg r, uint16_t idx) { encode(ADD, r, idx); }
|
||||||
void vaddi(Reg r, uint16 imm) { encode(ADDI, r, imm); }
|
void vaddi(Reg r, uint16_t imm) { encode(ADDI, r, imm); }
|
||||||
void vsub(Reg r, uint16 idx) { encode(SUB, r, idx); }
|
void vsub(Reg r, uint16_t idx) { encode(SUB, r, idx); }
|
||||||
void vsubi(Reg r, uint16 imm) { encode(SUBI, r, imm); }
|
void vsubi(Reg r, uint16_t imm) { encode(SUBI, r, imm); }
|
||||||
void vjnz(Reg r, int offset) { encode(JNZ, r, static_cast<uint16>(offset)); }
|
void vjnz(Reg r, int offset) { encode(JNZ, r, static_cast<uint16_t>(offset)); }
|
||||||
void vput(Reg r) { encode(PUT, r); }
|
void vput(Reg r) { encode(PUT, r); }
|
||||||
void setMark()
|
void setMark()
|
||||||
{
|
{
|
||||||
@ -73,12 +73,12 @@ public:
|
|||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
bool debug = false;//true;
|
bool debug = false;//true;
|
||||||
uint32 reg[2] = { 0, 0 };
|
uint32_t reg[2] = { 0, 0 };
|
||||||
const size_t end = code_.size();
|
const size_t end = code_.size();
|
||||||
uint32 pc = 0;
|
uint32_t pc = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint32 x = code_[pc];
|
uint32_t x = code_[pc];
|
||||||
uint32 code, r, imm;
|
uint32_t code, r, imm;
|
||||||
decode(code, r, imm, x);
|
decode(code, r, imm, x);
|
||||||
if (debug) {
|
if (debug) {
|
||||||
printf("---\n");
|
printf("---\n");
|
||||||
@ -149,11 +149,11 @@ public:
|
|||||||
xor_(edi, edi);
|
xor_(edi, edi);
|
||||||
mov(mem, (size_t)mem_);
|
mov(mem, (size_t)mem_);
|
||||||
const size_t end = code_.size();
|
const size_t end = code_.size();
|
||||||
uint32 pc = 0;
|
uint32_t pc = 0;
|
||||||
uint32 labelNum = 0;
|
uint32_t labelNum = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint32 x = code_[pc];
|
uint32_t x = code_[pc];
|
||||||
uint32 code, r, imm;
|
uint32_t code, r, imm;
|
||||||
decode(code, r, imm, x);
|
decode(code, r, imm, x);
|
||||||
L(Label::toStr(labelNum++));
|
L(Label::toStr(labelNum++));
|
||||||
switch (code) {
|
switch (code) {
|
||||||
@ -229,18 +229,18 @@ public:
|
|||||||
ret();
|
ret();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
uint32 mem_[65536];
|
uint32_t mem_[65536];
|
||||||
Buffer code_;
|
Buffer code_;
|
||||||
int mark_;
|
int mark_;
|
||||||
void decode(uint32& code, uint32& r, uint32& imm, uint32 x)
|
void decode(uint32_t& code, uint32_t& r, uint32_t& imm, uint32_t x)
|
||||||
{
|
{
|
||||||
code = x >> 24;
|
code = x >> 24;
|
||||||
r = (x >> 16) & 0xff;
|
r = (x >> 16) & 0xff;
|
||||||
imm = x & 0xffff;
|
imm = x & 0xffff;
|
||||||
}
|
}
|
||||||
void encode(Code code, Reg r, uint16 imm = 0)
|
void encode(Code code, Reg r, uint16_t imm = 0)
|
||||||
{
|
{
|
||||||
uint32 x = (code << 24) | (r << 16) | imm;
|
uint32_t x = (code << 24) | (r << 16) | imm;
|
||||||
code_.push_back(x);
|
code_.push_back(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -262,7 +262,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
vldi(A, 1); // c
|
vldi(A, 1); // c
|
||||||
vst(A, 0); // p(1)
|
vst(A, 0); // p(1)
|
||||||
vldi(B, static_cast<uint16>(n));
|
vldi(B, static_cast<uint16_t>(n));
|
||||||
vst(B, 2); // n
|
vst(B, 2); // n
|
||||||
// lp
|
// lp
|
||||||
setMark();
|
setMark();
|
||||||
@ -283,9 +283,9 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void fibC(uint32 n)
|
void fibC(uint32_t n)
|
||||||
{
|
{
|
||||||
uint32 p, c, t;
|
uint32_t p, c, t;
|
||||||
p = 1;
|
p = 1;
|
||||||
c = 1;
|
c = 1;
|
||||||
lp:
|
lp:
|
||||||
|
228
externals/dynarmic/externals/xbyak/sample/toyvm.vcxproj
vendored
Executable file
228
externals/dynarmic/externals/xbyak/sample/toyvm.vcxproj
vendored
Executable file
@ -0,0 +1,228 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{2E41C7AF-39FF-454C-B081-37445378DCB3}</ProjectGuid>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<_ProjectFileVersion>15.0.27924.0</_ProjectFileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Midl>
|
||||||
|
<TypeLibraryName>.\Debug/toyvm.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Debug/toyvm.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\Debug/toyvm.pdb</ProgramDatabaseFile>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Midl>
|
||||||
|
<TypeLibraryName>.\Release/toyvm.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Release/toyvm.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\Debug/toyvm.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Debug/toyvm.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>.\Debug/toyvm.pdb</ProgramDatabaseFile>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Midl>
|
||||||
|
<TargetEnvironment>X64</TargetEnvironment>
|
||||||
|
<TypeLibraryName>.\Release/toyvm.tlb</TypeLibraryName>
|
||||||
|
<HeaderFileName />
|
||||||
|
</Midl>
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeaderOutputFile>.\Release/toyvm.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</ClCompile>
|
||||||
|
<ResourceCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<Culture>0x0411</Culture>
|
||||||
|
</ResourceCompile>
|
||||||
|
<Link>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<DataExecutionPrevention />
|
||||||
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
<Bscmake>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
</Bscmake>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="toyvm.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
31
externals/dynarmic/externals/xbyak/test/Makefile
vendored
31
externals/dynarmic/externals/xbyak/test/Makefile
vendored
@ -1,9 +1,18 @@
|
|||||||
TARGET = make_nm normalize_prefix jmp address bad_address misc cvt_test cvt_test32
|
TARGET = make_nm normalize_prefix bad_address misc cvt_test cvt_test32 noexception
|
||||||
XBYAK_INC=../xbyak/xbyak.h
|
XBYAK_INC=../xbyak/xbyak.h
|
||||||
|
UNAME_S=$(shell uname -s)
|
||||||
BIT=32
|
BIT=32
|
||||||
ifeq ($(shell uname -m),x86_64)
|
ifeq ($(shell uname -m),x86_64)
|
||||||
BIT=64
|
BIT=64
|
||||||
endif
|
endif
|
||||||
|
ONLY_64BIT=0
|
||||||
|
ifeq ($(UNAME_S),Darwin)
|
||||||
|
# 32-bit binary is not supported
|
||||||
|
ONLY_64BIT=1
|
||||||
|
endif
|
||||||
|
ifeq ($(ONLY_64BIT),0)
|
||||||
|
TARGET += jmp address
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(BIT),64)
|
ifeq ($(BIT),64)
|
||||||
TARGET += jmp64 address64
|
TARGET += jmp64 address64
|
||||||
@ -36,18 +45,24 @@ cvt_test: cvt_test.cpp ../xbyak/xbyak.h
|
|||||||
$(CXX) $(CFLAGS) $< -o $@
|
$(CXX) $(CFLAGS) $< -o $@
|
||||||
cvt_test32: cvt_test.cpp ../xbyak/xbyak.h
|
cvt_test32: cvt_test.cpp ../xbyak/xbyak.h
|
||||||
$(CXX) $(CFLAGS) $< -o $@ -DXBYAK32
|
$(CXX) $(CFLAGS) $< -o $@ -DXBYAK32
|
||||||
|
noexception: noexception.cpp ../xbyak/xbyak.h
|
||||||
|
$(CXX) $(CFLAGS) $< -o $@ -fno-exceptions
|
||||||
|
|
||||||
test: normalize_prefix jmp bad_address $(TARGET)
|
test_nm: normalize_prefix $(TARGET)
|
||||||
$(MAKE) -C ../gen
|
$(MAKE) -C ../gen
|
||||||
|
ifneq ($(ONLY_64BIT),1)
|
||||||
./test_nm.sh
|
./test_nm.sh
|
||||||
|
./test_nm.sh noexcept
|
||||||
|
./noexception
|
||||||
./test_nm.sh Y
|
./test_nm.sh Y
|
||||||
./test_nm.sh avx512
|
./test_nm.sh avx512
|
||||||
./test_address.sh
|
./test_address.sh
|
||||||
./jmp
|
./jmp
|
||||||
|
./cvt_test32
|
||||||
|
endif
|
||||||
./bad_address
|
./bad_address
|
||||||
./misc
|
./misc
|
||||||
./cvt_test
|
./cvt_test
|
||||||
./cvt_test32
|
|
||||||
ifeq ($(BIT),64)
|
ifeq ($(BIT),64)
|
||||||
./test_address.sh 64
|
./test_address.sh 64
|
||||||
./test_nm.sh 64
|
./test_nm.sh 64
|
||||||
@ -56,8 +71,10 @@ ifeq ($(BIT),64)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
test_avx: normalize_prefix
|
test_avx: normalize_prefix
|
||||||
|
ifneq ($(ONLY_64BIT),0)
|
||||||
./test_avx.sh
|
./test_avx.sh
|
||||||
./test_avx.sh Y
|
./test_avx.sh Y
|
||||||
|
endif
|
||||||
ifeq ($(BIT),64)
|
ifeq ($(BIT),64)
|
||||||
./test_address.sh 64
|
./test_address.sh 64
|
||||||
./test_avx.sh 64
|
./test_avx.sh 64
|
||||||
@ -65,10 +82,18 @@ ifeq ($(BIT),64)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
test_avx512: normalize_prefix
|
test_avx512: normalize_prefix
|
||||||
|
ifneq ($(ONLY_64BIT),0)
|
||||||
./test_avx512.sh
|
./test_avx512.sh
|
||||||
|
endif
|
||||||
ifeq ($(BIT),64)
|
ifeq ($(BIT),64)
|
||||||
./test_avx512.sh 64
|
./test_avx512.sh 64
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
test:
|
||||||
|
$(MAKE) test_nm
|
||||||
|
$(MAKE) test_avx
|
||||||
|
$(MAKE) test_avx512
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf *.o $(TARGET) lib_run nm.cpp nm_frame make_512
|
rm -rf *.o $(TARGET) lib_run nm.cpp nm_frame make_512
|
||||||
|
|
||||||
|
@ -1,47 +1,28 @@
|
|||||||
#include <xbyak/xbyak.h>
|
#include <xbyak/xbyak.h>
|
||||||
|
#include <cybozu/test.hpp>
|
||||||
#define TEST_EXCEPTION(state) \
|
|
||||||
{ \
|
|
||||||
num++; \
|
|
||||||
bool exception = false; \
|
|
||||||
try { \
|
|
||||||
state; \
|
|
||||||
} catch (...) { \
|
|
||||||
exception = true; \
|
|
||||||
} \
|
|
||||||
if (!exception) { \
|
|
||||||
printf("exception should arise for %s\n", #state); \
|
|
||||||
err++; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Code : Xbyak::CodeGenerator {
|
struct Code : Xbyak::CodeGenerator {
|
||||||
Code()
|
Code()
|
||||||
{
|
{
|
||||||
int err = 0;
|
CYBOZU_TEST_EXCEPTION(mov(eax, ptr [esp + esp]), std::exception);
|
||||||
int num = 0;
|
CYBOZU_TEST_EXCEPTION(mov(eax, ptr [ax]), std::exception); // not support
|
||||||
TEST_EXCEPTION(mov(eax, ptr [esp + esp]));
|
CYBOZU_TEST_EXCEPTION(mov(eax, ptr [esp * 4]), std::exception);
|
||||||
TEST_EXCEPTION(mov(eax, ptr [ax])); // not support
|
CYBOZU_TEST_EXCEPTION(mov(eax, ptr [eax * 16]), std::exception);
|
||||||
TEST_EXCEPTION(mov(eax, ptr [esp * 4]));
|
CYBOZU_TEST_EXCEPTION(mov(eax, ptr [eax + eax + eax]), std::exception);
|
||||||
TEST_EXCEPTION(mov(eax, ptr [eax * 16]));
|
CYBOZU_TEST_EXCEPTION(mov(eax, ptr [eax * 2 + ecx * 4]), std::exception);
|
||||||
TEST_EXCEPTION(mov(eax, ptr [eax + eax + eax]));
|
CYBOZU_TEST_EXCEPTION(mov(eax, ptr [eax * 2 + ecx * 4]), std::exception);
|
||||||
TEST_EXCEPTION(mov(eax, ptr [eax * 2 + ecx * 4]));
|
CYBOZU_TEST_EXCEPTION(mov(eax, ptr [xmm0]), std::exception);
|
||||||
TEST_EXCEPTION(mov(eax, ptr [eax * 2 + ecx * 4]));
|
CYBOZU_TEST_EXCEPTION(fld(dword [xmm0]), std::exception);
|
||||||
TEST_EXCEPTION(mov(eax, ptr [xmm0]));
|
CYBOZU_TEST_EXCEPTION(vgatherdpd(xmm0, ptr [eax * 2], ymm3), std::exception);
|
||||||
TEST_EXCEPTION(fld(dword [xmm0]));
|
CYBOZU_TEST_EXCEPTION(vgatherdpd(xmm0, ptr [xmm0 + xmm1], ymm3), std::exception);
|
||||||
TEST_EXCEPTION(vgatherdpd(xmm0, ptr [eax * 2], ymm3));
|
|
||||||
TEST_EXCEPTION(vgatherdpd(xmm0, ptr [xmm0 + xmm1], ymm3));
|
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
TEST_EXCEPTION(mov(eax, ptr [rax + eax]));
|
CYBOZU_TEST_EXCEPTION(mov(eax, ptr [rax + eax]), std::exception);
|
||||||
TEST_EXCEPTION(mov(eax, ptr [xmm0 + ymm0]));
|
CYBOZU_TEST_EXCEPTION(mov(eax, ptr [xmm0 + ymm0]), std::exception);
|
||||||
#endif
|
#endif
|
||||||
if (!err) {
|
|
||||||
printf("bad_address test %d ok\n", num);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int main()
|
CYBOZU_TEST_AUTO(exception)
|
||||||
{
|
{
|
||||||
Code c;
|
Code c;
|
||||||
}
|
}
|
||||||
|
141
externals/dynarmic/externals/xbyak/test/jmp.cpp
vendored
141
externals/dynarmic/externals/xbyak/test/jmp.cpp
vendored
@ -117,7 +117,7 @@ CYBOZU_TEST_AUTO(test1)
|
|||||||
int offset;
|
int offset;
|
||||||
bool isBack;
|
bool isBack;
|
||||||
bool isShort;
|
bool isShort;
|
||||||
uint8 result[6];
|
uint8_t result[6];
|
||||||
int size;
|
int size;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0, true, true, { 0xeb, 0xfe }, 2 },
|
{ 0, true, true, { 0xeb, 0xfe }, 2 },
|
||||||
@ -133,7 +133,7 @@ CYBOZU_TEST_AUTO(test1)
|
|||||||
const Tbl *p = &tbl[i];
|
const Tbl *p = &tbl[i];
|
||||||
for (int k = 0; k < 2; k++) {
|
for (int k = 0; k < 2; k++) {
|
||||||
TestJmp jmp(p->offset, p->isBack, p->isShort, k == 0);
|
TestJmp jmp(p->offset, p->isBack, p->isShort, k == 0);
|
||||||
const uint8 *q = (const uint8*)jmp.getCode();
|
const uint8_t *q = (const uint8_t*)jmp.getCode();
|
||||||
if (p->isBack) q += p->offset; /* skip nop */
|
if (p->isBack) q += p->offset; /* skip nop */
|
||||||
for (int j = 0; j < p->size; j++) {
|
for (int j = 0; j < p->size; j++) {
|
||||||
CYBOZU_TEST_EQUAL(q[j], p->result[j]);
|
CYBOZU_TEST_EQUAL(q[j], p->result[j]);
|
||||||
@ -205,6 +205,41 @@ CYBOZU_TEST_AUTO(testJmpCx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CYBOZU_TEST_AUTO(loop)
|
||||||
|
{
|
||||||
|
const uint8_t ok[] = {
|
||||||
|
// lp:
|
||||||
|
0x31, 0xC0, // xor eax, eax
|
||||||
|
0xE2, 0xFC, // loop lp
|
||||||
|
0xE0, 0xFA, // loopne lp
|
||||||
|
0xE1, 0xF8, // loope lp
|
||||||
|
};
|
||||||
|
struct Code : CodeGenerator {
|
||||||
|
Code(bool useLabel)
|
||||||
|
{
|
||||||
|
if (useLabel) {
|
||||||
|
Xbyak::Label lp = L();
|
||||||
|
xor_(eax, eax);
|
||||||
|
loop(lp);
|
||||||
|
loopne(lp);
|
||||||
|
loope(lp);
|
||||||
|
} else {
|
||||||
|
L("@@");
|
||||||
|
xor_(eax, eax);
|
||||||
|
loop("@b");
|
||||||
|
loopne("@b");
|
||||||
|
loope("@b");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Code code1(false);
|
||||||
|
CYBOZU_TEST_EQUAL(code1.getSize(), sizeof(ok));
|
||||||
|
CYBOZU_TEST_EQUAL_ARRAY(code1.getCode(), ok, sizeof(ok));
|
||||||
|
Code code2(true);
|
||||||
|
CYBOZU_TEST_EQUAL(code2.getSize(), sizeof(ok));
|
||||||
|
CYBOZU_TEST_EQUAL_ARRAY(code2.getCode(), ok, sizeof(ok));
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(disable : 4310)
|
#pragma warning(disable : 4310)
|
||||||
#endif
|
#endif
|
||||||
@ -337,11 +372,11 @@ CYBOZU_TEST_AUTO(test3)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Xbyak::uint8 bufL[4096 * 32];
|
uint8_t bufL[4096 * 32];
|
||||||
Xbyak::uint8 bufS[4096 * 2];
|
uint8_t bufS[4096 * 2];
|
||||||
|
|
||||||
struct MyAllocator : Xbyak::Allocator {
|
struct MyAllocator : Xbyak::Allocator {
|
||||||
Xbyak::uint8 *alloc(size_t size)
|
uint8_t *alloc(size_t size)
|
||||||
{
|
{
|
||||||
if (size < sizeof(bufS)) {
|
if (size < sizeof(bufS)) {
|
||||||
printf("test use bufS(%d)\n", (int)size);
|
printf("test use bufS(%d)\n", (int)size);
|
||||||
@ -354,7 +389,7 @@ struct MyAllocator : Xbyak::Allocator {
|
|||||||
fprintf(stderr, "no memory %d\n", (int)size);
|
fprintf(stderr, "no memory %d\n", (int)size);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
void free(Xbyak::uint8 *)
|
void free(uint8_t *)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
} myAlloc;
|
} myAlloc;
|
||||||
@ -393,6 +428,7 @@ CYBOZU_TEST_AUTO(test4)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __APPLE__
|
||||||
CYBOZU_TEST_AUTO(test5)
|
CYBOZU_TEST_AUTO(test5)
|
||||||
{
|
{
|
||||||
struct Test5 : Xbyak::CodeGenerator {
|
struct Test5 : Xbyak::CodeGenerator {
|
||||||
@ -440,8 +476,9 @@ CYBOZU_TEST_AUTO(test5)
|
|||||||
gm.assign((const char*)gc.getCode(), gc.getSize());
|
gm.assign((const char*)gc.getCode(), gc.getSize());
|
||||||
CYBOZU_TEST_EQUAL(fm, gm);
|
CYBOZU_TEST_EQUAL(fm, gm);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
size_t getValue(const uint8* p)
|
size_t getValue(const uint8_t* p)
|
||||||
{
|
{
|
||||||
size_t v = 0;
|
size_t v = 0;
|
||||||
for (size_t i = 0; i < sizeof(size_t); i++) {
|
for (size_t i = 0; i < sizeof(size_t); i++) {
|
||||||
@ -450,7 +487,7 @@ size_t getValue(const uint8* p)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkAddr(const uint8 *p, size_t offset, size_t expect)
|
void checkAddr(const uint8_t *p, size_t offset, size_t expect)
|
||||||
{
|
{
|
||||||
size_t v = getValue(p + offset);
|
size_t v = getValue(p + offset);
|
||||||
CYBOZU_TEST_EQUAL(v, size_t(p) + expect);
|
CYBOZU_TEST_EQUAL(v, size_t(p) + expect);
|
||||||
@ -498,7 +535,7 @@ CYBOZU_TEST_AUTO(MovLabel)
|
|||||||
|
|
||||||
const struct {
|
const struct {
|
||||||
int pos;
|
int pos;
|
||||||
uint8 ok;
|
uint8_t ok;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
#ifdef XBYAK32
|
#ifdef XBYAK32
|
||||||
{ 0x00, 0x90 },
|
{ 0x00, 0x90 },
|
||||||
@ -532,11 +569,11 @@ CYBOZU_TEST_AUTO(MovLabel)
|
|||||||
const bool useNewLabel = k == 0;
|
const bool useNewLabel = k == 0;
|
||||||
MovLabelCode code(grow, useNewLabel);
|
MovLabelCode code(grow, useNewLabel);
|
||||||
if (grow) code.ready();
|
if (grow) code.ready();
|
||||||
const uint8* const p = code.getCode();
|
const uint8_t* const p = code.getCode();
|
||||||
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
||||||
int pos = tbl[i].pos;
|
int pos = tbl[i].pos;
|
||||||
uint8 x = p[pos];
|
uint8_t x = p[pos];
|
||||||
uint8 ok = tbl[i].ok;
|
uint8_t ok = tbl[i].ok;
|
||||||
CYBOZU_TEST_EQUAL(x, ok);
|
CYBOZU_TEST_EQUAL(x, ok);
|
||||||
}
|
}
|
||||||
#ifdef XBYAK32
|
#ifdef XBYAK32
|
||||||
@ -1182,11 +1219,11 @@ CYBOZU_TEST_AUTO(rip_jmp)
|
|||||||
CYBOZU_TEST_EQUAL(ret, ret1234() + ret9999());
|
CYBOZU_TEST_EQUAL(ret, ret1234() + ret9999());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XBYAK64_GCC
|
#if 0
|
||||||
CYBOZU_TEST_AUTO(rip_addr)
|
CYBOZU_TEST_AUTO(rip_addr)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
assume |&x - &code| < 2GiB
|
we can't assume |&x - &code| < 2GiB anymore
|
||||||
*/
|
*/
|
||||||
static int x = 5;
|
static int x = 5;
|
||||||
struct Code : Xbyak::CodeGenerator {
|
struct Code : Xbyak::CodeGenerator {
|
||||||
@ -1201,6 +1238,8 @@ CYBOZU_TEST_AUTO(rip_addr)
|
|||||||
CYBOZU_TEST_EQUAL(x, 123);
|
CYBOZU_TEST_EQUAL(x, 123);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __APPLE__
|
||||||
CYBOZU_TEST_AUTO(rip_addr_with_fixed_buf)
|
CYBOZU_TEST_AUTO(rip_addr_with_fixed_buf)
|
||||||
{
|
{
|
||||||
MIE_ALIGN(4096) static char buf[8192];
|
MIE_ALIGN(4096) static char buf[8192];
|
||||||
@ -1225,6 +1264,7 @@ CYBOZU_TEST_AUTO(rip_addr_with_fixed_buf)
|
|||||||
code.setProtectModeRW();
|
code.setProtectModeRW();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
struct ReleaseTestCode : Xbyak::CodeGenerator {
|
struct ReleaseTestCode : Xbyak::CodeGenerator {
|
||||||
ReleaseTestCode(Label& L1, Label& L2, Label& L3)
|
ReleaseTestCode(Label& L1, Label& L2, Label& L3)
|
||||||
@ -1270,3 +1310,76 @@ CYBOZU_TEST_AUTO(release_label_after_code)
|
|||||||
printf("id=%d %d %d %d %d\n", L1.getId(), L2.getId(), L3.getId(), L4.getId(), L5.getId());
|
printf("id=%d %d %d %d %d\n", L1.getId(), L2.getId(), L3.getId(), L4.getId(), L5.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct JmpTypeCode : Xbyak::CodeGenerator {
|
||||||
|
void nops()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 130; i++) {
|
||||||
|
nop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// return jmp code size
|
||||||
|
size_t gen(bool pre, bool large, Xbyak::CodeGenerator::LabelType type)
|
||||||
|
{
|
||||||
|
Label label;
|
||||||
|
if (pre) {
|
||||||
|
L(label);
|
||||||
|
if (large) nops();
|
||||||
|
size_t pos = getSize();
|
||||||
|
jmp(label, type);
|
||||||
|
return getSize() - pos;
|
||||||
|
} else {
|
||||||
|
size_t pos = getSize();
|
||||||
|
jmp(label, type);
|
||||||
|
size_t size = getSize() - pos;
|
||||||
|
if (large) nops();
|
||||||
|
L(label);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CYBOZU_TEST_AUTO(setDefaultJmpNEAR)
|
||||||
|
{
|
||||||
|
const Xbyak::CodeGenerator::LabelType T_SHORT = Xbyak::CodeGenerator::T_SHORT;
|
||||||
|
const Xbyak::CodeGenerator::LabelType T_NEAR = Xbyak::CodeGenerator::T_NEAR;
|
||||||
|
const Xbyak::CodeGenerator::LabelType T_AUTO = Xbyak::CodeGenerator::T_AUTO;
|
||||||
|
const struct {
|
||||||
|
bool pre;
|
||||||
|
bool large;
|
||||||
|
Xbyak::CodeGenerator::LabelType type;
|
||||||
|
size_t expect1; // 0 means exception
|
||||||
|
size_t expect2;
|
||||||
|
} tbl[] = {
|
||||||
|
{ false, false, T_SHORT, 2, 2 },
|
||||||
|
{ false, false, T_NEAR, 5, 5 },
|
||||||
|
{ false, true, T_SHORT, 0, 0 },
|
||||||
|
{ false, true, T_NEAR, 5, 5 },
|
||||||
|
|
||||||
|
{ true, false, T_SHORT, 2, 2 },
|
||||||
|
{ true, false, T_NEAR, 5, 5 },
|
||||||
|
{ true, true, T_SHORT, 0, 0 },
|
||||||
|
{ true, true, T_NEAR, 5, 5 },
|
||||||
|
|
||||||
|
{ false, false, T_AUTO, 2, 5 },
|
||||||
|
{ false, true, T_AUTO, 0, 5 },
|
||||||
|
{ true, false, T_AUTO, 2, 2 },
|
||||||
|
{ true, true, T_AUTO, 5, 5 },
|
||||||
|
};
|
||||||
|
JmpTypeCode code1, code2;
|
||||||
|
code2.setDefaultJmpNEAR(true);
|
||||||
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
||||||
|
if (tbl[i].expect1) {
|
||||||
|
size_t size = code1.gen(tbl[i].pre, tbl[i].large, tbl[i].type);
|
||||||
|
CYBOZU_TEST_EQUAL(size, tbl[i].expect1);
|
||||||
|
} else {
|
||||||
|
CYBOZU_TEST_EXCEPTION(code1.gen(tbl[i].pre, tbl[i].large, tbl[i].type), std::exception);
|
||||||
|
}
|
||||||
|
if (tbl[i].expect2) {
|
||||||
|
size_t size = code2.gen(tbl[i].pre, tbl[i].large, tbl[i].type);
|
||||||
|
CYBOZU_TEST_EQUAL(size, tbl[i].expect2);
|
||||||
|
} else {
|
||||||
|
CYBOZU_TEST_EXCEPTION(code2.gen(tbl[i].pre, tbl[i].large, tbl[i].type), std::exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
205
externals/dynarmic/externals/xbyak/test/make_512.cpp
vendored
205
externals/dynarmic/externals/xbyak/test/make_512.cpp
vendored
@ -9,111 +9,111 @@ using namespace Xbyak;
|
|||||||
|
|
||||||
const int bitEnd = 64;
|
const int bitEnd = 64;
|
||||||
|
|
||||||
const uint64 YMM_SAE = 1ULL << 0;
|
const uint64_t YMM_SAE = 1ULL << 0;
|
||||||
const uint64 _XMM = 1ULL << 1;
|
const uint64_t _XMM = 1ULL << 1;
|
||||||
const uint64 _MEM = 1ULL << 2;
|
const uint64_t _MEM = 1ULL << 2;
|
||||||
const uint64 _REG32 = 1ULL << 3;
|
const uint64_t _REG32 = 1ULL << 3;
|
||||||
const uint64 EAX = 1ULL << 4;
|
const uint64_t EAX = 1ULL << 4;
|
||||||
const uint64 IMM32 = 1ULL << 5;
|
const uint64_t IMM32 = 1ULL << 5;
|
||||||
const uint64 IMM8 = 1ULL << 6;
|
const uint64_t IMM8 = 1ULL << 6;
|
||||||
const uint64 _REG8 = 1ULL << 7;
|
const uint64_t _REG8 = 1ULL << 7;
|
||||||
const uint64 _REG16 = 1ULL << 8;
|
const uint64_t _REG16 = 1ULL << 8;
|
||||||
const uint64 XMM_K = 1ULL << 9;
|
const uint64_t XMM_K = 1ULL << 9;
|
||||||
const uint64 YMM_K = 1ULL << 10;
|
const uint64_t YMM_K = 1ULL << 10;
|
||||||
const uint64 ZMM_K = 1ULL << 11;
|
const uint64_t ZMM_K = 1ULL << 11;
|
||||||
const uint64 AX = 1ULL << 12;
|
const uint64_t AX = 1ULL << 12;
|
||||||
const uint64 AL = 1ULL << 13;
|
const uint64_t AL = 1ULL << 13;
|
||||||
const uint64 IMM_1 = 1ULL << 14;
|
const uint64_t IMM_1 = 1ULL << 14;
|
||||||
const uint64 MEM8 = 1ULL << 15;
|
const uint64_t MEM8 = 1ULL << 15;
|
||||||
const uint64 MEM16 = 1ULL << 16;
|
const uint64_t MEM16 = 1ULL << 16;
|
||||||
const uint64 MEM32 = 1ULL << 17;
|
const uint64_t MEM32 = 1ULL << 17;
|
||||||
const uint64 VM32Z = 1ULL << 19;
|
const uint64_t VM32Z = 1ULL << 19;
|
||||||
const uint64 K_K = 1ULL << 20;
|
const uint64_t K_K = 1ULL << 20;
|
||||||
const uint64 MEM_ONLY_DISP = 1ULL << 21;
|
const uint64_t MEM_ONLY_DISP = 1ULL << 21;
|
||||||
const uint64 VM32X_K = 1ULL << 23;
|
const uint64_t VM32X_K = 1ULL << 23;
|
||||||
const uint64 _YMM = 1ULL << 24;
|
const uint64_t _YMM = 1ULL << 24;
|
||||||
const uint64 VM32X_32 = 1ULL << 39;
|
const uint64_t VM32X_32 = 1ULL << 39;
|
||||||
const uint64 VM32X_64 = 1ULL << 40;
|
const uint64_t VM32X_64 = 1ULL << 40;
|
||||||
const uint64 VM32Y_32 = 1ULL << 41;
|
const uint64_t VM32Y_32 = 1ULL << 41;
|
||||||
const uint64 VM32Y_64 = 1ULL << 42;
|
const uint64_t VM32Y_64 = 1ULL << 42;
|
||||||
const uint64 VM32Z_K = 1ULL << 32;
|
const uint64_t VM32Z_K = 1ULL << 32;
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
const uint64 _MEMe = 1ULL << 25;
|
const uint64_t _MEMe = 1ULL << 25;
|
||||||
const uint64 REG32_2 = 1ULL << 26; // r8d, ...
|
const uint64_t REG32_2 = 1ULL << 26; // r8d, ...
|
||||||
const uint64 REG16_2 = 1ULL << 27; // r8w, ...
|
const uint64_t REG16_2 = 1ULL << 27; // r8w, ...
|
||||||
const uint64 REG8_2 = 1ULL << 28; // r8b, ...
|
const uint64_t REG8_2 = 1ULL << 28; // r8b, ...
|
||||||
const uint64 REG8_3 = 1ULL << 29; // spl, ...
|
const uint64_t REG8_3 = 1ULL << 29; // spl, ...
|
||||||
const uint64 _REG64 = 1ULL << 30; // rax, ...
|
const uint64_t _REG64 = 1ULL << 30; // rax, ...
|
||||||
const uint64 _REG64_2 = 1ULL << 31; // r8, ...
|
const uint64_t _REG64_2 = 1ULL << 31; // r8, ...
|
||||||
const uint64 _XMM2 = 1ULL << 33;
|
const uint64_t _XMM2 = 1ULL << 33;
|
||||||
const uint64 _YMM2 = 1ULL << 34;
|
const uint64_t _YMM2 = 1ULL << 34;
|
||||||
const uint64 VM32X = VM32X_32 | VM32X_64;
|
const uint64_t VM32X = VM32X_32 | VM32X_64;
|
||||||
const uint64 VM32Y = VM32Y_32 | VM32Y_64;
|
const uint64_t VM32Y = VM32Y_32 | VM32Y_64;
|
||||||
#else
|
#else
|
||||||
const uint64 _MEMe = 0;
|
const uint64_t _MEMe = 0;
|
||||||
const uint64 REG32_2 = 0;
|
const uint64_t REG32_2 = 0;
|
||||||
const uint64 REG16_2 = 0;
|
const uint64_t REG16_2 = 0;
|
||||||
const uint64 REG8_2 = 0;
|
const uint64_t REG8_2 = 0;
|
||||||
const uint64 REG8_3 = 0;
|
const uint64_t REG8_3 = 0;
|
||||||
const uint64 _REG64 = 0;
|
const uint64_t _REG64 = 0;
|
||||||
const uint64 _REG64_2 = 0;
|
const uint64_t _REG64_2 = 0;
|
||||||
const uint64 _XMM2 = 0;
|
const uint64_t _XMM2 = 0;
|
||||||
const uint64 _YMM2 = 0;
|
const uint64_t _YMM2 = 0;
|
||||||
const uint64 VM32X = VM32X_32;
|
const uint64_t VM32X = VM32X_32;
|
||||||
const uint64 VM32Y = VM32Y_32;
|
const uint64_t VM32Y = VM32Y_32;
|
||||||
#endif
|
#endif
|
||||||
const uint64 REG64 = _REG64 | _REG64_2;
|
const uint64_t REG64 = _REG64 | _REG64_2;
|
||||||
const uint64 REG32 = _REG32 | REG32_2 | EAX;
|
const uint64_t REG32 = _REG32 | REG32_2 | EAX;
|
||||||
const uint64 REG16 = _REG16 | REG16_2 | AX;
|
const uint64_t REG16 = _REG16 | REG16_2 | AX;
|
||||||
const uint64 REG32e = REG32 | REG64;
|
const uint64_t REG32e = REG32 | REG64;
|
||||||
const uint64 REG8 = _REG8 | REG8_2|AL;
|
const uint64_t REG8 = _REG8 | REG8_2|AL;
|
||||||
const uint64 MEM = _MEM | _MEMe;
|
const uint64_t MEM = _MEM | _MEMe;
|
||||||
const uint64 MEM64 = 1ULL << 35;
|
const uint64_t MEM64 = 1ULL << 35;
|
||||||
const uint64 YMM_ER = 1ULL << 36;
|
const uint64_t YMM_ER = 1ULL << 36;
|
||||||
const uint64 VM32Y_K = 1ULL << 37;
|
const uint64_t VM32Y_K = 1ULL << 37;
|
||||||
const uint64 IMM_2 = 1ULL << 38;
|
const uint64_t IMM_2 = 1ULL << 38;
|
||||||
const uint64 IMM = IMM_1 | IMM_2;
|
const uint64_t IMM = IMM_1 | IMM_2;
|
||||||
const uint64 YMM = _YMM | _YMM2;
|
const uint64_t YMM = _YMM | _YMM2;
|
||||||
const uint64 K = 1ULL << 43;
|
const uint64_t K = 1ULL << 43;
|
||||||
const uint64 _ZMM = 1ULL << 44;
|
const uint64_t _ZMM = 1ULL << 44;
|
||||||
const uint64 _ZMM2 = 1ULL << 45;
|
const uint64_t _ZMM2 = 1ULL << 45;
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
const uint64 ZMM = _ZMM | _ZMM2;
|
const uint64_t ZMM = _ZMM | _ZMM2;
|
||||||
const uint64 _YMM3 = 1ULL << 46;
|
const uint64_t _YMM3 = 1ULL << 46;
|
||||||
#else
|
#else
|
||||||
const uint64 ZMM = _ZMM;
|
const uint64_t ZMM = _ZMM;
|
||||||
const uint64 _YMM3 = 0;
|
const uint64_t _YMM3 = 0;
|
||||||
#endif
|
#endif
|
||||||
const uint64 K2 = 1ULL << 47;
|
const uint64_t K2 = 1ULL << 47;
|
||||||
const uint64 ZMM_SAE = 1ULL << 48;
|
const uint64_t ZMM_SAE = 1ULL << 48;
|
||||||
const uint64 ZMM_ER = 1ULL << 49;
|
const uint64_t ZMM_ER = 1ULL << 49;
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
const uint64 _XMM3 = 1ULL << 50;
|
const uint64_t _XMM3 = 1ULL << 50;
|
||||||
#else
|
#else
|
||||||
const uint64 _XMM3 = 0;
|
const uint64_t _XMM3 = 0;
|
||||||
#endif
|
#endif
|
||||||
const uint64 XMM = _XMM | _XMM2 | _XMM3;
|
const uint64_t XMM = _XMM | _XMM2 | _XMM3;
|
||||||
const uint64 XMM_SAE = 1ULL << 51;
|
const uint64_t XMM_SAE = 1ULL << 51;
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
const uint64 XMM_KZ = 1ULL << 52;
|
const uint64_t XMM_KZ = 1ULL << 52;
|
||||||
const uint64 YMM_KZ = 1ULL << 53;
|
const uint64_t YMM_KZ = 1ULL << 53;
|
||||||
const uint64 ZMM_KZ = 1ULL << 54;
|
const uint64_t ZMM_KZ = 1ULL << 54;
|
||||||
#else
|
#else
|
||||||
const uint64 XMM_KZ = 0;
|
const uint64_t XMM_KZ = 0;
|
||||||
const uint64 YMM_KZ = 0;
|
const uint64_t YMM_KZ = 0;
|
||||||
const uint64 ZMM_KZ = 0;
|
const uint64_t ZMM_KZ = 0;
|
||||||
#endif
|
#endif
|
||||||
const uint64 MEM_K = 1ULL << 55;
|
const uint64_t MEM_K = 1ULL << 55;
|
||||||
const uint64 M_1to2 = 1ULL << 56;
|
const uint64_t M_1to2 = 1ULL << 56;
|
||||||
const uint64 M_1to4 = 1ULL << 57;
|
const uint64_t M_1to4 = 1ULL << 57;
|
||||||
const uint64 M_1to8 = 1ULL << 58;
|
const uint64_t M_1to8 = 1ULL << 58;
|
||||||
const uint64 M_1to16 = 1ULL << 59;
|
const uint64_t M_1to16 = 1ULL << 59;
|
||||||
const uint64 XMM_ER = 1ULL << 60;
|
const uint64_t XMM_ER = 1ULL << 60;
|
||||||
const uint64 M_xword = 1ULL << 61;
|
const uint64_t M_xword = 1ULL << 61;
|
||||||
const uint64 M_yword = 1ULL << 62;
|
const uint64_t M_yword = 1ULL << 62;
|
||||||
const uint64 MY_1to4 = 1ULL << 18;
|
const uint64_t MY_1to4 = 1ULL << 18;
|
||||||
|
|
||||||
const uint64 NOPARA = 1ULL << (bitEnd - 1);
|
const uint64_t NOPARA = 1ULL << (bitEnd - 1);
|
||||||
|
|
||||||
class Test {
|
class Test {
|
||||||
Test(const Test&);
|
Test(const Test&);
|
||||||
@ -121,7 +121,7 @@ class Test {
|
|||||||
const bool isXbyak_;
|
const bool isXbyak_;
|
||||||
int funcNum_;
|
int funcNum_;
|
||||||
// check all op1, op2, op3
|
// check all op1, op2, op3
|
||||||
void put(const std::string& nm, uint64 op1 = NOPARA, uint64 op2 = NOPARA, uint64 op3 = NOPARA, uint64 op4 = NOPARA) const
|
void put(const std::string& nm, uint64_t op1 = NOPARA, uint64_t op2 = NOPARA, uint64_t op3 = NOPARA, uint64_t op4 = NOPARA) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < bitEnd; i++) {
|
for (int i = 0; i < bitEnd; i++) {
|
||||||
if ((op1 & (1ULL << i)) == 0) continue;
|
if ((op1 & (1ULL << i)) == 0) continue;
|
||||||
@ -144,7 +144,7 @@ class Test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void put(const char *nm, uint64 op, const char *xbyak, const char *nasm) const
|
void put(const char *nm, uint64_t op, const char *xbyak, const char *nasm) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < bitEnd; i++) {
|
for (int i = 0; i < bitEnd; i++) {
|
||||||
if ((op & (1ULL << i)) == 0) continue;
|
if ((op & (1ULL << i)) == 0) continue;
|
||||||
@ -156,7 +156,7 @@ class Test {
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void put(const char *nm, const char *xbyak, const char *nasm = 0, uint64 op = NOPARA) const
|
void put(const char *nm, const char *xbyak, const char *nasm = 0, uint64_t op = NOPARA) const
|
||||||
{
|
{
|
||||||
if (nasm == 0) nasm = xbyak;
|
if (nasm == 0) nasm = xbyak;
|
||||||
for (int i = 0; i < bitEnd; i++) {
|
for (int i = 0; i < bitEnd; i++) {
|
||||||
@ -169,7 +169,7 @@ class Test {
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const char *get(uint64 type) const
|
const char *get(uint64_t type) const
|
||||||
{
|
{
|
||||||
int idx = (rand() / 31) & 7;
|
int idx = (rand() / 31) & 7;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -537,7 +537,7 @@ public:
|
|||||||
printf("vaddpd(%s%s%s, %s, %s%s); dump();\n", r1, pk, pz, r2, r3, saeTblXbyak[sae]);
|
printf("vaddpd(%s%s%s, %s, %s%s); dump();\n", r1, pk, pz, r2, r3, saeTblXbyak[sae]);
|
||||||
} else {
|
} else {
|
||||||
if (kIdx) CYBOZU_SNPRINTF(pk, sizeof(pk), "{k%d}", kIdx);
|
if (kIdx) CYBOZU_SNPRINTF(pk, sizeof(pk), "{k%d}", kIdx);
|
||||||
if (z) pz = "{z}";
|
if (z && kIdx) pz = "{z}";
|
||||||
printf("vaddpd %s%s%s, %s, %s%s\n", r1, pk, pz, r2, r3, saeTblNASM[sae]);
|
printf("vaddpd %s%s%s, %s, %s%s\n", r1, pk, pz, r2, r3, saeTblNASM[sae]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -574,9 +574,9 @@ public:
|
|||||||
for (size_t k = 0; k < N; k++) {
|
for (size_t k = 0; k < N; k++) {
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
for (int kIdx = 0; kIdx < 8; kIdx++) {
|
for (int kIdx = 0; kIdx < 8; kIdx++) {
|
||||||
|
put_vaddpd(xTbl[i], xTbl[j], xTbl[k], kIdx);
|
||||||
|
put_vaddpd(yTbl[i], yTbl[j], yTbl[k], kIdx);
|
||||||
for (int z = 0; z < 2; z++) {
|
for (int z = 0; z < 2; z++) {
|
||||||
put_vaddpd(xTbl[i], xTbl[j], xTbl[k], kIdx, z == 1);
|
|
||||||
put_vaddpd(yTbl[i], yTbl[j], yTbl[k], kIdx, z == 1);
|
|
||||||
for (int sae = 0; sae < 5; sae++) {
|
for (int sae = 0; sae < 5; sae++) {
|
||||||
put_vaddpd(zTbl[i], zTbl[j], zTbl[k], kIdx, z == 1, sae);
|
put_vaddpd(zTbl[i], zTbl[j], zTbl[k], kIdx, z == 1, sae);
|
||||||
}
|
}
|
||||||
@ -615,6 +615,13 @@ public:
|
|||||||
put(p->name, K, _YMM, _YMM | MEM, IMM8);
|
put(p->name, K, _YMM, _YMM | MEM, IMM8);
|
||||||
put(p->name, K, _ZMM, _ZMM | MEM, IMM8);
|
put(p->name, K, _ZMM, _ZMM | MEM, IMM8);
|
||||||
}
|
}
|
||||||
|
put("vcmppd", K, XMM, M_1to2, IMM8);
|
||||||
|
put("vcmppd", K, YMM, M_1to4, IMM8);
|
||||||
|
put("vcmppd", K, ZMM, M_1to8, IMM8);
|
||||||
|
|
||||||
|
put("vcmpps", K, XMM, M_1to4, IMM8);
|
||||||
|
put("vcmpps", K, YMM, M_1to8, IMM8);
|
||||||
|
put("vcmpps", K, ZMM, M_1to16, IMM8);
|
||||||
}
|
}
|
||||||
put("vcmppd", K2, ZMM, ZMM_SAE, IMM);
|
put("vcmppd", K2, ZMM, ZMM_SAE, IMM);
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
|
340
externals/dynarmic/externals/xbyak/test/make_nm.cpp
vendored
340
externals/dynarmic/externals/xbyak/test/make_nm.cpp
vendored
@ -1,5 +1,4 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#define XBYAK_NO_OP_NAMES
|
|
||||||
#include "xbyak/xbyak.h"
|
#include "xbyak/xbyak.h"
|
||||||
#include "xbyak/xbyak_bin2hex.h"
|
#include "xbyak/xbyak_bin2hex.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -11,111 +10,111 @@ using namespace Xbyak;
|
|||||||
|
|
||||||
const int bitEnd = 64;
|
const int bitEnd = 64;
|
||||||
|
|
||||||
const uint64 MMX = 1ULL << 0;
|
const uint64_t MMX = 1ULL << 0;
|
||||||
const uint64 _XMM = 1ULL << 1;
|
const uint64_t _XMM = 1ULL << 1;
|
||||||
const uint64 _MEM = 1ULL << 2;
|
const uint64_t _MEM = 1ULL << 2;
|
||||||
const uint64 _REG32 = 1ULL << 3;
|
const uint64_t _REG32 = 1ULL << 3;
|
||||||
const uint64 EAX = 1ULL << 4;
|
const uint64_t EAX = 1ULL << 4;
|
||||||
const uint64 IMM32 = 1ULL << 5;
|
const uint64_t IMM32 = 1ULL << 5;
|
||||||
const uint64 IMM8 = 1ULL << 6;
|
const uint64_t IMM8 = 1ULL << 6;
|
||||||
const uint64 _REG8 = 1ULL << 7;
|
const uint64_t _REG8 = 1ULL << 7;
|
||||||
const uint64 _REG16 = 1ULL << 8;
|
const uint64_t _REG16 = 1ULL << 8;
|
||||||
const uint64 NEG8 = 1ULL << 9;
|
const uint64_t NEG8 = 1ULL << 9;
|
||||||
const uint64 IMM16 = 1ULL << 10;
|
const uint64_t IMM16 = 1ULL << 10;
|
||||||
const uint64 NEG16 = 1ULL << 11;
|
const uint64_t NEG16 = 1ULL << 11;
|
||||||
const uint64 AX = 1ULL << 12;
|
const uint64_t AX = 1ULL << 12;
|
||||||
const uint64 AL = 1ULL << 13;
|
const uint64_t AL = 1ULL << 13;
|
||||||
const uint64 IMM_1 = 1ULL << 14;
|
const uint64_t IMM_1 = 1ULL << 14;
|
||||||
const uint64 MEM8 = 1ULL << 15;
|
const uint64_t MEM8 = 1ULL << 15;
|
||||||
const uint64 MEM16 = 1ULL << 16;
|
const uint64_t MEM16 = 1ULL << 16;
|
||||||
const uint64 MEM32 = 1ULL << 17;
|
const uint64_t MEM32 = 1ULL << 17;
|
||||||
const uint64 ONE = 1ULL << 19;
|
const uint64_t ONE = 1ULL << 19;
|
||||||
const uint64 CL = 1ULL << 20;
|
const uint64_t CL = 1ULL << 20;
|
||||||
const uint64 MEM_ONLY_DISP = 1ULL << 21;
|
const uint64_t MEM_ONLY_DISP = 1ULL << 21;
|
||||||
const uint64 NEG32 = 1ULL << 23;
|
const uint64_t NEG32 = 1ULL << 23;
|
||||||
const uint64 _YMM = 1ULL << 24;
|
const uint64_t _YMM = 1ULL << 24;
|
||||||
const uint64 VM32X_32 = 1ULL << 39;
|
const uint64_t VM32X_32 = 1ULL << 39;
|
||||||
const uint64 VM32X_64 = 1ULL << 40;
|
const uint64_t VM32X_64 = 1ULL << 40;
|
||||||
const uint64 VM32Y_32 = 1ULL << 41;
|
const uint64_t VM32Y_32 = 1ULL << 41;
|
||||||
const uint64 VM32Y_64 = 1ULL << 42;
|
const uint64_t VM32Y_64 = 1ULL << 42;
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
const uint64 _MEMe = 1ULL << 25;
|
const uint64_t _MEMe = 1ULL << 25;
|
||||||
const uint64 REG32_2 = 1ULL << 26; // r8d, ...
|
const uint64_t REG32_2 = 1ULL << 26; // r8d, ...
|
||||||
const uint64 REG16_2 = 1ULL << 27; // r8w, ...
|
const uint64_t REG16_2 = 1ULL << 27; // r8w, ...
|
||||||
const uint64 REG8_2 = 1ULL << 28; // r8b, ...
|
const uint64_t REG8_2 = 1ULL << 28; // r8b, ...
|
||||||
const uint64 REG8_3 = 1ULL << 29; // spl, ...
|
const uint64_t REG8_3 = 1ULL << 29; // spl, ...
|
||||||
const uint64 _REG64 = 1ULL << 30; // rax, ...
|
const uint64_t _REG64 = 1ULL << 30; // rax, ...
|
||||||
const uint64 _REG64_2 = 1ULL << 31; // r8, ...
|
const uint64_t _REG64_2 = 1ULL << 31; // r8, ...
|
||||||
const uint64 RAX = 1ULL << 32;
|
const uint64_t RAX = 1ULL << 32;
|
||||||
const uint64 _XMM2 = 1ULL << 33;
|
const uint64_t _XMM2 = 1ULL << 33;
|
||||||
const uint64 _YMM2 = 1ULL << 34;
|
const uint64_t _YMM2 = 1ULL << 34;
|
||||||
const uint64 VM32X = VM32X_32 | VM32X_64;
|
const uint64_t VM32X = VM32X_32 | VM32X_64;
|
||||||
const uint64 VM32Y = VM32Y_32 | VM32Y_64;
|
const uint64_t VM32Y = VM32Y_32 | VM32Y_64;
|
||||||
#else
|
#else
|
||||||
const uint64 _MEMe = 0;
|
const uint64_t _MEMe = 0;
|
||||||
const uint64 REG32_2 = 0;
|
const uint64_t REG32_2 = 0;
|
||||||
const uint64 REG16_2 = 0;
|
const uint64_t REG16_2 = 0;
|
||||||
const uint64 REG8_2 = 0;
|
const uint64_t REG8_2 = 0;
|
||||||
const uint64 REG8_3 = 0;
|
const uint64_t REG8_3 = 0;
|
||||||
const uint64 _REG64 = 0;
|
const uint64_t _REG64 = 0;
|
||||||
const uint64 _REG64_2 = 0;
|
const uint64_t _REG64_2 = 0;
|
||||||
const uint64 RAX = 0;
|
const uint64_t RAX = 0;
|
||||||
const uint64 _XMM2 = 0;
|
const uint64_t _XMM2 = 0;
|
||||||
const uint64 _YMM2 = 0;
|
const uint64_t _YMM2 = 0;
|
||||||
const uint64 VM32X = VM32X_32;
|
const uint64_t VM32X = VM32X_32;
|
||||||
const uint64 VM32Y = VM32Y_32;
|
const uint64_t VM32Y = VM32Y_32;
|
||||||
#endif
|
#endif
|
||||||
const uint64 REG64 = _REG64 | _REG64_2 | RAX;
|
const uint64_t REG64 = _REG64 | _REG64_2 | RAX;
|
||||||
const uint64 REG32 = _REG32 | REG32_2 | EAX;
|
const uint64_t REG32 = _REG32 | REG32_2 | EAX;
|
||||||
const uint64 REG16 = _REG16 | REG16_2 | AX;
|
const uint64_t REG16 = _REG16 | REG16_2 | AX;
|
||||||
const uint64 REG32e = REG32 | REG64;
|
const uint64_t REG32e = REG32 | REG64;
|
||||||
const uint64 REG8 = _REG8 | REG8_2|AL;
|
const uint64_t REG8 = _REG8 | REG8_2|AL;
|
||||||
const uint64 MEM = _MEM | _MEMe;
|
const uint64_t MEM = _MEM | _MEMe;
|
||||||
const uint64 MEM64 = 1ULL << 35;
|
const uint64_t MEM64 = 1ULL << 35;
|
||||||
const uint64 ST0 = 1ULL << 36;
|
const uint64_t ST0 = 1ULL << 36;
|
||||||
const uint64 STi = 1ULL << 37;
|
const uint64_t STi = 1ULL << 37;
|
||||||
const uint64 IMM_2 = 1ULL << 38;
|
const uint64_t IMM_2 = 1ULL << 38;
|
||||||
const uint64 IMM = IMM_1 | IMM_2;
|
const uint64_t IMM = IMM_1 | IMM_2;
|
||||||
const uint64 XMM = _XMM | _XMM2;
|
const uint64_t XMM = _XMM | _XMM2;
|
||||||
const uint64 YMM = _YMM | _YMM2;
|
const uint64_t YMM = _YMM | _YMM2;
|
||||||
const uint64 K = 1ULL << 43;
|
const uint64_t K = 1ULL << 43;
|
||||||
const uint64 _ZMM = 1ULL << 44;
|
const uint64_t _ZMM = 1ULL << 44;
|
||||||
const uint64 _ZMM2 = 1ULL << 45;
|
const uint64_t _ZMM2 = 1ULL << 45;
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
const uint64 ZMM = _ZMM | _ZMM2;
|
const uint64_t ZMM = _ZMM | _ZMM2;
|
||||||
const uint64 _YMM3 = 1ULL << 46;
|
const uint64_t _YMM3 = 1ULL << 46;
|
||||||
#else
|
#else
|
||||||
const uint64 ZMM = _ZMM;
|
const uint64_t ZMM = _ZMM;
|
||||||
const uint64 _YMM3 = 0;
|
const uint64_t _YMM3 = 0;
|
||||||
#endif
|
#endif
|
||||||
const uint64 K2 = 1ULL << 47;
|
const uint64_t K2 = 1ULL << 47;
|
||||||
const uint64 ZMM_SAE = 1ULL << 48;
|
const uint64_t ZMM_SAE = 1ULL << 48;
|
||||||
const uint64 ZMM_ER = 1ULL << 49;
|
const uint64_t ZMM_ER = 1ULL << 49;
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
const uint64 _XMM3 = 1ULL << 50;
|
const uint64_t _XMM3 = 1ULL << 50;
|
||||||
#endif
|
#endif
|
||||||
const uint64 XMM_SAE = 1ULL << 51;
|
const uint64_t XMM_SAE = 1ULL << 51;
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
const uint64 XMM_KZ = 1ULL << 52;
|
const uint64_t XMM_KZ = 1ULL << 52;
|
||||||
const uint64 YMM_KZ = 1ULL << 53;
|
const uint64_t YMM_KZ = 1ULL << 53;
|
||||||
const uint64 ZMM_KZ = 1ULL << 54;
|
const uint64_t ZMM_KZ = 1ULL << 54;
|
||||||
#else
|
#else
|
||||||
const uint64 XMM_KZ = 0;
|
const uint64_t XMM_KZ = 0;
|
||||||
const uint64 YMM_KZ = 0;
|
const uint64_t YMM_KZ = 0;
|
||||||
const uint64 ZMM_KZ = 0;
|
const uint64_t ZMM_KZ = 0;
|
||||||
#endif
|
#endif
|
||||||
const uint64 MEM_K = 1ULL << 55;
|
const uint64_t MEM_K = 1ULL << 55;
|
||||||
const uint64 M_1to2 = 1ULL << 56;
|
const uint64_t M_1to2 = 1ULL << 56;
|
||||||
const uint64 M_1to4 = 1ULL << 57;
|
const uint64_t M_1to4 = 1ULL << 57;
|
||||||
const uint64 M_1to8 = 1ULL << 58;
|
const uint64_t M_1to8 = 1ULL << 58;
|
||||||
const uint64 M_1to16 = 1ULL << 59;
|
const uint64_t M_1to16 = 1ULL << 59;
|
||||||
const uint64 XMM_ER = 1ULL << 60;
|
const uint64_t XMM_ER = 1ULL << 60;
|
||||||
const uint64 M_xword = 1ULL << 61;
|
const uint64_t M_xword = 1ULL << 61;
|
||||||
const uint64 M_yword = 1ULL << 62;
|
const uint64_t M_yword = 1ULL << 62;
|
||||||
const uint64 MY_1to4 = 1ULL << 18;
|
const uint64_t MY_1to4 = 1ULL << 18;
|
||||||
const uint64 BNDREG = 1ULL << 22;
|
const uint64_t BNDREG = 1ULL << 22;
|
||||||
|
|
||||||
const uint64 NOPARA = 1ULL << (bitEnd - 1);
|
const uint64_t NOPARA = 1ULL << (bitEnd - 1);
|
||||||
|
|
||||||
class Test {
|
class Test {
|
||||||
Test(const Test&);
|
Test(const Test&);
|
||||||
@ -132,7 +131,7 @@ class Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check all op1, op2, op3
|
// check all op1, op2, op3
|
||||||
void put(const std::string& nm, uint64 op1 = NOPARA, uint64 op2 = NOPARA, uint64 op3 = NOPARA, uint64 op4 = NOPARA) const
|
void put(const std::string& nm, uint64_t op1 = NOPARA, uint64_t op2 = NOPARA, uint64_t op3 = NOPARA, uint64_t op4 = NOPARA) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < bitEnd; i++) {
|
for (int i = 0; i < bitEnd; i++) {
|
||||||
if ((op1 & (1ULL << i)) == 0) continue;
|
if ((op1 & (1ULL << i)) == 0) continue;
|
||||||
@ -155,7 +154,7 @@ class Test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void put(const char *nm, uint64 op, const char *xbyak, const char *nasm) const
|
void put(const char *nm, uint64_t op, const char *xbyak, const char *nasm) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < bitEnd; i++) {
|
for (int i = 0; i < bitEnd; i++) {
|
||||||
if ((op & (1ULL << i)) == 0) continue;
|
if ((op & (1ULL << i)) == 0) continue;
|
||||||
@ -167,7 +166,7 @@ class Test {
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void put(const char *nm, const char *xbyak, const char *nasm = 0, uint64 op = NOPARA) const
|
void put(const char *nm, const char *xbyak, const char *nasm = 0, uint64_t op = NOPARA) const
|
||||||
{
|
{
|
||||||
if (nasm == 0) nasm = xbyak;
|
if (nasm == 0) nasm = xbyak;
|
||||||
for (int i = 0; i < bitEnd; i++) {
|
for (int i = 0; i < bitEnd; i++) {
|
||||||
@ -180,7 +179,7 @@ class Test {
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const char *get(uint64 type) const
|
const char *get(uint64_t type) const
|
||||||
{
|
{
|
||||||
int idx = (rand() / 31) & 7;
|
int idx = (rand() / 31) & 7;
|
||||||
if (type == ST0) {
|
if (type == ST0) {
|
||||||
@ -460,8 +459,14 @@ class Test {
|
|||||||
"cqo",
|
"cqo",
|
||||||
"cmpsq",
|
"cmpsq",
|
||||||
"movsq",
|
"movsq",
|
||||||
|
"popfq",
|
||||||
|
"pushfq",
|
||||||
|
"lodsq",
|
||||||
|
"movsq",
|
||||||
"scasq",
|
"scasq",
|
||||||
"stosq",
|
"stosq",
|
||||||
|
"syscall",
|
||||||
|
"sysret",
|
||||||
#else
|
#else
|
||||||
"aaa",
|
"aaa",
|
||||||
"aad",
|
"aad",
|
||||||
@ -469,6 +474,7 @@ class Test {
|
|||||||
"aas",
|
"aas",
|
||||||
"daa",
|
"daa",
|
||||||
"das",
|
"das",
|
||||||
|
"into",
|
||||||
"popad",
|
"popad",
|
||||||
"popfd",
|
"popfd",
|
||||||
"pusha",
|
"pusha",
|
||||||
@ -493,9 +499,17 @@ class Test {
|
|||||||
"cmpsb",
|
"cmpsb",
|
||||||
"cmpsw",
|
"cmpsw",
|
||||||
"cmpsd",
|
"cmpsd",
|
||||||
|
"int3",
|
||||||
|
"leave",
|
||||||
|
"lodsb",
|
||||||
|
"lodsw",
|
||||||
|
"lodsd",
|
||||||
"movsb",
|
"movsb",
|
||||||
"movsw",
|
"movsw",
|
||||||
"movsd",
|
"movsd",
|
||||||
|
"outsb",
|
||||||
|
"outsw",
|
||||||
|
"outsd",
|
||||||
"scasb",
|
"scasb",
|
||||||
"scasw",
|
"scasw",
|
||||||
"scasd",
|
"scasd",
|
||||||
@ -508,6 +522,8 @@ class Test {
|
|||||||
"stc",
|
"stc",
|
||||||
"std",
|
"std",
|
||||||
"sti",
|
"sti",
|
||||||
|
"sysenter",
|
||||||
|
"sysexit",
|
||||||
|
|
||||||
"emms",
|
"emms",
|
||||||
"pause",
|
"pause",
|
||||||
@ -540,6 +556,8 @@ class Test {
|
|||||||
"fabs",
|
"fabs",
|
||||||
"faddp",
|
"faddp",
|
||||||
"fchs",
|
"fchs",
|
||||||
|
"fclex",
|
||||||
|
"fnclex",
|
||||||
"fcom",
|
"fcom",
|
||||||
"fcomp",
|
"fcomp",
|
||||||
"fcompp",
|
"fcompp",
|
||||||
@ -579,15 +597,52 @@ class Test {
|
|||||||
"fxtract",
|
"fxtract",
|
||||||
"fyl2x",
|
"fyl2x",
|
||||||
"fyl2xp1",
|
"fyl2xp1",
|
||||||
|
|
||||||
|
"monitorx",
|
||||||
|
"mwaitx",
|
||||||
|
"clzero",
|
||||||
};
|
};
|
||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
put(tbl[i]);
|
put(tbl[i]);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
const char memTbl[][16] = {
|
||||||
|
"clflush",
|
||||||
|
"clflushopt",
|
||||||
|
"fbld",
|
||||||
|
"fbstp",
|
||||||
|
"fldcw",
|
||||||
|
"fldenv",
|
||||||
|
"frstor",
|
||||||
|
"fsave",
|
||||||
|
"fnsave",
|
||||||
|
"fstcw",
|
||||||
|
"fnstcw",
|
||||||
|
"fstenv",
|
||||||
|
"fnstenv",
|
||||||
|
"fstsw",
|
||||||
|
"fnstsw",
|
||||||
|
"fxrstor",
|
||||||
|
};
|
||||||
|
for (size_t i = 0; i < NUM_OF_ARRAY(memTbl); i++) {
|
||||||
|
put(memTbl[i], MEM);
|
||||||
|
}
|
||||||
|
put("fstsw", AX);
|
||||||
|
put("fnstsw", AX);
|
||||||
|
}
|
||||||
|
|
||||||
put("bswap", REG32e);
|
put("bswap", REG32e);
|
||||||
put("lea", REG32e|REG16, MEM);
|
put("lea", REG32e|REG16, MEM);
|
||||||
put("fldcw", MEM);
|
put("enter", IMM, IMM);
|
||||||
put("fstcw", MEM);
|
put(isXbyak_ ? "int_" : "int", IMM8);
|
||||||
|
put(isXbyak_ ? "in_" : "in", AL|AX|EAX, IMM8);
|
||||||
|
puts(isXbyak_ ? "in_(al, dx); dump();" : "in al, dx");
|
||||||
|
puts(isXbyak_ ? "in_(ax, dx); dump();" : "in ax, dx");
|
||||||
|
puts(isXbyak_ ? "in_(eax, dx); dump();" : "in eax, dx");
|
||||||
|
put(isXbyak_ ? "out_" : "out", IMM8, AL|AX|EAX);
|
||||||
|
puts(isXbyak_ ? "out_(dx, al); dump();" : "out dx, al");
|
||||||
|
puts(isXbyak_ ? "out_(dx, ax); dump();" : "out dx, ax");
|
||||||
|
puts(isXbyak_ ? "out_(dx, eax); dump();" : "out dx, eax");
|
||||||
}
|
}
|
||||||
void putJmp() const
|
void putJmp() const
|
||||||
{
|
{
|
||||||
@ -803,7 +858,7 @@ class Test {
|
|||||||
SD = 1 << 3
|
SD = 1 << 3
|
||||||
};
|
};
|
||||||
const struct {
|
const struct {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
const char *name;
|
const char *name;
|
||||||
} sufTbl[] = {
|
} sufTbl[] = {
|
||||||
{ 0, "ps" },
|
{ 0, "ps" },
|
||||||
@ -812,7 +867,7 @@ class Test {
|
|||||||
{ 0xF2, "sd" },
|
{ 0xF2, "sd" },
|
||||||
};
|
};
|
||||||
static const struct XmmTbl1 {
|
static const struct XmmTbl1 {
|
||||||
uint8 code;
|
uint8_t code;
|
||||||
int mode;
|
int mode;
|
||||||
const char *name;
|
const char *name;
|
||||||
bool hasImm;
|
bool hasImm;
|
||||||
@ -841,7 +896,7 @@ class Test {
|
|||||||
for (size_t j = 0; j < NUM_OF_ARRAY(sufTbl); j++) {
|
for (size_t j = 0; j < NUM_OF_ARRAY(sufTbl); j++) {
|
||||||
if (!(p->mode & (1 << j))) continue;
|
if (!(p->mode & (1 << j))) continue;
|
||||||
char buf[16];
|
char buf[16];
|
||||||
sprintf(buf, "%s%s", p->name, sufTbl[j].name);
|
snprintf(buf, sizeof(buf), "%s%s", p->name, sufTbl[j].name);
|
||||||
if (p->hasImm) {
|
if (p->hasImm) {
|
||||||
put(buf, XMM, XMM|MEM, IMM);
|
put(buf, XMM, XMM|MEM, IMM);
|
||||||
} else {
|
} else {
|
||||||
@ -891,8 +946,8 @@ class Test {
|
|||||||
{
|
{
|
||||||
static const struct Tbl {
|
static const struct Tbl {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint64 op1;
|
uint64_t op1;
|
||||||
uint64 op2;
|
uint64_t op2;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ "cvtpi2ps", XMM, MMX|MEM },
|
{ "cvtpi2ps", XMM, MMX|MEM },
|
||||||
{ "cvtps2pi", MMX, XMM|MEM },
|
{ "cvtps2pi", MMX, XMM|MEM },
|
||||||
@ -928,7 +983,9 @@ class Test {
|
|||||||
}
|
}
|
||||||
void putCmov() const
|
void putCmov() const
|
||||||
{
|
{
|
||||||
const char tbl[][4] = {
|
const struct {
|
||||||
|
const char *s;
|
||||||
|
} tbl[] = {
|
||||||
"o",
|
"o",
|
||||||
"no",
|
"no",
|
||||||
"b",
|
"b",
|
||||||
@ -961,12 +1018,12 @@ class Test {
|
|||||||
"g",
|
"g",
|
||||||
};
|
};
|
||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
char buf[16];
|
char buf[32];
|
||||||
sprintf(buf, "cmov%s", tbl[i]);
|
snprintf(buf, sizeof(buf), "cmov%s", tbl[i].s);
|
||||||
put(buf, REG16, REG16|MEM);
|
put(buf, REG16, REG16|MEM);
|
||||||
put(buf, REG32, REG32|MEM);
|
put(buf, REG32, REG32|MEM);
|
||||||
put(buf, REG64, REG64|MEM);
|
put(buf, REG64, REG64|MEM);
|
||||||
sprintf(buf, "set%s", tbl[i]);
|
snprintf(buf, sizeof(buf), "set%s", tbl[i].s);
|
||||||
put(buf, REG8|REG8_3|MEM);
|
put(buf, REG8|REG8_3|MEM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1088,6 +1145,33 @@ class Test {
|
|||||||
put("pop", REG32|MEM32);
|
put("pop", REG32|MEM32);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
void putPushPop8_16() const
|
||||||
|
{
|
||||||
|
const struct {
|
||||||
|
int b;
|
||||||
|
uint32_t v;
|
||||||
|
} tbl[] = {
|
||||||
|
{ 8, 0x7f },
|
||||||
|
{ 8, 0x80 },
|
||||||
|
{ 8, 0xff },
|
||||||
|
{ 8, 0x100 },
|
||||||
|
{ 8, 0x12345 },
|
||||||
|
{ 16, 0x7fff },
|
||||||
|
{ 16, 0x8000 },
|
||||||
|
{ 16, 0xffff },
|
||||||
|
{ 16, 0x10000 },
|
||||||
|
{ 16, 0x12345 },
|
||||||
|
};
|
||||||
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
|
const char *b = tbl[i].b == 8 ? "byte" : "word";
|
||||||
|
uint32_t v = tbl[i].v;
|
||||||
|
if (isXbyak_) {
|
||||||
|
printf("push(%s, 0x%x);dump();\n", b, v);
|
||||||
|
} else {
|
||||||
|
printf("push %s 0x%x\n", b, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
void putTest() const
|
void putTest() const
|
||||||
{
|
{
|
||||||
const char *p = "test";
|
const char *p = "test";
|
||||||
@ -1121,6 +1205,30 @@ class Test {
|
|||||||
put("mov", REG64, tbl[i].a, tbl[i].b);
|
put("mov", REG64, tbl[i].a, tbl[i].b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void putLoadSeg() const
|
||||||
|
{
|
||||||
|
const struct Tbl {
|
||||||
|
const char *name;
|
||||||
|
bool support64Bit;
|
||||||
|
} tbl[] = {
|
||||||
|
#ifdef XBYAK32
|
||||||
|
{ "lds", false },
|
||||||
|
{ "les", false },
|
||||||
|
#endif
|
||||||
|
{ "lss", true },
|
||||||
|
{ "lfs", true },
|
||||||
|
{ "lgs", true },
|
||||||
|
};
|
||||||
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
|
const Tbl *p = &tbl[i];
|
||||||
|
put(p->name, REG16|REG32, MEM);
|
||||||
|
#ifdef XBYAK64
|
||||||
|
if (p->support64Bit) {
|
||||||
|
put(p->name, REG64, MEM);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
// only nasm
|
// only nasm
|
||||||
void putMovImm64() const
|
void putMovImm64() const
|
||||||
{
|
{
|
||||||
@ -1176,6 +1284,7 @@ class Test {
|
|||||||
put("cmpxchg8b", MEM);
|
put("cmpxchg8b", MEM);
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
put("cmpxchg16b", MEM);
|
put("cmpxchg16b", MEM);
|
||||||
|
put("fxrstor64", MEM);
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
const char tbl[][8] = {
|
const char tbl[][8] = {
|
||||||
@ -1384,9 +1493,9 @@ class Test {
|
|||||||
void putMPX() const
|
void putMPX() const
|
||||||
{
|
{
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
const uint64 reg = REG64;
|
const uint64_t reg = REG64;
|
||||||
#else
|
#else
|
||||||
const uint64 reg = REG32;
|
const uint64_t reg = REG32;
|
||||||
#endif
|
#endif
|
||||||
put("bndcl", BNDREG, reg|MEM);
|
put("bndcl", BNDREG, reg|MEM);
|
||||||
put("bndcu", BNDREG, reg|MEM);
|
put("bndcu", BNDREG, reg|MEM);
|
||||||
@ -2414,6 +2523,7 @@ public:
|
|||||||
separateFunc();
|
separateFunc();
|
||||||
putSSE4_2();
|
putSSE4_2();
|
||||||
putSeg(); // same behavior as yasm for mov rax, cx
|
putSeg(); // same behavior as yasm for mov rax, cx
|
||||||
|
putPushPop8_16();
|
||||||
#else
|
#else
|
||||||
putSIMPLE();
|
putSIMPLE();
|
||||||
putReg1();
|
putReg1();
|
||||||
@ -2423,6 +2533,7 @@ public:
|
|||||||
putPushPop();
|
putPushPop();
|
||||||
putTest();
|
putTest();
|
||||||
separateFunc();
|
separateFunc();
|
||||||
|
putLoadSeg();
|
||||||
putEtc();
|
putEtc();
|
||||||
putShift();
|
putShift();
|
||||||
putShxd();
|
putShxd();
|
||||||
@ -2447,7 +2558,6 @@ public:
|
|||||||
putFpuMem32_64();
|
putFpuMem32_64();
|
||||||
separateFunc();
|
separateFunc();
|
||||||
putFpuMem16_32_64();
|
putFpuMem16_32_64();
|
||||||
put("clflush", MEM); // current nasm is ok
|
|
||||||
putFpu();
|
putFpu();
|
||||||
putFpuFpu();
|
putFpuFpu();
|
||||||
putCmp();
|
putCmp();
|
||||||
@ -2546,7 +2656,7 @@ public:
|
|||||||
printf("vaddpd(%s%s%s, %s, %s%s); dump();\n", r1, pk, pz, r2, r3, saeTblXbyak[sae]);
|
printf("vaddpd(%s%s%s, %s, %s%s); dump();\n", r1, pk, pz, r2, r3, saeTblXbyak[sae]);
|
||||||
} else {
|
} else {
|
||||||
if (kIdx) CYBOZU_SNPRINTF(pk, sizeof(pk), "{k%d}", kIdx);
|
if (kIdx) CYBOZU_SNPRINTF(pk, sizeof(pk), "{k%d}", kIdx);
|
||||||
if (z) pz = "{z}";
|
if (z && kIdx) pz = "{z}";
|
||||||
printf("vaddpd %s%s%s, %s, %s%s\n", r1, pk, pz, r2, r3, saeTblNASM[sae]);
|
printf("vaddpd %s%s%s, %s, %s%s\n", r1, pk, pz, r2, r3, saeTblNASM[sae]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2583,9 +2693,9 @@ public:
|
|||||||
for (size_t k = 0; k < N; k++) {
|
for (size_t k = 0; k < N; k++) {
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
for (int kIdx = 0; kIdx < 8; kIdx++) {
|
for (int kIdx = 0; kIdx < 8; kIdx++) {
|
||||||
|
put_vaddpd(xTbl[i], xTbl[j], xTbl[k], kIdx);
|
||||||
|
put_vaddpd(yTbl[i], yTbl[j], yTbl[k], kIdx);
|
||||||
for (int z = 0; z < 2; z++) {
|
for (int z = 0; z < 2; z++) {
|
||||||
put_vaddpd(xTbl[i], xTbl[j], xTbl[k], kIdx, z == 1);
|
|
||||||
put_vaddpd(yTbl[i], yTbl[j], yTbl[k], kIdx, z == 1);
|
|
||||||
for (int sae = 0; sae < 5; sae++) {
|
for (int sae = 0; sae < 5; sae++) {
|
||||||
put_vaddpd(zTbl[i], zTbl[j], zTbl[k], kIdx, z == 1, sae);
|
put_vaddpd(zTbl[i], zTbl[j], zTbl[k], kIdx, z == 1, sae);
|
||||||
}
|
}
|
||||||
|
134
externals/dynarmic/externals/xbyak/test/misc.cpp
vendored
134
externals/dynarmic/externals/xbyak/test/misc.cpp
vendored
@ -97,13 +97,43 @@ CYBOZU_TEST_AUTO(align)
|
|||||||
CYBOZU_TEST_EQUAL(size_t(getCurr()) % alignSize, 0u);
|
CYBOZU_TEST_EQUAL(size_t(getCurr()) % alignSize, 0u);
|
||||||
}
|
}
|
||||||
align(alignSize);
|
align(alignSize);
|
||||||
const uint8 *p = getCurr();
|
const uint8_t *p = getCurr();
|
||||||
// do nothing if aligned
|
// do nothing if aligned
|
||||||
align(alignSize);
|
align(alignSize);
|
||||||
CYBOZU_TEST_EQUAL(p, getCurr());
|
CYBOZU_TEST_EQUAL(p, getCurr());
|
||||||
}
|
}
|
||||||
} c;
|
} c;
|
||||||
}
|
}
|
||||||
|
CYBOZU_TEST_AUTO(kmask)
|
||||||
|
{
|
||||||
|
struct Code : Xbyak::CodeGenerator {
|
||||||
|
Code()
|
||||||
|
{
|
||||||
|
CYBOZU_TEST_EXCEPTION(kmovb(k1, ax), std::exception);
|
||||||
|
CYBOZU_TEST_EXCEPTION(kmovw(k1, ax), std::exception);
|
||||||
|
CYBOZU_TEST_EXCEPTION(kmovd(k1, ax), std::exception);
|
||||||
|
CYBOZU_TEST_EXCEPTION(kmovq(k1, eax), std::exception);
|
||||||
|
#ifdef XBYAK64
|
||||||
|
CYBOZU_TEST_EXCEPTION(kmovb(k1, rax), std::exception);
|
||||||
|
CYBOZU_TEST_EXCEPTION(kmovw(k1, rax), std::exception);
|
||||||
|
CYBOZU_TEST_EXCEPTION(kmovd(k1, rax), std::exception);
|
||||||
|
CYBOZU_TEST_NO_EXCEPTION(kmovq(k1, rax));
|
||||||
|
#endif
|
||||||
|
CYBOZU_TEST_NO_EXCEPTION(vmovaps(xm0|k0, ptr[eax]));
|
||||||
|
checkT_z();
|
||||||
|
}
|
||||||
|
void checkT_z()
|
||||||
|
{
|
||||||
|
const uint8_t *p1 = getCurr();
|
||||||
|
vmovaps(zm0, ptr[eax]);
|
||||||
|
const uint8_t *p2 = getCurr();
|
||||||
|
vmovaps(zm0|T_z, ptr[eax]);
|
||||||
|
const uint8_t *end = getCurr();
|
||||||
|
CYBOZU_TEST_EQUAL(p2 - p1, end - p2);
|
||||||
|
CYBOZU_TEST_EQUAL_ARRAY(p1, p2, end - p2);
|
||||||
|
}
|
||||||
|
} c;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
CYBOZU_TEST_AUTO(vfmaddps)
|
CYBOZU_TEST_AUTO(vfmaddps)
|
||||||
@ -683,4 +713,106 @@ CYBOZU_TEST_AUTO(gf2)
|
|||||||
CYBOZU_TEST_EQUAL(c.getSize(), n);
|
CYBOZU_TEST_EQUAL(c.getSize(), n);
|
||||||
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
|
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CYBOZU_TEST_AUTO(bf16)
|
||||||
|
{
|
||||||
|
struct Code : Xbyak::CodeGenerator {
|
||||||
|
Code()
|
||||||
|
{
|
||||||
|
vcvtne2ps2bf16(xmm0 | k1, xmm1, ptr [rax + 64]);
|
||||||
|
vcvtne2ps2bf16(ymm0 | k1 | T_z, ymm0, ptr [rax + 64]);
|
||||||
|
vcvtne2ps2bf16(zmm0 | k1, zmm1, ptr [rax + 64]);
|
||||||
|
|
||||||
|
vcvtneps2bf16(xmm0, xword [rax + 64]);
|
||||||
|
vcvtneps2bf16(xmm0 | k1, yword [rax + 64]);
|
||||||
|
vcvtneps2bf16(ymm0 | k1, zword [rax + 64]);
|
||||||
|
vcvtneps2bf16(ymm0 | k1, ptr [rax + 64]);
|
||||||
|
|
||||||
|
vdpbf16ps(xmm0 | k1, xmm1, ptr [rax + 64]);
|
||||||
|
vdpbf16ps(ymm0 | k1, ymm1, ptr [rax + 64]);
|
||||||
|
vdpbf16ps(zmm0 | k1, zmm1, ptr [rax + 64]);
|
||||||
|
}
|
||||||
|
} c;
|
||||||
|
const uint8_t tbl[] = {
|
||||||
|
0x62, 0xf2, 0x77, 0x09, 0x72, 0x40, 0x04,
|
||||||
|
0x62, 0xf2, 0x7f, 0xa9, 0x72, 0x40, 0x02,
|
||||||
|
0x62, 0xf2, 0x77, 0x49, 0x72, 0x40, 0x01,
|
||||||
|
|
||||||
|
0x62, 0xf2, 0x7e, 0x08, 0x72, 0x40, 0x04,
|
||||||
|
0x62, 0xf2, 0x7e, 0x29, 0x72, 0x40, 0x02,
|
||||||
|
0x62, 0xf2, 0x7e, 0x49, 0x72, 0x40, 0x01,
|
||||||
|
0x62, 0xf2, 0x7e, 0x49, 0x72, 0x40, 0x01,
|
||||||
|
|
||||||
|
0x62, 0xf2, 0x76, 0x09, 0x52, 0x40, 0x04,
|
||||||
|
0x62, 0xf2, 0x76, 0x29, 0x52, 0x40, 0x02,
|
||||||
|
0x62, 0xf2, 0x76, 0x49, 0x52, 0x40, 0x01,
|
||||||
|
};
|
||||||
|
const size_t n = sizeof(tbl) / sizeof(tbl[0]);
|
||||||
|
CYBOZU_TEST_EQUAL(c.getSize(), n);
|
||||||
|
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
CYBOZU_TEST_AUTO(AMX)
|
||||||
|
{
|
||||||
|
struct Code : Xbyak::CodeGenerator {
|
||||||
|
Code()
|
||||||
|
{
|
||||||
|
ldtilecfg(ptr[rax + rcx * 4 + 64]);
|
||||||
|
sttilecfg(ptr[rsp + rax * 8 + 128]);
|
||||||
|
tileloadd(tmm3, ptr[rdi + rdx * 2 + 8]);
|
||||||
|
tileloaddt1(tmm4, ptr[r8 + r9 + 32]);
|
||||||
|
tilerelease();
|
||||||
|
tilestored(ptr[r10 + r11 * 2 + 32], tmm2);
|
||||||
|
tilezero(tmm7);
|
||||||
|
tdpbssd(tmm1, tmm2, tmm3);
|
||||||
|
tdpbsud(tmm2, tmm3, tmm4);
|
||||||
|
tdpbusd(tmm3, tmm4, tmm5);
|
||||||
|
tdpbuud(tmm4, tmm5, tmm6);
|
||||||
|
tdpbf16ps(tmm5, tmm6, tmm7);
|
||||||
|
}
|
||||||
|
} c;
|
||||||
|
// generated code by patch
|
||||||
|
const uint8_t tbl[] = {
|
||||||
|
0xc4, 0xe2, 0x78, 0x49, 0x44, 0x88, 0x40, 0xc4, 0xe2, 0x79, 0x49, 0x84, 0xc4, 0x80, 0x00, 0x00,
|
||||||
|
0x00, 0xc4, 0xe2, 0x7b, 0x4b, 0x5c, 0x57, 0x08, 0xc4, 0x82, 0x79, 0x4b, 0x64, 0x08, 0x20, 0xc4,
|
||||||
|
0xe2, 0x78, 0x49, 0xc0, 0xc4, 0x82, 0x7a, 0x4b, 0x54, 0x5a, 0x20, 0xc4, 0xe2, 0x7b, 0x49, 0xf8,
|
||||||
|
0xc4, 0xe2, 0x63, 0x5e, 0xca, 0xc4, 0xe2, 0x5a, 0x5e, 0xd3, 0xc4, 0xe2, 0x51, 0x5e, 0xdc, 0xc4,
|
||||||
|
0xe2, 0x48, 0x5e, 0xe5, 0xc4, 0xe2, 0x42, 0x5c, 0xee,
|
||||||
|
};
|
||||||
|
const size_t n = sizeof(tbl) / sizeof(tbl[0]);
|
||||||
|
CYBOZU_TEST_EQUAL(c.getSize(), n);
|
||||||
|
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
CYBOZU_TEST_AUTO(tileloadd)
|
||||||
|
{
|
||||||
|
struct Code : Xbyak::CodeGenerator {
|
||||||
|
Code()
|
||||||
|
{
|
||||||
|
tileloadd(tmm1, ptr[r8+r8]);
|
||||||
|
tileloadd(tmm1, ptr[rax+rcx*4]);
|
||||||
|
tileloadd(tmm1, ptr[r8+r9*1+0x40]);
|
||||||
|
}
|
||||||
|
void notSupported()
|
||||||
|
{
|
||||||
|
tileloadd(tmm1, ptr[r8]);
|
||||||
|
}
|
||||||
|
void notSupported2()
|
||||||
|
{
|
||||||
|
tileloadd(tmm1, ptr[r8*2]);
|
||||||
|
}
|
||||||
|
} c;
|
||||||
|
const uint8_t tbl[] = {
|
||||||
|
0xC4, 0x82, 0x7B, 0x4B, 0x0C, 0x00,
|
||||||
|
0xC4, 0xE2, 0x7B, 0x4B, 0x0C, 0x88,
|
||||||
|
0xC4, 0x82, 0x7B, 0x4B, 0x4C, 0x08, 0x40,
|
||||||
|
};
|
||||||
|
const size_t n = sizeof(tbl) / sizeof(tbl[0]);
|
||||||
|
CYBOZU_TEST_EQUAL(c.getSize(), n);
|
||||||
|
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
|
||||||
|
|
||||||
|
// current version does not support this sibmem format
|
||||||
|
CYBOZU_TEST_EXCEPTION(c.notSupported(), std::exception);
|
||||||
|
CYBOZU_TEST_EXCEPTION(c.notSupported2(), std::exception);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#define XBYAK_NO_OP_NAMES
|
|
||||||
#define XBYAK_ENABLE_OMITTED_OPERAND
|
#define XBYAK_ENABLE_OMITTED_OPERAND
|
||||||
#include "xbyak/xbyak.h"
|
#include "xbyak/xbyak.h"
|
||||||
|
#define CYBOZU_TEST_DISABLE_AUTO_RUN
|
||||||
|
#include "cybozu/test.hpp"
|
||||||
|
|
||||||
using namespace Xbyak;
|
using namespace Xbyak;
|
||||||
|
|
||||||
@ -15,39 +16,27 @@ public:
|
|||||||
#include "nm.cpp"
|
#include "nm.cpp"
|
||||||
};
|
};
|
||||||
|
|
||||||
#define _STR(x) #x
|
|
||||||
#define TEST(syntax) err = true; try { syntax; err = false; } catch (Xbyak::Error) { } catch (...) { } if (!err) printf("should be err:%s;\n", _STR(syntax))
|
|
||||||
|
|
||||||
class ErrorSample : public CodeGenerator {
|
class ErrorSample : public CodeGenerator {
|
||||||
void operator=(const ErrorSample&);
|
void operator=(const ErrorSample&);
|
||||||
public:
|
public:
|
||||||
void gen()
|
void gen()
|
||||||
{
|
{
|
||||||
bool err;
|
#ifndef XBYAK_NO_EXCEPTION
|
||||||
TEST(mov(ptr[eax],1));
|
CYBOZU_TEST_EXCEPTION(mov(ptr[eax],1), std::exception);
|
||||||
TEST(test(ptr[eax],1));
|
CYBOZU_TEST_EXCEPTION(test(ptr[eax],1), std::exception);
|
||||||
TEST(adc(ptr[eax],1));
|
CYBOZU_TEST_EXCEPTION(adc(ptr[eax],1), std::exception);
|
||||||
TEST(setz(eax));
|
CYBOZU_TEST_EXCEPTION(setz(eax), std::exception);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
try
|
|
||||||
{
|
{
|
||||||
size_t size = sizeof(Xbyak::Operand);
|
// the size of Operand exceeds 32 bit.
|
||||||
if (size != 4) {
|
CYBOZU_TEST_EQUAL(sizeof(Xbyak::Operand), 8u);
|
||||||
printf("sizeof Operand %d\n", (int)size);
|
Sample s;
|
||||||
}
|
s.gen();
|
||||||
try {
|
|
||||||
Sample s;
|
|
||||||
s.gen();
|
|
||||||
} catch (std::exception& e) {
|
|
||||||
printf("ERR:%s\n", e.what());
|
|
||||||
} catch (...) {
|
|
||||||
printf("unknown error\n");
|
|
||||||
}
|
|
||||||
ErrorSample es;
|
ErrorSample es;
|
||||||
es.gen();
|
es.gen();
|
||||||
} catch (std::exception& e) {
|
|
||||||
printf("err %s\n", e.what());
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
111
externals/dynarmic/externals/xbyak/test/noexception.cpp
vendored
Executable file
111
externals/dynarmic/externals/xbyak/test/noexception.cpp
vendored
Executable file
@ -0,0 +1,111 @@
|
|||||||
|
#define XBYAK_NO_EXCEPTION
|
||||||
|
#include <xbyak/xbyak.h>
|
||||||
|
|
||||||
|
using namespace Xbyak;
|
||||||
|
|
||||||
|
int g_err = 0;
|
||||||
|
int g_test = 0;
|
||||||
|
|
||||||
|
void assertEq(int x, int y)
|
||||||
|
{
|
||||||
|
if (x != y) {
|
||||||
|
printf("ERR x=%d y=%d\n", x, y);
|
||||||
|
g_err++;
|
||||||
|
}
|
||||||
|
g_test++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void assertBool(bool b)
|
||||||
|
{
|
||||||
|
if (!b) {
|
||||||
|
printf("ERR assertBool\n");
|
||||||
|
g_err++;
|
||||||
|
}
|
||||||
|
g_test++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test1()
|
||||||
|
{
|
||||||
|
const int v = 123;
|
||||||
|
struct Code : CodeGenerator {
|
||||||
|
Code()
|
||||||
|
{
|
||||||
|
mov(eax, v);
|
||||||
|
ret();
|
||||||
|
}
|
||||||
|
} c;
|
||||||
|
int (*f)() = c.getCode<int (*)()>();
|
||||||
|
assertEq(f(), v);
|
||||||
|
assertEq(Xbyak::GetError(), ERR_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test2()
|
||||||
|
{
|
||||||
|
struct Code : CodeGenerator {
|
||||||
|
Code()
|
||||||
|
{
|
||||||
|
Label lp;
|
||||||
|
L(lp);
|
||||||
|
L(lp);
|
||||||
|
}
|
||||||
|
} c;
|
||||||
|
assertEq(Xbyak::GetError(), ERR_LABEL_IS_REDEFINED);
|
||||||
|
Xbyak::ClearError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test3()
|
||||||
|
{
|
||||||
|
static struct EmptyAllocator : Xbyak::Allocator {
|
||||||
|
uint8_t *alloc() { return 0; }
|
||||||
|
} emptyAllocator;
|
||||||
|
struct Code : CodeGenerator {
|
||||||
|
Code() : CodeGenerator(8, 0, &emptyAllocator)
|
||||||
|
{
|
||||||
|
mov(eax, 3);
|
||||||
|
assertBool(Xbyak::GetError() == 0);
|
||||||
|
mov(eax, 3);
|
||||||
|
mov(eax, 3);
|
||||||
|
assertBool(Xbyak::GetError() != 0);
|
||||||
|
Xbyak::ClearError();
|
||||||
|
assertBool(Xbyak::GetError() == 0);
|
||||||
|
}
|
||||||
|
} c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test4()
|
||||||
|
{
|
||||||
|
struct Code : CodeGenerator {
|
||||||
|
Code()
|
||||||
|
{
|
||||||
|
mov(ptr[eax], 1);
|
||||||
|
assertBool(Xbyak::GetError() != 0);
|
||||||
|
Xbyak::ClearError();
|
||||||
|
|
||||||
|
test(ptr[eax], 1);
|
||||||
|
assertBool(Xbyak::GetError() != 0);
|
||||||
|
Xbyak::ClearError();
|
||||||
|
|
||||||
|
adc(ptr[eax], 1);
|
||||||
|
assertBool(Xbyak::GetError() != 0);
|
||||||
|
Xbyak::ClearError();
|
||||||
|
|
||||||
|
setz(eax);
|
||||||
|
assertBool(Xbyak::GetError() != 0);
|
||||||
|
Xbyak::ClearError();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test1();
|
||||||
|
test2();
|
||||||
|
test3();
|
||||||
|
test4();
|
||||||
|
if (g_err) {
|
||||||
|
printf("err %d/%d\n", g_err, g_test);
|
||||||
|
} else {
|
||||||
|
printf("all ok %d\n", g_test);
|
||||||
|
}
|
||||||
|
return g_err != 0;
|
||||||
|
}
|
@ -6,7 +6,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
|
||||||
typedef unsigned char uint8;
|
typedef unsigned char uint8_t;
|
||||||
|
|
||||||
std::string normalize(const std::string& line)
|
std::string normalize(const std::string& line)
|
||||||
{
|
{
|
||||||
|
2
externals/dynarmic/externals/xbyak/test/set_opt.bat
vendored
Executable file
2
externals/dynarmic/externals/xbyak/test/set_opt.bat
vendored
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
@echo off
|
||||||
|
set OPT=/EHsc -I../xbyak -I./ /W4 -D_CRT_SECURE_NO_WARNINGS /nologo
|
@ -218,7 +218,7 @@ void check(int x, int y)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void verify(const Xbyak::uint8 *f, int pNum)
|
void verify(const Xbyak::uint8_t *f, int pNum)
|
||||||
{
|
{
|
||||||
switch (pNum) {
|
switch (pNum) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -264,7 +264,7 @@ void testAll()
|
|||||||
}
|
}
|
||||||
for (int tNum = 0; tNum < maxNum; tNum++) {
|
for (int tNum = 0; tNum < maxNum; tNum++) {
|
||||||
// printf("pNum=%d, tNum=%d, stackSize=%d\n", pNum, tNum | opt, stackSize);
|
// printf("pNum=%d, tNum=%d, stackSize=%d\n", pNum, tNum | opt, stackSize);
|
||||||
const Xbyak::uint8 *f = code.getCurr();
|
const Xbyak::uint8_t *f = code.getCurr();
|
||||||
code.gen(pNum, tNum | opt, stackSize);
|
code.gen(pNum, tNum | opt, stackSize);
|
||||||
verify(f, pNum);
|
verify(f, pNum);
|
||||||
/*
|
/*
|
||||||
|
@ -20,7 +20,6 @@ echo "compile nm_frame.cpp"
|
|||||||
g++ $CFLAGS -DXBYAK_TEST nm_frame.cpp -o nm_frame
|
g++ $CFLAGS -DXBYAK_TEST nm_frame.cpp -o nm_frame
|
||||||
./nm_frame > x.lst
|
./nm_frame > x.lst
|
||||||
diff ok.lst x.lst && echo "ok"
|
diff ok.lst x.lst && echo "ok"
|
||||||
wc x.lst
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,12 +33,11 @@ g++ $CFLAGS make_nm.cpp -o make_nm
|
|||||||
./make_nm > a.asm
|
./make_nm > a.asm
|
||||||
echo "asm"
|
echo "asm"
|
||||||
$EXE -f$OPT3 a.asm -l a.lst
|
$EXE -f$OPT3 a.asm -l a.lst
|
||||||
awk '{if (index($3, "-")) { conti=substr($3, 0, length($3) - 1) } else { conti = conti $3; print conti; conti = "" }} ' < a.lst | $FILTER > ok.lst
|
awk '{if (index($3, "-")) { conti=substr($3, 0, length($3) - 1) } else { conti = conti $3; print conti; conti = "" }} ' < a.lst | $FILTER | grep -v "1+1" > ok.lst
|
||||||
|
|
||||||
echo "xbyak"
|
echo "xbyak"
|
||||||
./make_nm jit > nm.cpp
|
./make_nm jit > nm.cpp
|
||||||
echo "compile nm_frame.cpp"
|
echo "compile nm_frame.cpp"
|
||||||
g++ $CFLAGS -DXBYAK_TEST nm_frame.cpp -o nm_frame
|
g++ $CFLAGS -DXBYAK_TEST nm_frame.cpp -o nm_frame
|
||||||
./nm_frame | $FILTER > x.lst
|
./nm_frame | $FILTER > x.lst
|
||||||
diff ok.lst x.lst && echo "ok"
|
diff -B ok.lst x.lst && echo "ok"
|
||||||
exit 0
|
|
||||||
|
@ -29,5 +29,4 @@ echo "xbyak"
|
|||||||
echo "compile nm_frame.cpp"
|
echo "compile nm_frame.cpp"
|
||||||
g++ $CFLAGS -DXBYAK_TEST nm_frame.cpp -o nm_frame -DXBYAK_AVX512
|
g++ $CFLAGS -DXBYAK_TEST nm_frame.cpp -o nm_frame -DXBYAK_AVX512
|
||||||
./nm_frame | $FILTER > x.lst
|
./nm_frame | $FILTER > x.lst
|
||||||
diff ok.lst x.lst && echo "ok"
|
diff -B ok.lst x.lst && echo "ok"
|
||||||
exit 0
|
|
||||||
|
@ -7,3 +7,7 @@ echo ** yasm-avx(32bit) ***
|
|||||||
call test_avx Y
|
call test_avx Y
|
||||||
echo ** yasm-avx(64bit) ***
|
echo ** yasm-avx(64bit) ***
|
||||||
call test_avx Y64
|
call test_avx Y64
|
||||||
|
echo ** nasm-avx512(32bit) ***
|
||||||
|
call test_avx512
|
||||||
|
echo ** nasm-avx512(64bit) ***
|
||||||
|
call test_avx512 64
|
||||||
|
@ -17,6 +17,10 @@ if /i "%1"=="Y" (
|
|||||||
set OPT2=-DUSE_YASM -DXBYAK64
|
set OPT2=-DUSE_YASM -DXBYAK64
|
||||||
set OPT3=win64
|
set OPT3=win64
|
||||||
set FILTER=normalize_prefix
|
set FILTER=normalize_prefix
|
||||||
|
) else if /i "%1"=="noexcept" (
|
||||||
|
set EXE=nasm.exe
|
||||||
|
set OPT2=-DXBYAK32 -DXBYAK_NO_EXCEPTION
|
||||||
|
set OPT3=win32
|
||||||
) else (
|
) else (
|
||||||
set EXE=nasm.exe
|
set EXE=nasm.exe
|
||||||
set OPT2=-DXBYAK32
|
set OPT2=-DXBYAK32
|
||||||
@ -27,7 +31,7 @@ bmake -f Makefile.win all
|
|||||||
echo cl -I../ make_nm.cpp %OPT% %OPT2% /EHs
|
echo cl -I../ make_nm.cpp %OPT% %OPT2% /EHs
|
||||||
cl -I../ make_nm.cpp %OPT% %OPT2% /EHs
|
cl -I../ make_nm.cpp %OPT% %OPT2% /EHs
|
||||||
make_nm > a.asm
|
make_nm > a.asm
|
||||||
rm a.lst
|
rm -rf a.lst
|
||||||
echo %EXE% -f %OPT3% -l a.lst a.asm
|
echo %EXE% -f %OPT3% -l a.lst a.asm
|
||||||
%EXE% -f %OPT3% -l a.lst a.asm
|
%EXE% -f %OPT3% -l a.lst a.asm
|
||||||
rem connect "?????-" and "??"
|
rem connect "?????-" and "??"
|
||||||
@ -39,5 +43,4 @@ if /i "%Y%"=="1" (
|
|||||||
make_nm jit > nm.cpp
|
make_nm jit > nm.cpp
|
||||||
cl -I../ -DXBYAK_TEST nm_frame.cpp %OPT% %OPT2%
|
cl -I../ -DXBYAK_TEST nm_frame.cpp %OPT% %OPT2%
|
||||||
nm_frame |%FILTER% > x.lst
|
nm_frame |%FILTER% > x.lst
|
||||||
diff -w x.lst ok.lst
|
diff -wb x.lst ok.lst && echo "ok"
|
||||||
wc x.lst
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user